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

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

Issue 2472483002: Sk4fLinearGradient fuzzer fixes (Closed)
Patch Set: GM 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 | « gm/gradients.cpp ('k') | 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 "Sk4fLinearGradient.h" 8 #include "Sk4fLinearGradient.h"
9 #include "Sk4x4f.h" 9 #include "Sk4x4f.h"
10 #include "SkXfermode.h" 10 #include "SkXfermode.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 SkScalar pinFx<SkShader::kMirror_TileMode>(SkScalar fx) { 98 SkScalar pinFx<SkShader::kMirror_TileMode>(SkScalar fx) {
99 const SkScalar f = SkScalarMod(fx, 2.0f); 99 const SkScalar f = SkScalarMod(fx, 2.0f);
100 return f < 0 ? f + 2 : f; 100 return f < 0 ? f + 2 : f;
101 } 101 }
102 102
103 // true when x is in [k1,k2), or [k2, k1) when the interval is reversed. 103 // true when x is in [k1,k2), or [k2, k1) when the interval is reversed.
104 // TODO(fmalita): hoist the reversed interval check out of this helper. 104 // TODO(fmalita): hoist the reversed interval check out of this helper.
105 bool in_range(SkScalar x, SkScalar k1, SkScalar k2) { 105 bool in_range(SkScalar x, SkScalar k1, SkScalar k2) {
106 SkASSERT(k1 != k2); 106 SkASSERT(k1 != k2);
107 return (k1 < k2) 107 return (k1 < k2)
108 ? (x >= k1 && x < k2) 108 ? (x >= k1 && x < k2)
109 : (x > k2 && x <= k1); 109 : (x >= k2 && x < k1);
110 } 110 }
111 111
112 } // anonymous namespace 112 } // anonymous namespace
113 113
114 SkLinearGradient:: 114 SkLinearGradient::
115 LinearGradient4fContext::LinearGradient4fContext(const SkLinearGradient& shader, 115 LinearGradient4fContext::LinearGradient4fContext(const SkLinearGradient& shader,
116 const ContextRec& rec) 116 const ContextRec& rec)
117 : INHERITED(shader, rec) { 117 : INHERITED(shader, rec) {
118 118
119 // Our fast path expects interval points to be monotonically increasing in x . 119 // Our fast path expects interval points to be monotonically increasing in x .
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 : fAdvX((i->fP1 - fx) / dx) 287 : fAdvX((i->fP1 - fx) / dx)
288 , fFirstInterval(firstInterval) 288 , fFirstInterval(firstInterval)
289 , fLastInterval(lastInterval) 289 , fLastInterval(lastInterval)
290 , fInterval(i) 290 , fInterval(i)
291 , fDx(dx) 291 , fDx(dx)
292 , fIsVertical(is_vertical) 292 , fIsVertical(is_vertical)
293 { 293 {
294 SkASSERT(fAdvX >= 0); 294 SkASSERT(fAdvX >= 0);
295 SkASSERT(firstInterval <= lastInterval); 295 SkASSERT(firstInterval <= lastInterval);
296 SkASSERT(in_range(fx, i->fP0, i->fP1)); 296 SkASSERT(in_range(fx, i->fP0, i->fP1));
297
298 if (tileMode != kClamp_TileMode && !is_vertical) {
299 const auto spanX = (lastInterval->fP1 - firstInterval->fP0) / dx;
300 SkASSERT(spanX >= 0);
301
302 // If we're in a repeating tile mode and the whole gradient is compr essed into a
303 // fraction of a pixel, we just use the average color in zero-ramp m ode.
304 // This also avoids cases where we make no progress due to interval advances being
305 // close to zero.
306 static constexpr SkScalar kMinSpanX = .25f;
307 if (spanX < kMinSpanX) {
308 this->init_average_props();
309 return;
310 }
311 }
312
297 this->compute_interval_props(fx - i->fP0); 313 this->compute_interval_props(fx - i->fP0);
298 } 314 }
299 315
300 SkScalar currentAdvance() const { 316 SkScalar currentAdvance() const {
301 SkASSERT(fAdvX >= 0); 317 SkASSERT(fAdvX >= 0);
302 SkASSERT(fAdvX <= (fInterval->fP1 - fInterval->fP0) / fDx); 318 SkASSERT(fAdvX <= (fInterval->fP1 - fInterval->fP0) / fDx || !isfinite(f AdvX));
303 return fAdvX; 319 return fAdvX;
304 } 320 }
305 321
306 bool currentRampIsZero() const { return fZeroRamp; } 322 bool currentRampIsZero() const { return fZeroRamp; }
307 const Sk4f& currentColor() const { return fCc; } 323 const Sk4f& currentColor() const { return fCc; }
308 const Sk4f& currentColorGrad() const { return fDcDx; } 324 const Sk4f& currentColorGrad() const { return fDcDx; }
309 325
310 void advance(SkScalar advX) { 326 void advance(SkScalar advX) {
311 SkASSERT(advX > 0); 327 SkASSERT(advX > 0);
312 SkASSERT(fAdvX >= 0); 328 SkASSERT(fAdvX >= 0);
(...skipping 14 matching lines...) Expand all
327 343
328 if (fInterval->isZeroRamp()) { 344 if (fInterval->isZeroRamp()) {
329 fDcDx = 0; 345 fDcDx = 0;
330 } else { 346 } else {
331 const Sk4f dC = DstTraits<dstType, premul>::load(fInterval->fDc); 347 const Sk4f dC = DstTraits<dstType, premul>::load(fInterval->fDc);
332 fCc = fCc + dC * Sk4f(t); 348 fCc = fCc + dC * Sk4f(t);
333 fDcDx = dC * fDx; 349 fDcDx = dC * fDx;
334 } 350 }
335 } 351 }
336 352
353 void init_average_props() {
354 fAdvX = SK_ScalarInfinity;
355 fZeroRamp = true;
356 fDcDx = 0;
357 fCc = Sk4f(0);
358
359 // TODO: precompute the average at interval setup time?
360 for (const auto* i = fFirstInterval; i <= fLastInterval; ++i) {
361 // Each interval contributes its average color to the total/weighted average:
362 //
363 // C = (c0 + c1) / 2 = (c0 + c0 + dc * (p1 - p0)) / 2
364 //
365 // Avg += C * (p1 - p0)
366 //
367 const auto dp = i->fP1 - i->fP0;
368 auto c = DstTraits<dstType, premul>::load(i->fC0);
369 if (!i->fZeroRamp) {
370 c = c + DstTraits<dstType, premul>::load(i->fDc) * dp * 0.5f;
371 }
372 fCc = fCc + c * dp;
373 }
374 }
375
337 const Interval* next_interval(const Interval* i) const { 376 const Interval* next_interval(const Interval* i) const {
338 SkASSERT(i >= fFirstInterval); 377 SkASSERT(i >= fFirstInterval);
339 SkASSERT(i <= fLastInterval); 378 SkASSERT(i <= fLastInterval);
340 i++; 379 i++;
341 380
342 if (tileMode == kClamp_TileMode) { 381 if (tileMode == kClamp_TileMode) {
343 SkASSERT(i <= fLastInterval); 382 SkASSERT(i <= fLastInterval);
344 return i; 383 return i;
345 } 384 }
346 385
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 static_cast<const LinearGradient4fContext*>(state->fCtx); 518 static_cast<const LinearGradient4fContext*>(state->fCtx);
480 519
481 if (ctx->fColorsArePremul) { 520 if (ctx->fColorsArePremul) {
482 ctx->shadePremulSpan<DstType::F16, ApplyPremul::False>( 521 ctx->shadePremulSpan<DstType::F16, ApplyPremul::False>(
483 x, y, dst.writable_addr64(x, y), count); 522 x, y, dst.writable_addr64(x, y), count);
484 } else { 523 } else {
485 ctx->shadePremulSpan<DstType::F16, ApplyPremul::True>( 524 ctx->shadePremulSpan<DstType::F16, ApplyPremul::True>(
486 x, y, dst.writable_addr64(x, y), count); 525 x, y, dst.writable_addr64(x, y), count);
487 } 526 }
488 } 527 }
OLDNEW
« no previous file with comments | « gm/gradients.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698