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