diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-03 20:14:26 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-03 20:14:26 +0000 |
commit | 99c114e0ac732ba01705e24d12f5e4dd7e144abd (patch) | |
tree | d60428959061d6b86b8bfd13fcec141cceb053ff /src | |
parent | 7265e725555098637498db2f397623d7991ceb4b (diff) |
We were numerically overflowing our 16bit coordinates that we communicate
between these two procs. The fixes was in two parts:
1. Just don't draw bitmaps larger than 64K-1 in width or height, since we
can't represent those coordinates in our transport format (yet).
2. Perform an unsigned shift during the calculation, so we don't get
sign-extension bleed when packing the two values (X,Y) into our 32bit
slot.
Review URL: https://codereview.appspot.com/6173046
git-svn-id: http://skia.googlecode.com/svn/trunk@3836 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBitmapProcShader.cpp | 12 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_matrixProcs.cpp | 19 |
2 files changed, 24 insertions, 7 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 7ae6afca81..3abfc8d230 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -271,12 +271,22 @@ static bool canUseColorShader(const SkBitmap& bm, SkColor* color) { #include "SkTemplatesPriv.h" +static bool bitmapIsTooBig(const SkBitmap& bm) { + // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it + // communicates between its matrix-proc and its sampler-proc. Until we can + // widen that, we have to reject bitmaps that are larger. + // + const int maxSize = 65535; + + return bm.width() > maxSize || bm.height() > maxSize; +} + SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, void* storage, size_t storageSize) { SkShader* shader; SkColor color; - if (src.isNull()) { + if (src.isNull() || bitmapIsTooBig(src)) { SK_PLACEMENT_NEW(shader, SkEmptyShader, storage, storageSize); } else if (canUseColorShader(src, &color)) { diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp index 15e7bebbe7..a8a2821524 100644 --- a/src/core/SkBitmapProcState_matrixProcs.cpp +++ b/src/core/SkBitmapProcState_matrixProcs.cpp @@ -9,6 +9,13 @@ #include "SkShader.h" #include "SkUtils.h" +// Helper to ensure that when we shift down, we do it w/o sign-extension +// so the caller doesn't have to manually mask off the top 16 bits +// +static unsigned SK_USHIFT16(unsigned x) { + return x >> 16; +} + /* returns 0...(n-1) given any x (positive or negative). As an example, if n (which is always positive) is 5... @@ -32,8 +39,8 @@ void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count); void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count); #define MAKENAME(suffix) ClampX_ClampY ## suffix -#define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max) -#define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max) +#define TILEX_PROCF(fx, max) SkClampMax(SK_USHIFT16(fx), max) +#define TILEY_PROCF(fy, max) SkClampMax(SK_USHIFT16(fy), max) #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF) #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF) #define CHECK_FOR_DECAL @@ -44,8 +51,8 @@ void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count); #endif #define MAKENAME(suffix) RepeatX_RepeatY ## suffix -#define TILEX_PROCF(fx, max) (((fx) & 0xFFFF) * ((max) + 1) >> 16) -#define TILEY_PROCF(fy, max) (((fy) & 0xFFFF) * ((max) + 1) >> 16) +#define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1)) +#define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1)) #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF) #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF) #if defined(__ARM_HAVE_NEON) @@ -63,8 +70,8 @@ void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count); #define PREAMBLE_PARAM_Y , SkBitmapProcState::FixedTileProc tileProcY, SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcY #define PREAMBLE_ARG_X , tileProcX, tileLowBitsProcX #define PREAMBLE_ARG_Y , tileProcY, tileLowBitsProcY -#define TILEX_PROCF(fx, max) (tileProcX(fx) * ((max) + 1) >> 16) -#define TILEY_PROCF(fy, max) (tileProcY(fy) * ((max) + 1) >> 16) +#define TILEX_PROCF(fx, max) SK_USHIFT16(tileProcX(fx) * ((max) + 1)) +#define TILEY_PROCF(fy, max) SK_USHIFT16(tileProcY(fy) * ((max) + 1)) #define TILEX_LOW_BITS(fx, max) tileLowBitsProcX(fx, (max) + 1) #define TILEY_LOW_BITS(fy, max) tileLowBitsProcY(fy, (max) + 1) #include "SkBitmapProcState_matrix.h" |