OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 #include "Sk4fGradientPriv.h" | 8 #include "Sk4fGradientPriv.h" |
9 #include "Sk4fLinearGradient.h" | 9 #include "Sk4fLinearGradient.h" |
10 #include "SkXfermode.h" | |
10 | 11 |
11 namespace { | 12 namespace { |
12 | 13 |
13 template<typename DstType, bool do_premul> | 14 template<typename DstType, SkColorProfileType, bool do_premul> |
14 void fill(const Sk4f& c, DstType* dst, int n); | 15 void fill(const Sk4f& c, DstType* dst, int n); |
15 | 16 |
16 template<> | 17 template<> |
17 void fill<SkPM4f, false>(const Sk4f& c, SkPM4f* dst, int n) { | 18 void fill<SkPM4f, kLinear_SkColorProfileType, false>(const Sk4f& c, SkPM4f* dst, int n) { |
18 while (n > 0) { | 19 while (n > 0) { |
19 c.store(dst++); | 20 c.store(dst++); |
20 n--; | 21 n--; |
21 } | 22 } |
22 } | 23 } |
23 | 24 |
24 template<> | 25 template<> |
25 void fill<SkPM4f, true>(const Sk4f& c, SkPM4f* dst, int n) { | 26 void fill<SkPM4f, kLinear_SkColorProfileType, true>(const Sk4f& c, SkPM4f* dst, int n) { |
26 fill<SkPM4f, false>(premul_4f(c), dst, n); | 27 fill<SkPM4f, kLinear_SkColorProfileType, false>(premul_4f(c), dst, n); |
27 } | 28 } |
28 | 29 |
29 template<> | 30 template<> |
30 void fill<SkPMColor, false>(const Sk4f& c, SkPMColor* dst, int n) { | 31 void fill<SkPMColor, kLinear_SkColorProfileType, false>(const Sk4f& c, SkPMColor * dst, int n) { |
31 sk_memset32(dst, trunc_from_255<false>(c), n); | 32 sk_memset32(dst, trunc_from_255<false>(c), n); |
32 } | 33 } |
33 | 34 |
34 template<> | 35 template<> |
35 void fill<SkPMColor, true>(const Sk4f& c, SkPMColor* dst, int n) { | 36 void fill<SkPMColor, kLinear_SkColorProfileType, true>(const Sk4f& c, SkPMColor* dst, int n) { |
36 sk_memset32(dst, trunc_from_255<true>(c), n); | 37 sk_memset32(dst, trunc_from_255<true>(c), n); |
37 } | 38 } |
38 | 39 |
39 template<typename DstType, bool do_premul> | 40 template<> |
41 void fill<SkPMColor, kSRGB_SkColorProfileType, false>(const Sk4f& c, SkPMColor* dst, int n) { | |
42 // FIXME: this assumes opaque colors. Handle unpremultiplication. | |
43 const SkPMColor pmc = Sk4f_toS32(c); | |
44 sk_memset32(dst, pmc, n); | |
45 } | |
46 | |
47 template<> | |
48 void fill<SkPMColor, kSRGB_SkColorProfileType, true>(const Sk4f& c, SkPMColor* d st, int n) { | |
49 const SkPMColor s32 = Sk4f_toS32(c); | |
50 const SkPMColor pmc = SkPreMultiplyARGB(SkGetPackedA32(s32), SkGetPackedR32( s32), | |
51 SkGetPackedG32(s32), SkGetPackedB32( s32)); | |
52 sk_memset32(dst, pmc, n); | |
53 } | |
54 | |
55 template<> | |
56 void fill<uint64_t, kLinear_SkColorProfileType, false>(const Sk4f& c, uint64_t* dst, int n) { | |
57 const uint64_t c64 = SkFloatToHalf_01(c); | |
58 while (n > 0) { | |
reed1
2016/03/18 14:28:59
sk_memset64() ?
f(malita)
2016/03/18 16:54:11
added/done.
| |
59 *dst++ = c64; | |
60 n--; | |
61 } | |
62 } | |
63 | |
64 template<> | |
65 void fill<uint64_t, kLinear_SkColorProfileType, true>(const Sk4f& c, uint64_t* d st, int n) { | |
66 fill<uint64_t, kLinear_SkColorProfileType, false>(premul_4f(c), dst, n); | |
67 } | |
68 | |
69 template<typename DstType, SkColorProfileType profile, bool do_premul> | |
40 void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) { | 70 void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) { |
41 SkASSERT(n > 0); | 71 SkASSERT(n > 0); |
42 | 72 |
43 const Sk4f dc2 = dc + dc; | 73 const Sk4f dc2 = dc + dc; |
44 const Sk4f dc4 = dc2 + dc2; | 74 const Sk4f dc4 = dc2 + dc2; |
45 | 75 |
46 Sk4f c0 = c ; | 76 Sk4f c0 = c ; |
47 Sk4f c1 = c + dc; | 77 Sk4f c1 = c + dc; |
48 Sk4f c2 = c0 + dc2; | 78 Sk4f c2 = c0 + dc2; |
49 Sk4f c3 = c1 + dc2; | 79 Sk4f c3 = c1 + dc2; |
50 | 80 |
51 while (n >= 4) { | 81 while (n >= 4) { |
52 store4x<DstType, do_premul>(c0, c1, c2, c3, dst); | 82 store4x<DstType, profile, do_premul>(c0, c1, c2, c3, dst); |
53 dst += 4; | 83 dst += 4; |
54 | 84 |
55 c0 = c0 + dc4; | 85 c0 = c0 + dc4; |
56 c1 = c1 + dc4; | 86 c1 = c1 + dc4; |
57 c2 = c2 + dc4; | 87 c2 = c2 + dc4; |
58 c3 = c3 + dc4; | 88 c3 = c3 + dc4; |
59 n -= 4; | 89 n -= 4; |
60 } | 90 } |
61 if (n & 2) { | 91 if (n & 2) { |
62 store<DstType, do_premul>(c0, dst++); | 92 store<DstType, profile, do_premul>(c0, dst++); |
63 store<DstType, do_premul>(c1, dst++); | 93 store<DstType, profile, do_premul>(c1, dst++); |
64 c0 = c0 + dc2; | 94 c0 = c0 + dc2; |
65 } | 95 } |
66 if (n & 1) { | 96 if (n & 1) { |
67 store<DstType, do_premul>(c0, dst); | 97 store<DstType, profile, do_premul>(c0, dst); |
68 } | 98 } |
69 } | 99 } |
70 | 100 |
71 template<SkShader::TileMode> | 101 template<SkShader::TileMode> |
72 SkScalar pinFx(SkScalar); | 102 SkScalar pinFx(SkScalar); |
73 | 103 |
74 template<> | 104 template<> |
75 SkScalar pinFx<SkShader::kClamp_TileMode>(SkScalar fx) { | 105 SkScalar pinFx<SkShader::kClamp_TileMode>(SkScalar fx) { |
76 return fx; | 106 return fx; |
77 } | 107 } |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 void SkLinearGradient:: | 186 void SkLinearGradient:: |
157 LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) { | 187 LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) { |
158 if (!this->isFast()) { | 188 if (!this->isFast()) { |
159 this->INHERITED::shadeSpan(x, y, dst, count); | 189 this->INHERITED::shadeSpan(x, y, dst, count); |
160 return; | 190 return; |
161 } | 191 } |
162 | 192 |
163 // TODO: plumb dithering | 193 // TODO: plumb dithering |
164 SkASSERT(count > 0); | 194 SkASSERT(count > 0); |
165 if (fColorsArePremul) { | 195 if (fColorsArePremul) { |
166 this->shadePremulSpan<SkPMColor, false>(x, y, dst, count); | 196 this->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, false>(x, y , dst, count); |
167 } else { | 197 } else { |
168 this->shadePremulSpan<SkPMColor, true>(x, y, dst, count); | 198 this->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, true>(x, y, dst, count); |
169 } | 199 } |
170 } | 200 } |
171 | 201 |
172 void SkLinearGradient:: | 202 void SkLinearGradient:: |
173 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { | 203 LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { |
174 if (!this->isFast()) { | 204 if (!this->isFast()) { |
175 this->INHERITED::shadeSpan4f(x, y, dst, count); | 205 this->INHERITED::shadeSpan4f(x, y, dst, count); |
176 return; | 206 return; |
177 } | 207 } |
178 | 208 |
179 // TONOTDO: plumb dithering | 209 // TONOTDO: plumb dithering |
180 SkASSERT(count > 0); | 210 SkASSERT(count > 0); |
181 if (fColorsArePremul) { | 211 if (fColorsArePremul) { |
182 this->shadePremulSpan<SkPM4f, false>(x, y, dst, count); | 212 this->shadePremulSpan<SkPM4f, kLinear_SkColorProfileType, false>(x, y, d st, count); |
183 } else { | 213 } else { |
184 this->shadePremulSpan<SkPM4f, true>(x, y, dst, count); | 214 this->shadePremulSpan<SkPM4f, kLinear_SkColorProfileType, true>(x, y, ds t, count); |
185 } | 215 } |
186 } | 216 } |
187 | 217 |
188 template<typename DstType, bool do_premul> | 218 template<typename DstType, SkColorProfileType profile, bool do_premul> |
189 void SkLinearGradient:: | 219 void SkLinearGradient:: |
190 LinearGradient4fContext::shadePremulSpan(int x, int y, | 220 LinearGradient4fContext::shadePremulSpan(int x, int y, |
191 DstType dst[], | 221 DstType dst[], |
192 int count) const { | 222 int count) const { |
193 const SkLinearGradient& shader = | 223 const SkLinearGradient& shader = |
194 static_cast<const SkLinearGradient&>(fShader); | 224 static_cast<const SkLinearGradient&>(fShader); |
195 switch (shader.fTileMode) { | 225 switch (shader.fTileMode) { |
196 case kClamp_TileMode: | 226 case kClamp_TileMode: |
197 this->shadeSpanInternal<DstType, | 227 this->shadeSpanInternal<DstType, |
228 profile, | |
198 do_premul, | 229 do_premul, |
199 kClamp_TileMode>(x, y, dst, count); | 230 kClamp_TileMode>(x, y, dst, count); |
200 break; | 231 break; |
201 case kRepeat_TileMode: | 232 case kRepeat_TileMode: |
202 this->shadeSpanInternal<DstType, | 233 this->shadeSpanInternal<DstType, |
234 profile, | |
203 do_premul, | 235 do_premul, |
204 kRepeat_TileMode>(x, y, dst, count); | 236 kRepeat_TileMode>(x, y, dst, count); |
205 break; | 237 break; |
206 case kMirror_TileMode: | 238 case kMirror_TileMode: |
207 this->shadeSpanInternal<DstType, | 239 this->shadeSpanInternal<DstType, |
240 profile, | |
208 do_premul, | 241 do_premul, |
209 kMirror_TileMode>(x, y, dst, count); | 242 kMirror_TileMode>(x, y, dst, count); |
210 break; | 243 break; |
211 } | 244 } |
212 } | 245 } |
213 | 246 |
214 template<typename DstType, bool do_premul, SkShader::TileMode tileMode> | 247 template<typename DstType, SkColorProfileType profile, bool do_premul, |
248 SkShader::TileMode tileMode> | |
215 void SkLinearGradient:: | 249 void SkLinearGradient:: |
216 LinearGradient4fContext::shadeSpanInternal(int x, int y, | 250 LinearGradient4fContext::shadeSpanInternal(int x, int y, |
217 DstType dst[], | 251 DstType dst[], |
218 int count) const { | 252 int count) const { |
219 SkPoint pt; | 253 SkPoint pt; |
220 fDstToPosProc(fDstToPos, | 254 fDstToPosProc(fDstToPos, |
221 x + SK_ScalarHalf, | 255 x + SK_ScalarHalf, |
222 y + SK_ScalarHalf, | 256 y + SK_ScalarHalf, |
223 &pt); | 257 &pt); |
224 const SkScalar fx = pinFx<tileMode>(pt.x()); | 258 const SkScalar fx = pinFx<tileMode>(pt.x()); |
225 const SkScalar dx = fDstToPos.getScaleX(); | 259 const SkScalar dx = fDstToPos.getScaleX(); |
226 LinearIntervalProcessor<DstType, tileMode> proc(fIntervals.begin(), | 260 LinearIntervalProcessor<DstType, profile, tileMode> proc(fIntervals.begin(), |
227 fIntervals.end() - 1, | 261 fIntervals.end() - 1, |
228 this->findInterval(fx), | 262 this->findInterval( fx), |
229 fx, | 263 fx, |
230 dx, | 264 dx, |
231 SkScalarNearlyZero(dx * coun t)); | 265 SkScalarNearlyZero( dx * count)); |
232 while (count > 0) { | 266 while (count > 0) { |
233 // What we really want here is SkTPin(advance, 1, count) | 267 // What we really want here is SkTPin(advance, 1, count) |
234 // but that's a significant perf hit for >> stops; investigate. | 268 // but that's a significant perf hit for >> stops; investigate. |
235 const int n = SkScalarTruncToInt( | 269 const int n = SkScalarTruncToInt( |
236 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count))); | 270 SkTMin<SkScalar>(proc.currentAdvance() + 1, SkIntToScalar(count))); |
237 | 271 |
238 // The current interval advance can be +inf (e.g. when reaching | 272 // The current interval advance can be +inf (e.g. when reaching |
239 // the clamp mode end intervals) - when that happens, we expect to | 273 // the clamp mode end intervals) - when that happens, we expect to |
240 // a) consume all remaining count in one swoop | 274 // a) consume all remaining count in one swoop |
241 // b) return a zero color gradient | 275 // b) return a zero color gradient |
242 SkASSERT(SkScalarIsFinite(proc.currentAdvance()) | 276 SkASSERT(SkScalarIsFinite(proc.currentAdvance()) |
243 || (n == count && proc.currentRampIsZero())); | 277 || (n == count && proc.currentRampIsZero())); |
244 | 278 |
245 if (proc.currentRampIsZero()) { | 279 if (proc.currentRampIsZero()) { |
246 fill<DstType, do_premul>(proc.currentColor(), | 280 fill<DstType, profile, do_premul>(proc.currentColor(), |
247 dst, n); | 281 dst, n); |
248 } else { | 282 } else { |
249 ramp<DstType, do_premul>(proc.currentColor(), | 283 ramp<DstType, profile, do_premul>(proc.currentColor(), |
250 proc.currentColorGrad(), | 284 proc.currentColorGrad(), |
251 dst, n); | 285 dst, n); |
252 } | 286 } |
253 | 287 |
254 proc.advance(SkIntToScalar(n)); | 288 proc.advance(SkIntToScalar(n)); |
255 count -= n; | 289 count -= n; |
256 dst += n; | 290 dst += n; |
257 } | 291 } |
258 } | 292 } |
259 | 293 |
260 template<typename DstType, SkShader::TileMode tileMode> | 294 template<typename DstType, SkColorProfileType profile, SkShader::TileMode tileMo de> |
261 class SkLinearGradient:: | 295 class SkLinearGradient:: |
262 LinearGradient4fContext::LinearIntervalProcessor { | 296 LinearGradient4fContext::LinearIntervalProcessor { |
263 public: | 297 public: |
264 LinearIntervalProcessor(const Interval* firstInterval, | 298 LinearIntervalProcessor(const Interval* firstInterval, |
265 const Interval* lastInterval, | 299 const Interval* lastInterval, |
266 const Interval* i, | 300 const Interval* i, |
267 SkScalar fx, | 301 SkScalar fx, |
268 SkScalar dx, | 302 SkScalar dx, |
269 bool is_vertical) | 303 bool is_vertical) |
270 : fDstComponentScale(dst_component_scale<DstType>()) | 304 : fAdvX((i->fP1 - fx) / dx) |
271 , fAdvX((i->fP1 - fx) / dx) | |
272 , fFirstInterval(firstInterval) | 305 , fFirstInterval(firstInterval) |
273 , fLastInterval(lastInterval) | 306 , fLastInterval(lastInterval) |
274 , fInterval(i) | 307 , fInterval(i) |
275 , fDx(dx) | 308 , fDx(dx) |
276 , fIsVertical(is_vertical) | 309 , fIsVertical(is_vertical) |
277 { | 310 { |
278 SkASSERT(firstInterval <= lastInterval); | 311 SkASSERT(firstInterval <= lastInterval); |
279 SkASSERT(in_range(fx, i->fP0, i->fP1)); | 312 SkASSERT(in_range(fx, i->fP0, i->fP1)); |
280 this->compute_interval_props(fx - i->fP0); | 313 this->compute_interval_props(fx - i->fP0); |
281 } | 314 } |
(...skipping 19 matching lines...) Expand all Loading... | |
301 | 334 |
302 fCc = fCc + fDcDx * Sk4f(advX); | 335 fCc = fCc + fDcDx * Sk4f(advX); |
303 fAdvX -= advX; | 336 fAdvX -= advX; |
304 } | 337 } |
305 | 338 |
306 private: | 339 private: |
307 void compute_interval_props(SkScalar t) { | 340 void compute_interval_props(SkScalar t) { |
308 fDc = dst_swizzle<DstType>(fInterval->fDc); | 341 fDc = dst_swizzle<DstType>(fInterval->fDc); |
309 fCc = dst_swizzle<DstType>(fInterval->fC0); | 342 fCc = dst_swizzle<DstType>(fInterval->fC0); |
310 fCc = fCc + fDc * Sk4f(t); | 343 fCc = fCc + fDc * Sk4f(t); |
311 fCc = fCc * fDstComponentScale; | 344 fCc = scale_for_dest<DstType, profile>(fCc); |
312 fDcDx = fDc * fDstComponentScale * Sk4f(fDx); | 345 fDcDx = scale_for_dest<DstType, profile>(fDc * Sk4f(fDx)); |
313 fZeroRamp = fIsVertical || fInterval->isZeroRamp(); | 346 fZeroRamp = fIsVertical || fInterval->isZeroRamp(); |
314 } | 347 } |
315 | 348 |
316 const Interval* next_interval(const Interval* i) const { | 349 const Interval* next_interval(const Interval* i) const { |
317 SkASSERT(i >= fFirstInterval); | 350 SkASSERT(i >= fFirstInterval); |
318 SkASSERT(i <= fLastInterval); | 351 SkASSERT(i <= fLastInterval); |
319 i++; | 352 i++; |
320 | 353 |
321 if (tileMode == kClamp_TileMode) { | 354 if (tileMode == kClamp_TileMode) { |
322 SkASSERT(i <= fLastInterval); | 355 SkASSERT(i <= fLastInterval); |
(...skipping 12 matching lines...) Expand all Loading... | |
335 fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx; | 368 fAdvX = (fInterval->fP1 - fInterval->fP0) / fDx; |
336 SkASSERT(fAdvX > 0); | 369 SkASSERT(fAdvX > 0); |
337 } while (advX >= fAdvX); | 370 } while (advX >= fAdvX); |
338 | 371 |
339 compute_interval_props(0); | 372 compute_interval_props(0); |
340 | 373 |
341 SkASSERT(advX >= 0); | 374 SkASSERT(advX >= 0); |
342 return advX; | 375 return advX; |
343 } | 376 } |
344 | 377 |
345 const Sk4f fDstComponentScale; // cached dst scale (PMC: 255, PM4f: 1) | |
346 | |
347 // Current interval properties. | 378 // Current interval properties. |
348 Sk4f fDc; // local color gradient (dc/dt) | 379 Sk4f fDc; // local color gradient (dc/dt) |
349 Sk4f fDcDx; // dst color gradient (dc/dx) | 380 Sk4f fDcDx; // dst color gradient (dc/dx) |
350 Sk4f fCc; // current color, interpolated in dst | 381 Sk4f fCc; // current color, interpolated in dst |
351 SkScalar fAdvX; // remaining interval advance in dst | 382 SkScalar fAdvX; // remaining interval advance in dst |
352 bool fZeroRamp; // current interval color grad is 0 | 383 bool fZeroRamp; // current interval color grad is 0 |
353 | 384 |
354 const Interval* fFirstInterval; | 385 const Interval* fFirstInterval; |
355 const Interval* fLastInterval; | 386 const Interval* fLastInterval; |
356 const Interval* fInterval; // current interval | 387 const Interval* fInterval; // current interval |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 *ts++ = t4[0]; | 426 *ts++ = t4[0]; |
396 } | 427 } |
397 } else { | 428 } else { |
398 for (int i = 0; i < count; ++i) { | 429 for (int i = 0; i < count; ++i) { |
399 fDstToPosProc(fDstToPos, sx, sy, &pt); | 430 fDstToPosProc(fDstToPos, sx, sy, &pt); |
400 ts[i] = pt.x(); | 431 ts[i] = pt.x(); |
401 sx += SK_Scalar1; | 432 sx += SK_Scalar1; |
402 } | 433 } |
403 } | 434 } |
404 } | 435 } |
436 | |
437 SkShader::Context::BlitProc SkLinearGradient:: | |
438 LinearGradient4fContext::onChooseBlitProc(const SkImageInfo& info, BlitState* st ate) { | |
439 SkXfermode::Mode mode; | |
440 if (!SkXfermode::AsMode(state->fXfer, &mode)) { | |
441 return nullptr; | |
442 } | |
443 | |
444 const SkGradientShaderBase& shader = static_cast<const SkGradientShaderBase& >(fShader); | |
445 if (mode != SkXfermode::kSrc_Mode && | |
446 !(mode == SkXfermode::kSrcOver_Mode && shader.colorsAreOpaque())) { | |
447 return nullptr; | |
448 } | |
449 | |
450 switch (info.colorType()) { | |
451 case kN32_SkColorType: | |
452 return D32_BlitProc; | |
453 case kRGBA_F16_SkColorType: | |
454 return D64_BlitProc; | |
455 default: | |
456 return nullptr; | |
457 } | |
458 } | |
459 | |
460 void SkLinearGradient:: | |
461 LinearGradient4fContext::D32_BlitProc(BlitState* state, int x, int y, const SkPi xmap& dst, | |
462 int count, const SkAlpha aa[]) { | |
463 // FIXME: ignoring coverage for now | |
464 const LinearGradient4fContext* ctx = | |
465 static_cast<const LinearGradient4fContext*>(state->fCtx); | |
466 | |
467 if (dst.info().isLinear()) { | |
468 if (ctx->fColorsArePremul) { | |
469 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, false>( | |
470 x, y, dst.writable_addr32(x, y), count); | |
471 } else { | |
472 ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, true>( | |
473 x, y, dst.writable_addr32(x, y), count); | |
474 } | |
475 } else { | |
476 if (ctx->fColorsArePremul) { | |
477 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, false>( | |
478 x, y, dst.writable_addr32(x, y), count); | |
479 } else { | |
480 ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, true>( | |
481 x, y, dst.writable_addr32(x, y), count); | |
482 } | |
483 } | |
484 } | |
485 | |
486 void SkLinearGradient:: | |
487 LinearGradient4fContext::D64_BlitProc(BlitState* state, int x, int y, const SkPi xmap& dst, | |
488 int count, const SkAlpha aa[]) { | |
489 // FIXME: ignoring coverage for now | |
490 const LinearGradient4fContext* ctx = | |
491 static_cast<const LinearGradient4fContext*>(state->fCtx); | |
492 | |
493 if (ctx->fColorsArePremul) { | |
494 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, false>( | |
495 x, y, dst.writable_addr64(x, y), count); | |
496 } else { | |
497 ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, true>( | |
498 x, y, dst.writable_addr64(x, y), count); | |
499 } | |
500 } | |
OLD | NEW |