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 |