diff options
author | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-30 12:50:58 +0000 |
---|---|---|
committer | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-30 12:50:58 +0000 |
commit | 9a136cdf89222c11b0dae86e19ff0b14956f929a (patch) | |
tree | 44f007a586303dce4a7a7024fd785eee22da61fe /skia | |
parent | e91a73a43d79d437c59a5a44396e919628f3f707 (diff) | |
download | chromium_src-9a136cdf89222c11b0dae86e19ff0b14956f929a.zip chromium_src-9a136cdf89222c11b0dae86e19ff0b14956f929a.tar.gz chromium_src-9a136cdf89222c11b0dae86e19ff0b14956f929a.tar.bz2 |
Integrate change of Skia upstream.
This is a cherry-pick of the following change:
http://code.google.com/p/skia/source/detail?r=159
We introduce this change for the 'lighter' composite operation. We need kAdd_Mode, which is introduced in this change for the operation.
Patch by Shinichiro Hamaji.
BUG=1619
Review URL: http://codereview.chromium.org/93093
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14938 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia')
-rw-r--r-- | skia/effects/SkBlurMask.cpp | 13 | ||||
-rw-r--r-- | skia/effects/SkEmbossMaskFilter.cpp | 4 | ||||
-rw-r--r-- | skia/effects/SkKernel33MaskFilter.cpp | 3 | ||||
-rw-r--r-- | skia/effects/SkLayerRasterizer.cpp | 8 | ||||
-rw-r--r-- | skia/include/SkMask.h | 8 | ||||
-rw-r--r-- | skia/include/SkPorterDuff.h | 1 | ||||
-rw-r--r-- | skia/sgl/SkDraw.cpp | 14 | ||||
-rw-r--r-- | skia/sgl/SkMask.cpp | 42 | ||||
-rw-r--r-- | skia/sgl/SkXfermode.cpp | 29 |
9 files changed, 82 insertions, 40 deletions
diff --git a/skia/effects/SkBlurMask.cpp b/skia/effects/SkBlurMask.cpp index a7b3202..d60288b 100644 --- a/skia/effects/SkBlurMask.cpp +++ b/skia/effects/SkBlurMask.cpp @@ -234,10 +234,15 @@ bool SkBlurMask::Blur(SkMask* dst, const SkMask& src, if (src.fImage) { + size_t dstSize = dst->computeImageSize(); + if (0 == dstSize) { + return false; // too big to allocate, abort + } + int sw = src.fBounds.width(); int sh = src.fBounds.height(); const uint8_t* sp = src.fImage; - uint8_t* dp = SkMask::AllocImage(dst->computeImageSize()); + uint8_t* dp = SkMask::AllocImage(dstSize); SkAutoTCallVProc<uint8_t, SkMask_FreeImage> autoCall(dp); @@ -258,7 +263,11 @@ bool SkBlurMask::Blur(SkMask* dst, const SkMask& src, // the blur into it (applying the src) if (style == kInner_Style) { - dst->fImage = SkMask::AllocImage(src.computeImageSize()); + size_t srcSize = src.computeImageSize(); + if (0 == srcSize) { + return false; // too big to allocate, abort + } + dst->fImage = SkMask::AllocImage(srcSize); merge_src_with_blur(dst->fImage, sp, sw, sh, dp + rx + ry*dst->fBounds.width(), dst->fBounds.width()); diff --git a/skia/effects/SkEmbossMaskFilter.cpp b/skia/effects/SkEmbossMaskFilter.cpp index fcfad9d..67c8024 100644 --- a/skia/effects/SkEmbossMaskFilter.cpp +++ b/skia/effects/SkEmbossMaskFilter.cpp @@ -88,7 +88,9 @@ bool SkEmbossMaskFilter::filterMask(SkMask* dst, const SkMask& src, const SkMatr { uint8_t* alphaPlane = dst->fImage; size_t planeSize = dst->computeImageSize(); - + if (0 == planeSize) { + return false; // too big to allocate, abort + } dst->fImage = SkMask::AllocImage(planeSize * 3); memcpy(dst->fImage, alphaPlane, planeSize); SkMask::FreeImage(alphaPlane); diff --git a/skia/effects/SkKernel33MaskFilter.cpp b/skia/effects/SkKernel33MaskFilter.cpp index a30ea4a..429e120 100644 --- a/skia/effects/SkKernel33MaskFilter.cpp +++ b/skia/effects/SkKernel33MaskFilter.cpp @@ -19,6 +19,9 @@ bool SkKernel33ProcMaskFilter::filterMask(SkMask* dst, const SkMask& src, const dst->fRowBytes = dst->fBounds.width(); size_t size = dst->computeImageSize(); + if (0 == size) { + return false; // too big to allocate, abort + } dst->fImage = SkMask::AllocImage(size); const int h = src.fBounds.height(); diff --git a/skia/effects/SkLayerRasterizer.cpp b/skia/effects/SkLayerRasterizer.cpp index 390e3a3..4fd1d26 100644 --- a/skia/effects/SkLayerRasterizer.cpp +++ b/skia/effects/SkLayerRasterizer.cpp @@ -108,8 +108,12 @@ bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, { mask->fFormat = SkMask::kA8_Format; mask->fRowBytes = SkToU16(mask->fBounds.width()); - mask->fImage = SkMask::AllocImage(mask->computeImageSize()); - memset(mask->fImage, 0, mask->computeImageSize()); + size_t size = mask->computeImageSize(); + if (0 == size) { + return false; // too big to allocate, abort + } + mask->fImage = SkMask::AllocImage(size); + memset(mask->fImage, 0, size); } if (SkMask::kJustComputeBounds_CreateMode != mode) diff --git a/skia/include/SkMask.h b/skia/include/SkMask.h index 764ead6..77f1f36 100644 --- a/skia/include/SkMask.h +++ b/skia/include/SkMask.h @@ -40,12 +40,18 @@ struct SkMask { uint16_t fRowBytes; uint8_t fFormat; // Format + /** Returns true if the mask is empty: i.e. it has an empty bounds. + */ + bool isEmpty() const { return fBounds.isEmpty(); } + /** Return the byte size of the mask, assuming only 1 plane. - Does not account for k3D_Format. For that, use computeFormatImageSize() + Does not account for k3D_Format. For that, use computeTotalImageSize() + If there is an overflow of 32bits, then returns 0. */ size_t computeImageSize() const; /** Return the byte size of the mask, taking into account any extra planes (e.g. k3D_Format). + If there is an overflow of 32bits, then returns 0. */ size_t computeTotalImageSize() const; diff --git a/skia/include/SkPorterDuff.h b/skia/include/SkPorterDuff.h index f03e9cb..44c5477 100644 --- a/skia/include/SkPorterDuff.h +++ b/skia/include/SkPorterDuff.h @@ -48,6 +48,7 @@ public: kLighten_Mode, //!< [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] kMultiply_Mode, //!< [Sa * Da, Sc * Dc] kScreen_Mode, //!< [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] + kAdd_Mode, //!< Saturate(S + D) kModeCount }; diff --git a/skia/sgl/SkDraw.cpp b/skia/sgl/SkDraw.cpp index 2f0ddff..40b9026 100644 --- a/skia/sgl/SkDraw.cpp +++ b/skia/sgl/SkDraw.cpp @@ -911,11 +911,16 @@ void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, return; } } + mask.fFormat = SkMask::kA8_Format; mask.fRowBytes = SkAlign4(mask.fBounds.width()); + size_t size = mask.computeImageSize(); + if (0 == size) { + // the mask is too big to allocated, draw nothing + return; + } // allocate (and clear) our temp buffer to hold the transformed bitmap - size_t size = mask.computeImageSize(); SkAutoMalloc storage(size); mask.fImage = (uint8_t*)storage.get(); memset(mask.fImage, 0, size); @@ -2336,7 +2341,12 @@ bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { mask->fFormat = SkMask::kA8_Format; mask->fRowBytes = mask->fBounds.width(); - mask->fImage = SkMask::AllocImage(mask->computeImageSize()); + size_t size = mask->computeImageSize(); + if (0 == size) { + // we're too big to allocate the mask, abort + return false; + } + mask->fImage = SkMask::AllocImage(size); memset(mask->fImage, 0, mask->computeImageSize()); } diff --git a/skia/sgl/SkMask.cpp b/skia/sgl/SkMask.cpp index 1a03b16..337204b 100644 --- a/skia/sgl/SkMask.cpp +++ b/skia/sgl/SkMask.cpp @@ -15,41 +15,29 @@ ** limitations under the License. */ -#include <limits> - +#include "Sk64.h" #include "SkMask.h" -size_t SkMask::computeImageSize() const -{ - // Prevent too large a number. There is a better fix for this in Skia - // trunk where it returns failure. - long long size = (long long)fBounds.height() * (long long)fRowBytes; - if (size >= std::numeric_limits<size_t>::max() / 2) { -#ifdef WIN32 - __debugbreak(); -#else - abort(); -#endif +/** returns the product if it is positive and fits in 31 bits. Otherwise this + returns 0. + */ +static int32_t safeMul32(int32_t a, int32_t b) { + Sk64 size; + size.setMul(a, b); + if (size.is32() && size.isPos()) { + return size.get32(); } + return 0; +} - return size; +size_t SkMask::computeImageSize() const { + return safeMul32(fBounds.height(), fRowBytes); } -size_t SkMask::computeTotalImageSize() const -{ +size_t SkMask::computeTotalImageSize() const { size_t size = this->computeImageSize(); - if (fFormat == SkMask::k3D_Format) { - // See computeImageSize for why we want to stop here. - if (size > std::numeric_limits<size_t>::max() / 3) { -#ifdef WIN32 - __debugbreak(); -#else - abort(); -#endif - } - - size *= 3; + size = safeMul32(size, 3); } return size; } diff --git a/skia/sgl/SkXfermode.cpp b/skia/sgl/SkXfermode.cpp index e8a202d..1b2479f 100644 --- a/skia/sgl/SkXfermode.cpp +++ b/skia/sgl/SkXfermode.cpp @@ -43,6 +43,16 @@ static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { return result; } +static unsigned saturated_add(unsigned a, unsigned b) { + SkASSERT(a <= 255); + SkASSERT(b <= 255); + unsigned sum = a + b; + if (sum > 255) { + sum = 255; + } + return sum; +} + /////////////////////////////////////////////////////////////////////////////// bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { @@ -495,6 +505,14 @@ static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { return SkPackARGB32(a, r, g, b); } +static SkPMColor add_modeproc(SkPMColor src, SkPMColor dst) { + unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); + unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); + unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); + unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); + return SkPackARGB32(a, r, g, b); +} + /////////////////////////////////////////////////////////////////////////////// class SkClearXfermode : public SkProcCoeffXfermode { @@ -696,6 +714,8 @@ struct ProcCoeff { SkXfermode::Coeff fDC; }; +#define CANNOT_USE_COEFF SkXfermode::Coeff(-1) + static const ProcCoeff gProcCoeffs[] = { { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, @@ -709,12 +729,11 @@ static const ProcCoeff gProcCoeffs[] = { { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, - // these two can't be represented as coefficients - { darken_modeproc, SkXfermode::Coeff(-1), SkXfermode::Coeff(-1) }, - { lighten_modeproc, SkXfermode::Coeff(-1), SkXfermode::Coeff(-1) }, - // these can use coefficients + { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, + { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, { mult_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, - { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff } + { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, + { add_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF } }; SkXfermode* SkPorterDuff::CreateXfermode(SkPorterDuff::Mode mode) { |