| Index: src/core/SkComposeShader.cpp
 | 
| diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
 | 
| index 77bc46f30a3fc98798478a0ed621861e9955c765..f53eedf8764d01e275be11801243a6d0189258a1 100644
 | 
| --- a/src/core/SkComposeShader.cpp
 | 
| +++ b/src/core/SkComposeShader.cpp
 | 
| @@ -45,10 +45,6 @@
 | 
|      fShaderA->unref();
 | 
|  }
 | 
|  
 | 
| -size_t SkComposeShader::contextSize() const {
 | 
| -    return sizeof(ComposeShaderContext) + fShaderA->contextSize() + fShaderB->contextSize();
 | 
| -}
 | 
| -
 | 
|  class SkAutoAlphaRestore {
 | 
|  public:
 | 
|      SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) {
 | 
| @@ -73,34 +69,18 @@
 | 
|      buffer.writeFlattenable(fMode);
 | 
|  }
 | 
|  
 | 
| -/*  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 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 need to keep the calls to setContext/endContext balanced, since if we
 | 
| +    return false, our endContext() will not be called.
 | 
|   */
 | 
| -bool SkComposeShader::validContext(const SkBitmap& device,
 | 
| -                                   const SkPaint& paint,
 | 
| -                                   const SkMatrix& matrix,
 | 
| -                                   SkMatrix* totalInverse) const {
 | 
| -    if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) {
 | 
| +bool SkComposeShader::setContext(const SkBitmap& device,
 | 
| +                                 const SkPaint& paint,
 | 
| +                                 const SkMatrix& matrix) {
 | 
| +    if (!this->INHERITED::setContext(device, paint, matrix)) {
 | 
|          return false;
 | 
| -    }
 | 
| -
 | 
| -    // we preconcat our localMatrix (if any) with the device matrix
 | 
| -    // before calling our sub-shaders
 | 
| -
 | 
| -    SkMatrix tmpM;
 | 
| -
 | 
| -    tmpM.setConcat(matrix, this->getLocalMatrix());
 | 
| -
 | 
| -    return fShaderA->validContext(device, paint, tmpM) &&
 | 
| -           fShaderB->validContext(device, paint, tmpM);
 | 
| -}
 | 
| -
 | 
| -SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const SkPaint& paint,
 | 
| -                                                  const SkMatrix& matrix, void* storage) const {
 | 
| -    if (!this->validContext(device, paint, matrix)) {
 | 
| -        return NULL;
 | 
|      }
 | 
|  
 | 
|      // we preconcat our localMatrix (if any) with the device matrix
 | 
| @@ -112,43 +92,36 @@
 | 
|  
 | 
|      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));
 | 
| +    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;
 | 
|  }
 | 
|  
 | 
| -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();
 | 
| +void SkComposeShader::endContext() {
 | 
| +    fShaderB->endContext();
 | 
| +    fShaderA->endContext();
 | 
| +    this->INHERITED::endContext();
 | 
|  }
 | 
|  
 | 
|  // 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::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());
 | 
| +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());
 | 
|  
 | 
|      SkPMColor   tmp[TMP_COLOR_COUNT];
 | 
|  
 | 
| @@ -161,8 +134,8 @@
 | 
|                  n = TMP_COLOR_COUNT;
 | 
|              }
 | 
|  
 | 
| -            shaderContextA->shadeSpan(x, y, result, n);
 | 
| -            shaderContextB->shadeSpan(x, y, tmp, n);
 | 
| +            shaderA->shadeSpan(x, y, result, n);
 | 
| +            shaderB->shadeSpan(x, y, tmp, n);
 | 
|  
 | 
|              if (256 == scale) {
 | 
|                  for (int i = 0; i < n; i++) {
 | 
| @@ -186,8 +159,8 @@
 | 
|                  n = TMP_COLOR_COUNT;
 | 
|              }
 | 
|  
 | 
| -            shaderContextA->shadeSpan(x, y, result, n);
 | 
| -            shaderContextB->shadeSpan(x, y, tmp, n);
 | 
| +            shaderA->shadeSpan(x, y, result, n);
 | 
| +            shaderB->shadeSpan(x, y, tmp, n);
 | 
|              mode->xfer32(result, tmp, n, NULL);
 | 
|  
 | 
|              if (256 == scale) {
 | 
| 
 |