diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 155 | ||||
-rw-r--r-- | src/effects/gradients/SkGradientShaderPriv.h | 34 | ||||
-rw-r--r-- | src/effects/gradients/SkLinearGradient.cpp | 167 | ||||
-rw-r--r-- | src/effects/gradients/SkLinearGradient.h | 6 | ||||
-rw-r--r-- | src/effects/gradients/SkRadialGradient.cpp | 9 | ||||
-rw-r--r-- | src/effects/gradients/SkRadialGradient.h | 3 | ||||
-rw-r--r-- | src/effects/gradients/SkSweepGradient.cpp | 146 | ||||
-rw-r--r-- | src/effects/gradients/SkSweepGradient.h | 6 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointConicalGradient.cpp | 9 | ||||
-rw-r--r-- | src/effects/gradients/SkTwoPointConicalGradient.h | 3 |
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; |