Index: src/core/SkComposeShader.cpp |
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp |
index b5ea63c24c5ed7e60dbe54d671ef9f59c076953d..8aefed4233297c15eab0dc6cf48cd73fbf11f6c4 100644 |
--- a/src/core/SkComposeShader.cpp |
+++ b/src/core/SkComposeShader.cpp |
@@ -45,6 +45,11 @@ SkComposeShader::~SkComposeShader() { |
fShaderA->unref(); |
} |
+size_t SkComposeShader::shaderImplSize() const { |
+ return sizeof(ComposeImpl) + fShaderA->shaderImplSize() |
+ + fShaderB->shaderImplSize(); |
+} |
+ |
class SkAutoAlphaRestore { |
public: |
SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { |
@@ -73,13 +78,11 @@ void SkComposeShader::flatten(SkWriteBuffer& buffer) const { |
always let them see opaque alpha, and if the paint really |
is translucent, then we apply that after the fact. |
- We need to keep the calls to setContext/endContext balanced, since if we |
- return false, our endContext() will not be called. |
*/ |
-bool SkComposeShader::setContext(const SkBitmap& device, |
- const SkPaint& paint, |
- const SkMatrix& matrix) { |
- if (!this->INHERITED::setContext(device, paint, matrix)) { |
+bool SkComposeShader::validContext(const SkBitmap& device, |
+ const SkPaint& paint, |
+ const SkMatrix& matrix) { |
+ if (!this->INHERITED::validContext(device, paint, matrix)) { |
return false; |
} |
@@ -90,27 +93,52 @@ bool SkComposeShader::setContext(const SkBitmap& device, |
tmpM.setConcat(matrix, this->getLocalMatrix()); |
+ return fShaderA->validContext(device, paint, tmpM) |
+ && fShaderB->validContext(device, paint, tmpM); |
+} |
+ |
+SkShaderGenerator::ShaderImpl* SkComposeShader::createShaderImpl( |
+ const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, void* storage) const |
+{ |
+ SkASSERT(this->validContext(device, paint, matrix)); |
+ |
+ // we preconcat our localMatrix (if any) with the device matrix |
+ // before calling our sub-shaders |
+ |
+ SkMatrix tmpM; |
+ |
+ tmpM.setConcat(matrix, this->getLocalMatrix()); |
+ |
SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); |
- bool setContextA = fShaderA->setContext(device, paint, tmpM); |
- bool setContextB = fShaderB->setContext(device, paint, tmpM); |
- if (!setContextA || !setContextB) { |
- if (setContextB) { |
- fShaderB->endContext(); |
- } |
- else if (setContextA) { |
- fShaderA->endContext(); |
- } |
- this->INHERITED::endContext(); |
- return false; |
- } |
- return true; |
+ char* aStorage = (char*) storage + sizeof(ComposeImpl); |
+ char* bStorage = aStorage + fShaderA->shaderImplSize(); |
+ |
+ ShaderImpl* implA = fShaderA->createShaderImpl(device, paint, matrix, |
+ aStorage); |
+ ShaderImpl* implB = fShaderB->createShaderImpl(device, paint, matrix, |
+ bStorage); |
+ |
+ // Both functions must succeed; otherwise validContext should have returned |
+ // false. |
+ SkASSERT(implA); |
+ SkASSERT(implB); |
+ |
+ return SkNEW_PLACEMENT_ARGS(storage, ComposeImpl, |
+ (*this, device, paint, matrix, implA, implB)); |
} |
-void SkComposeShader::endContext() { |
- fShaderB->endContext(); |
- fShaderA->endContext(); |
- this->INHERITED::endContext(); |
+SkComposeShader::ComposeImpl::ComposeImpl(const SkComposeShader& shader, |
+ const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix, |
+ ShaderImpl* shaderImplA, ShaderImpl* shaderImplB) |
+ : INHERITED(shader, device, paint, matrix) |
+ , fShaderImplA(shaderImplA) |
+ , fShaderImplB(shaderImplB) {} |
+ |
+void SkComposeShader::ComposeImpl::~ComposeImpl() { |
+ fShaderImplA->~ShaderImpl(); |
+ fShaderImplB->~ShaderImpl(); |
} |
// larger is better (fewer times we have to loop), but we shouldn't |
@@ -118,9 +146,7 @@ void SkComposeShader::endContext() { |
#define TMP_COLOR_COUNT 64 |
void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { |
- SkShader* shaderA = fShaderA; |
- SkShader* shaderB = fShaderB; |
- SkXfermode* mode = fMode; |
+ SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode; |
unsigned scale = SkAlpha255To256(this->getPaintAlpha()); |
SkPMColor tmp[TMP_COLOR_COUNT]; |
@@ -134,8 +160,8 @@ void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { |
n = TMP_COLOR_COUNT; |
} |
- shaderA->shadeSpan(x, y, result, n); |
- shaderB->shadeSpan(x, y, tmp, n); |
+ fShaderImplA->shadeSpan(x, y, result, n); |
+ fShaderImplB->shadeSpan(x, y, tmp, n); |
if (256 == scale) { |
for (int i = 0; i < n; i++) { |
@@ -159,8 +185,8 @@ void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { |
n = TMP_COLOR_COUNT; |
} |
- shaderA->shadeSpan(x, y, result, n); |
- shaderB->shadeSpan(x, y, tmp, n); |
+ fShaderImplA->shadeSpan(x, y, result, n); |
+ fShaderImplB->shadeSpan(x, y, tmp, n); |
mode->xfer32(result, tmp, n, NULL); |
if (256 == scale) { |