summaryrefslogtreecommitdiffstats
path: root/skia
diff options
context:
space:
mode:
authordeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-30 12:50:58 +0000
committerdeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-30 12:50:58 +0000
commit9a136cdf89222c11b0dae86e19ff0b14956f929a (patch)
tree44f007a586303dce4a7a7024fd785eee22da61fe /skia
parente91a73a43d79d437c59a5a44396e919628f3f707 (diff)
downloadchromium_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.cpp13
-rw-r--r--skia/effects/SkEmbossMaskFilter.cpp4
-rw-r--r--skia/effects/SkKernel33MaskFilter.cpp3
-rw-r--r--skia/effects/SkLayerRasterizer.cpp8
-rw-r--r--skia/include/SkMask.h8
-rw-r--r--skia/include/SkPorterDuff.h1
-rw-r--r--skia/sgl/SkDraw.cpp14
-rw-r--r--skia/sgl/SkMask.cpp42
-rw-r--r--skia/sgl/SkXfermode.cpp29
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) {