aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Reed <reed@google.com>2009-06-15 12:37:46 -0400
committerMike Reed <reed@google.com>2009-06-15 12:51:30 -0400
commitf294d10d594ac335ea3bd09caec89004d41edc5c (patch)
tree4e6b485f97bee16f397c04c66cb3ffa3d1fee2b8
parentf87ea139deed57504b433fc4e1bf98c85ef0da80 (diff)
downloadexternal_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.h8
-rw-r--r--include/core/SkShader.h10
-rw-r--r--include/images/SkImageDecoder.h38
-rw-r--r--src/core/SkBitmapProcShader.cpp11
-rw-r--r--src/core/SkBlitter.cpp25
-rw-r--r--src/core/SkBlitter_RGB16.cpp421
-rw-r--r--src/core/SkCoreBlitters.h21
-rw-r--r--src/core/SkShader.cpp11
-rw-r--r--src/effects/SkGradientShader.cpp78
-rw-r--r--src/images/SkImageDecoder.cpp13
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;