Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Unified Diff: src/effects/gradients/SkGradientShader.cpp

Issue 15893002: Add flag to gradients to interpolate colors in premul space. Experimental API to encapsulate the sh… (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/effects/SkGradientShader.h ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/gradients/SkGradientShader.cpp
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index d1ab539c076a716279cb888857e75ee4850686ad..6dcbb05f7e1eae0b19dcdb9bfa7dad6d021fc22f 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -19,6 +19,7 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
fMapper = desc.fMapper;
SkSafeRef(fMapper);
+ fGradFlags = SkToU8(desc.fFlags);
SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount);
SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs));
@@ -128,8 +129,21 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) {
this->initCommon();
}
-SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) :
- INHERITED(buffer) {
+static uint32_t pack_mode_flags(SkShader::TileMode mode, uint32_t flags) {
+ SkASSERT(0 == (flags >> 28));
+ SkASSERT(0 == ((uint32_t)mode >> 4));
+ return (flags << 4) | mode;
+}
+
+static SkShader::TileMode unpack_mode(uint32_t packed) {
+ return (SkShader::TileMode)(packed & 0xF);
+}
+
+static uint32_t unpack_flags(uint32_t packed) {
+ return packed >> 4;
+}
+
+SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
fCacheAlpha = 256;
fMapper = buffer.readFlattenableT<SkUnitMapper>();
@@ -147,7 +161,11 @@ SkGradientShaderBase::SkGradientShaderBase(SkFlattenableReadBuffer& buffer) :
}
buffer.readColorArray(fOrigColors);
- fTileMode = (TileMode)buffer.readUInt();
+ {
+ uint32_t packed = buffer.readUInt();
+ fGradFlags = SkToU8(unpack_flags(packed));
+ fTileMode = unpack_mode(packed);
+ }
fTileProc = gTileProcs[fTileMode];
fRecs = (Rec*)(fOrigColors + colorCount);
if (colorCount > 2) {
@@ -186,7 +204,7 @@ void SkGradientShaderBase::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fMapper);
buffer.writeColorArray(fOrigColors, fColorCount);
- buffer.writeUInt(fTileMode);
+ buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags));
if (fColorCount > 2) {
Rec* recs = fRecs;
for (int i = 1; i < fColorCount; i++) {
@@ -288,39 +306,58 @@ void SkGradientShaderBase::Build16bitCache(uint16_t cache[], SkColor c0, SkColor
} while (--count != 0);
}
+/*
+ * r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
+ * release builds, we saw a compiler error where the 0xFF parameter in
+ * SkPackARGB32() was being totally ignored whenever it was called with
+ * a non-zero add (e.g. 0x8000).
+ *
+ * We found two work-arounds:
+ * 1. change r,g,b to unsigned (or just one of them)
+ * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
+ * of using |
+ *
+ * We chose #1 just because it was more localized.
+ * See http://code.google.com/p/skia/issues/detail?id=1113
+ *
+ * The type SkUFixed encapsulate this need for unsigned, but logically Fixed.
+ */
+typedef uint32_t SkUFixed;
+
void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
- int count, U8CPU paintAlpha) {
+ int count, U8CPU paintAlpha, uint32_t gradFlags) {
SkASSERT(count > 1);
// need to apply paintAlpha to our two endpoints
- SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
- SkFixed da;
- {
- int tmp = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
- da = SkIntToFixed(tmp - a) / (count - 1);
- }
+ uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
+ uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
- /*
- * r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
- * release builds, we saw a compiler error where the 0xFF parameter in
- * SkPackARGB32() was being totally ignored whenever it was called with
- * a non-zero add (e.g. 0x8000).
- *
- * We found two work-arounds:
- * 1. change r,g,b to unsigned (or just one of them)
- * 2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
- * of using |
- *
- * We chose #1 just because it was more localized.
- * See http://code.google.com/p/skia/issues/detail?id=1113
- */
- uint32_t r = SkColorGetR(c0);
- uint32_t g = SkColorGetG(c0);
- uint32_t b = SkColorGetB(c0);
- SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
- SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
- SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);
+ const bool interpInPremul = SkToBool(gradFlags &
+ SkGradientShader::kInterpolateColorsInPremul_Flag);
+
+ uint32_t r0 = SkColorGetR(c0);
+ uint32_t g0 = SkColorGetG(c0);
+ uint32_t b0 = SkColorGetB(c0);
+
+ uint32_t r1 = SkColorGetR(c1);
+ uint32_t g1 = SkColorGetG(c1);
+ uint32_t b1 = SkColorGetB(c1);
+
+ if (interpInPremul) {
+ r0 = SkMulDiv255Round(r0, a0);
+ g0 = SkMulDiv255Round(g0, a0);
+ b0 = SkMulDiv255Round(b0, a0);
+
+ r1 = SkMulDiv255Round(r1, a1);
+ g1 = SkMulDiv255Round(g1, a1);
+ b1 = SkMulDiv255Round(b1, a1);
+ }
+
+ SkFixed da = SkIntToFixed(a1 - a0) / (count - 1);
+ SkFixed dr = SkIntToFixed(r1 - r0) / (count - 1);
+ SkFixed dg = SkIntToFixed(g1 - g0) / (count - 1);
+ SkFixed db = SkIntToFixed(b1 - b0) / (count - 1);
/* We pre-add 1/8 to avoid having to add this to our [0] value each time
in the loop. Without this, the bias for each would be
@@ -328,9 +365,10 @@ void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo
With this trick, we can add 0 for the first (no-op) and just adjust the
others.
*/
- r = SkIntToFixed(r) + 0x2000;
- g = SkIntToFixed(g) + 0x2000;
- b = SkIntToFixed(b) + 0x2000;
+ SkUFixed a = SkIntToFixed(a0) + 0x2000;
+ SkUFixed r = SkIntToFixed(r0) + 0x2000;
+ SkUFixed g = SkIntToFixed(g0) + 0x2000;
+ SkUFixed b = SkIntToFixed(b0) + 0x2000;
/*
* Our dither-cell (spatially) is
@@ -343,7 +381,7 @@ void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo
* [3] -> [ 5/8 ... 7/8 ) values near 3/4
*/
- if (0xFF == a && 0 == da) {
+ if (0xFF == a0 && 0 == da) {
do {
cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0 ) >> 16,
(g + 0 ) >> 16,
@@ -362,8 +400,31 @@ void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColo
g += dg;
b += db;
} while (--count != 0);
- } else {
- a = SkIntToFixed(a) + 0x2000;
+ } else if (interpInPremul) {
+ do {
+ cache[kCache32Count*0] = SkPackARGB32((a + 0 ) >> 16,
+ (r + 0 ) >> 16,
+ (g + 0 ) >> 16,
+ (b + 0 ) >> 16);
+ cache[kCache32Count*1] = SkPackARGB32((a + 0x8000) >> 16,
+ (r + 0x8000) >> 16,
+ (g + 0x8000) >> 16,
+ (b + 0x8000) >> 16);
+ cache[kCache32Count*2] = SkPackARGB32((a + 0xC000) >> 16,
+ (r + 0xC000) >> 16,
+ (g + 0xC000) >> 16,
+ (b + 0xC000) >> 16);
+ cache[kCache32Count*3] = SkPackARGB32((a + 0x4000) >> 16,
+ (r + 0x4000) >> 16,
+ (g + 0x4000) >> 16,
+ (b + 0x4000) >> 16);
+ cache += 1;
+ a += da;
+ r += dr;
+ g += dg;
+ b += db;
+ } while (--count != 0);
+ } else { // interpolate in unpreml space
do {
cache[kCache32Count*0] = SkPremultiplyARGBInline((a + 0 ) >> 16,
(r + 0 ) >> 16,
@@ -463,7 +524,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
if (fColorCount == 2) {
Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
- kCache32Count, fCacheAlpha);
+ kCache32Count, fCacheAlpha, fGradFlags);
} else {
Rec* rec = fRecs;
int prevIndex = 0;
@@ -473,8 +534,8 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
if (nextIndex > prevIndex)
Build32bitCache(fCache32 + prevIndex, fOrigColors[i-1],
- fOrigColors[i],
- nextIndex - prevIndex + 1, fCacheAlpha);
+ fOrigColors[i], nextIndex - prevIndex + 1,
+ fCacheAlpha, fGradFlags);
prevIndex = nextIndex;
}
}
@@ -522,8 +583,8 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
return;
}
- // build our key: [numColors + colors[] + {positions[]} ]
- int count = 1 + fColorCount;
+ // build our key: [numColors + colors[] + {positions[]} + flags ]
+ int count = 1 + fColorCount + 1;
if (fColorCount > 2) {
count += fColorCount - 1; // fRecs[].fPos
}
@@ -539,6 +600,7 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap) const {
*buffer++ = fRecs[i].fPos;
}
}
+ *buffer++ = fGradFlags;
SkASSERT(buffer - storage.get() == count);
///////////////////////////////////
@@ -583,6 +645,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
}
info->fColorCount = fColorCount;
info->fTileMode = fTileMode;
+ info->fGradientFlags = fGradFlags;
}
}
@@ -643,26 +706,28 @@ static void desc_init(SkGradientShaderBase::Descriptor* desc,
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper) {
+ SkUnitMapper* mapper, uint32_t flags) {
desc->fColors = colors;
desc->fPos = pos;
desc->fCount = colorCount;
desc->fTileMode = mode;
desc->fMapper = mapper;
+ desc->fFlags = flags;
}
SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2],
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper) {
+ SkUnitMapper* mapper,
+ uint32_t flags) {
if (NULL == pts || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper);
+ desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
return SkNEW_ARGS(SkLinearGradient, (pts, desc));
}
@@ -670,14 +735,15 @@ SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius,
const SkColor colors[],
const SkScalar pos[], int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper) {
+ SkUnitMapper* mapper,
+ uint32_t flags) {
if (radius <= 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper);
+ desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
return SkNEW_ARGS(SkRadialGradient, (center, radius, desc));
}
@@ -689,27 +755,29 @@ SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start,
const SkScalar pos[],
int colorCount,
SkShader::TileMode mode,
- SkUnitMapper* mapper) {
+ SkUnitMapper* mapper,
+ uint32_t flags) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper);
+ desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
return SkNEW_ARGS(SkTwoPointRadialGradient,
(start, startRadius, end, endRadius, desc));
}
SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
- SkScalar startRadius,
- const SkPoint& end,
- SkScalar endRadius,
- const SkColor colors[],
- const SkScalar pos[],
- int colorCount,
- SkShader::TileMode mode,
- SkUnitMapper* mapper) {
+ SkScalar startRadius,
+ const SkPoint& end,
+ SkScalar endRadius,
+ const SkColor colors[],
+ const SkScalar pos[],
+ int colorCount,
+ SkShader::TileMode mode,
+ SkUnitMapper* mapper,
+ uint32_t flags) {
if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) {
return NULL;
}
@@ -719,7 +787,7 @@ SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, mode, mapper);
+ desc_init(&desc, colors, pos, colorCount, mode, mapper, flags);
return SkNEW_ARGS(SkTwoPointConicalGradient,
(start, startRadius, end, endRadius, desc));
}
@@ -727,14 +795,15 @@ SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start,
SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy,
const SkColor colors[],
const SkScalar pos[],
- int colorCount, SkUnitMapper* mapper) {
+ int colorCount, SkUnitMapper* mapper,
+ uint32_t flags) {
if (NULL == colors || colorCount < 1) {
return NULL;
}
EXPAND_1_COLOR(colorCount);
SkGradientShaderBase::Descriptor desc;
- desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper);
+ desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper, flags);
return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc));
}
« no previous file with comments | « include/effects/SkGradientShader.h ('k') | src/effects/gradients/SkGradientShaderPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698