aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-05-04 19:38:48 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-05 13:01:29 +0000
commita377184a5ded8c3cf9a295e13057cf9f9b635bd2 (patch)
tree6d6fa32c1dd7116e0a099b5f1c51935123621ff3 /src/effects
parent02ab8cc2909d99377e4200cd426a02c0b482a040 (diff)
Retry "Factor out common code from sweep and linear."
We weren't handing failure correctly, sending radials and two point conics and any other unsupported cases back too far out, instead of the default SkShader::onAppendStages(). This reverts commit 02ab8cc2909d99377e4200cd426a02c0b482a040. Change-Id: I80cb028c37071e0146ee4b48b210fc8bc87b290f Reviewed-on: https://skia-review.googlesource.com/15481 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Mike Klein <mtklein@chromium.org>
Diffstat (limited to 'src/effects')
-rw-r--r--src/effects/gradients/SkGradientShader.cpp155
-rw-r--r--src/effects/gradients/SkGradientShaderPriv.h34
-rw-r--r--src/effects/gradients/SkLinearGradient.cpp167
-rw-r--r--src/effects/gradients/SkLinearGradient.h6
-rw-r--r--src/effects/gradients/SkRadialGradient.cpp9
-rw-r--r--src/effects/gradients/SkRadialGradient.h3
-rw-r--r--src/effects/gradients/SkSweepGradient.cpp146
-rw-r--r--src/effects/gradients/SkSweepGradient.h6
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient.cpp9
-rw-r--r--src/effects/gradients/SkTwoPointConicalGradient.h3
10 files changed, 219 insertions, 319 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 276eaac8ed..03048dbd70 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -12,8 +12,8 @@
#include "SkLinearGradient.h"
#include "SkMallocPixelRef.h"
#include "SkRadialGradient.h"
-#include "SkTwoPointConicalGradient.h"
#include "SkSweepGradient.h"
+#include "SkTwoPointConicalGradient.h"
enum GradientSerializationFlags {
// Bits 29:31 used for various boolean flags
@@ -347,6 +347,155 @@ void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
}
+bool SkGradientShaderBase::onAppendStages(
+ SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc,
+ const SkMatrix& ctm, const SkPaint& paint,
+ const SkMatrix* localM) const
+{
+ // Local matrix not supported currently. Remove once we have a generic RP wrapper.
+ if (localM || !getLocalMatrix().isIdentity()) {
+ return false;
+ }
+
+ SkMatrix matrix;
+ if (!ctm.invert(&matrix)) {
+ return false;
+ }
+
+ SkRasterPipeline p;
+ if (!this->adjustMatrixAndAppendStages(alloc, &matrix, &p)) {
+ return false;
+ }
+
+ auto* m = alloc->makeArrayDefault<float>(9);
+ if (matrix.asAffine(m)) {
+ // TODO: mapping y is not needed; split the matrix stages to save some math?
+ pipeline->append(SkRasterPipeline::matrix_2x3, m);
+ } else {
+ matrix.get9(m);
+ pipeline->append(SkRasterPipeline::matrix_perspective, m);
+ }
+
+ pipeline->extend(p);
+
+ const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag;
+ auto prepareColor = [premulGrad, dstCS, this](int i) {
+ SkColor4f c = dstCS ? to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS)
+ : SkColor4f_from_SkColor(fOrigColors[i], nullptr);
+ return premulGrad ? c.premul()
+ : SkPM4f::From4f(Sk4f::Load(&c));
+ };
+
+ // The two-stop case with stops at 0 and 1.
+ if (fColorCount == 2 && fOrigPos == nullptr) {
+ const SkPM4f c_l = prepareColor(0),
+ c_r = prepareColor(1);
+
+ // See F and B below.
+ auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2);
+ f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f());
+ f_and_b[1] = c_l;
+
+ pipeline->append(SkRasterPipeline::linear_gradient_2stops, f_and_b);
+ } else {
+
+ struct Stop { float t; SkPM4f f, b; };
+ struct Ctx { size_t n; Stop* stops; SkPM4f start; };
+
+ auto* ctx = alloc->make<Ctx>();
+ ctx->start = prepareColor(0);
+
+ // For each stop we calculate a bias B and a scale factor F, such that
+ // for any t between stops n and n+1, the color we want is B[n] + F[n]*t.
+ auto init_stop = [](float t_l, float t_r, SkPM4f c_l, SkPM4f c_r, Stop *stop) {
+ auto F = SkPM4f::From4f((c_r.to4f() - c_l.to4f()) / (t_r - t_l));
+ auto B = SkPM4f::From4f(c_l.to4f() - (F.to4f() * t_l));
+ *stop = {t_l, F, B};
+ };
+
+ if (fOrigPos == nullptr) {
+ // Handle evenly distributed stops.
+
+ float dt = 1.0f / (fColorCount - 1);
+ // In the evenly distributed case, fColorCount is the number of stops. There are no
+ // dummy entries.
+ auto* stopsArray = alloc->makeArrayDefault<Stop>(fColorCount);
+
+ float t_l = 0;
+ SkPM4f c_l = ctx->start;
+ for (int i = 0; i < fColorCount - 1; i++) {
+ // Use multiply instead of accumulating error using repeated addition.
+ float t_r = (i + 1) * dt;
+ SkPM4f c_r = prepareColor(i + 1);
+ init_stop(t_l, t_r, c_l, c_r, &stopsArray[i]);
+
+ t_l = t_r;
+ c_l = c_r;
+ }
+
+ // Force the last stop.
+ stopsArray[fColorCount - 1].t = 1;
+ stopsArray[fColorCount - 1].f = SkPM4f::From4f(Sk4f{0});
+ stopsArray[fColorCount - 1].b = prepareColor(fColorCount - 1);
+
+ ctx->n = fColorCount;
+ ctx->stops = stopsArray;
+ } else {
+ // Handle arbitrary stops.
+
+ // Remove the dummy stops inserted by SkGradientShaderBase::SkGradientShaderBase
+ // because they are naturally handled by the search method.
+ int firstStop;
+ int lastStop;
+ if (fColorCount > 2) {
+ firstStop = fOrigColors4f[0] != fOrigColors4f[1] ? 0 : 1;
+ lastStop = fOrigColors4f[fColorCount - 2] != fOrigColors4f[fColorCount - 1]
+ ? fColorCount - 1 : fColorCount - 2;
+ } else {
+ firstStop = 0;
+ lastStop = 1;
+ }
+ int realCount = lastStop - firstStop + 1;
+
+ // This is the maximum number of stops. There may be fewer stops because the duplicate
+ // points of hard stops are removed.
+ auto* stopsArray = alloc->makeArrayDefault<Stop>(realCount);
+
+ size_t stopCount = 0;
+ float t_l = fOrigPos[firstStop];
+ SkPM4f c_l = prepareColor(firstStop);
+ // N.B. lastStop is the index of the last stop, not one after.
+ for (int i = firstStop; i < lastStop; i++) {
+ float t_r = fOrigPos[i + 1];
+ SkPM4f c_r = prepareColor(i + 1);
+ if (t_l < t_r) {
+ init_stop(t_l, t_r, c_l, c_r, &stopsArray[stopCount]);
+ stopCount += 1;
+ }
+ t_l = t_r;
+ c_l = c_r;
+ }
+
+ stopsArray[stopCount].t = fOrigPos[lastStop];
+ stopsArray[stopCount].f = SkPM4f::From4f(Sk4f{0});
+ stopsArray[stopCount].b = prepareColor(lastStop);
+ stopCount += 1;
+
+ ctx->n = stopCount;
+ ctx->stops = stopsArray;
+ }
+
+ pipeline->append(SkRasterPipeline::linear_gradient, ctx);
+ }
+
+ if (!premulGrad && !this->colorsAreOpaque()) {
+ pipeline->append(SkRasterPipeline::premul);
+ }
+
+ return true;
+}
+
+
bool SkGradientShaderBase::isOpaque() const {
return fColorsAreOpaque;
}
@@ -1173,7 +1322,7 @@ GrGradientEffect::ColorType GrGradientEffect::determineColorType(
} else if (SkScalarNearlyEqual(shader.fOrigPos[0], 0.0f) &&
SkScalarNearlyEqual(shader.fOrigPos[1], 1.0f) &&
SkScalarNearlyEqual(shader.fOrigPos[2], 1.0f)) {
-
+
return kHardStopRightEdged_ColorType;
}
}
@@ -1369,7 +1518,7 @@ uint32_t GrGradientEffect::GLSLProcessor::GenBaseGradientKey(const GrProcessor&
} else if (GrGradientEffect::kHardStopRightEdged_ColorType == e.getColorType()) {
key |= kHardStopZeroOneOneKey;
}
-
+
if (SkShader::TileMode::kClamp_TileMode == e.fTileMode) {
key |= kClampTileMode;
} else if (SkShader::TileMode::kRepeat_TileMode == e.fTileMode) {
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 0feb44bfc8..8c188de39b 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -17,6 +17,8 @@
#include "SkColorPriv.h"
#include "SkColorSpace.h"
#include "SkOnce.h"
+#include "SkPM4fPriv.h"
+#include "SkRasterPipeline.h"
#include "SkReadBuffer.h"
#include "SkShader.h"
#include "SkUtils.h"
@@ -201,28 +203,21 @@ public:
uint32_t getGradFlags() const { return fGradFlags; }
protected:
+ struct Rec {
+ SkFixed fPos; // 0...1
+ uint32_t fScale; // (1 << 24) / range
+ };
+
class GradientShaderBase4fContext;
SkGradientShaderBase(SkReadBuffer& );
void flatten(SkWriteBuffer&) const override;
SK_TO_STRING_OVERRIDE()
- const SkMatrix fPtsToUnit;
- TileMode fTileMode;
- TileProc fTileProc;
- uint8_t fGradFlags;
-
- struct Rec {
- SkFixed fPos; // 0...1
- uint32_t fScale; // (1 << 24) / range
- };
- Rec* fRecs;
-
void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
bool onAsLuminanceColor(SkColor*) const override;
-
void initLinearBitmap(SkBitmap* bitmap) const;
/*
@@ -236,6 +231,14 @@ protected:
SkColor* colorSrc, Rec* recSrc,
int count);
+ bool onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc,
+ const SkMatrix& ctm, const SkPaint& paint,
+ const SkMatrix* localM) const override;
+
+ virtual bool adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
+ SkMatrix* matrix,
+ SkRasterPipeline* p) const { return false; }
+
template <typename T, typename... Args>
static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
@@ -245,6 +248,12 @@ protected:
return ctx;
}
+ const SkMatrix fPtsToUnit;
+ TileMode fTileMode;
+ TileProc fTileProc;
+ uint8_t fGradFlags;
+ Rec* fRecs;
+
private:
enum {
kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
@@ -277,6 +286,7 @@ private:
typedef SkShader INHERITED;
};
+
static inline int init_dither_toggle(int x, int y) {
x &= 1;
y = (y & 1) << 1;
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index 24cb1b592d..0b51da1ec1 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -83,178 +83,31 @@ SkShader::Context* SkLinearGradient::onMakeContext(
: CheckedMakeContext< LinearGradientContext>(alloc, *this, rec);
}
-//
-// Stages:
-//
-// * matrix (map dst -> grad space)
-// * clamp/repeat/mirror (tiling)
-// * linear_gradient_2stops (lerp c0/c1)
-// * optional premul
-//
-bool SkLinearGradient::onAppendStages(SkRasterPipeline* p,
- SkColorSpace* dstCS,
- SkArenaAlloc* alloc,
- const SkMatrix& ctm,
- const SkPaint& paint,
- const SkMatrix* localM) const {
- // Local matrix not supported currently. Remove once we have a generic RP wrapper.
- if (localM || !getLocalMatrix().isIdentity()) {
- return false;
- }
-
- SkMatrix dstToPts;
- if (!ctm.invert(&dstToPts)) {
- return false;
- }
-
- const auto dstToUnit = SkMatrix::Concat(fPtsToUnit, dstToPts);
-
- // If the gradient is less than a quarter of a pixel, this falls into the subpixel gradient code
- // handled on a different path.
- SkVector dx = dstToUnit.mapVector(1, 0);
- if (dx.fX >= 4) {
- return false;
- }
-
- auto* m = alloc->makeArrayDefault<float>(9);
- if (dstToUnit.asAffine(m)) {
- // TODO: mapping y is not needed; split the matrix stages to save some math?
- p->append(SkRasterPipeline::matrix_2x3, m);
- } else {
- dstToUnit.get9(m);
- p->append(SkRasterPipeline::matrix_perspective, m);
- }
+bool SkLinearGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
+ SkMatrix* matrix,
+ SkRasterPipeline* p) const {
+ *matrix = SkMatrix::Concat(fPtsToUnit, *matrix);
+ // If the gradient is less than a quarter of a pixel, this falls into the
+ // subpixel gradient code handled on a different path.
+ SkVector dx = matrix->mapVector(1, 0);
+ if (dx.fX >= 4) { return false; }
- // TODO: clamp/repeat/mirror const 1f stages?
auto* limit = alloc->make<float>(1.0f);
-
- const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag;
- auto prepareColor = [premulGrad, dstCS, this](int i) {
- SkColor4f c = dstCS ? to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS)
- : SkColor4f_from_SkColor(fOrigColors[i], nullptr);
- return premulGrad ? c.premul()
- : SkPM4f::From4f(Sk4f::Load(&c));
- };
-
- // The two-stop case with stops at 0 and 1.
if (fColorCount == 2 && fOrigPos == nullptr) {
switch (fTileMode) {
- case kClamp_TileMode: p->append(SkRasterPipeline:: clamp_x, limit); break;
+ case kClamp_TileMode: p->append(SkRasterPipeline::clamp_x, limit); break;
case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, limit); break;
case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, limit); break;
}
-
- const SkPM4f c_l = prepareColor(0),
- c_r = prepareColor(1);
-
- // See F and B below.
- auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2);
- f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f());
- f_and_b[1] = c_l;
-
- p->append(SkRasterPipeline::linear_gradient_2stops, f_and_b);
} else {
switch (fTileMode) {
// The search strategy does not need clamping. It has implicit hard stops at the
// first and last stop.
- case kClamp_TileMode: break;
+ case kClamp_TileMode: break;
case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, limit); break;
case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, limit); break;
}
-
- struct Stop { float t; SkPM4f f, b; };
- struct Ctx { size_t n; Stop* stops; SkPM4f start; };
-
- auto* ctx = alloc->make<Ctx>();
- ctx->start = prepareColor(0);
-
- // For each stop we calculate a bias B and a scale factor F, such that
- // for any t between stops n and n+1, the color we want is B[n] + F[n]*t.
- auto init_stop = [](float t_l, float t_r, SkPM4f c_l, SkPM4f c_r, Stop *stop) {
- auto F = SkPM4f::From4f((c_r.to4f() - c_l.to4f()) / (t_r - t_l));
- auto B = SkPM4f::From4f(c_l.to4f() - (F.to4f() * t_l));
- *stop = {t_l, F, B};
- };
-
- if (fOrigPos == nullptr) {
- // Handle evenly distributed stops.
-
- float dt = 1.0f / (fColorCount - 1);
- // In the evenly distributed case, fColorCount is the number of stops. There are no
- // dummy entries.
- auto* stopsArray = alloc->makeArrayDefault<Stop>(fColorCount);
-
- float t_l = 0;
- SkPM4f c_l = ctx->start;
- for (int i = 0; i < fColorCount - 1; i++) {
- // Use multiply instead of accumulating error using repeated addition.
- float t_r = (i + 1) * dt;
- SkPM4f c_r = prepareColor(i + 1);
- init_stop(t_l, t_r, c_l, c_r, &stopsArray[i]);
-
- t_l = t_r;
- c_l = c_r;
- }
-
- // Force the last stop.
- stopsArray[fColorCount - 1].t = 1;
- stopsArray[fColorCount - 1].f = SkPM4f::From4f(Sk4f{0});
- stopsArray[fColorCount - 1].b = prepareColor(fColorCount - 1);
-
- ctx->n = fColorCount;
- ctx->stops = stopsArray;
- } else {
- // Handle arbitrary stops.
-
- // Remove the dummy stops inserted by SkGradientShaderBase::SkGradientShaderBase
- // because they are naturally handled by the search method.
- int firstStop;
- int lastStop;
- if (fColorCount > 2) {
- firstStop = fOrigColors4f[0] != fOrigColors4f[1] ? 0 : 1;
- lastStop = fOrigColors4f[fColorCount - 2] != fOrigColors4f[fColorCount - 1]
- ? fColorCount - 1 : fColorCount - 2;
- } else {
- firstStop = 0;
- lastStop = 1;
- }
- int realCount = lastStop - firstStop + 1;
-
- // This is the maximum number of stops. There may be fewer stops because the duplicate
- // points of hard stops are removed.
- auto* stopsArray = alloc->makeArrayDefault<Stop>(realCount);
-
- size_t stopCount = 0;
- float t_l = fOrigPos[firstStop];
- SkPM4f c_l = prepareColor(firstStop);
- // N.B. lastStop is the index of the last stop, not one after.
- for (int i = firstStop; i < lastStop; i++) {
- float t_r = fOrigPos[i + 1];
- SkPM4f c_r = prepareColor(i + 1);
- if (t_l < t_r) {
- init_stop(t_l, t_r, c_l, c_r, &stopsArray[stopCount]);
- stopCount += 1;
- }
- t_l = t_r;
- c_l = c_r;
- }
-
- stopsArray[stopCount].t = fOrigPos[lastStop];
- stopsArray[stopCount].f = SkPM4f::From4f(Sk4f{0});
- stopsArray[stopCount].b = prepareColor(lastStop);
- stopCount += 1;
-
- ctx->n = stopCount;
- ctx->stops = stopsArray;
- }
-
- p->append(SkRasterPipeline::linear_gradient, ctx);
- }
-
- if (!premulGrad && !this->colorsAreOpaque()) {
- p->append(SkRasterPipeline::premul);
}
-
return true;
}
diff --git a/src/effects/gradients/SkLinearGradient.h b/src/effects/gradients/SkLinearGradient.h
index f860568147..19a965c7bb 100644
--- a/src/effects/gradients/SkLinearGradient.h
+++ b/src/effects/gradients/SkLinearGradient.h
@@ -68,8 +68,10 @@ protected:
void flatten(SkWriteBuffer& buffer) const override;
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
- bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
- const SkMatrix&, const SkPaint&, const SkMatrix*) const override;
+ bool adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
+ SkMatrix* matrix,
+ SkRasterPipeline* p) const final;
+
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index 71cdb9fe17..6a1a19f001 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -393,3 +393,12 @@ void SkRadialGradient::toString(SkString* str) const {
str->append(")");
}
#endif
+
+bool SkRadialGradient::onAppendStages(SkRasterPipeline* p,
+ SkColorSpace* dstCS,
+ SkArenaAlloc* alloc,
+ const SkMatrix& ctm,
+ const SkPaint& paint,
+ const SkMatrix* localM) const {
+ return SkShader::onAppendStages(p, dstCS, alloc, ctm, paint, localM);
+}
diff --git a/src/effects/gradients/SkRadialGradient.h b/src/effects/gradients/SkRadialGradient.h
index c43df09146..df1badd5ac 100644
--- a/src/effects/gradients/SkRadialGradient.h
+++ b/src/effects/gradients/SkRadialGradient.h
@@ -38,6 +38,9 @@ protected:
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
+ bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
+ const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM) const override;
+
private:
const SkPoint fCenter;
const SkScalar fRadius;
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index 81fdfe481b..b3a24cd16e 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -311,150 +311,12 @@ void SkSweepGradient::toString(SkString* str) const {
str->append(")");
}
-bool SkSweepGradient::onAppendStages(SkRasterPipeline* p,
- SkColorSpace* dstCS,
- SkArenaAlloc* alloc,
- const SkMatrix& ctm,
- const SkPaint& paint,
- const SkMatrix* localM) const {
- // Local matrix not supported currently. Remove once we have a generic RP wrapper.
- if (localM || !getLocalMatrix().isIdentity()) {
- return false;
- }
-
- SkMatrix dstToSrc;
- if (!ctm.invert(&dstToSrc)) {
- return false;
- }
-
- const auto dstToCenter = SkMatrix::Concat(
- SkMatrix::MakeTrans(-fCenter.fX, -fCenter.fY), dstToSrc);
-
- auto* m = alloc->makeArrayDefault<float>(9);
- if (dstToCenter.asAffine(m)) {
- // TODO: mapping y is not needed; split the matrix stages to save some math?
- p->append(SkRasterPipeline::matrix_2x3, m);
- } else {
- dstToCenter.get9(m);
- p->append(SkRasterPipeline::matrix_perspective, m);
- }
-
+bool SkSweepGradient::adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
+ SkMatrix* matrix,
+ SkRasterPipeline* p) const {
+ matrix->postTranslate(-fCenter.fX, -fCenter.fY);
p->append(SkRasterPipeline::xy_to_polar_unit);
- const bool premulGrad = fGradFlags & SkGradientShader::kInterpolateColorsInPremul_Flag;
- auto prepareColor = [premulGrad, dstCS, this](int i) {
- SkColor4f c = dstCS ? to_colorspace(fOrigColors4f[i], fColorSpace.get(), dstCS)
- : SkColor4f_from_SkColor(fOrigColors[i], nullptr);
- return premulGrad ? c.premul()
- : SkPM4f::From4f(Sk4f::Load(&c));
- };
-
- // The two-stop case with stops at 0 and 1.
- if (fColorCount == 2 && fOrigPos == nullptr) {
- const SkPM4f c_l = prepareColor(0),
- c_r = prepareColor(1);
-
- // See F and B below.
- auto* f_and_b = alloc->makeArrayDefault<SkPM4f>(2);
- f_and_b[0] = SkPM4f::From4f(c_r.to4f() - c_l.to4f());
- f_and_b[1] = c_l;
-
- p->append(SkRasterPipeline::linear_gradient_2stops, f_and_b);
- } else {
-
- struct Stop { float t; SkPM4f f, b; };
- struct Ctx { size_t n; Stop* stops; SkPM4f start; };
-
- auto* ctx = alloc->make<Ctx>();
- ctx->start = prepareColor(0);
-
- // For each stop we calculate a bias B and a scale factor F, such that
- // for any t between stops n and n+1, the color we want is B[n] + F[n]*t.
- auto init_stop = [](float t_l, float t_r, SkPM4f c_l, SkPM4f c_r, Stop *stop) {
- auto F = SkPM4f::From4f((c_r.to4f() - c_l.to4f()) / (t_r - t_l));
- auto B = SkPM4f::From4f(c_l.to4f() - (F.to4f() * t_l));
- *stop = {t_l, F, B};
- };
-
- if (fOrigPos == nullptr) {
- // Handle evenly distributed stops.
-
- float dt = 1.0f / (fColorCount - 1);
- // In the evenly distributed case, fColorCount is the number of stops. There are no
- // dummy entries.
- auto* stopsArray = alloc->makeArrayDefault<Stop>(fColorCount);
-
- float t_l = 0;
- SkPM4f c_l = ctx->start;
- for (int i = 0; i < fColorCount - 1; i++) {
- // Use multiply instead of accumulating error using repeated addition.
- float t_r = (i + 1) * dt;
- SkPM4f c_r = prepareColor(i + 1);
- init_stop(t_l, t_r, c_l, c_r, &stopsArray[i]);
-
- t_l = t_r;
- c_l = c_r;
- }
-
- // Force the last stop.
- stopsArray[fColorCount - 1].t = 1;
- stopsArray[fColorCount - 1].f = SkPM4f::From4f(Sk4f{0});
- stopsArray[fColorCount - 1].b = prepareColor(fColorCount - 1);
-
- ctx->n = fColorCount;
- ctx->stops = stopsArray;
- } else {
- // Handle arbitrary stops.
-
- // Remove the dummy stops inserted by SkGradientShaderBase::SkGradientShaderBase
- // because they are naturally handled by the search method.
- int firstStop;
- int lastStop;
- if (fColorCount > 2) {
- firstStop = fOrigColors4f[0] != fOrigColors4f[1] ? 0 : 1;
- lastStop = fOrigColors4f[fColorCount - 2] != fOrigColors4f[fColorCount - 1]
- ? fColorCount - 1 : fColorCount - 2;
- } else {
- firstStop = 0;
- lastStop = 1;
- }
- int realCount = lastStop - firstStop + 1;
-
- // This is the maximum number of stops. There may be fewer stops because the duplicate
- // points of hard stops are removed.
- auto* stopsArray = alloc->makeArrayDefault<Stop>(realCount);
-
- size_t stopCount = 0;
- float t_l = fOrigPos[firstStop];
- SkPM4f c_l = prepareColor(firstStop);
- // N.B. lastStop is the index of the last stop, not one after.
- for (int i = firstStop; i < lastStop; i++) {
- float t_r = fOrigPos[i + 1];
- SkPM4f c_r = prepareColor(i + 1);
- if (t_l < t_r) {
- init_stop(t_l, t_r, c_l, c_r, &stopsArray[stopCount]);
- stopCount += 1;
- }
- t_l = t_r;
- c_l = c_r;
- }
-
- stopsArray[stopCount].t = fOrigPos[lastStop];
- stopsArray[stopCount].f = SkPM4f::From4f(Sk4f{0});
- stopsArray[stopCount].b = prepareColor(lastStop);
- stopCount += 1;
-
- ctx->n = stopCount;
- ctx->stops = stopsArray;
- }
-
- p->append(SkRasterPipeline::linear_gradient, ctx);
- }
-
- if (!premulGrad && !this->colorsAreOpaque()) {
- p->append(SkRasterPipeline::premul);
- }
-
return true;
}
diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h
index 45c4233d88..5f12744b4d 100644
--- a/src/effects/gradients/SkSweepGradient.h
+++ b/src/effects/gradients/SkSweepGradient.h
@@ -38,9 +38,9 @@ protected:
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
- bool onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* space, SkArenaAlloc* alloc,
- const SkMatrix& matrix, const SkPaint& paint,
- const SkMatrix* localM) const override;
+ bool adjustMatrixAndAppendStages(SkArenaAlloc* alloc,
+ SkMatrix* matrix,
+ SkRasterPipeline* p) const final;
private:
const SkPoint fCenter;
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index ced299ee23..bc97700827 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -419,3 +419,12 @@ void SkTwoPointConicalGradient::toString(SkString* str) const {
str->append(")");
}
#endif
+
+bool SkTwoPointConicalGradient::onAppendStages(SkRasterPipeline* p,
+ SkColorSpace* dstCS,
+ SkArenaAlloc* alloc,
+ const SkMatrix& ctm,
+ const SkPaint& paint,
+ const SkMatrix* localM) const {
+ return SkShader::onAppendStages(p, dstCS, alloc, ctm, paint, localM);
+}
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.h b/src/effects/gradients/SkTwoPointConicalGradient.h
index b32f52c1e0..d5de47eb9a 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.h
+++ b/src/effects/gradients/SkTwoPointConicalGradient.h
@@ -79,6 +79,9 @@ protected:
Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
sk_sp<SkShader> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;
+ bool onAppendStages(SkRasterPipeline*, SkColorSpace* dstCS, SkArenaAlloc*,
+ const SkMatrix& ctm, const SkPaint&, const SkMatrix* localM) const override;
+
private:
SkPoint fCenter1;
SkPoint fCenter2;