| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "SkPDFShader.h" | 9 #include "SkPDFShader.h" |
| 10 | 10 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 SkVector vec = pts[1] - pts[0]; | 33 SkVector vec = pts[1] - pts[0]; |
| 34 SkScalar mag = vec.length(); | 34 SkScalar mag = vec.length(); |
| 35 SkScalar inv = mag ? SkScalarInvert(mag) : 0; | 35 SkScalar inv = mag ? SkScalarInvert(mag) : 0; |
| 36 | 36 |
| 37 vec.scale(inv); | 37 vec.scale(inv); |
| 38 matrix->setSinCos(vec.fY, vec.fX); | 38 matrix->setSinCos(vec.fY, vec.fX); |
| 39 matrix->preScale(mag, mag); | 39 matrix->preScale(mag, mag); |
| 40 matrix->postTranslate(pts[0].fX, pts[0].fY); | 40 matrix->postTranslate(pts[0].fX, pts[0].fY); |
| 41 } | 41 } |
| 42 | 42 |
| 43 static const int kColorComponents = 3; |
| 44 typedef uint8_t ColorTuple[kColorComponents]; |
| 45 |
| 43 /* Assumes t + startOffset is on the stack and does a linear interpolation on t | 46 /* Assumes t + startOffset is on the stack and does a linear interpolation on t |
| 44 between startOffset and endOffset from prevColor to curColor (for each color | 47 between startOffset and endOffset from prevColor to curColor (for each color |
| 45 component), leaving the result in component order on the stack. It assumes | 48 component), leaving the result in component order on the stack. It assumes |
| 46 there are always 3 components per color. | 49 there are always 3 components per color. |
| 47 @param range endOffset - startOffset | 50 @param range endOffset - startOffset |
| 48 @param curColor[components] The current color components. | 51 @param curColor[components] The current color components. |
| 49 @param prevColor[components] The previous color components. | 52 @param prevColor[components] The previous color components. |
| 50 @param result The result ps function. | 53 @param result The result ps function. |
| 51 */ | 54 */ |
| 52 static void interpolateColorCode(SkScalar range, SkScalar* curColor, | 55 static void interpolateColorCode(SkScalar range, const ColorTuple& curColor, |
| 53 SkScalar* prevColor, | 56 const ColorTuple& prevColor, |
| 54 SkDynamicMemoryWStream* result) { | 57 SkDynamicMemoryWStream* result) { |
| 55 SkASSERT(range != SkIntToScalar(0)); | 58 SkASSERT(range != SkIntToScalar(0)); |
| 56 static const int kColorComponents = 3; | |
| 57 | 59 |
| 58 // Figure out how to scale each color component. | 60 // Figure out how to scale each color component. |
| 59 SkScalar multiplier[kColorComponents]; | 61 SkScalar multiplier[kColorComponents]; |
| 60 for (int i = 0; i < kColorComponents; i++) { | 62 for (int i = 0; i < kColorComponents; i++) { |
| 61 multiplier[i] = (curColor[i] - prevColor[i]) / range; | 63 static const SkScalar kColorScale = SkScalarInvert(255); |
| 64 multiplier[i] = kColorScale * (curColor[i] - prevColor[i]) / range; |
| 62 } | 65 } |
| 63 | 66 |
| 64 // Calculate when we no longer need to keep a copy of the input parameter t. | 67 // Calculate when we no longer need to keep a copy of the input parameter t. |
| 65 // If the last component to use t is i, then dupInput[0..i - 1] = true | 68 // If the last component to use t is i, then dupInput[0..i - 1] = true |
| 66 // and dupInput[i .. components] = false. | 69 // and dupInput[i .. components] = false. |
| 67 bool dupInput[kColorComponents]; | 70 bool dupInput[kColorComponents]; |
| 68 dupInput[kColorComponents - 1] = false; | 71 dupInput[kColorComponents - 1] = false; |
| 69 for (int i = kColorComponents - 2; i >= 0; i--) { | 72 for (int i = kColorComponents - 2; i >= 0; i--) { |
| 70 dupInput[i] = dupInput[i + 1] || multiplier[i + 1] != 0; | 73 dupInput[i] = dupInput[i + 1] || multiplier[i + 1] != 0; |
| 71 } | 74 } |
| 72 | 75 |
| 73 if (!dupInput[0] && multiplier[0] == 0) { | 76 if (!dupInput[0] && multiplier[0] == 0) { |
| 74 result->writeText("pop "); | 77 result->writeText("pop "); |
| 75 } | 78 } |
| 76 | 79 |
| 77 for (int i = 0; i < kColorComponents; i++) { | 80 for (int i = 0; i < kColorComponents; i++) { |
| 78 // If the next components needs t and this component will consume a | 81 // If the next components needs t and this component will consume a |
| 79 // copy, make another copy. | 82 // copy, make another copy. |
| 80 if (dupInput[i] && multiplier[i] != 0) { | 83 if (dupInput[i] && multiplier[i] != 0) { |
| 81 result->writeText("dup "); | 84 result->writeText("dup "); |
| 82 } | 85 } |
| 83 | 86 |
| 84 if (multiplier[i] == 0) { | 87 if (multiplier[i] == 0) { |
| 85 SkPDFUtils::AppendScalar(prevColor[i], result); | 88 SkPDFUtils::AppendColorComponent(prevColor[i], result); |
| 86 result->writeText(" "); | 89 result->writeText(" "); |
| 87 } else { | 90 } else { |
| 88 if (multiplier[i] != 1) { | 91 if (multiplier[i] != 1) { |
| 89 SkPDFUtils::AppendScalar(multiplier[i], result); | 92 SkPDFUtils::AppendScalar(multiplier[i], result); |
| 90 result->writeText(" mul "); | 93 result->writeText(" mul "); |
| 91 } | 94 } |
| 92 if (prevColor[i] != 0) { | 95 if (prevColor[i] != 0) { |
| 93 SkPDFUtils::AppendScalar(prevColor[i], result); | 96 SkPDFUtils::AppendColorComponent(prevColor[i], result); |
| 94 result->writeText(" add "); | 97 result->writeText(" add "); |
| 95 } | 98 } |
| 96 } | 99 } |
| 97 | 100 |
| 98 if (dupInput[i]) { | 101 if (dupInput[i]) { |
| 99 result->writeText("exch\n"); | 102 result->writeText("exch\n"); |
| 100 } | 103 } |
| 101 } | 104 } |
| 102 } | 105 } |
| 103 | 106 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 115 colorData[2][r,g,b]); | 118 colorData[2][r,g,b]); |
| 116 } else { | 119 } else { |
| 117 | 120 |
| 118 ... } else { | 121 ... } else { |
| 119 return colorData[info.fColorCount - 1][r,g,b]; | 122 return colorData[info.fColorCount - 1][r,g,b]; |
| 120 } | 123 } |
| 121 ... | 124 ... |
| 122 } | 125 } |
| 123 } | 126 } |
| 124 */ | 127 */ |
| 125 static const int kColorComponents = 3; | |
| 126 typedef SkScalar ColorTuple[kColorComponents]; | |
| 127 static void gradientFunctionCode(const SkShader::GradientInfo& info, | 128 static void gradientFunctionCode(const SkShader::GradientInfo& info, |
| 128 SkDynamicMemoryWStream* result) { | 129 SkDynamicMemoryWStream* result) { |
| 129 /* We want to linearly interpolate from the previous color to the next. | 130 /* We want to linearly interpolate from the previous color to the next. |
| 130 Scale the colors from 0..255 to 0..1 and determine the multipliers | 131 Scale the colors from 0..255 to 0..1 and determine the multipliers |
| 131 for interpolation. | 132 for interpolation. |
| 132 C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. | 133 C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. |
| 133 */ | 134 */ |
| 134 | 135 |
| 135 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); | 136 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); |
| 136 ColorTuple *colorData = colorDataAlloc.get(); | 137 ColorTuple *colorData = colorDataAlloc.get(); |
| 137 const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); | |
| 138 for (int i = 0; i < info.fColorCount; i++) { | 138 for (int i = 0; i < info.fColorCount; i++) { |
| 139 colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); | 139 colorData[i][0] = SkColorGetR(info.fColors[i]); |
| 140 colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); | 140 colorData[i][1] = SkColorGetG(info.fColors[i]); |
| 141 colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); | 141 colorData[i][2] = SkColorGetB(info.fColors[i]); |
| 142 } | 142 } |
| 143 | 143 |
| 144 // Clamp the initial color. | 144 // Clamp the initial color. |
| 145 result->writeText("dup 0 le {pop "); | 145 result->writeText("dup 0 le {pop "); |
| 146 SkPDFUtils::AppendScalar(colorData[0][0], result); | 146 SkPDFUtils::AppendColorComponent(colorData[0][0], result); |
| 147 result->writeText(" "); | 147 result->writeText(" "); |
| 148 SkPDFUtils::AppendScalar(colorData[0][1], result); | 148 SkPDFUtils::AppendColorComponent(colorData[0][1], result); |
| 149 result->writeText(" "); | 149 result->writeText(" "); |
| 150 SkPDFUtils::AppendScalar(colorData[0][2], result); | 150 SkPDFUtils::AppendColorComponent(colorData[0][2], result); |
| 151 result->writeText(" }\n"); | 151 result->writeText(" }\n"); |
| 152 | 152 |
| 153 // The gradient colors. | 153 // The gradient colors. |
| 154 int gradients = 0; | 154 int gradients = 0; |
| 155 for (int i = 1 ; i < info.fColorCount; i++) { | 155 for (int i = 1 ; i < info.fColorCount; i++) { |
| 156 if (info.fColorOffsets[i] == info.fColorOffsets[i - 1]) { | 156 if (info.fColorOffsets[i] == info.fColorOffsets[i - 1]) { |
| 157 continue; | 157 continue; |
| 158 } | 158 } |
| 159 gradients++; | 159 gradients++; |
| 160 | 160 |
| 161 result->writeText("{dup "); | 161 result->writeText("{dup "); |
| 162 SkPDFUtils::AppendScalar(info.fColorOffsets[i], result); | 162 SkPDFUtils::AppendScalar(info.fColorOffsets[i], result); |
| 163 result->writeText(" le {"); | 163 result->writeText(" le {"); |
| 164 if (info.fColorOffsets[i - 1] != 0) { | 164 if (info.fColorOffsets[i - 1] != 0) { |
| 165 SkPDFUtils::AppendScalar(info.fColorOffsets[i - 1], result); | 165 SkPDFUtils::AppendScalar(info.fColorOffsets[i - 1], result); |
| 166 result->writeText(" sub\n"); | 166 result->writeText(" sub\n"); |
| 167 } | 167 } |
| 168 | 168 |
| 169 interpolateColorCode(info.fColorOffsets[i] - info.fColorOffsets[i - 1], | 169 interpolateColorCode(info.fColorOffsets[i] - info.fColorOffsets[i - 1], |
| 170 colorData[i], colorData[i - 1], result); | 170 colorData[i], colorData[i - 1], result); |
| 171 result->writeText("}\n"); | 171 result->writeText("}\n"); |
| 172 } | 172 } |
| 173 | 173 |
| 174 // Clamp the final color. | 174 // Clamp the final color. |
| 175 result->writeText("{pop "); | 175 result->writeText("{pop "); |
| 176 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][0], result); | 176 SkPDFUtils::AppendColorComponent(colorData[info.fColorCount - 1][0], result)
; |
| 177 result->writeText(" "); | 177 result->writeText(" "); |
| 178 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][1], result); | 178 SkPDFUtils::AppendColorComponent(colorData[info.fColorCount - 1][1], result)
; |
| 179 result->writeText(" "); | 179 result->writeText(" "); |
| 180 SkPDFUtils::AppendScalar(colorData[info.fColorCount - 1][2], result); | 180 SkPDFUtils::AppendColorComponent(colorData[info.fColorCount - 1][2], result)
; |
| 181 | 181 |
| 182 for (int i = 0 ; i < gradients + 1; i++) { | 182 for (int i = 0 ; i < gradients + 1; i++) { |
| 183 result->writeText("} ifelse\n"); | 183 result->writeText("} ifelse\n"); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 static sk_sp<SkPDFDict> createInterpolationFunction(const ColorTuple& color1, | 187 static sk_sp<SkPDFDict> createInterpolationFunction(const ColorTuple& color1, |
| 188 const ColorTuple& color2) { | 188 const ColorTuple& color2) { |
| 189 auto retval = sk_make_sp<SkPDFDict>(); | 189 auto retval = sk_make_sp<SkPDFDict>(); |
| 190 | 190 |
| 191 auto c0 = sk_make_sp<SkPDFArray>(); | 191 auto c0 = sk_make_sp<SkPDFArray>(); |
| 192 c0->appendScalar(color1[0]); | 192 c0->appendColorComponent(color1[0]); |
| 193 c0->appendScalar(color1[1]); | 193 c0->appendColorComponent(color1[1]); |
| 194 c0->appendScalar(color1[2]); | 194 c0->appendColorComponent(color1[2]); |
| 195 retval->insertObject("C0", std::move(c0)); | 195 retval->insertObject("C0", std::move(c0)); |
| 196 | 196 |
| 197 auto c1 = sk_make_sp<SkPDFArray>(); | 197 auto c1 = sk_make_sp<SkPDFArray>(); |
| 198 c1->appendScalar(color2[0]); | 198 c1->appendColorComponent(color2[0]); |
| 199 c1->appendScalar(color2[1]); | 199 c1->appendColorComponent(color2[1]); |
| 200 c1->appendScalar(color2[2]); | 200 c1->appendColorComponent(color2[2]); |
| 201 retval->insertObject("C1", std::move(c1)); | 201 retval->insertObject("C1", std::move(c1)); |
| 202 | 202 |
| 203 auto domain = sk_make_sp<SkPDFArray>(); | 203 auto domain = sk_make_sp<SkPDFArray>(); |
| 204 domain->appendScalar(0); | 204 domain->appendScalar(0); |
| 205 domain->appendScalar(1.0f); | 205 domain->appendScalar(1.0f); |
| 206 retval->insertObject("Domain", std::move(domain)); | 206 retval->insertObject("Domain", std::move(domain)); |
| 207 | 207 |
| 208 retval->insertInt("FunctionType", 2); | 208 retval->insertInt("FunctionType", 2); |
| 209 retval->insertScalar("N", 1.0f); | 209 retval->insertScalar("N", 1.0f); |
| 210 | 210 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 241 colorOffsets[i] += 0.00001f; | 241 colorOffsets[i] += 0.00001f; |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 // check if last 2 stops coincide | 244 // check if last 2 stops coincide |
| 245 if (colorOffsets[i - 1] == colorOffsets[i]) { | 245 if (colorOffsets[i - 1] == colorOffsets[i]) { |
| 246 colorOffsets[i - 1] -= 0.00001f; | 246 colorOffsets[i - 1] -= 0.00001f; |
| 247 } | 247 } |
| 248 | 248 |
| 249 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(colorCount); | 249 SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(colorCount); |
| 250 ColorTuple *colorData = colorDataAlloc.get(); | 250 ColorTuple *colorData = colorDataAlloc.get(); |
| 251 const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); | |
| 252 for (int i = 0; i < colorCount; i++) { | 251 for (int i = 0; i < colorCount; i++) { |
| 253 colorData[i][0] = SkScalarMul(SkColorGetR(colors[i]), scale); | 252 colorData[i][0] = SkColorGetR(colors[i]); |
| 254 colorData[i][1] = SkScalarMul(SkColorGetG(colors[i]), scale); | 253 colorData[i][1] = SkColorGetG(colors[i]); |
| 255 colorData[i][2] = SkScalarMul(SkColorGetB(colors[i]), scale); | 254 colorData[i][2] = SkColorGetB(colors[i]); |
| 256 } | 255 } |
| 257 | 256 |
| 258 // no need for a stitch function if there are only 2 stops. | 257 // no need for a stitch function if there are only 2 stops. |
| 259 if (colorCount == 2) | 258 if (colorCount == 2) |
| 260 return createInterpolationFunction(colorData[0], colorData[1]); | 259 return createInterpolationFunction(colorData[0], colorData[1]); |
| 261 | 260 |
| 262 auto encode = sk_make_sp<SkPDFArray>(); | 261 auto encode = sk_make_sp<SkPDFArray>(); |
| 263 auto bounds = sk_make_sp<SkPDFArray>(); | 262 auto bounds = sk_make_sp<SkPDFArray>(); |
| 264 auto functions = sk_make_sp<SkPDFArray>(); | 263 auto functions = sk_make_sp<SkPDFArray>(); |
| 265 | 264 |
| (...skipping 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 return false; | 1410 return false; |
| 1412 } | 1411 } |
| 1413 | 1412 |
| 1414 void SkPDFShader::State::AllocateGradientInfoStorage() { | 1413 void SkPDFShader::State::AllocateGradientInfoStorage() { |
| 1415 fColorData.set(sk_malloc_throw( | 1414 fColorData.set(sk_malloc_throw( |
| 1416 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); | 1415 fInfo.fColorCount * (sizeof(SkColor) + sizeof(SkScalar)))); |
| 1417 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); | 1416 fInfo.fColors = reinterpret_cast<SkColor*>(fColorData.get()); |
| 1418 fInfo.fColorOffsets = | 1417 fInfo.fColorOffsets = |
| 1419 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); | 1418 reinterpret_cast<SkScalar*>(fInfo.fColors + fInfo.fColorCount); |
| 1420 } | 1419 } |
| OLD | NEW |