| 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 27 matching lines...) Expand all Loading... |
| 38 } | 38 } |
| 39 fMode = buffer.readXfermode(); | 39 fMode = buffer.readXfermode(); |
| 40 } | 40 } |
| 41 | 41 |
| 42 SkComposeShader::~SkComposeShader() { | 42 SkComposeShader::~SkComposeShader() { |
| 43 SkSafeUnref(fMode); | 43 SkSafeUnref(fMode); |
| 44 fShaderB->unref(); | 44 fShaderB->unref(); |
| 45 fShaderA->unref(); | 45 fShaderA->unref(); |
| 46 } | 46 } |
| 47 | 47 |
| 48 size_t SkComposeShader::contextSize() const { | |
| 49 return sizeof(ComposeShaderContext) + fShaderA->contextSize() + fShaderB->co
ntextSize(); | |
| 50 } | |
| 51 | |
| 52 class SkAutoAlphaRestore { | 48 class SkAutoAlphaRestore { |
| 53 public: | 49 public: |
| 54 SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { | 50 SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { |
| 55 fAlpha = paint->getAlpha(); | 51 fAlpha = paint->getAlpha(); |
| 56 fPaint = paint; | 52 fPaint = paint; |
| 57 paint->setAlpha(newAlpha); | 53 paint->setAlpha(newAlpha); |
| 58 } | 54 } |
| 59 | 55 |
| 60 ~SkAutoAlphaRestore() { | 56 ~SkAutoAlphaRestore() { |
| 61 fPaint->setAlpha(fAlpha); | 57 fPaint->setAlpha(fAlpha); |
| 62 } | 58 } |
| 63 private: | 59 private: |
| 64 SkPaint* fPaint; | 60 SkPaint* fPaint; |
| 65 uint8_t fAlpha; | 61 uint8_t fAlpha; |
| 66 }; | 62 }; |
| 67 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) | 63 #define SkAutoAlphaRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoAlphaRestore) |
| 68 | 64 |
| 69 void SkComposeShader::flatten(SkWriteBuffer& buffer) const { | 65 void SkComposeShader::flatten(SkWriteBuffer& buffer) const { |
| 70 this->INHERITED::flatten(buffer); | 66 this->INHERITED::flatten(buffer); |
| 71 buffer.writeFlattenable(fShaderA); | 67 buffer.writeFlattenable(fShaderA); |
| 72 buffer.writeFlattenable(fShaderB); | 68 buffer.writeFlattenable(fShaderB); |
| 73 buffer.writeFlattenable(fMode); | 69 buffer.writeFlattenable(fMode); |
| 74 } | 70 } |
| 75 | 71 |
| 76 /* We call validContext/createContext on our two worker shaders. | 72 /* We call setContext on our two worker shaders. However, we |
| 77 However, we always let them see opaque alpha, and if the paint | 73 always let them see opaque alpha, and if the paint really |
| 78 really is translucent, then we apply that after the fact. | 74 is translucent, then we apply that after the fact. |
| 79 | 75 |
| 76 We need to keep the calls to setContext/endContext balanced, since if we |
| 77 return false, our endContext() will not be called. |
| 80 */ | 78 */ |
| 81 bool SkComposeShader::validContext(const SkBitmap& device, | 79 bool SkComposeShader::setContext(const SkBitmap& device, |
| 82 const SkPaint& paint, | 80 const SkPaint& paint, |
| 83 const SkMatrix& matrix, | 81 const SkMatrix& matrix) { |
| 84 SkMatrix* totalInverse) const { | 82 if (!this->INHERITED::setContext(device, paint, matrix)) { |
| 85 if (!this->INHERITED::validContext(device, paint, matrix, totalInverse)) { | |
| 86 return false; | 83 return false; |
| 87 } | 84 } |
| 88 | 85 |
| 89 // we preconcat our localMatrix (if any) with the device matrix | 86 // we preconcat our localMatrix (if any) with the device matrix |
| 90 // before calling our sub-shaders | |
| 91 | |
| 92 SkMatrix tmpM; | |
| 93 | |
| 94 tmpM.setConcat(matrix, this->getLocalMatrix()); | |
| 95 | |
| 96 return fShaderA->validContext(device, paint, tmpM) && | |
| 97 fShaderB->validContext(device, paint, tmpM); | |
| 98 } | |
| 99 | |
| 100 SkShader::Context* SkComposeShader::createContext(const SkBitmap& device, const
SkPaint& paint, | |
| 101 const SkMatrix& matrix, void*
storage) const { | |
| 102 if (!this->validContext(device, paint, matrix)) { | |
| 103 return NULL; | |
| 104 } | |
| 105 | |
| 106 // we preconcat our localMatrix (if any) with the device matrix | |
| 107 // before calling our sub-shaders | 87 // before calling our sub-shaders |
| 108 | 88 |
| 109 SkMatrix tmpM; | 89 SkMatrix tmpM; |
| 110 | 90 |
| 111 tmpM.setConcat(matrix, this->getLocalMatrix()); | 91 tmpM.setConcat(matrix, this->getLocalMatrix()); |
| 112 | 92 |
| 113 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); | 93 SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF); |
| 114 | 94 |
| 115 char* aStorage = (char*) storage + sizeof(ComposeShaderContext); | 95 bool setContextA = fShaderA->setContext(device, paint, tmpM); |
| 116 char* bStorage = aStorage + fShaderA->contextSize(); | 96 bool setContextB = fShaderB->setContext(device, paint, tmpM); |
| 117 | 97 if (!setContextA || !setContextB) { |
| 118 SkShader::Context* contextA = fShaderA->createContext(device, paint, tmpM, a
Storage); | 98 if (setContextB) { |
| 119 SkShader::Context* contextB = fShaderB->createContext(device, paint, tmpM, b
Storage); | 99 fShaderB->endContext(); |
| 120 | 100 } |
| 121 // Both functions must succeed; otherwise validContext should have returned | 101 else if (setContextA) { |
| 122 // false. | 102 fShaderA->endContext(); |
| 123 SkASSERT(contextA); | 103 } |
| 124 SkASSERT(contextB); | 104 this->INHERITED::endContext(); |
| 125 | 105 return false; |
| 126 return SkNEW_PLACEMENT_ARGS(storage, ComposeShaderContext, | 106 } |
| 127 (*this, device, paint, matrix, contextA, context
B)); | 107 return true; |
| 128 } | 108 } |
| 129 | 109 |
| 130 SkComposeShader::ComposeShaderContext::ComposeShaderContext( | 110 void SkComposeShader::endContext() { |
| 131 const SkComposeShader& shader, const SkBitmap& device, | 111 fShaderB->endContext(); |
| 132 const SkPaint& paint, const SkMatrix& matrix, | 112 fShaderA->endContext(); |
| 133 SkShader::Context* contextA, SkShader::Context* contextB) | 113 this->INHERITED::endContext(); |
| 134 : INHERITED(shader, device, paint, matrix) | |
| 135 , fShaderContextA(contextA) | |
| 136 , fShaderContextB(contextB) {} | |
| 137 | |
| 138 SkComposeShader::ComposeShaderContext::~ComposeShaderContext() { | |
| 139 fShaderContextA->SkShader::Context::~Context(); | |
| 140 fShaderContextB->SkShader::Context::~Context(); | |
| 141 } | 114 } |
| 142 | 115 |
| 143 // larger is better (fewer times we have to loop), but we shouldn't | 116 // larger is better (fewer times we have to loop), but we shouldn't |
| 144 // take up too much stack-space (each element is 4 bytes) | 117 // take up too much stack-space (each element is 4 bytes) |
| 145 #define TMP_COLOR_COUNT 64 | 118 #define TMP_COLOR_COUNT 64 |
| 146 | 119 |
| 147 void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor re
sult[], int count) { | 120 void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { |
| 148 SkShader::Context* shaderContextA = fShaderContextA; | 121 SkShader* shaderA = fShaderA; |
| 149 SkShader::Context* shaderContextB = fShaderContextB; | 122 SkShader* shaderB = fShaderB; |
| 150 SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode
; | 123 SkXfermode* mode = fMode; |
| 151 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); | 124 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); |
| 152 | 125 |
| 153 SkPMColor tmp[TMP_COLOR_COUNT]; | 126 SkPMColor tmp[TMP_COLOR_COUNT]; |
| 154 | 127 |
| 155 if (NULL == mode) { // implied SRC_OVER | 128 if (NULL == mode) { // implied SRC_OVER |
| 156 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 | 129 // TODO: when we have a good test-case, should use SkBlitRow::Proc32 |
| 157 // for these loops | 130 // for these loops |
| 158 do { | 131 do { |
| 159 int n = count; | 132 int n = count; |
| 160 if (n > TMP_COLOR_COUNT) { | 133 if (n > TMP_COLOR_COUNT) { |
| 161 n = TMP_COLOR_COUNT; | 134 n = TMP_COLOR_COUNT; |
| 162 } | 135 } |
| 163 | 136 |
| 164 shaderContextA->shadeSpan(x, y, result, n); | 137 shaderA->shadeSpan(x, y, result, n); |
| 165 shaderContextB->shadeSpan(x, y, tmp, n); | 138 shaderB->shadeSpan(x, y, tmp, n); |
| 166 | 139 |
| 167 if (256 == scale) { | 140 if (256 == scale) { |
| 168 for (int i = 0; i < n; i++) { | 141 for (int i = 0; i < n; i++) { |
| 169 result[i] = SkPMSrcOver(tmp[i], result[i]); | 142 result[i] = SkPMSrcOver(tmp[i], result[i]); |
| 170 } | 143 } |
| 171 } else { | 144 } else { |
| 172 for (int i = 0; i < n; i++) { | 145 for (int i = 0; i < n; i++) { |
| 173 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), | 146 result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), |
| 174 scale); | 147 scale); |
| 175 } | 148 } |
| 176 } | 149 } |
| 177 | 150 |
| 178 result += n; | 151 result += n; |
| 179 x += n; | 152 x += n; |
| 180 count -= n; | 153 count -= n; |
| 181 } while (count > 0); | 154 } while (count > 0); |
| 182 } else { // use mode for the composition | 155 } else { // use mode for the composition |
| 183 do { | 156 do { |
| 184 int n = count; | 157 int n = count; |
| 185 if (n > TMP_COLOR_COUNT) { | 158 if (n > TMP_COLOR_COUNT) { |
| 186 n = TMP_COLOR_COUNT; | 159 n = TMP_COLOR_COUNT; |
| 187 } | 160 } |
| 188 | 161 |
| 189 shaderContextA->shadeSpan(x, y, result, n); | 162 shaderA->shadeSpan(x, y, result, n); |
| 190 shaderContextB->shadeSpan(x, y, tmp, n); | 163 shaderB->shadeSpan(x, y, tmp, n); |
| 191 mode->xfer32(result, tmp, n, NULL); | 164 mode->xfer32(result, tmp, n, NULL); |
| 192 | 165 |
| 193 if (256 == scale) { | 166 if (256 == scale) { |
| 194 for (int i = 0; i < n; i++) { | 167 for (int i = 0; i < n; i++) { |
| 195 result[i] = SkAlphaMulQ(result[i], scale); | 168 result[i] = SkAlphaMulQ(result[i], scale); |
| 196 } | 169 } |
| 197 } | 170 } |
| 198 | 171 |
| 199 result += n; | 172 result += n; |
| 200 x += n; | 173 x += n; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 212 str->append(" ShaderB: "); | 185 str->append(" ShaderB: "); |
| 213 fShaderB->toString(str); | 186 fShaderB->toString(str); |
| 214 str->append(" Xfermode: "); | 187 str->append(" Xfermode: "); |
| 215 fMode->toString(str); | 188 fMode->toString(str); |
| 216 | 189 |
| 217 this->INHERITED::toString(str); | 190 this->INHERITED::toString(str); |
| 218 | 191 |
| 219 str->append(")"); | 192 str->append(")"); |
| 220 } | 193 } |
| 221 #endif | 194 #endif |
| OLD | NEW |