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 "Sk4fGradientBase.h" | 8 #include "Sk4fGradientBase.h" |
| 9 | 9 |
| 10 #include <functional> | 10 #include <functional> |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 Sk4f pack_color(SkColor c, bool premul, const Sk4f& component_scale) { | 14 Sk4f pack_color(SkColor c, bool premul, const Sk4f& component_scale) { |
| 15 const SkColor4f c4f = SkColor4f::FromColor(c); | 15 const SkColor4f c4f = SkColor4f::FromColor(c); |
| 16 const Sk4f pm4f = premul | 16 const Sk4f pm4f = premul |
| 17 ? c4f.premul().to4f() | 17 ? c4f.premul().to4f() |
| 18 : Sk4f{c4f.fR, c4f.fG, c4f.fB, c4f.fA}; | 18 : Sk4f{c4f.fR, c4f.fG, c4f.fB, c4f.fA}; |
| 19 | 19 |
| 20 return pm4f * component_scale; | 20 return pm4f * component_scale; |
| 21 } | 21 } |
| 22 | 22 |
| 23 template<SkShader::TileMode> | |
| 24 SkScalar tileProc(SkScalar t); | |
| 25 | |
| 26 template<> | |
| 27 SkScalar tileProc<SkShader::kClamp_TileMode>(SkScalar t) { | |
| 28 // synthetic clamp-mode edge intervals allow for a free-floating t: | |
| 29 // [-inf..0)[0..1)[1..+inf) | |
| 30 return t; | |
| 31 } | |
| 32 | |
| 33 template<> | |
| 34 SkScalar tileProc<SkShader::kRepeat_TileMode>(SkScalar t) { | |
| 35 // t % 1 (intervals range: [0..1)) | |
| 36 return t - SkScalarFloorToScalar(t); | |
| 37 } | |
| 38 | |
| 39 template<> | |
| 40 SkScalar tileProc<SkShader::kMirror_TileMode>(SkScalar t) { | |
| 41 // t % 2 (synthetic mirror intervals expand the range to [0..2) | |
| 42 return t - SkScalarFloorToScalar(t / 2) * 2; | |
| 43 } | |
| 44 | |
| 45 class IntervalIterator { | 23 class IntervalIterator { |
| 46 public: | 24 public: |
| 47 IntervalIterator(const SkColor* colors, const SkScalar* pos, int count, bool reverse) | 25 IntervalIterator(const SkColor* colors, const SkScalar* pos, int count, bool reverse) |
| 48 : fColors(colors) | 26 : fColors(colors) |
| 49 , fPos(pos) | 27 , fPos(pos) |
| 50 , fCount(count) | 28 , fCount(count) |
| 51 , fFirstPos(reverse ? SK_Scalar1 : 0) | 29 , fFirstPos(reverse ? SK_Scalar1 : 0) |
| 52 , fBegin(reverse ? count - 1 : 0) | 30 , fBegin(reverse ? count - 1 : 0) |
| 53 , fAdvance(reverse ? -1 : 1) { | 31 , fAdvance(reverse ? -1 : 1) { |
| 54 SkASSERT(colors); | 32 SkASSERT(colors); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 count -= n; | 325 count -= n; |
| 348 } while (count > 0); | 326 } while (count > 0); |
| 349 } | 327 } |
| 350 | 328 |
| 351 template<DstType dstType, ApplyPremul premul, SkShader::TileMode tileMode> | 329 template<DstType dstType, ApplyPremul premul, SkShader::TileMode tileMode> |
| 352 class SkGradientShaderBase::GradientShaderBase4fContext::TSampler { | 330 class SkGradientShaderBase::GradientShaderBase4fContext::TSampler { |
| 353 public: | 331 public: |
| 354 TSampler(const GradientShaderBase4fContext& ctx) | 332 TSampler(const GradientShaderBase4fContext& ctx) |
| 355 : fFirstInterval(ctx.fIntervals.begin()) | 333 : fFirstInterval(ctx.fIntervals.begin()) |
| 356 , fLastInterval(ctx.fIntervals.end() - 1) | 334 , fLastInterval(ctx.fIntervals.end() - 1) |
| 357 , fInterval(nullptr) { | 335 , fInterval(nullptr) |
| 336 , fLargestLessThanTwo(nextafterf(2, 0)) { | |
| 358 SkASSERT(fLastInterval >= fFirstInterval); | 337 SkASSERT(fLastInterval >= fFirstInterval); |
| 359 } | 338 } |
| 360 | 339 |
| 361 Sk4f sample(SkScalar t) { | 340 Sk4f sample(SkScalar t) { |
| 362 const SkScalar tiled_t = tileProc<tileMode>(t); | 341 const auto tiled_t = tileProc(t); |
| 363 | 342 |
| 364 if (!fInterval) { | 343 if (!fInterval) { |
| 365 // Very first sample => locate the initial interval. | 344 // Very first sample => locate the initial interval. |
| 366 // TODO: maybe do this in ctor to remove a branch? | 345 // TODO: maybe do this in ctor to remove a branch? |
| 367 fInterval = this->findFirstInterval(tiled_t); | 346 fInterval = this->findFirstInterval(tiled_t); |
| 368 this->loadIntervalData(fInterval); | 347 this->loadIntervalData(fInterval); |
| 369 } else if (tiled_t < fInterval->fP0 || tiled_t >= fInterval->fP1) { | 348 } else if (tiled_t < fInterval->fP0 || tiled_t >= fInterval->fP1) { |
| 370 fInterval = this->findNextInterval(t, tiled_t); | 349 fInterval = this->findNextInterval(t, tiled_t); |
| 371 this->loadIntervalData(fInterval); | 350 this->loadIntervalData(fInterval); |
| 372 } | 351 } |
| 373 | 352 |
| 374 fPrevT = t; | 353 fPrevT = t; |
| 375 return lerp(tiled_t); | 354 return lerp(tiled_t); |
| 376 } | 355 } |
| 377 | 356 |
| 378 private: | 357 private: |
| 358 SkScalar tileProc(SkScalar t) const { | |
| 359 switch (tileMode) { | |
| 360 case kClamp_TileMode: | |
| 361 // synthetic clamp-mode edge intervals allow for a free-floating t: | |
| 362 // [-inf..0)[0..1)[1..+inf) | |
| 363 return t; | |
| 364 case kRepeat_TileMode: | |
| 365 // t % 1 (intervals range: [0..1)) | |
| 366 return t - SkScalarFloorToScalar(t); | |
| 367 case kMirror_TileMode: | |
| 368 // t % 2 (synthetic mirror intervals expand the range to [0..2) | |
| 369 // Due to the extra arithmetic, we must clamp to ensure the value re mains less than 2. | |
| 370 return SkTMin(t - SkScalarFloorToScalar(t / 2) * 2, fLargestLessThan Two); | |
| 371 } | |
| 372 | |
| 373 SK_ABORT("Unhandled tile mode."); | |
| 374 return 0; | |
| 375 } | |
| 376 | |
| 379 Sk4f lerp(SkScalar t) { | 377 Sk4f lerp(SkScalar t) { |
| 380 SkASSERT(t >= fInterval->fP0 && t < fInterval->fP1); | 378 SkASSERT(t >= fInterval->fP0 && t < fInterval->fP1); |
| 381 return fCc + fDc * (t - fInterval->fP0); | 379 return fCc + fDc * (t - fInterval->fP0); |
| 382 } | 380 } |
| 383 | 381 |
| 384 const Interval* findFirstInterval(SkScalar t) const { | 382 const Interval* findFirstInterval(SkScalar t) const { |
| 385 // Binary search. | 383 // Binary search. |
| 386 const Interval* i0 = fFirstInterval; | 384 const Interval* i0 = fFirstInterval; |
| 387 const Interval* i1 = fLastInterval; | 385 const Interval* i1 = fLastInterval; |
| 388 | 386 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 | 430 |
| 433 void loadIntervalData(const Interval* i) { | 431 void loadIntervalData(const Interval* i) { |
| 434 fCc = DstTraits<dstType, premul>::load(i->fC0); | 432 fCc = DstTraits<dstType, premul>::load(i->fC0); |
| 435 fDc = DstTraits<dstType, premul>::load(i->fDc); | 433 fDc = DstTraits<dstType, premul>::load(i->fDc); |
| 436 } | 434 } |
| 437 | 435 |
| 438 const Interval* fFirstInterval; | 436 const Interval* fFirstInterval; |
| 439 const Interval* fLastInterval; | 437 const Interval* fLastInterval; |
| 440 const Interval* fInterval; | 438 const Interval* fInterval; |
| 441 SkScalar fPrevT; | 439 SkScalar fPrevT; |
| 440 SkScalar fLargestLessThanTwo; | |
|
herb_g
2016/11/04 14:58:44
Can this be static constexpr?
f(malita)
2016/11/04 15:05:53
Unfortunately not, nextafterf is not constexpr :(
| |
| 442 Sk4f fCc; | 441 Sk4f fCc; |
| 443 Sk4f fDc; | 442 Sk4f fDc; |
| 444 }; | 443 }; |
| OLD | NEW |