aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkColorFilter.h22
-rw-r--r--include/effects/SkColorMatrixFilter.h2
-rw-r--r--include/effects/SkModeColorFilter.h2
-rw-r--r--src/core/SkColorFilter.cpp15
-rw-r--r--src/core/SkFilterShader.cpp19
-rw-r--r--src/core/SkFilterShader.h1
-rw-r--r--src/effects/SkColorFilters.cpp54
-rw-r--r--src/effects/SkColorMatrixFilter.cpp39
8 files changed, 136 insertions, 18 deletions
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index ea314811ba..fe151a2533 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -68,15 +68,31 @@ public:
@param count the number of entries in the src[] and result[] arrays
@param result written by the filter
*/
- virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) const = 0;
+ virtual void filterSpan(const SkPMColor src[], int count,
+ SkPMColor result[]) const = 0;
+ /** Called with a scanline of colors, as if there was a shader installed.
+ The implementation writes out its filtered version into result[].
+ Note: shader and result may be the same buffer.
+ @param src array of colors, possibly generated by a shader
+ @param count the number of entries in the src[] and result[] arrays
+ @param result written by the filter
+ */
+ virtual void filterSpan16(const uint16_t shader[], int count,
+ uint16_t result[]) const;
enum Flags {
- /** If set the filter methods will not change the alpha channel of the colors.
+ /** If set the filter methods will not change the alpha channel of the
+ colors.
*/
kAlphaUnchanged_Flag = 0x01,
+ /** If set, this subclass implements filterSpan16(). If this flag is
+ set, then kAlphaUnchanged_Flag must also be set.
+ */
+ kHasFilter16_Flag = 0x02
};
- /** Returns the flags for this filter. Override in subclasses to return custom flags.
+ /** Returns the flags for this filter. Override in subclasses to return
+ custom flags.
*/
virtual uint32_t getFlags() const { return 0; }
diff --git a/include/effects/SkColorMatrixFilter.h b/include/effects/SkColorMatrixFilter.h
index 4cb24bad5d..7ec0a6f65c 100644
--- a/include/effects/SkColorMatrixFilter.h
+++ b/include/effects/SkColorMatrixFilter.h
@@ -20,7 +20,9 @@ public:
return SkNEW_ARGS(SkColorMatrixFilter, (array));
}
+ // overrides from SkColorFilter
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const SK_OVERRIDE;
+ void filterSpan16(const uint16_t src[], int count, uint16_t[]) const SK_OVERRIDE;
uint32_t getFlags() const SK_OVERRIDE;
bool asColorMatrix(SkScalar matrix[20]) const SK_OVERRIDE;
SkColorFilter* newComposed(const SkColorFilter*) const SK_OVERRIDE;
diff --git a/include/effects/SkModeColorFilter.h b/include/effects/SkModeColorFilter.h
index 6d0d3ccaa0..4bb7a43db4 100644
--- a/include/effects/SkModeColorFilter.h
+++ b/include/effects/SkModeColorFilter.h
@@ -28,6 +28,7 @@ public:
bool asColorMode(SkColor*, SkXfermode::Mode*) const SK_OVERRIDE;
uint32_t getFlags() const SK_OVERRIDE;
void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE;
+ void filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const SK_OVERRIDE;
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const SK_OVERRIDE {
@@ -52,6 +53,7 @@ private:
// cache
SkPMColor fPMColor;
SkXfermodeProc fProc;
+ SkXfermodeProc16 fProc16;
void updateCache();
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 45950ad0b5..0a9cd93e34 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -22,6 +22,15 @@ bool SkColorFilter::asComponentTable(SkBitmap*) const {
return false;
}
+void SkColorFilter::filterSpan16(const uint16_t s[], int count, uint16_t d[]) const {
+ SkASSERT(this->getFlags() & SkColorFilter::kHasFilter16_Flag);
+ SkDEBUGFAIL("missing implementation of SkColorFilter::filterSpan16");
+
+ if (d != s) {
+ memcpy(d, s, count * sizeof(uint16_t));
+ }
+}
+
SkColor SkColorFilter::filterColor(SkColor c) const {
SkPMColor dst, src = SkPreMultiplyColor(c);
this->filterSpan(&src, 1, &dst);
@@ -52,6 +61,12 @@ public:
fOuter->filterSpan(result, count, result);
}
+ void filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const SK_OVERRIDE {
+ SkASSERT(this->getFlags() & kHasFilter16_Flag);
+ fInner->filterSpan16(shader, count, result);
+ fOuter->filterSpan16(result, count, result);
+ }
+
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const SK_OVERRIDE {
SkString outerS, innerS;
diff --git a/src/core/SkFilterShader.cpp b/src/core/SkFilterShader.cpp
index a10a7c9d77..48c4b8b477 100644
--- a/src/core/SkFilterShader.cpp
+++ b/src/core/SkFilterShader.cpp
@@ -46,12 +46,13 @@ uint32_t SkFilterShader::FilterShaderContext::getFlags() const {
uint32_t shaderF = fShaderContext->getFlags();
uint32_t filterF = filterShader.fFilter->getFlags();
- // filters don't support 16bit, so clear the matching bit in the shader
- shaderF &= ~SkShader::kHasSpan16_Flag;
-
+ // if the filter doesn't support 16bit, clear the matching bit in the shader
+ if (!(filterF & SkColorFilter::kHasFilter16_Flag)) {
+ shaderF &= ~SkShader::kHasSpan16_Flag;
+ }
// if the filter might change alpha, clear the opaque flag in the shader
if (!(filterF & SkColorFilter::kAlphaUnchanged_Flag)) {
- shaderF &= ~SkShader::kOpaqueAlpha_Flag;
+ shaderF &= ~(SkShader::kOpaqueAlpha_Flag | SkShader::kHasSpan16_Flag);
}
return shaderF;
}
@@ -86,6 +87,16 @@ void SkFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor resu
filterShader.fFilter->filterSpan(result, count, result);
}
+void SkFilterShader::FilterShaderContext::shadeSpan16(int x, int y, uint16_t result[], int count) {
+ const SkFilterShader& filterShader = static_cast<const SkFilterShader&>(fShader);
+
+ SkASSERT(fShaderContext->getFlags() & SkShader::kHasSpan16_Flag);
+ SkASSERT(filterShader.fFilter->getFlags() & SkColorFilter::kHasFilter16_Flag);
+
+ fShaderContext->shadeSpan16(x, y, result, count);
+ filterShader.fFilter->filterSpan16(result, count, result);
+}
+
#ifndef SK_IGNORE_TO_STRING
void SkFilterShader::toString(SkString* str) const {
str->append("SkFilterShader: (");
diff --git a/src/core/SkFilterShader.h b/src/core/SkFilterShader.h
index 65291c8f39..dca9567e66 100644
--- a/src/core/SkFilterShader.h
+++ b/src/core/SkFilterShader.h
@@ -28,6 +28,7 @@ public:
uint32_t getFlags() const SK_OVERRIDE;
void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+ void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
void set3DMask(const SkMask* mask) SK_OVERRIDE {
// forward to our proxy
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
index 8c021e452b..8bcd0ebc5d 100644
--- a/src/effects/SkColorFilters.cpp
+++ b/src/effects/SkColorFilters.cpp
@@ -27,14 +27,7 @@ bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) cons
}
uint32_t SkModeColorFilter::getFlags() const {
- switch (fMode) {
- case SkXfermode::kDst_Mode: //!< [Da, Dc]
- case SkXfermode::kSrcATop_Mode: //!< [Da, Sc * Da + (1 - Sa) * Dc]
- return kAlphaUnchanged_Flag;
- default:
- break;
- }
- return 0;
+ return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
}
void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
@@ -46,6 +39,16 @@ void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColo
}
}
+void SkModeColorFilter::filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const {
+ SkASSERT(this->getFlags() & kHasFilter16_Flag);
+
+ SkPMColor color = fPMColor;
+ SkXfermodeProc16 proc16 = fProc16;
+
+ for (int i = 0; i < count; i++) {
+ result[i] = proc16(color, shader[i]);
+ }
+}
void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
buffer.writeColor(fColor);
buffer.writeUInt(fMode);
@@ -54,6 +57,7 @@ void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
void SkModeColorFilter::updateCache() {
fPMColor = SkPreMultiplyColor(fColor);
fProc = SkXfermode::GetProc(fMode);
+ fProc16 = SkXfermode::GetProc16(fMode, fColor);
}
SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
@@ -384,10 +388,25 @@ class Src_SkModeColorFilter : public SkModeColorFilter {
public:
Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
- void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE {
+ uint32_t getFlags() const SK_OVERRIDE {
+ if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
+ return kAlphaUnchanged_Flag | kHasFilter16_Flag;
+ } else {
+ return 0;
+ }
+ }
+
+ virtual void filterSpan(const SkPMColor shader[], int count,
+ SkPMColor result[]) const SK_OVERRIDE {
sk_memset32(result, this->getPMColor(), count);
}
+ virtual void filterSpan16(const uint16_t shader[], int count,
+ uint16_t result[]) const SK_OVERRIDE {
+ SkASSERT(this->getFlags() & kHasFilter16_Flag);
+ sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
+ }
+
private:
typedef SkModeColorFilter INHERITED;
};
@@ -399,10 +418,25 @@ public:
fColor32Proc = SkBlitRow::ColorProcFactory();
}
- void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE {
+ uint32_t getFlags() const SK_OVERRIDE {
+ if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
+ return kAlphaUnchanged_Flag | kHasFilter16_Flag;
+ } else {
+ return 0;
+ }
+ }
+
+ virtual void filterSpan(const SkPMColor shader[], int count,
+ SkPMColor result[]) const SK_OVERRIDE {
fColor32Proc(result, shader, count, this->getPMColor());
}
+ virtual void filterSpan16(const uint16_t shader[], int count,
+ uint16_t result[]) const SK_OVERRIDE {
+ SkASSERT(this->getFlags() & kHasFilter16_Flag);
+ sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
+ }
+
private:
SkBlitRow::ColorProc fColor32Proc;
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 3bdda61187..04c00c951f 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -139,6 +139,9 @@ static void Add16(const SkColorMatrixFilter::State& state,
result[3] = a;
}
+#define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag | \
+ SkColorFilter::kHasFilter16_Flag)
+
// src is [20] but some compilers won't accept __restrict__ on anything
// but an raw pointer or reference
void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) {
@@ -180,7 +183,7 @@ void SkColorMatrixFilter::initState(const SkScalar* SK_RESTRICT src) {
fProc = shiftIs16 ? General16 : General;
fFlags = changesAlpha ? 0 : SkColorFilter::kAlphaUnchanged_Flag;
} else {
- fFlags = SkColorFilter::kAlphaUnchanged_Flag;
+ fFlags = kNO_ALPHA_FLAGS;
int32_t needsScale = (array[SkColorMatrix::kR_Scale] - one) |
(array[SkColorMatrix::kG_Scale] - one) |
@@ -362,6 +365,40 @@ void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count, SkPMColor
}
}
+void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
+ uint16_t dst[]) const {
+ SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag);
+
+ Proc proc = fProc;
+ const State& state = fState;
+ int32_t result[4];
+
+ if (NULL == proc) {
+ if (src != dst) {
+ memcpy(dst, src, count * sizeof(uint16_t));
+ }
+ return;
+ }
+
+ for (int i = 0; i < count; i++) {
+ uint16_t c = src[i];
+
+ // expand to 8bit components (since our matrix translate is 8bit biased
+ unsigned r = SkPacked16ToR32(c);
+ unsigned g = SkPacked16ToG32(c);
+ unsigned b = SkPacked16ToB32(c);
+
+ proc(state, r, g, b, 0, result);
+
+ r = pin(result[0], SK_R32_MASK);
+ g = pin(result[1], SK_G32_MASK);
+ b = pin(result[2], SK_B32_MASK);
+
+ // now packed it back down to 16bits (hmmm, could dither...)
+ dst[i] = SkPack888ToRGB16(r, g, b);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
void SkColorMatrixFilter::flatten(SkWriteBuffer& buffer) const {