| 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) {
|
|
|