summaryrefslogtreecommitdiff
path: root/core/SkComposeShader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/SkComposeShader.cpp')
-rw-r--r--core/SkComposeShader.cpp55
1 files changed, 21 insertions, 34 deletions
diff --git a/core/SkComposeShader.cpp b/core/SkComposeShader.cpp
index df8215c1..7a7dce66 100644
--- a/core/SkComposeShader.cpp
+++ b/core/SkComposeShader.cpp
@@ -73,55 +73,38 @@ void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
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.
-
- */
-bool SkComposeShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const {
- if (!this->INHERITED::validContext(rec, totalInverse)) {
- return false;
+template <typename T> void safe_call_destructor(T* obj) {
+ if (obj) {
+ obj->~T();
}
-
- // we preconcat our localMatrix (if any) with the device matrix
- // before calling our sub-shaders
-
- SkMatrix tmpM;
- tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix());
-
- ContextRec newRec(rec);
- newRec.fMatrix = &tmpM;
-
- return fShaderA->validContext(newRec) && fShaderB->validContext(newRec);
}
-SkShader::Context* SkComposeShader::createContext(const ContextRec& rec, void* storage) const {
- if (!this->validContext(rec)) {
- return NULL;
- }
-
- // TODO : must fix this to not "cheat" and modify fPaint
- SkAutoAlphaRestore restore(const_cast<SkPaint*>(rec.fPaint), 0xFF);
-
+SkShader::Context* SkComposeShader::onCreateContext(const ContextRec& rec, void* storage) const {
char* aStorage = (char*) storage + sizeof(ComposeShaderContext);
char* bStorage = aStorage + fShaderA->contextSize();
// we preconcat our localMatrix (if any) with the device matrix
// before calling our sub-shaders
-
SkMatrix tmpM;
tmpM.setConcat(*rec.fMatrix, this->getLocalMatrix());
+ // Our sub-shaders need to see opaque, so by combining them we don't double-alphatize the
+ // result. ComposeShader itself will respect the alpha, and post-apply it after calling the
+ // sub-shaders.
+ SkPaint opaquePaint(*rec.fPaint);
+ opaquePaint.setAlpha(0xFF);
+
ContextRec newRec(rec);
newRec.fMatrix = &tmpM;
+ newRec.fPaint = &opaquePaint;
SkShader::Context* contextA = fShaderA->createContext(newRec, aStorage);
SkShader::Context* contextB = fShaderB->createContext(newRec, bStorage);
-
- // Both functions must succeed; otherwise validContext should have returned
- // false.
- SkASSERT(contextA);
- SkASSERT(contextB);
+ if (!contextA || !contextB) {
+ safe_call_destructor(contextA);
+ safe_call_destructor(contextB);
+ return NULL;
+ }
return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, (*this, rec, contextA, contextB));
}
@@ -148,6 +131,10 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re
SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode;
unsigned scale = SkAlpha255To256(this->getPaintAlpha());
+#ifdef SK_BUILD_FOR_ANDROID
+ scale = 256; // ugh -- maintain old bug/behavior for now
+#endif
+
SkPMColor tmp[TMP_COLOR_COUNT];
if (NULL == mode) { // implied SRC_OVER
@@ -188,7 +175,7 @@ void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re
shaderContextB->shadeSpan(x, y, tmp, n);
mode->xfer32(result, tmp, n, NULL);
- if (256 == scale) {
+ if (256 != scale) {
for (int i = 0; i < n; i++) {
result[i] = SkAlphaMulQ(result[i], scale);
}