| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkComposeShader.h" | 10 #include "SkComposeShader.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 }; | 62 }; |
| 63 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) | 63 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) |
| 64 | 64 |
| 65 void SkComposeShader::flatten(SkWriteBuffer& buffer) const { | 65 void SkComposeShader::flatten(SkWriteBuffer& buffer) const { |
| 66 this->INHERITED::flatten(buffer); | 66 this->INHERITED::flatten(buffer); |
| 67 buffer.writeFlattenable(fShaderA); | 67 buffer.writeFlattenable(fShaderA); |
| 68 buffer.writeFlattenable(fShaderB); | 68 buffer.writeFlattenable(fShaderB); |
| 69 buffer.writeFlattenable(fMode); | 69 buffer.writeFlattenable(fMode); |
| 70 } | 70 } |
| 71 | 71 |
| 72 struct ComposeContext { |
| 73 SkShader::Context* fContextA; |
| 74 SkShader::Context* fContextB; |
| 75 }; |
| 76 |
| 77 // Helper function to get the ComposeContext from the Context. |
| 78 static ComposeContext* get_compose_context(SkShader::Context* c, const SkShader&
shader) { |
| 79 return (ComposeContext*) shader.getMyContext(c); |
| 80 } |
| 81 |
| 82 size_t SkComposeShader::getMySpaceNeededForContext() const { |
| 83 return sizeof(ComposeContext); |
| 84 } |
| 85 |
| 72 /* We call setContext on our two worker shaders. However, we | 86 /* We call setContext on our two worker shaders. However, we |
| 73 always let them see opaque alpha, and if the paint really | 87 always let them see opaque alpha, and if the paint really |
| 74 is translucent, then we apply that after the fact. | 88 is translucent, then we apply that after the fact. |
| 75 | 89 |
| 76 We need to keep the calls to setContext/endContext balanced, since if we | 90 We need to keep the calls to setContext/endContext balanced, since if we |
| 77 return false, our endContext() will not be called. | 91 return false, our endContext() will not be called. |
| 78 */ | 92 */ |
| 79 bool SkComposeShader::setContext(const SkBitmap& device, | 93 bool SkComposeShader::onSetContext(Context* c, const SkBitmap& device, |
| 80 const SkPaint& paint, | 94 const SkPaint& paint, |
| 81 const SkMatrix& matrix) { | 95 const SkMatrix& matrix) { |
| 82 if (!this->INHERITED::setContext(device, paint, matrix)) { | 96 if (!this->INHERITED::onSetContext(c, device, paint, matrix)) { |
| 83 return false; | 97 return false; |
| 84 } | 98 } |
| 85 | 99 |
| 86 // we preconcat our localMatrix (if any) with the device matrix | 100 // we preconcat our localMatrix (if any) with the device matrix |
| 87 // before calling our sub-shaders | 101 // before calling our sub-shaders |
| 88 | 102 |
| 89 SkMatrix tmpM; | 103 SkMatrix tmpM; |
| 90 | 104 |
| 105 // Will come from the paint. |
| 91 tmpM.setConcat(matrix, this->getLocalMatrix()); | 106 tmpM.setConcat(matrix, this->getLocalMatrix()); |
| 92 | 107 |
| 93 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); | 108 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); |
| 94 | 109 |
| 95 bool setContextA = fShaderA->setContext(device, paint, tmpM); | 110 SkShader::Context* contextA = fShaderA->setContext(device, paint, tmpM); |
| 96 bool setContextB = fShaderB->setContext(device, paint, tmpM); | 111 if (!contextA) { |
| 97 if (!setContextA || !setContextB) { | |
| 98 if (setContextB) { | |
| 99 fShaderB->endContext(); | |
| 100 } | |
| 101 else if (setContextA) { | |
| 102 fShaderA->endContext(); | |
| 103 } | |
| 104 this->INHERITED::endContext(); | |
| 105 return false; | 112 return false; |
| 106 } | 113 } |
| 114 |
| 115 SkShader::Context* contextB = fShaderB->setContext(device, paint, tmpM); |
| 116 if (!contextB) { |
| 117 SkDELETE(contextA); |
| 118 return false; |
| 119 } |
| 120 |
| 121 ComposeContext* composeContext = get_compose_context(c, *this); |
| 122 composeContext->fContextA = contextA; |
| 123 composeContext->fContextB = contextB; |
| 124 |
| 107 return true; | 125 return true; |
| 108 } | 126 } |
| 109 | 127 |
| 110 void SkComposeShader::endContext() { | 128 void SkComposeShader::endContext(Context* c) { |
| 111 fShaderB->endContext(); | 129 ComposeContext* composeContext = get_compose_context(c, *this); |
| 112 fShaderA->endContext(); | 130 |
| 113 this->INHERITED::endContext(); | 131 fShaderB->endContext(c->fContextA); |
| 132 fShaderA->endContext(c->fContextB); |
| 133 this->INHERITED::endContext(c); |
| 114 } | 134 } |
| 115 | 135 |
| 116 // larger is better (fewer times we have to loop), but we shouldn't | 136 // larger is better (fewer times we have to loop), but we shouldn't |
| 117 // take up too much stack-space (each element is 4 bytes) | 137 // take up too much stack-space (each element is 4 bytes) |
| 118 #define TMP_COLOR_COUNT 64 | 138 #define TMP_COLOR_COUNT 64 |
| 119 | 139 |
| 120 void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { | 140 void SkComposeShader::shadeSpan(Context* c, int x, int y, SkPMColor result[], in
t count) { |
| 121 SkShader* shaderA = fShaderA; | 141 SkShader* shaderA = fShaderA; |
| 122 SkShader* shaderB = fShaderB; | 142 SkShader* shaderB = fShaderB; |
| 123 SkXfermode* mode = fMode; | 143 SkXfermode* mode = fMode; |
| 124 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); | 144 unsigned scale = SkAlpha255To256(c->getPaintAlpha()); |
| 125 | 145 |
| 126 SkPMColor tmp[TMP_COLOR_COUNT]; | 146 SkPMColor tmp[TMP_COLOR_COUNT]; |
| 127 | 147 |
| 148 ComposeContext* composeContext = get_compose_context(c, *this); |
| 149 |
| 128 if (NULL == mode) { // implied SRC_OVER | 150 if (NULL == mode) { // implied SRC_OVER |
| 129 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 | 151 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 |
| 130 // for these loops | 152 // for these loops |
| 131 do { | 153 do { |
| 132 int n = count; | 154 int n = count; |
| 133 if (n > TMP_COLOR_COUNT) { | 155 if (n > TMP_COLOR_COUNT) { |
| 134 n = TMP_COLOR_COUNT; | 156 n = TMP_COLOR_COUNT; |
| 135 } | 157 } |
| 136 | 158 |
| 137 shaderA->shadeSpan(x, y, result, n); | 159 shaderA->shadeSpan(composeContext->fContextA, x, y, result, n); |
| 138 shaderB->shadeSpan(x, y, tmp, n); | 160 shaderB->shadeSpan(composeContext->fContextB, x, y, tmp, n); |
| 139 | 161 |
| 140 if (256 == scale) { | 162 if (256 == scale) { |
| 141 for (int i = 0; i < n; i++) { | 163 for (int i = 0; i < n; i++) { |
| 142 result[i] = SkPMSrcOver(tmp[i], result[i]); | 164 result[i] = SkPMSrcOver(tmp[i], result[i]); |
| 143 } | 165 } |
| 144 } else { | 166 } else { |
| 145 for (int i = 0; i < n; i++) { | 167 for (int i = 0; i < n; i++) { |
| 146 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), | 168 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), |
| 147 scale); | 169 scale); |
| 148 } | 170 } |
| 149 } | 171 } |
| 150 | 172 |
| 151 result += n; | 173 result += n; |
| 152 x += n; | 174 x += n; |
| 153 count -= n; | 175 count -= n; |
| 154 } while (count > 0); | 176 } while (count > 0); |
| 155 } else { // use mode for the composition | 177 } else { // use mode for the composition |
| 156 do { | 178 do { |
| 157 int n = count; | 179 int n = count; |
| 158 if (n > TMP_COLOR_COUNT) { | 180 if (n > TMP_COLOR_COUNT) { |
| 159 n = TMP_COLOR_COUNT; | 181 n = TMP_COLOR_COUNT; |
| 160 } | 182 } |
| 161 | 183 |
| 162 shaderA->shadeSpan(x, y, result, n); | 184 shaderA->shadeSpan(composeContext->fContextA, x, y, result, n); |
| 163 shaderB->shadeSpan(x, y, tmp, n); | 185 shaderB->shadeSpan(composeContext->fContextB, x, y, tmp, n); |
| 164 mode->xfer32(result, tmp, n, NULL); | 186 mode->xfer32(result, tmp, n, NULL); |
| 165 | 187 |
| 166 if (256 == scale) { | 188 if (256 == scale) { |
| 167 for (int i = 0; i < n; i++) { | 189 for (int i = 0; i < n; i++) { |
| 168 result[i] = SkAlphaMulQ(result[i], scale); | 190 result[i] = SkAlphaMulQ(result[i], scale); |
| 169 } | 191 } |
| 170 } | 192 } |
| 171 | 193 |
| 172 result += n; | 194 result += n; |
| 173 x += n; | 195 x += n; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 185 str->append(" ShaderB: "); | 207 str->append(" ShaderB: "); |
| 186 fShaderB->toString(str); | 208 fShaderB->toString(str); |
| 187 str->append(" Xfermode: "); | 209 str->append(" Xfermode: "); |
| 188 fMode->toString(str); | 210 fMode->toString(str); |
| 189 | 211 |
| 190 this->INHERITED::toString(str); | 212 this->INHERITED::toString(str); |
| 191 | 213 |
| 192 str->append(")"); | 214 str->append(")"); |
| 193 } | 215 } |
| 194 #endif | 216 #endif |
| OLD | NEW |