Chromium Code Reviews| 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 |