Index: src/core/SkDraw.cpp |
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp |
index 05b06453dbf200df8cebccfc3aee4c69825d5143..d74c1700d17fa4bea1389484fc6593c02aba2c82 100644 |
--- a/src/core/SkDraw.cpp |
+++ b/src/core/SkDraw.cpp |
@@ -2355,13 +2355,35 @@ static bool texture_to_matrix(const VertState& state, const SkPoint verts[], |
return matrix->setPolyToPoly(src, dst, 3); |
} |
+/** |
+ * This class is NOT immutable due to the setup() method being called repeatedly after |
+ * the shader has been associated with a paint. This is okay because we only ever |
+ * associate this shader with temporary paints. |
+ */ |
class SkTriColorShader : public SkShader { |
public: |
SkTriColorShader() {} |
- bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); |
+ // TODO(dominikg): Feels like this should be part of the context, but we don't have |
+ // access to it where we need it. |
+ bool setup(const SkPoint pts[], const SkColor colors[], int, int, int, const SkMatrix&); |
+ |
+ virtual SkShader::Context* createContext( |
+ const SkBitmap&, const SkPaint&, const SkMatrix&, void*) const SK_OVERRIDE; |
+ virtual size_t contextSize() const SK_OVERRIDE; |
+ |
+ class TriColorShaderContext : public SkShader::Context { |
+ public: |
+ TriColorShaderContext(const SkTriColorShader& shader, const SkBitmap& device, |
+ const SkPaint& paint, const SkMatrix& matrix); |
+ virtual ~TriColorShaderContext(); |
+ |
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; |
+ private: |
+ const SkTriColorShader& fTriColorShader; |
scroggo
2014/03/24 21:24:46
Any reason SkTriColorShader does not simply static
Dominik Grewe
2014/03/26 17:22:22
Done.
|
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; |
+ typedef SkShader::Context INHERITED; |
+ }; |
SK_DEVELOPER_TO_STRING() |
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader) |
@@ -2376,8 +2398,17 @@ private: |
typedef SkShader INHERITED; |
}; |
+SkShader::Context* SkTriColorShader::createContext(const SkBitmap& device, const SkPaint& paint, |
+ const SkMatrix& matrix, void* storage) const { |
+ if (!this->validContext(device, paint, matrix)) { |
+ return NULL; |
+ } |
+ |
+ return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, device, paint, matrix)); |
+} |
+ |
bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], |
- int index0, int index1, int index2) { |
+ int index0, int index1, int index2, const SkMatrix& matrix) { |
scroggo
2014/03/24 21:24:46
Maybe rename this parameter to make it clear what
Dominik Grewe
2014/03/26 17:22:22
It's not the totalInverse though, is it? We use it
scroggo
2014/03/26 23:13:09
Oh, I misread the code below...
|
fColors[0] = SkPreMultiplyColor(colors[index0]); |
fColors[1] = SkPreMultiplyColor(colors[index1]); |
@@ -2394,7 +2425,9 @@ bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], |
if (!m.invert(&im)) { |
return false; |
} |
- return fDstToUnit.setConcat(im, this->getTotalInverse()); |
+ SkMatrix inverse; |
+ SkASSERT(matrix.invert(&inverse)); |
scroggo
2014/03/26 23:13:09
I seemed to have overlooked this part. I take it t
Dominik Grewe
2014/03/27 14:27:20
Actually, if we add a SkBlitter::getShaderContext(
scroggo
2014/03/27 18:05:33
That seems even better to me.
|
+ return fDstToUnit.setConcat(im, inverse); |
} |
#include "SkColorPriv.h" |
@@ -2411,11 +2444,23 @@ static int ScalarTo256(SkScalar v) { |
return SkAlpha255To256(scale); |
} |
-void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
+ |
+SkTriColorShader::TriColorShaderContext::TriColorShaderContext( |
+ const SkTriColorShader& shader, const SkBitmap& device, |
scroggo
2014/03/24 21:24:46
nit: Parameters that fit on the same line should g
Dominik Grewe
2014/03/26 17:22:22
If I move the first one to the same line and line
|
+ const SkPaint& paint, const SkMatrix& matrix) |
+ : INHERITED(shader, device, paint, matrix) |
+ , fTriColorShader(shader) {} |
+ |
+SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} |
+ |
+size_t SkTriColorShader::contextSize() const { |
+ return sizeof(TriColorShaderContext); |
+} |
+void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
SkPoint src; |
for (int i = 0; i < count; i++) { |
- fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); |
+ fTriColorShader.fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); |
x += 1; |
int scale1 = ScalarTo256(src.fX); |
@@ -2430,9 +2475,9 @@ void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
scale0 = 0; |
} |
- dstC[i] = SkAlphaMulQ(fColors[0], scale0) + |
- SkAlphaMulQ(fColors[1], scale1) + |
- SkAlphaMulQ(fColors[2], scale2); |
+ dstC[i] = SkAlphaMulQ(fTriColorShader.fColors[0], scale0) + |
+ SkAlphaMulQ(fTriColorShader.fColors[1], scale1) + |
+ SkAlphaMulQ(fTriColorShader.fColors[2], scale2); |
} |
} |
@@ -2518,8 +2563,8 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
} |
SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); |
- // important that we abort early, as below we may manipulate the shader |
- // and that is only valid if the shader returned true from setContext. |
+ // Important that we abort early, as below we may manipulate the shader context |
+ // and that is only valid if a context was successfully created from the shader. |
// If it returned false, then our blitter will be the NullBlitter. |
if (blitter->isNullBlitter()) { |
return; |
@@ -2536,30 +2581,19 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
savedLocalM = shader->getLocalMatrix(); |
} |
- // setContext has already been called and verified to return true |
- // by the constructor of SkAutoBlitterChoose |
- bool prevContextSuccess = true; |
while (vertProc(&state)) { |
if (NULL != textures) { |
if (texture_to_matrix(state, vertices, textures, &tempM)) { |
tempM.postConcat(savedLocalM); |
shader->setLocalMatrix(tempM); |
- // Need to recall setContext since we changed the local matrix. |
- // However, we also need to balance the calls this with a |
- // call to endContext which requires tracking the result of |
- // the previous call to setContext. |
- if (prevContextSuccess) { |
- shader->endContext(); |
- } |
- prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix); |
- if (!prevContextSuccess) { |
+ if (!blitter->resetShaderContext(*fBitmap, p, *fMatrix)) { |
Dominik Grewe
2014/03/21 12:52:50
Afaict, we want to create a new shader context her
scroggo
2014/03/24 21:24:46
This seems like a fine way to do it to me.
|
continue; |
} |
} |
} |
if (NULL != colors) { |
if (!triShader.setup(vertices, colors, |
- state.f0, state.f1, state.f2)) { |
+ state.f0, state.f1, state.f2, *fMatrix)) { |
continue; |
} |
} |
@@ -2574,13 +2608,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
if (NULL != shader) { |
shader->setLocalMatrix(savedLocalM); |
} |
- |
- // If the final call to setContext fails we must make it suceed so that the |
- // call to endContext in the destructor for SkAutoBlitterChoose is balanced. |
- if (!prevContextSuccess) { |
- prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I()); |
- SkASSERT(prevContextSuccess); |
- } |
} else { |
// no colors[] and no texture |
HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); |