Index: src/effects/gradients/SkGradientShader.cpp |
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp |
index 21bf8858b54d7fb0b3f4edf8fe4d8504be3c2963..7cc906336ad24cb3d0a5e204e6f00c61a211fe6c 100644 |
--- a/src/effects/gradients/SkGradientShader.cpp |
+++ b/src/effects/gradients/SkGradientShader.cpp |
@@ -12,6 +12,61 @@ |
#include "SkTwoPointConicalGradient.h" |
#include "SkSweepGradient.h" |
+void SkGradientShaderBase::Descriptor::flatten(SkWriteBuffer& buffer) const { |
+ buffer.writeColorArray(fColors, fCount); |
+ if (fPos) { |
+ buffer.writeBool(true); |
+ buffer.writeScalarArray(fPos, fCount); |
+ } else { |
+ buffer.writeBool(false); |
+ } |
+ buffer.write32(fTileMode); |
+ buffer.write32(fGradFlags); |
+ if (fLocalMatrix) { |
+ buffer.writeBool(true); |
+ buffer.writeMatrix(*fLocalMatrix); |
+ } else { |
+ buffer.writeBool(false); |
+ } |
+} |
+ |
+bool SkGradientShaderBase::DescriptorScope::unflatten(SkReadBuffer& buffer) { |
+ fCount = buffer.getArrayCount(); |
+ if (fCount > kStorageCount) { |
+ size_t allocSize = (sizeof(SkColor) + sizeof(SkScalar)) * fCount; |
+ fDynamicStorage.reset(allocSize); |
+ fColors = (SkColor*)fDynamicStorage.get(); |
+ fPos = (SkScalar*)(fColors + fCount); |
+ } else { |
+ fColors = fColorStorage; |
+ fPos = fPosStorage; |
+ } |
+ |
+ if (!buffer.readColorArray(const_cast<SkColor*>(fColors), fCount)) { |
+ return false; |
+ } |
+ if (buffer.readBool()) { |
+ if (!buffer.readScalarArray(const_cast<SkScalar*>(fPos), fCount)) { |
+ return false; |
+ } |
+ } else { |
+ fPos = NULL; |
+ } |
+ |
+ fTileMode = (SkShader::TileMode)buffer.read32(); |
+ fGradFlags = buffer.read32(); |
+ |
+ if (buffer.readBool()) { |
+ fLocalMatrix = &fLocalMatrixStorage; |
+ buffer.readMatrix(&fLocalMatrixStorage); |
+ } else { |
+ fLocalMatrix = NULL; |
+ } |
+ return buffer.isValid(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////////////////// |
+ |
SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) |
: INHERITED(desc.fLocalMatrix) |
{ |
@@ -47,6 +102,9 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) |
if (fColorCount > kColorStorageCount) { |
size_t size = sizeof(SkColor) + sizeof(Rec); |
+ if (desc.fPos) { |
+ size += sizeof(SkScalar); |
+ } |
fOrigColors = reinterpret_cast<SkColor*>( |
sk_malloc_throw(size * fColorCount)); |
} |
@@ -67,13 +125,23 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) |
} |
} |
- fRecs = (Rec*)(fOrigColors + fColorCount); |
+ if (desc.fPos && fColorCount) { |
+ fOrigPos = (SkScalar*)(fOrigColors + fColorCount); |
+ fRecs = (Rec*)(fOrigPos + fColorCount); |
+ } else { |
+ fOrigPos = NULL; |
+ fRecs = (Rec*)(fOrigColors + fColorCount); |
+ } |
+ |
if (fColorCount > 2) { |
Rec* recs = fRecs; |
recs->fPos = 0; |
// recs->fScale = 0; // unused; |
recs += 1; |
if (desc.fPos) { |
+ SkScalar* origPosPtr = fOrigPos; |
+ *origPosPtr++ = 0; |
+ |
/* We need to convert the user's array of relative positions into |
fixed-point positions and scale factors. We need these results |
to be strictly monotonic (no two values equal or out of order). |
@@ -81,26 +149,22 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) |
value if it sees a segment out of order, and it assures that |
we start at 0 and end at 1.0 |
*/ |
- SkFixed prev = 0; |
+ SkScalar prev = 0; |
int startIndex = dummyFirst ? 0 : 1; |
int count = desc.fCount + dummyLast; |
for (int i = startIndex; i < count; i++) { |
// force the last value to be 1.0 |
- SkFixed curr; |
+ SkScalar curr; |
if (i == desc.fCount) { // we're really at the dummyLast |
- curr = SK_Fixed1; |
+ curr = 1; |
} else { |
- curr = SkScalarToFixed(desc.fPos[i]); |
+ curr = SkScalarPin(desc.fPos[i], 0, 1); |
} |
- // pin curr withing range |
- if (curr < 0) { |
- curr = 0; |
- } else if (curr > SK_Fixed1) { |
- curr = SK_Fixed1; |
- } |
- recs->fPos = curr; |
+ *origPosPtr++ = curr; |
+ |
+ recs->fPos = SkScalarToFixed(curr); |
if (curr > prev) { |
- recs->fScale = (1 << 24) / (curr - prev); |
+ recs->fScale = (1 << 24) / SkScalarToFixed(curr - prev); |
} else { |
recs->fScale = 0; // ignore this segment |
} |
@@ -109,6 +173,8 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) |
recs += 1; |
} |
} else { // assume even distribution |
+ fOrigPos = NULL; |
+ |
SkFixed dp = SK_Fixed1 / (desc.fCount - 1); |
SkFixed p = dp; |
SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp |
@@ -121,16 +187,18 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) |
recs->fPos = SK_Fixed1; |
recs->fScale = scale; |
} |
+ } else if (desc.fPos) { |
+ SkASSERT(2 == fColorCount); |
+ fOrigPos[0] = SkScalarPin(desc.fPos[0], 0, 1); |
+ fOrigPos[1] = SkScalarPin(desc.fPos[1], fOrigPos[0], 1); |
+ if (0 == fOrigPos[0] && 1 == fOrigPos[1]) { |
+ fOrigPos = NULL; |
+ } |
} |
this->initCommon(); |
} |
-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; |
-} |
- |
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING |
static SkShader::TileMode unpack_mode(uint32_t packed) { |
return (SkShader::TileMode)(packed & 0xF); |
} |
@@ -177,6 +245,7 @@ SkGradientShaderBase::SkGradientShaderBase(SkReadBuffer& buffer) : INHERITED(buf |
buffer.readMatrix(&fPtsToUnit); |
this->initCommon(); |
} |
+#endif |
SkGradientShaderBase::~SkGradientShaderBase() { |
if (fOrigColors != fStorage) { |
@@ -193,17 +262,16 @@ void SkGradientShaderBase::initCommon() { |
} |
void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const { |
- this->INHERITED::flatten(buffer); |
- buffer.writeColorArray(fOrigColors, fColorCount); |
- buffer.writeUInt(pack_mode_flags(fTileMode, fGradFlags)); |
- if (fColorCount > 2) { |
- Rec* recs = fRecs; |
- for (int i = 1; i < fColorCount; i++) { |
- buffer.writeInt(recs[i].fPos); |
- buffer.writeUInt(recs[i].fScale); |
- } |
- } |
- buffer.writeMatrix(fPtsToUnit); |
+ Descriptor desc; |
+ desc.fColors = fOrigColors; |
+ desc.fPos = fOrigPos; |
+ desc.fCount = fColorCount; |
+ desc.fTileMode = fTileMode; |
+ desc.fGradFlags = fGradFlags; |
+ |
+ const SkMatrix& m = this->getLocalMatrix(); |
+ desc.fLocalMatrix = m.isIdentity() ? NULL : &m; |
+ desc.flatten(buffer); |
} |
SkGradientShaderBase::GpuColorType SkGradientShaderBase::getGpuColorType(SkColor colors[3]) const { |