Tiling support for SkSweepGradient

Expand the sweep gradient definition to include a color stop angular range ([0, 360] by default).

Color stop positions in [0,1] are mapped to this range, and drawing outside is controlled by a
tile mode param.

This is closer to the CSS gradients spec and allows us to use fewer color stops in Blink conic
gradients.

Impl-wise, the remapping is effected after t calculation, and before tiling.

Change-Id: I5d71be01d134404d6eb9d7e2a904ec636b39f855
Reviewed-on: https://skia-review.googlesource.com/27704
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Florin Malita 2017-08-01 16:38:08 -04:00 committed by Skia Commit-Bot
parent ce06e261e6
commit 5a9a981edf
8 changed files with 207 additions and 68 deletions

View File

@ -1033,3 +1033,41 @@ DEF_SIMPLE_GM(fancy_gradients, canvas, 800, 300) {
SkBlendMode::kExclusion); SkBlendMode::kExclusion);
}); });
} }
DEF_SIMPLE_GM(sweep_tiling, canvas, 512, 512) {
static constexpr SkScalar size = 160;
static constexpr SkColor colors[] = { SK_ColorBLUE, SK_ColorYELLOW, SK_ColorGREEN };
static constexpr SkScalar pos[] = { 0, .25f, .50f };
static_assert(SK_ARRAY_COUNT(colors) == SK_ARRAY_COUNT(pos), "size mismatch");
static constexpr SkShader::TileMode modes[] = { SkShader::kClamp_TileMode,
SkShader::kRepeat_TileMode,
SkShader::kMirror_TileMode };
static const struct {
SkScalar start, end;
} angles[] = {
{ -330, -270 },
{ 30, 90 },
{ 390, 450 },
};
SkPaint p;
const SkRect r = SkRect::MakeWH(size, size);
for (auto mode : modes) {
{
SkAutoCanvasRestore acr(canvas, true);
for (auto angle : angles) {
p.setShader(SkGradientShader::MakeSweep(size / 2, size / 2, colors, pos,
SK_ARRAY_COUNT(colors), mode,
angle.start, angle.end, 0, nullptr));
canvas->drawRect(r, p);
canvas->translate(size * 1.1f, 0);
}
}
canvas->translate(0, size * 1.1f);
}
}

View File

@ -177,7 +177,8 @@ static sk_sp<SkShader> make_grad(SkShader::TileMode tx, SkShader::TileMode ty) {
case 1: case 1:
return SkGradientShader::MakeRadial(center, rad, colors, nullptr, SK_ARRAY_COUNT(colors), tx); return SkGradientShader::MakeRadial(center, rad, colors, nullptr, SK_ARRAY_COUNT(colors), tx);
case 2: case 2:
return SkGradientShader::MakeSweep(center.fX, center.fY, colors, nullptr, SK_ARRAY_COUNT(colors)); return SkGradientShader::MakeSweep(center.fX, center.fY, colors, nullptr,
SK_ARRAY_COUNT(colors), tx, 135, 225, 0, nullptr);
} }
return nullptr; return nullptr;
} }

View File

@ -199,10 +199,11 @@ private:
// V54: ComposeShader can use a Mode or a Lerp // V54: ComposeShader can use a Mode or a Lerp
// V55: Drop blendmode[] from MergeImageFilter // V55: Drop blendmode[] from MergeImageFilter
// V56: Add TileMode in SkBlurImageFilter. // V56: Add TileMode in SkBlurImageFilter.
// V57: Sweep tiling info.
// Only SKPs within the min/current picture version range (inclusive) can be read. // Only SKPs within the min/current picture version range (inclusive) can be read.
static const uint32_t MIN_PICTURE_VERSION = 51; // Produced by Chrome ~M56. static const uint32_t MIN_PICTURE_VERSION = 51; // Produced by Chrome ~M56.
static const uint32_t CURRENT_PICTURE_VERSION = 56; static const uint32_t CURRENT_PICTURE_VERSION = 57;
static bool IsValidPictInfo(const SkPictInfo& info); static bool IsValidPictInfo(const SkPictInfo& info);
static sk_sp<SkPicture> Forwardport(const SkPictInfo&, static sk_sp<SkPicture> Forwardport(const SkPictInfo&,

View File

@ -158,44 +158,69 @@ public:
/** Returns a shader that generates a sweep gradient given a center. /** Returns a shader that generates a sweep gradient given a center.
<p /> <p />
@param cx The X coordinate of the center of the sweep @param cx The X coordinate of the center of the sweep
@param cx The Y coordinate of the center of the sweep @param cx The Y coordinate of the center of the sweep
@param colors The array[count] of colors, to be distributed around the center. @param colors The array[count] of colors, to be distributed around the center, within
@param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of the gradient angle range.
each corresponding color in the colors array. If this is NULL, @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative
the the colors are distributed evenly between the center and edge of the circle. position of each corresponding color in the colors array. If this is
If this is not null, the values must begin with 0, end with 1.0, and NULL, then the colors are distributed evenly within the angular range.
intermediate values must be strictly increasing. If this is not null, the values must begin with 0, end with 1.0, and
@param count Must be >= 2. The number of colors (and pos if not NULL) entries intermediate values must be strictly increasing.
@param count Must be >= 2. The number of colors (and pos if not NULL) entries
@param mode Tiling mode: controls drawing outside of the gradient angular range.
@param startAngle Start of the angular range, corresponding to pos == 0.
@param endAngle End of the angular range, corresponding to pos == 1.
*/ */
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy, static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor colors[], const SkScalar pos[], int count, const SkColor colors[], const SkScalar pos[], int count,
SkShader::TileMode mode,
SkScalar startAngle, SkScalar endAngle,
uint32_t flags, const SkMatrix* localMatrix); uint32_t flags, const SkMatrix* localMatrix);
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor colors[], const SkScalar pos[], int count,
uint32_t flags, const SkMatrix* localMatrix) {
return MakeSweep(cx, cy, colors, pos, count, SkShader::kClamp_TileMode, 0, 360, flags,
localMatrix);
}
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy, static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor colors[], const SkScalar pos[], int count) { const SkColor colors[], const SkScalar pos[], int count) {
return MakeSweep(cx, cy, colors, pos, count, 0, NULL); return MakeSweep(cx, cy, colors, pos, count, 0, nullptr);
} }
/** Returns a shader that generates a sweep gradient given a center. /** Returns a shader that generates a sweep gradient given a center.
<p /> <p />
@param cx The X coordinate of the center of the sweep @param cx The X coordinate of the center of the sweep
@param cx The Y coordinate of the center of the sweep @param cx The Y coordinate of the center of the sweep
@param colors The array[count] of colors, to be distributed around the center. @param colors The array[count] of colors, to be distributed around the center, within
@param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of the gradient angle range.
each corresponding color in the colors array. If this is NULL, @param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative
the the colors are distributed evenly between the center and edge of the circle. position of each corresponding color in the colors array. If this is
If this is not null, the values must begin with 0, end with 1.0, and NULL, then the colors are distributed evenly within the angular range.
intermediate values must be strictly increasing. If this is not null, the values must begin with 0, end with 1.0, and
@param count Must be >= 2. The number of colors (and pos if not NULL) entries intermediate values must be strictly increasing.
@param count Must be >= 2. The number of colors (and pos if not NULL) entries
@param mode Tiling mode: controls drawing outside of the gradient angular range.
@param startAngle Start of the angular range, corresponding to pos == 0.
@param endAngle End of the angular range, corresponding to pos == 1.
*/ */
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy, static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace, const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count, const SkScalar pos[], int count,
SkShader::TileMode mode,
SkScalar startAngle, SkScalar endAngle,
uint32_t flags, const SkMatrix* localMatrix); uint32_t flags, const SkMatrix* localMatrix);
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count,
uint32_t flags, const SkMatrix* localMatrix) {
return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count,
SkShader::kClamp_TileMode, 0, 360, flags, localMatrix);
}
static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy, static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace, const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], int count) { const SkScalar pos[], int count) {
return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, 0, NULL); return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, 0, nullptr);
} }
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()

View File

@ -74,6 +74,7 @@ public:
kComposeShaderCanLerp_Version = 54, kComposeShaderCanLerp_Version = 54,
kNoModesInMergeImageFilter_Verison = 55, kNoModesInMergeImageFilter_Verison = 55,
kTileModeInBlurImageFilter_Version = 56, kTileModeInBlurImageFilter_Version = 56,
kTileInfoInSweepGradient_Version = 57,
}; };
/** /**

View File

@ -1228,11 +1228,14 @@ sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy,
const SkColor colors[], const SkColor colors[],
const SkScalar pos[], const SkScalar pos[],
int colorCount, int colorCount,
SkShader::TileMode mode,
SkScalar startAngle,
SkScalar endAngle,
uint32_t flags, uint32_t flags,
const SkMatrix* localMatrix) { const SkMatrix* localMatrix) {
ColorConverter converter(colors, colorCount); ColorConverter converter(colors, colorCount);
return MakeSweep(cx, cy, converter.fColors4f.begin(), nullptr, pos, colorCount, flags, return MakeSweep(cx, cy, converter.fColors4f.begin(), nullptr, pos, colorCount,
localMatrix); mode, startAngle, endAngle, flags, localMatrix);
} }
sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy, sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy,
@ -1240,26 +1243,39 @@ sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy,
sk_sp<SkColorSpace> colorSpace, sk_sp<SkColorSpace> colorSpace,
const SkScalar pos[], const SkScalar pos[],
int colorCount, int colorCount,
SkShader::TileMode mode,
SkScalar startAngle,
SkScalar endAngle,
uint32_t flags, uint32_t flags,
const SkMatrix* localMatrix) { const SkMatrix* localMatrix) {
if (!valid_grad(colors, pos, colorCount, SkShader::kClamp_TileMode)) { if (!valid_grad(colors, pos, colorCount, mode)) {
return nullptr; return nullptr;
} }
if (1 == colorCount) { if (1 == colorCount) {
return SkShader::MakeColorShader(colors[0], std::move(colorSpace)); return SkShader::MakeColorShader(colors[0], std::move(colorSpace));
} }
if (startAngle >= endAngle) {
return nullptr;
}
if (localMatrix && !localMatrix->invert(nullptr)) { if (localMatrix && !localMatrix->invert(nullptr)) {
return nullptr; return nullptr;
} }
auto mode = SkShader::kClamp_TileMode; if (startAngle <= 0 && endAngle >= 360) {
// If the t-range includes [0,1], then we can always use clamping (presumably faster).
mode = SkShader::kClamp_TileMode;
}
ColorStopOptimizer opt(colors, pos, colorCount, mode); ColorStopOptimizer opt(colors, pos, colorCount, mode);
SkGradientShaderBase::Descriptor desc; SkGradientShaderBase::Descriptor desc;
desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags, desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags,
localMatrix); localMatrix);
return sk_make_sp<SkSweepGradient>(cx, cy, desc);
const SkScalar t0 = startAngle / 360,
t1 = endAngle / 360;
return sk_make_sp<SkSweepGradient>(SkPoint::Make(cx, cy), t0, t1, desc);
} }
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader)

View File

@ -11,18 +11,14 @@
#include "SkPM4fPriv.h" #include "SkPM4fPriv.h"
#include "SkRasterPipeline.h" #include "SkRasterPipeline.h"
static SkMatrix translate(SkScalar dx, SkScalar dy) { SkSweepGradient::SkSweepGradient(const SkPoint& center, SkScalar t0, SkScalar t1,
SkMatrix matrix; const Descriptor& desc)
matrix.setTranslate(dx, dy); : SkGradientShaderBase(desc, SkMatrix::MakeTrans(-center.x(), -center.y()))
return matrix; , fCenter(center)
} , fTBias(-t0)
, fTScale(1 / (t1 - t0))
SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor& desc)
: SkGradientShaderBase(desc, translate(-cx, -cy))
, fCenter(SkPoint::Make(cx, cy))
{ {
// overwrite the tilemode to a canonical value (since sweep ignores it) SkASSERT(t0 < t1);
fTileMode = SkShader::kClamp_TileMode;
} }
SkShader::GradientType SkSweepGradient::asAGradient(GradientInfo* info) const { SkShader::GradientType SkSweepGradient::asAGradient(GradientInfo* info) const {
@ -39,14 +35,27 @@ sk_sp<SkFlattenable> SkSweepGradient::CreateProc(SkReadBuffer& buffer) {
return nullptr; return nullptr;
} }
const SkPoint center = buffer.readPoint(); const SkPoint center = buffer.readPoint();
SkScalar startAngle = 0,
endAngle = 360;
if (!buffer.isVersionLT(SkReadBuffer::kTileInfoInSweepGradient_Version)) {
const auto tBias = buffer.readScalar(),
tScale = buffer.readScalar();
startAngle = -tBias * 360;
endAngle = (1 / tScale - tBias) * 360;
}
return SkGradientShader::MakeSweep(center.x(), center.y(), desc.fColors, return SkGradientShader::MakeSweep(center.x(), center.y(), desc.fColors,
std::move(desc.fColorSpace), desc.fPos, desc.fCount, std::move(desc.fColorSpace), desc.fPos, desc.fCount,
desc.fTileMode, startAngle, endAngle,
desc.fGradFlags, desc.fLocalMatrix); desc.fGradFlags, desc.fLocalMatrix);
} }
void SkSweepGradient::flatten(SkWriteBuffer& buffer) const { void SkSweepGradient::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
buffer.writePoint(fCenter); buffer.writePoint(fCenter);
buffer.writeScalar(fTBias);
buffer.writeScalar(fTScale);
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -62,8 +71,9 @@ class GrSweepGradient : public GrGradientEffect {
public: public:
class GLSLSweepProcessor; class GLSLSweepProcessor;
static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args) { static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar tBias,
auto processor = sk_sp<GrSweepGradient>(new GrSweepGradient(args)); SkScalar tScale) {
auto processor = sk_sp<GrSweepGradient>(new GrSweepGradient(args, tBias, tScale));
return processor->isValid() ? std::move(processor) : nullptr; return processor->isValid() ? std::move(processor) : nullptr;
} }
@ -74,12 +84,17 @@ public:
} }
private: private:
explicit GrSweepGradient(const CreateArgs& args) explicit GrSweepGradient(const CreateArgs& args, SkScalar tBias, SkScalar tScale)
: INHERITED(args, args.fShader->colorsAreOpaque()) { : INHERITED(args, args.fShader->colorsAreOpaque())
, fTBias(tBias)
, fTScale(tScale){
this->initClassID<GrSweepGradient>(); this->initClassID<GrSweepGradient>();
} }
explicit GrSweepGradient(const GrSweepGradient& that) : INHERITED(that) { explicit GrSweepGradient(const GrSweepGradient& that)
: INHERITED(that)
, fTBias(that.fTBias)
, fTScale(that.fTScale) {
this->initClassID<GrSweepGradient>(); this->initClassID<GrSweepGradient>();
} }
@ -88,8 +103,18 @@ private:
virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps, virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const override; GrProcessorKeyBuilder* b) const override;
bool onIsEqual(const GrFragmentProcessor& base) const override {
const GrSweepGradient& fp = base.cast<GrSweepGradient>();
return INHERITED::onIsEqual(base)
&& fTBias == fp.fTBias
&& fTScale == fp.fTScale;
}
GR_DECLARE_FRAGMENT_PROCESSOR_TEST GR_DECLARE_FRAGMENT_PROCESSOR_TEST
SkScalar fTBias;
SkScalar fTScale;
typedef GrGradientEffect INHERITED; typedef GrGradientEffect INHERITED;
}; };
@ -97,17 +122,38 @@ private:
class GrSweepGradient::GLSLSweepProcessor : public GrGradientEffect::GLSLProcessor { class GrSweepGradient::GLSLSweepProcessor : public GrGradientEffect::GLSLProcessor {
public: public:
GLSLSweepProcessor(const GrProcessor&) {} GLSLSweepProcessor(const GrProcessor&)
: fCachedTBias(SK_FloatNaN)
, fCachedTScale(SK_FloatNaN) {}
virtual void emitCode(EmitArgs&) override; void emitCode(EmitArgs&) override;
static void GenKey(const GrProcessor& processor, const GrShaderCaps&, GrProcessorKeyBuilder* b) { static void GenKey(const GrProcessor& processor, const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
b->add32(GenBaseGradientKey(processor)); b->add32(GenBaseGradientKey(processor));
} }
private: protected:
typedef GrGradientEffect::GLSLProcessor INHERITED; void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& processor) override {
INHERITED::onSetData(pdman, processor);
const GrSweepGradient& data = processor.cast<GrSweepGradient>();
if (fCachedTBias != data.fTBias || fCachedTScale != data.fTScale) {
fCachedTBias = data.fTBias;
fCachedTScale = data.fTScale;
pdman.set2f(fTBiasScaleUni, fCachedTBias, fCachedTScale);
}
}
private:
UniformHandle fTBiasScaleUni;
// Uploaded uniform values.
float fCachedTBias,
fCachedTScale;
typedef GrGradientEffect::GLSLProcessor INHERITED;
}; };
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -147,22 +193,28 @@ sk_sp<GrFragmentProcessor> GrSweepGradient::TestCreate(GrProcessorTestData* d) {
void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) { void GrSweepGradient::GLSLSweepProcessor::emitCode(EmitArgs& args) {
const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>(); const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
this->emitUniforms(args.fUniformHandler, ge); GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]); this->emitUniforms(uniformHandler, ge);
SkString t; fTBiasScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType,
kDefault_GrSLPrecision, "SweepFSParams");
const char* tBiasScaleV = uniformHandler->getUniformCStr(fTBiasScaleUni);
const SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
// On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is
// atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in
// (sqrt(x^2 + y^2) + x) as the second parameter to atan2 in these cases. We let the device
// handle the undefined behavior of the second paramenter being 0 instead of doing the
// divide ourselves and using atan instead.
const SkString atan = args.fShaderCaps->atan2ImplementedAsAtanYOverX()
? SkStringPrintf("2.0 * atan(- %s.y, length(%s) - %s.x)",
coords2D.c_str(), coords2D.c_str(), coords2D.c_str())
: SkStringPrintf("atan(- %s.y, - %s.x)", coords2D.c_str(), coords2D.c_str());
// 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi] // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
if (args.fShaderCaps->atan2ImplementedAsAtanYOverX()) { const SkString t = SkStringPrintf("((%s * 0.1591549430918 + 0.5 + %s[0]) * %s[1])",
// On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is atan.c_str(), tBiasScaleV, tBiasScaleV);
// atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in
// (sqrt(x^2 + y^2) + x) as the second parameter to atan2 in these cases. We let the device
// handle the undefined behavior of the second paramenter being 0 instead of doing the
// divide ourselves and using atan instead.
t.printf("(2.0 * atan(- %s.y, length(%s) - %s.x) * 0.1591549430918 + 0.5)",
coords2D.c_str(), coords2D.c_str(), coords2D.c_str());
} else {
t.printf("(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5)",
coords2D.c_str(), coords2D.c_str());
}
this->emitColor(args.fFragBuilder, this->emitColor(args.fFragBuilder,
args.fUniformHandler, args.fUniformHandler,
args.fShaderCaps, args.fShaderCaps,
@ -192,8 +244,9 @@ sk_sp<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(const AsFPArgs&
sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(), sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
args.fDstColorSpace); args.fDstColorSpace);
sk_sp<GrFragmentProcessor> inner(GrSweepGradient::Make( sk_sp<GrFragmentProcessor> inner(GrSweepGradient::Make(
GrGradientEffect::CreateArgs(args.fContext, this, &matrix, SkShader::kClamp_TileMode, GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode,
std::move(colorSpaceXform), SkToBool(args.fDstColorSpace)))); std::move(colorSpaceXform), SkToBool(args.fDstColorSpace)),
fTBias, fTScale));
if (!inner) { if (!inner) {
return nullptr; return nullptr;
} }
@ -224,9 +277,11 @@ void SkSweepGradient::toString(SkString* str) const {
str->append(")"); str->append(")");
} }
void SkSweepGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline* p, void SkSweepGradient::appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* p,
SkRasterPipeline*) const { SkRasterPipeline*) const {
p->append(SkRasterPipeline::xy_to_unit_angle); p->append(SkRasterPipeline::xy_to_unit_angle);
p->append_matrix(alloc, SkMatrix::Concat(SkMatrix::MakeScale(fTScale, 1),
SkMatrix::MakeTrans(fTBias , 0)));
} }
#endif #endif

View File

@ -12,7 +12,7 @@
class SkSweepGradient final : public SkGradientShaderBase { class SkSweepGradient final : public SkGradientShaderBase {
public: public:
SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&); SkSweepGradient(const SkPoint& center, SkScalar t0, SkScalar t1, const Descriptor&);
GradientType asAGradient(GradientInfo* info) const override; GradientType asAGradient(GradientInfo* info) const override;
@ -33,7 +33,9 @@ protected:
bool onIsRasterPipelineOnly() const override { return true; } bool onIsRasterPipelineOnly() const override { return true; }
private: private:
const SkPoint fCenter; const SkPoint fCenter;
const SkScalar fTBias,
fTScale;
friend class SkGradientShader; friend class SkGradientShader;
typedef SkGradientShaderBase INHERITED; typedef SkGradientShaderBase INHERITED;