aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2017-07-29 18:23:10 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-29 23:01:10 +0000
commit9c2212fa79e03ea7f3527bf4c30b3e6bbd560932 (patch)
treec8c00eb8ef3978310d67f44645460500d1a6b407 /src
parent28a586966d5862312ed9e1b8d7de25b25b0f1b48 (diff)
Don't instantiate degenerate 2pt gradients
We can catch the condition at construction time, no need to defer. Change-Id: I973b9e1b79998e2b334e3a91694c793882dfd65a Reviewed-on: https://skia-review.googlesource.com/26564 Commit-Queue: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Klein <mtklein@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/shaders/gradients/SkGradientShader.cpp8
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.cpp54
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.h24
3 files changed, 58 insertions, 28 deletions
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 56a8fe317b..c9a69e2a55 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -1202,8 +1202,8 @@ sk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start,
if (!flipGradient) {
desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags,
localMatrix);
- return sk_make_sp<SkTwoPointConicalGradient>(start, startRadius, end, endRadius,
- flipGradient, desc);
+ return SkTwoPointConicalGradient::Create(start, startRadius, end, endRadius, flipGradient,
+ desc);
} else {
SkAutoSTArray<8, SkColor4f> colorsNew(opt.fCount);
SkAutoSTArray<8, SkScalar> posNew(opt.fCount);
@@ -1222,8 +1222,8 @@ sk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start,
flags, localMatrix);
}
- return sk_make_sp<SkTwoPointConicalGradient>(end, endRadius, start, startRadius,
- flipGradient, desc);
+ return SkTwoPointConicalGradient::Create(end, endRadius, start, startRadius, flipGradient,
+ desc);
}
}
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index 22ae177559..479d85ffd8 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -10,16 +10,47 @@
#include "SkRasterPipeline.h"
#include "../../jumper/SkJumper.h"
+sk_sp<SkShader> SkTwoPointConicalGradient::Create(const SkPoint& c0, SkScalar r0,
+ const SkPoint& c1, SkScalar r1,
+ bool flipped, const Descriptor& desc) {
+ SkMatrix gradientMatrix;
+ Type gradientType;
+
+ if (SkScalarNearlyZero((c0 - c1).length())) {
+ // Concentric case: we can pretend we're radial (with a tiny twist).
+ gradientMatrix = SkMatrix::MakeTrans(-c1.x(), -c1.y());
+ gradientMatrix.postScale(1 / r1, 1 / r1);
+
+ gradientType = Type::kRadial;
+ } else {
+ const SkPoint centers[2] = { c0 , c1 };
+ const SkPoint unitvec[2] = { {0, 0}, {1, 0} };
+
+ if (!gradientMatrix.setPolyToPoly(centers, unitvec, 2)) {
+ // Degenerate case.
+ return nullptr;
+ }
+
+ // General two-point case.
+ gradientType = Type::kTwoPoint;
+ }
+
+ return sk_sp<SkShader>(new SkTwoPointConicalGradient(c0, r0, c1, r1, flipped, desc,
+ gradientType, gradientMatrix));
+}
+
SkTwoPointConicalGradient::SkTwoPointConicalGradient(
const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- bool flippedGrad, const Descriptor& desc)
- : SkGradientShaderBase(desc, SkMatrix::I())
+ bool flippedGrad, const Descriptor& desc,
+ Type type, const SkMatrix& gradientMatrix)
+ : SkGradientShaderBase(desc, gradientMatrix)
, fCenter1(start)
, fCenter2(end)
, fRadius1(startRadius)
, fRadius2(endRadius)
, fFlippedGrad(flippedGrad)
+ , fType(type)
{
// this is degenerate, and should be caught by our caller
SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2);
@@ -176,15 +207,12 @@ bool SkTwoPointConicalGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
SkMatrix* matrix,
SkRasterPipeline* p,
SkRasterPipeline* postPipeline) const {
- const auto dCenter = (fCenter1 - fCenter2).length();
+ matrix->postConcat(fPtsToUnit);
+
const auto dRadius = fRadius2 - fRadius1;
SkASSERT(dRadius >= 0);
- // When the two circles are concentric, we can pretend we're radial (with a tiny *twist).
- if (SkScalarNearlyZero(dCenter)) {
- const SkMatrix tmp = SkMatrix::Concat(SkMatrix::MakeScale(1 / fRadius2, 1 / fRadius2),
- SkMatrix::MakeTrans(-fCenter1.fX, -fCenter1.fY));
- matrix->postConcat(tmp);
+ if (fType == Type::kRadial) {
p->append(SkRasterPipeline::xy_to_radius);
// Tiny twist: radial computes a t for [0, r2], but we want a t for [r1, r2].
@@ -197,15 +225,7 @@ bool SkTwoPointConicalGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
return true;
}
- // 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;
- const SkPoint centers[2] = { fCenter1, fCenter2 };
- const SkPoint unitvec[2] = { {0, 0}, {1, 0} };
- if (!map_to_unit_vector.setPolyToPoly(centers, unitvec, 2)) {
- return false;
- }
- matrix->postConcat(map_to_unit_vector);
+ const auto dCenter = (fCenter1 - fCenter2).length();
// Since we've squashed the centers into a unit vector, we must also scale
// all the coefficient variables by (1 / dCenter).
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.h b/src/shaders/gradients/SkTwoPointConicalGradient.h
index 41909c900d..8b11963802 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.h
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.h
@@ -13,9 +13,9 @@
class SkTwoPointConicalGradient final : public SkGradientShaderBase {
public:
- SkTwoPointConicalGradient(const SkPoint& start, SkScalar startRadius,
- const SkPoint& end, SkScalar endRadius,
- bool flippedGrad, const Descriptor&);
+ static sk_sp<SkShader> Create(const SkPoint& start, SkScalar startRadius,
+ const SkPoint& end, SkScalar endRadius,
+ bool flippedGrad, const Descriptor&);
SkShader::GradientType asAGradient(GradientInfo* info) const override;
#if SK_SUPPORT_GPU
@@ -35,7 +35,6 @@ public:
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTwoPointConicalGradient)
protected:
- SkTwoPointConicalGradient(SkReadBuffer& buffer);
void flatten(SkWriteBuffer& buffer) const override;
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
@@ -47,11 +46,22 @@ protected:
bool onIsRasterPipelineOnly() const override { return true; }
private:
- SkPoint fCenter1;
- SkPoint fCenter2;
+ enum class Type {
+ kRadial,
+ kTwoPoint,
+ };
+
+ SkTwoPointConicalGradient(const SkPoint& c0, SkScalar r0,
+ const SkPoint& c1, SkScalar r1,
+ bool flippedGrad, const Descriptor&,
+ Type, const SkMatrix&);
+
+ SkPoint fCenter1;
+ SkPoint fCenter2;
SkScalar fRadius1;
SkScalar fRadius2;
- bool fFlippedGrad;
+ bool fFlippedGrad;
+ Type fType;
friend class SkGradientShader;
typedef SkGradientShaderBase INHERITED;