Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(282)

Side by Side Diff: src/effects/gradients/Sk4fGradientBase.cpp

Issue 2472763002: Fix fuzzer assert in GradientShaderBase4fContext::TSampler (Closed)
Patch Set: Win build fix Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698