diff options
Diffstat (limited to 'src/core/SkComposeShader.cpp')
-rw-r--r-- | src/core/SkComposeShader.cpp | 97 |
1 files changed, 62 insertions, 35 deletions
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp index f53eedf876..77bc46f30a 100644 --- a/src/core/SkComposeShader.cpp +++ b/src/core/SkComposeShader.cpp @@ -45,6 +45,10 @@ SkComposeShader::~SkComposeShader() { fShaderA->unref(); } +size_t SkComposeShader::contextSize() const { + return sizeof(ComposeShaderContext) + fShaderA->contextSize() + fShaderB->contextSize(); +} + class SkAutoAlphaRestore { public: SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { @@ -69,17 +73,16 @@ void SkComposeShader::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fMode); } -/* We call setContext on our two worker shaders. However, we - always let them see opaque alpha, and if the paint really - is translucent, then we apply that after the fact. +/* We call validContext/createContext on our two worker shaders. + However, we 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, + SkMatrix* totalInverse) const { + if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { return false; } @@ -90,38 +93,62 @@ bool SkComposeShader::setContext(const SkBitmap& device, tmpM.setConcat(matrix, this->getLocalMatrix()); - SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); + return fShaderA->validContext(device, paint, tmpM) && + fShaderB->validContext(device, paint, tmpM); +} - 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; +SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix, void* storage) const { + if (!this->validContext(device, paint, matrix)) { + return NULL; } - return true; + + // 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); + + char* aStorage = (char*) storage + sizeof(ComposeShaderContext); + char* bStorage = aStorage + fShaderA->contextSize(); + + SkShader::Context* contextA = fShaderA->createContext(device, paint, tmpM, aStorage); + SkShader::Context* contextB = fShaderB->createContext(device, paint, tmpM, bStorage); + + // Both functions must succeed; otherwise validContext should have returned + // false. + SkASSERT(contextA); + SkASSERT(contextB); + + return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, + (*this, device, paint, matrix, contextA, contextB)); } -void SkComposeShader::endContext() { - fShaderB->endContext(); - fShaderA->endContext(); - this->INHERITED::endContext(); +SkComposeShader::ComposeShaderContext::ComposeShaderContext( + const SkComposeShader& shader, const SkBitmap& device, + const SkPaint& paint, const SkMatrix& matrix, + SkShader::Context* contextA, SkShader::Context* contextB) + : INHERITED(shader, device, paint, matrix) + , fShaderContextA(contextA) + , fShaderContextB(contextB) {} + +SkComposeShader::ComposeShaderContext::~ComposeShaderContext() { + fShaderContextA->~Context(); + fShaderContextB->~Context(); } // larger is better (fewer times we have to loop), but we shouldn't // take up too much stack-space (each element is 4 bytes) #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; - unsigned scale = SkAlpha255To256(this->getPaintAlpha()); +void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { + SkShader::Context* shaderContextA = fShaderContextA; + SkShader::Context* shaderContextB = fShaderContextB; + SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode; + unsigned scale = SkAlpha255To256(this->getPaintAlpha()); SkPMColor tmp[TMP_COLOR_COUNT]; @@ -134,8 +161,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); + shaderContextA->shadeSpan(x, y, result, n); + shaderContextB->shadeSpan(x, y, tmp, n); if (256 == scale) { for (int i = 0; i < n; i++) { @@ -159,8 +186,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); + shaderContextA->shadeSpan(x, y, result, n); + shaderContextB->shadeSpan(x, y, tmp, n); mode->xfer32(result, tmp, n, NULL); if (256 == scale) { |