diff options
author | Mike Reed <reed@google.com> | 2009-06-15 12:37:46 -0400 |
---|---|---|
committer | Mike Reed <reed@google.com> | 2009-06-15 12:51:30 -0400 |
commit | f294d10d594ac335ea3bd09caec89004d41edc5c (patch) | |
tree | 4e6b485f97bee16f397c04c66cb3ffa3d1fee2b8 | |
parent | f87ea139deed57504b433fc4e1bf98c85ef0da80 (diff) | |
download | external_skia-f294d10d594ac335ea3bd09caec89004d41edc5c.zip external_skia-f294d10d594ac335ea3bd09caec89004d41edc5c.tar.gz external_skia-f294d10d594ac335ea3bd09caec89004d41edc5c.tar.bz2 |
add constY flag to shaders
add opaque special case to 16bit blitter
add Format optional arg to decoder helpers
-rw-r--r-- | include/core/SkColorShader.h | 8 | ||||
-rw-r--r-- | include/core/SkShader.h | 10 | ||||
-rw-r--r-- | include/images/SkImageDecoder.h | 38 | ||||
-rw-r--r-- | src/core/SkBitmapProcShader.cpp | 11 | ||||
-rw-r--r-- | src/core/SkBlitter.cpp | 25 | ||||
-rw-r--r-- | src/core/SkBlitter_RGB16.cpp | 421 | ||||
-rw-r--r-- | src/core/SkCoreBlitters.h | 21 | ||||
-rw-r--r-- | src/core/SkShader.cpp | 11 | ||||
-rw-r--r-- | src/effects/SkGradientShader.cpp | 78 | ||||
-rw-r--r-- | src/images/SkImageDecoder.cpp | 13 |
10 files changed, 359 insertions, 277 deletions
diff --git a/include/core/SkColorShader.h b/include/core/SkColorShader.h index f9c3dc3..7c5f941 100644 --- a/include/core/SkColorShader.h +++ b/include/core/SkColorShader.h @@ -29,14 +29,15 @@ public: /** Create a ColorShader that will inherit its color from the Paint at draw time. */ - SkColorShader() : fInheritColor(true) {} + SkColorShader() : fFlags(0), fInheritColor(true) {} + /** Create a ColorShader that ignores the color in the paint, and uses the specified color. Note: like all shaders, at draw time the paint's alpha will be respected, and is applied to the specified color. */ - SkColorShader(SkColor c) : fColor(c), fInheritColor(false) {} + SkColorShader(SkColor c) : fColor(c), fFlags(0), fInheritColor(false) {} - virtual uint32_t getFlags(); + virtual uint32_t getFlags() { return fFlags; } virtual uint8_t getSpan16Alpha() const; virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix); @@ -54,6 +55,7 @@ private: } SkColor fColor; // ignored if fInheritColor is true SkPMColor fPMColor; // cached after setContext() + uint32_t fFlags; // cached after setContext() uint16_t fColor16; // cached after setContext() SkBool8 fInheritColor; diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 7c13e3d..8fac8cb 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -63,14 +63,22 @@ public: enum Flags { //!< set if all of the colors will be opaque kOpaqueAlpha_Flag = 0x01, + //! set if this shader's shadeSpan16() method can be called kHasSpan16_Flag = 0x02, + /** Set this bit if the shader's native data type is instrinsically 16 bit, meaning that calling the 32bit shadeSpan() entry point will mean the the impl has to up-sample 16bit data into 32bit. Used as a a means of clearing a dither request if the it will have no effect */ - kIntrinsicly16_Flag = 0x04 + kIntrinsicly16_Flag = 0x04, + + /** set (after setContext) if the spans only vary in X (const in Y). + e.g. an Nx1 bitmap that is being tiled in Y, or a linear-gradient + that varies from left-to-right + */ + kConstInY_Flag = 0x08 }; /** Called sometimes before drawing with this shader. diff --git a/include/images/SkImageDecoder.h b/include/images/SkImageDecoder.h index d2b23a1..de63345 100644 --- a/include/images/SkImageDecoder.h +++ b/include/images/SkImageDecoder.h @@ -160,12 +160,16 @@ public: there is a conflict (e.g. the image has per-pixel alpha and the bitmap's config does not support that), in which case the decoder will choose a closest match configuration. + + @param format On success, if format is non-null, it is set to the format + of the decoded file. On failure it is ignored. */ static bool DecodeFile(const char file[], SkBitmap* bitmap, - SkBitmap::Config prefConfig, Mode); - static bool DecodeFile(const char file[], SkBitmap* bitmap) - { - return DecodeFile(file, bitmap, SkBitmap::kNo_Config, kDecodePixels_Mode); + SkBitmap::Config prefConfig, Mode, + Format* format = NULL); + static bool DecodeFile(const char file[], SkBitmap* bitmap) { + return DecodeFile(file, bitmap, SkBitmap::kNo_Config, + kDecodePixels_Mode, NULL); } /** Decode the image stored in the specified memory buffer, and store the result in bitmap. Return true for success or false on failure. @@ -176,13 +180,16 @@ public: there is a conflict (e.g. the image has per-pixel alpha and the bitmap's config does not support that), in which case the decoder will choose a closest match configuration. - */ + + @param format On success, if format is non-null, it is set to the format + of the decoded buffer. On failure it is ignored. + */ static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap, - SkBitmap::Config prefConfig, Mode); - static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap) - { + SkBitmap::Config prefConfig, Mode, + Format* format = NULL); + static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap){ return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config, - kDecodePixels_Mode); + kDecodePixels_Mode, NULL); } /** Decode the image stored in the specified SkStream, and store the result in bitmap. Return true for success or false on failure. @@ -193,13 +200,16 @@ public: format, unless there is a conflict (e.g. the image has per-pixel alpha and the bitmap's config does not support that), in which case the decoder will choose a closest match configuration. - */ + + @param format On success, if format is non-null, it is set to the format + of the decoded stream. On failure it is ignored. + */ static bool DecodeStream(SkStream* stream, SkBitmap* bitmap, - SkBitmap::Config prefConfig, Mode); - static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) - { + SkBitmap::Config prefConfig, Mode, + Format* format = NULL); + static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) { return DecodeStream(stream, bitmap, SkBitmap::kNo_Config, - kDecodePixels_Mode); + kDecodePixels_Mode, NULL); } /** Return the default config for the running device. diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 8ba57c4..2302e0f 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -67,6 +67,11 @@ void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) { buffer.write8(fState.fTileModeY); } +static bool only_scale_and_translate(const SkMatrix& matrix) { + unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; + return (matrix.getType() & ~mask) == 0; +} + bool SkBitmapProcShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { @@ -117,6 +122,12 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device, default: break; } + + // if we're only 1-pixel heigh, and we don't rotate, then we can claim this + if (1 == fState.fBitmap->height() && + only_scale_and_translate(this->getTotalInverse())) { + fFlags |= kConstInY_Flag; + } return true; } diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 25303ac..e47e782 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -935,11 +935,21 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, storage, storageSize, (device, paint)); else SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, storage, storageSize, (device, paint)); + } else { + SkColor color = paint.getColor(); + if (0 == SkColorGetA(color)) { + SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); + } else if (SK_ColorBLACK == color) { + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage, + storageSize, (device, paint)); + } else if (0xFF == SkColorGetA(color)) { + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Opaque_Blitter, storage, + storageSize, (device, paint)); + } else { + SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage, + storageSize, (device, paint)); + } } - else if (paint.getColor() == SK_ColorBLACK) - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Black_Blitter, storage, storageSize, (device, paint)); - else - SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Blitter, storage, storageSize, (device, paint)); break; case SkBitmap::kARGB_8888_Config: @@ -977,17 +987,16 @@ const uint32_t gMask_00FF00FF = 0xFF00FF; ////////////////////////////////////////////////////////////////////////////////////////////////////// SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) -{ + : INHERITED(device) { fShader = paint.getShader(); SkASSERT(fShader); fShader->ref(); fShader->beginSession(); + fShaderFlags = fShader->getFlags(); } -SkShaderBlitter::~SkShaderBlitter() -{ +SkShaderBlitter::~SkShaderBlitter() { fShader->endSession(); fShader->unref(); } diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp index b253662..955f4c1 100644 --- a/src/core/SkBlitter_RGB16.cpp +++ b/src/core/SkBlitter_RGB16.cpp @@ -154,68 +154,28 @@ void SkRGB16_Black_Blitter::blitAntiH(int x, int y, } } -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint) - : INHERITED(device) { - SkColor color = paint.getColor(); - - fSrcColor32 = SkPreMultiplyColor(color); - fScale = SkAlpha255To256(SkColorGetA(color)); - - int r = SkColorGetR(color); - int g = SkColorGetG(color); - int b = SkColorGetB(color); - - fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b); - // if we're dithered, use fRawDither16 to hold that. - if ((fDoDither = paint.isDither()) != false) { - fRawDither16 = SkDitherPack888ToRGB16(r, g, b); - } - - fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS), - SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS), - SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS)); -} +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// -const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) { - if (!fDoDither && 256 == fScale) { - *value = fRawColor16; - return &fDevice; - } - return NULL; -} +SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkBitmap& device, + const SkPaint& paint) +: INHERITED(device, paint) {} -void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { +void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) SK_RESTRICT { SkASSERT(width > 0); SkASSERT(x + width <= fDevice.width()); - - if (fScale == 0) { - return; - } - uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); uint16_t srcColor = fColor16; - if (256 == fScale) { - SkASSERT(fRawColor16 == srcColor); - if (fDoDither) { - uint16_t ditherColor = fRawDither16; - if ((x ^ y) & 1) { - SkTSwap(ditherColor, srcColor); - } - sk_dither_memset16(device, srcColor, ditherColor, width); - } else { - sk_memset16(device, srcColor, width); + SkASSERT(fRawColor16 == srcColor); + if (fDoDither) { + uint16_t ditherColor = fRawDither16; + if ((x ^ y) & 1) { + SkTSwap(ditherColor, srcColor); } + sk_dither_memset16(device, srcColor, ditherColor, width); } else { - // TODO: respect fDoDither - SkPMColor src32 = fSrcColor32; - do { - *device = SkSrcOver32To16(src32, *device); - device += 1; - } while (--width != 0); + sk_memset16(device, srcColor, width); } } @@ -224,92 +184,58 @@ static int Bool2Int(bool value) { return !!value; } -void SkRGB16_Blitter::blitAntiH(int x, int y, - const SkAlpha* SK_RESTRICT antialias, - const int16_t* SK_RESTRICT runs) SK_RESTRICT { - if (fScale == 0) { - return; - } - +void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y, + const SkAlpha* SK_RESTRICT antialias, + const int16_t* SK_RESTRICT runs) SK_RESTRICT { uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); uint16_t srcColor = fRawColor16; - unsigned scale = fScale; int ditherInt = Bool2Int(fDoDither); - - if (256 == scale) { - uint16_t ditherColor = fRawDither16; - // if we have no dithering, this will always fail - if ((x ^ y) & ditherInt) { - SkTSwap(ditherColor, srcColor); + uint16_t ditherColor = fRawDither16; + // if we have no dithering, this will always fail + if ((x ^ y) & ditherInt) { + SkTSwap(ditherColor, srcColor); + } + for (;;) { + int count = runs[0]; + SkASSERT(count >= 0); + if (count <= 0) { + return; } - for (;;) { - int count = runs[0]; - SkASSERT(count >= 0); - if (count <= 0) { - return; - } - runs += count; + runs += count; - unsigned aa = antialias[0]; - antialias += count; - if (aa) { - if (aa == 255) { - if (ditherInt) { - sk_dither_memset16(device, srcColor, - ditherColor, count); - } else { - sk_memset16(device, srcColor, count); - } + unsigned aa = antialias[0]; + antialias += count; + if (aa) { + if (aa == 255) { + if (ditherInt) { + sk_dither_memset16(device, srcColor, + ditherColor, count); } else { - // TODO: respect fDoDither - unsigned scale5 = SkAlpha255To256(aa) >> 3; - uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; - scale5 = 32 - scale5; // now we can use it on the device - int n = count; - do { - uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; - *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); - } while (--n != 0); - goto DONE; + sk_memset16(device, srcColor, count); } - } - device += count; - - DONE: - // if we have no dithering, this will always fail - if (count & ditherInt) { - SkTSwap(ditherColor, srcColor); - } - } - } else { - // TODO: respect fDoDither - for (;;) { - int count = runs[0]; - SkASSERT(count >= 0); - if (count <= 0) { - return; - } - runs += count; - - unsigned aa = antialias[0]; - antialias += count; - if (aa) { - unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3); - uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; - scale5 = 32 - scale5; + } else { + // TODO: respect fDoDither + unsigned scale5 = SkAlpha255To256(aa) >> 3; + uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; + scale5 = 32 - scale5; // now we can use it on the device + int n = count; do { uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); - } while (--count != 0); - continue; + } while (--n != 0); + goto DONE; } - device += count; + } + device += count; + + DONE: + // if we have no dithering, this will always fail + if (count & ditherInt) { + SkTSwap(ditherColor, srcColor); } } } -////////////////////////////////////////////////////////////////////////////////////// - #define solid_8_pixels(mask, dst, color) \ do { \ if (mask & 0x80) dst[0] = color; \ @@ -329,6 +255,138 @@ void SkRGB16_Blitter::blitAntiH(int x, int y, #define SK_BLITBWMASK_DEVTYPE uint16_t #include "SkBlitBWMaskTemplate.h" +static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) { + return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5)); +} + +void SkRGB16_Opaque_Blitter::blitMask(const SkMask& SK_RESTRICT mask, + const SkIRect& SK_RESTRICT clip) SK_RESTRICT { + if (mask.fFormat == SkMask::kBW_Format) { + SkRGB16_BlitBW(fDevice, mask, clip, fColor16); + return; + } + + uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); + const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); + int width = clip.width(); + int height = clip.height(); + unsigned deviceRB = fDevice.rowBytes() - (width << 1); + unsigned maskRB = mask.fRowBytes - width; + uint32_t color32 = SkExpand_rgb_16(fRawColor16); + + do { + int w = width; + do { + *device = blend_compact(color32, SkExpand_rgb_16(*device), + SkAlpha255To256(*alpha++) >> 3); + device += 1; + } while (--w != 0); + device = (uint16_t*)((char*)device + deviceRB); + alpha += maskRB; + } while (--height != 0); +} + +void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) { + SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); + unsigned deviceRB = fDevice.rowBytes(); + uint16_t color16 = fColor16; + + if (fDoDither) { + uint16_t ditherColor = fRawDither16; + if ((x ^ y) & 1) { + SkTSwap(ditherColor, color16); + } + while (--height >= 0) { + sk_dither_memset16(device, color16, ditherColor, width); + SkTSwap(ditherColor, color16); + device = (uint16_t*)((char*)device + deviceRB); + } + } else { // no dither + while (--height >= 0) { + sk_memset16(device, color16, width); + device = (uint16_t*)((char*)device + deviceRB); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint) + : INHERITED(device) { + SkColor color = paint.getColor(); + + fSrcColor32 = SkPreMultiplyColor(color); + fScale = SkAlpha255To256(SkColorGetA(color)); + + int r = SkColorGetR(color); + int g = SkColorGetG(color); + int b = SkColorGetB(color); + + fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b); + // if we're dithered, use fRawDither16 to hold that. + if ((fDoDither = paint.isDither()) != false) { + fRawDither16 = SkDitherPack888ToRGB16(r, g, b); + } + + fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS), + SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS), + SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS)); +} + +const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) { + if (!fDoDither && 256 == fScale) { + *value = fRawColor16; + return &fDevice; + } + return NULL; +} + +void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { + SkASSERT(width > 0); + SkASSERT(x + width <= fDevice.width()); + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); + + // TODO: respect fDoDither + SkPMColor src32 = fSrcColor32; + do { + *device = SkSrcOver32To16(src32, *device); + device += 1; + } while (--width != 0); +} + +void SkRGB16_Blitter::blitAntiH(int x, int y, + const SkAlpha* SK_RESTRICT antialias, + const int16_t* SK_RESTRICT runs) SK_RESTRICT { + uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); + uint16_t srcColor = fRawColor16; + unsigned scale = fScale; + + // TODO: respect fDoDither + for (;;) { + int count = runs[0]; + SkASSERT(count >= 0); + if (count <= 0) { + return; + } + runs += count; + + unsigned aa = antialias[0]; + antialias += count; + if (aa) { + unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3); + uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; + scale5 = 32 - scale5; + do { + uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; + *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); + } while (--count != 0); + continue; + } + device += count; + } +} + static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale, U16CPU srcColor) { if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale); @@ -348,21 +406,10 @@ static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale, #define SK_BLITBWMASK_DEVTYPE uint16_t #include "SkBlitBWMaskTemplate.h" -static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) { - return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5)); -} - void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask, const SkIRect& SK_RESTRICT clip) SK_RESTRICT { - if (fScale == 0) { - return; - } if (mask.fFormat == SkMask::kBW_Format) { - if (fScale == 256) { - SkRGB16_BlitBW(fDevice, mask, clip, fColor16); - } else { - SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16); - } + SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16); return; } @@ -374,38 +421,22 @@ void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask, unsigned maskRB = mask.fRowBytes - width; uint32_t color32 = SkExpand_rgb_16(fRawColor16); - if (256 == fScale) { + unsigned scale256 = fScale; + do { + int w = width; do { - int w = width; - do { - *device = blend_compact(color32, SkExpand_rgb_16(*device), - SkAlpha255To256(*alpha++) >> 3); - device += 1; - } while (--w != 0); - device = (uint16_t*)((char*)device + deviceRB); - alpha += maskRB; - } while (--height != 0); - } else { // scale < 256 - unsigned scale256 = fScale; - do { - int w = width; - do { - unsigned aa = *alpha++; - unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3); - uint32_t src32 = color32 * scale; - uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale); - *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); - } while (--w != 0); - device = (uint16_t*)((char*)device + deviceRB); - alpha += maskRB; - } while (--height != 0); - } + unsigned aa = *alpha++; + unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3); + uint32_t src32 = color32 * scale; + uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale); + *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); + } while (--w != 0); + device = (uint16_t*)((char*)device + deviceRB); + alpha += maskRB; + } while (--height != 0); } void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { - if (fScale == 0) { - return; - } uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); uint16_t color16 = fRawColor16; unsigned deviceRB = fDevice.rowBytes(); @@ -442,39 +473,15 @@ void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); - - if (fScale == 0) { - return; - } uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); unsigned deviceRB = fDevice.rowBytes(); - uint16_t color16 = fColor16; + SkPMColor src32 = fSrcColor32; - if (256 == fScale) { - if (fDoDither) { - uint16_t ditherColor = fRawDither16; - if ((x ^ y) & 1) { - SkTSwap(ditherColor, color16); - } - while (--height >= 0) { - sk_dither_memset16(device, color16, ditherColor, width); - SkTSwap(ditherColor, color16); - device = (uint16_t*)((char*)device + deviceRB); - } - } else { // no dither - while (--height >= 0) { - sk_memset16(device, color16, width); - device = (uint16_t*)((char*)device + deviceRB); - } - } - } else { - SkPMColor src32 = fSrcColor32; - while (--height >= 0) { - for (int i = width - 1; i >= 0; --i) { - device[i] = SkSrcOver32To16(src32, device[i]); - } - device = (uint16_t*)((char*)device + deviceRB); + while (--height >= 0) { + for (int i = width - 1; i >= 0; --i) { + device[i] = SkSrcOver32To16(src32, device[i]); } + device = (uint16_t*)((char*)device + deviceRB); } } @@ -483,7 +490,7 @@ void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device, const SkPaint& paint) : SkRGB16_Shader_Blitter(device, paint) { - SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags())); + SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags)); } void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { @@ -569,7 +576,7 @@ SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, // compute SkBlitRow::Procs unsigned flags = 0; - uint32_t shaderFlags = fShader->getFlags(); + uint32_t shaderFlags = fShaderFlags; // shaders take care of global alpha, so we never set it in SkBlitRow if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) { flags |= SkBlitRow::kSrcPixelAlpha_Flag; @@ -597,6 +604,30 @@ void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) { fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y); } +void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) { + SkShader* shader = fShader; + SkBlitRow::Proc proc = fOpaqueProc; + SkPMColor* buffer = fBuffer; + uint16_t* dst = fDevice.getAddr16(x, y); + size_t dstRB = fDevice.rowBytes(); + + if (fShaderFlags & SkShader::kConstInY_Flag) { + shader->shadeSpan(x, y, buffer, width); + do { + proc(dst, buffer, width, 0xFF, x, y); + y += 1; + dst = (uint16_t*)((char*)dst + dstRB); + } while (--height); + } else { + do { + shader->shadeSpan(x, y, buffer, width); + proc(dst, buffer, width, 0xFF, x, y); + y += 1; + dst = (uint16_t*)((char*)dst + dstRB); + } while (--height); + } +} + static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) { int count = 0; for (;;) { diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index 5b3497e..d45467f 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -38,7 +38,8 @@ public: virtual ~SkShaderBlitter(); protected: - SkShader* fShader; + uint32_t fShaderFlags; + SkShader* fShader; private: // illegal @@ -161,7 +162,7 @@ public: virtual void blitMask(const SkMask&, const SkIRect&); virtual const SkBitmap* justAnOpaqueColor(uint32_t*); -private: +protected: SkPMColor fSrcColor32; unsigned fScale; uint16_t fColor16; // already scaled by fScale @@ -175,10 +176,21 @@ private: typedef SkRasterBlitter INHERITED; }; +class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter { +public: + SkRGB16_Opaque_Blitter(const SkBitmap& device, const SkPaint& paint); + virtual void blitH(int x, int y, int width); + virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); + virtual void blitRect(int x, int y, int width, int height); + virtual void blitMask(const SkMask&, const SkIRect&); + +private: + typedef SkRGB16_Blitter INHERITED; +}; + class SkRGB16_Black_Blitter : public SkRGB16_Blitter { public: SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint); - virtual void blitMask(const SkMask&, const SkIRect&); virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); @@ -192,7 +204,8 @@ public: virtual ~SkRGB16_Shader_Blitter(); virtual void blitH(int x, int y, int width); virtual void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]); - + virtual void blitRect(int x, int y, int width, int height); + protected: SkPMColor* fBuffer; SkBlitRow::Proc fOpaqueProc; diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index dd9c859..5567914 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -210,6 +210,7 @@ SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, #include "SkUtils.h" SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) { + fFlags = 0; // computed in setContext fInheritColor = b.readU8(); if (fInheritColor) { return; @@ -226,11 +227,6 @@ void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) { buffer.write32(fColor); } -uint32_t SkColorShader::getFlags() { - return (SkGetPackedA32(fPMColor) == 255 ? kOpaqueAlpha_Flag : 0) | - kHasSpan16_Flag; -} - uint8_t SkColorShader::getSpan16Alpha() const { return SkGetPackedA32(fPMColor); } @@ -267,6 +263,11 @@ bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, } fPMColor = SkPackARGB32(a, r, g, b); + fFlags = kHasSpan16_Flag | kConstInY_Flag; + if (SkGetPackedA32(fPMColor) == 255) { + fFlags |= kOpaqueAlpha_Flag; + } + return true; } diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp index 696def6..e1a92ba 100644 --- a/src/effects/SkGradientShader.cpp +++ b/src/effects/SkGradientShader.cpp @@ -620,6 +620,7 @@ public: } } + virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&); virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count); virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*); @@ -646,6 +647,19 @@ private: typedef Gradient_Shader INHERITED; }; +bool Linear_Gradient::setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } + + unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; + if ((fDstToIndex.getType() & ~mask) == 0) { + fFlags |= SkShader::kConstInY_Flag; + } + return true; +} + // Return true if fx, fx+dx, fx+2*dx, ... is always in range static inline bool no_need_for_clamp(int fx, int dx, int count) { @@ -662,31 +676,27 @@ void Linear_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count) TileProc proc = fTileProc; const SkPMColor* cache = this->getCache32(); - if (fDstToIndexClass != kPerspective_MatrixClass) - { + if (fDstToIndexClass != kPerspective_MatrixClass) { dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt); SkFixed dx, fx = SkScalarToFixed(srcPt.fX); + // preround fx by half the amount we throw away + fx += 1 << 7; - if (fDstToIndexClass == kFixedStepInX_MatrixClass) - { + if (fDstToIndexClass == kFixedStepInX_MatrixClass) { SkFixed dxStorage[1]; (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL); dx = dxStorage[0]; - } - else - { + } else { SkASSERT(fDstToIndexClass == kLinear_MatrixClass); dx = SkScalarToFixed(fDstToIndex.getScaleX()); } - if (SkFixedNearlyZero(dx)) // we're a vertical gradient, so no change in a span - { + if (SkFixedNearlyZero(dx)) { + // we're a vertical gradient, so no change in a span unsigned fi = proc(fx); SkASSERT(fi <= 0xFFFF); sk_memset32(dstC, cache[fi >> (16 - kCache32Bits)], count); - } - else if (proc == clamp_tileproc) - { + } else if (proc == clamp_tileproc) { #if 0 if (no_need_for_clamp(fx, dx, count)) { @@ -716,18 +726,14 @@ void Linear_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count) fx += dx; *dstC++ = cache[fi]; } while (--count != 0); - } - else if (proc == mirror_tileproc) - { + } else if (proc == mirror_tileproc) { do { unsigned fi = mirror_8bits(fx >> 8); SkASSERT(fi <= 0xFF); fx += dx; *dstC++ = cache[fi]; } while (--count != 0); - } - else - { + } else { SkASSERT(proc == repeat_tileproc); do { unsigned fi = repeat_8bits(fx >> 8); @@ -736,9 +742,7 @@ void Linear_Gradient::shadeSpan(int x, int y, SkPMColor dstC[], int count) *dstC++ = cache[fi]; } while (--count != 0); } - } - else - { + } else { SkScalar dstX = SkIntToScalar(x); SkScalar dstY = SkIntToScalar(y); do { @@ -804,25 +808,23 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) int toggle = ((x ^ y) & 1) << kCache16Bits; #endif - if (fDstToIndexClass != kPerspective_MatrixClass) - { + if (fDstToIndexClass != kPerspective_MatrixClass) { dstProc(fDstToIndex, SkIntToScalar(x), SkIntToScalar(y), &srcPt); SkFixed dx, fx = SkScalarToFixed(srcPt.fX); + // preround fx by half the amount we throw away + fx += 1 << 7; - if (fDstToIndexClass == kFixedStepInX_MatrixClass) - { + if (fDstToIndexClass == kFixedStepInX_MatrixClass) { SkFixed dxStorage[1]; (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), dxStorage, NULL); dx = dxStorage[0]; - } - else - { + } else { SkASSERT(fDstToIndexClass == kLinear_MatrixClass); dx = SkScalarToFixed(fDstToIndex.getScaleX()); } - if (SkFixedNearlyZero(dx)) // we're a vertical gradient, so no change in a span - { + if (SkFixedNearlyZero(dx)) { + // we're a vertical gradient, so no change in a span unsigned fi = proc(fx) >> 10; SkASSERT(fi <= 63); #ifdef TEST_GRADIENT_DITHER @@ -830,9 +832,7 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) #else sk_memset16(dstC, cache[fi], count); #endif - } - else if (proc == clamp_tileproc) - { + } else if (proc == clamp_tileproc) { do { unsigned fi = SkClampMax(fx >> 10, 63); SkASSERT(fi <= 63); @@ -844,9 +844,7 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) *dstC++ = cache[fi]; #endif } while (--count != 0); - } - else if (proc == mirror_tileproc) - { + } else if (proc == mirror_tileproc) { do { unsigned fi = mirror_6bits(fx >> 10); SkASSERT(fi <= 0x3F); @@ -858,9 +856,7 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) *dstC++ = cache[fi]; #endif } while (--count != 0); - } - else - { + } else { SkASSERT(proc == repeat_tileproc); do { unsigned fi = repeat_6bits(fx >> 10); @@ -874,9 +870,7 @@ void Linear_Gradient::shadeSpan16(int x, int y, uint16_t dstC[], int count) #endif } while (--count != 0); } - } - else - { + } else { SkScalar dstX = SkIntToScalar(x); SkScalar dstY = SkIntToScalar(y); do { diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index b910df6..4f9fa9b 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -120,13 +120,13 @@ bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, /////////////////////////////////////////////////////////////////////////////// bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, - SkBitmap::Config pref, Mode mode) { + SkBitmap::Config pref, Mode mode, Format* format) { SkASSERT(file); SkASSERT(bm); SkFILEStream stream(file); if (stream.isValid()) { - if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode)) { + if (SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format)) { bm->pixelRef()->setURI(file); } return true; @@ -135,18 +135,18 @@ bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, } bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, - SkBitmap::Config pref, Mode mode) { + SkBitmap::Config pref, Mode mode, Format* format) { if (0 == size) { return false; } SkASSERT(buffer); SkMemoryStream stream(buffer, size); - return SkImageDecoder::DecodeStream(&stream, bm, pref, mode); + return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); } bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, - SkBitmap::Config pref, Mode mode) { + SkBitmap::Config pref, Mode mode, Format* format) { SkASSERT(stream); SkASSERT(bm); @@ -155,6 +155,9 @@ bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm, if (NULL != codec) { success = codec->decode(stream, bm, pref, mode); + if (success && format) { + *format = codec->getFormat(); + } delete codec; } return success; |