aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders/gradients/SkTwoPointConicalGradient.cpp
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-06-29 11:03:45 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-29 15:34:47 +0000
commit9026fe13a751582e58e98f9bf735c18b4719d7fe (patch)
tree6c3f03fb9be33f18d1d686a10839e096ab030393 /src/shaders/gradients/SkTwoPointConicalGradient.cpp
parent762466e9fe0478bcf11fba532998e81e33b3069e (diff)
2pt conical stage for focal-point-outside case
A couple of annoyances here: 1) the prev vector_scale stage is not usable for masking, as NaN values can propagate through => switch to actual masking 2) for the outside case, we must select the min root when the gradient is flipped => split into two templated stages (_min, _max) (I'm not convinced that we need to flip the gradient for RP at all; we can investigate later) Change-Id: I0283812d613a53124f2987d1aea1f26e4533655e Reviewed-on: https://skia-review.googlesource.com/21162 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src/shaders/gradients/SkTwoPointConicalGradient.cpp')
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.cpp36
1 files changed, 27 insertions, 9 deletions
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index 0f48cc20e3..07934ed613 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -453,11 +453,6 @@ bool SkTwoPointConicalGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
return true;
}
- if (dCenter + fRadius1 > fRadius2) {
- // We only handle well behaved cases for now.
- return false;
- }
-
// To simplify the stage math, we transform the universe (translate/scale/rotate)
// such that fCenter1 -> (0, 0) and fCenter2 -> (1, 0).
SkMatrix map_to_unit_vector;
@@ -475,14 +470,37 @@ bool SkTwoPointConicalGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
ctx->fR0 = fRadius1 / dCenter;
ctx->fDR = dRadius / dCenter;
+ // Is the solver guaranteed to not produce degenerates?
+ bool isWellBehaved = true;
+
if (SkScalarNearlyZero(coeffA)) {
// The focal point is on the edge of the end circle.
p->append(SkRasterPipeline::xy_to_2pt_conical_linear, ctx);
- // To handle degenerate values (NaN, r < 0), the t stage sets up a scale/mask
- // context, which we post-apply to force transparent black.
- postPipeline->append(SkRasterPipeline::vector_scale, &ctx->fMask);
+ isWellBehaved = false;
} else {
- p->append(SkRasterPipeline::xy_to_2pt_conical_quadratic, ctx);
+ if (dCenter + fRadius1 > fRadius2) {
+ // The focal point is outside the end circle.
+
+ // We want the larger root, per spec:
+ // "For all values of ω where r(ω) > 0, starting with the value of ω nearest
+ // to positive infinity and ending with the value of ω nearest to negative
+ // infinity, draw the circumference of the circle with radius r(ω) at position
+ // (x(ω), y(ω)), with the color at ω, but only painting on the parts of the
+ // bitmap that have not yet been painted on by earlier circles in this step for
+ // this rendering of the gradient."
+ // (https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createradialgradient)
+ p->append(fFlippedGrad ? SkRasterPipeline::xy_to_2pt_conical_quadratic_min
+ : SkRasterPipeline::xy_to_2pt_conical_quadratic_max, ctx);
+ isWellBehaved = false;
+ } else {
+ // The focal point is inside (well-behaved case).
+ p->append(SkRasterPipeline::xy_to_2pt_conical_quadratic_max, ctx);
+ }
+ }
+
+ if (!isWellBehaved) {
+ p->append(SkRasterPipeline::mask_2pt_conical_degenerates, ctx);
+ postPipeline->append(SkRasterPipeline::apply_vector_mask, &ctx->fMask);
}
return true;