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:
parent
ce06e261e6
commit
5a9a981edf
@ -1033,3 +1033,41 @@ DEF_SIMPLE_GM(fancy_gradients, canvas, 800, 300) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -177,7 +177,8 @@ static sk_sp<SkShader> make_grad(SkShader::TileMode tx, SkShader::TileMode ty) {
|
||||
case 1:
|
||||
return SkGradientShader::MakeRadial(center, rad, colors, nullptr, SK_ARRAY_COUNT(colors), tx);
|
||||
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;
|
||||
}
|
||||
|
@ -199,10 +199,11 @@ private:
|
||||
// V54: ComposeShader can use a Mode or a Lerp
|
||||
// V55: Drop blendmode[] from MergeImageFilter
|
||||
// V56: Add TileMode in SkBlurImageFilter.
|
||||
// V57: Sweep tiling info.
|
||||
|
||||
// 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 CURRENT_PICTURE_VERSION = 56;
|
||||
static const uint32_t CURRENT_PICTURE_VERSION = 57;
|
||||
|
||||
static bool IsValidPictInfo(const SkPictInfo& info);
|
||||
static sk_sp<SkPicture> Forwardport(const SkPictInfo&,
|
||||
|
@ -158,44 +158,69 @@ public:
|
||||
|
||||
/** Returns a shader that generates a sweep gradient given a center.
|
||||
<p />
|
||||
@param cx The X 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 pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
|
||||
each corresponding color in the colors array. If this is NULL,
|
||||
the the colors are distributed evenly between the center and edge of the circle.
|
||||
If this is not null, the values must begin with 0, end with 1.0, and
|
||||
intermediate values must be strictly increasing.
|
||||
@param count Must be >= 2. The number of colors (and pos if not NULL) entries
|
||||
@param cx The X 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, within
|
||||
the gradient angle range.
|
||||
@param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative
|
||||
position of each corresponding color in the colors array. If this is
|
||||
NULL, then the colors are distributed evenly within the angular range.
|
||||
If this is not null, the values must begin with 0, end with 1.0, and
|
||||
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,
|
||||
const SkColor colors[], const SkScalar pos[], int count,
|
||||
SkShader::TileMode mode,
|
||||
SkScalar startAngle, SkScalar endAngle,
|
||||
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,
|
||||
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.
|
||||
<p />
|
||||
@param cx The X 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 pos May be NULL. The array[count] of SkScalars, or NULL, of the relative position of
|
||||
each corresponding color in the colors array. If this is NULL,
|
||||
the the colors are distributed evenly between the center and edge of the circle.
|
||||
If this is not null, the values must begin with 0, end with 1.0, and
|
||||
intermediate values must be strictly increasing.
|
||||
@param count Must be >= 2. The number of colors (and pos if not NULL) entries
|
||||
@param cx The X 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, within
|
||||
the gradient angle range.
|
||||
@param pos May be NULL. The array[count] of SkScalars, or NULL, of the relative
|
||||
position of each corresponding color in the colors array. If this is
|
||||
NULL, then the colors are distributed evenly within the angular range.
|
||||
If this is not null, the values must begin with 0, end with 1.0, and
|
||||
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,
|
||||
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
|
||||
const SkScalar pos[], int count,
|
||||
SkShader::TileMode mode,
|
||||
SkScalar startAngle, SkScalar endAngle,
|
||||
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,
|
||||
const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,
|
||||
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()
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
kComposeShaderCanLerp_Version = 54,
|
||||
kNoModesInMergeImageFilter_Verison = 55,
|
||||
kTileModeInBlurImageFilter_Version = 56,
|
||||
kTileInfoInSweepGradient_Version = 57,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1228,11 +1228,14 @@ sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy,
|
||||
const SkColor colors[],
|
||||
const SkScalar pos[],
|
||||
int colorCount,
|
||||
SkShader::TileMode mode,
|
||||
SkScalar startAngle,
|
||||
SkScalar endAngle,
|
||||
uint32_t flags,
|
||||
const SkMatrix* localMatrix) {
|
||||
ColorConverter converter(colors, colorCount);
|
||||
return MakeSweep(cx, cy, converter.fColors4f.begin(), nullptr, pos, colorCount, flags,
|
||||
localMatrix);
|
||||
return MakeSweep(cx, cy, converter.fColors4f.begin(), nullptr, pos, colorCount,
|
||||
mode, startAngle, endAngle, flags, localMatrix);
|
||||
}
|
||||
|
||||
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,
|
||||
const SkScalar pos[],
|
||||
int colorCount,
|
||||
SkShader::TileMode mode,
|
||||
SkScalar startAngle,
|
||||
SkScalar endAngle,
|
||||
uint32_t flags,
|
||||
const SkMatrix* localMatrix) {
|
||||
if (!valid_grad(colors, pos, colorCount, SkShader::kClamp_TileMode)) {
|
||||
if (!valid_grad(colors, pos, colorCount, mode)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (1 == colorCount) {
|
||||
return SkShader::MakeColorShader(colors[0], std::move(colorSpace));
|
||||
}
|
||||
if (startAngle >= endAngle) {
|
||||
return nullptr;
|
||||
}
|
||||
if (localMatrix && !localMatrix->invert(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);
|
||||
|
||||
SkGradientShaderBase::Descriptor desc;
|
||||
desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags,
|
||||
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)
|
||||
|
@ -11,18 +11,14 @@
|
||||
#include "SkPM4fPriv.h"
|
||||
#include "SkRasterPipeline.h"
|
||||
|
||||
static SkMatrix translate(SkScalar dx, SkScalar dy) {
|
||||
SkMatrix matrix;
|
||||
matrix.setTranslate(dx, dy);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
SkSweepGradient::SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor& desc)
|
||||
: SkGradientShaderBase(desc, translate(-cx, -cy))
|
||||
, fCenter(SkPoint::Make(cx, cy))
|
||||
SkSweepGradient::SkSweepGradient(const SkPoint& center, SkScalar t0, SkScalar t1,
|
||||
const Descriptor& desc)
|
||||
: SkGradientShaderBase(desc, SkMatrix::MakeTrans(-center.x(), -center.y()))
|
||||
, fCenter(center)
|
||||
, fTBias(-t0)
|
||||
, fTScale(1 / (t1 - t0))
|
||||
{
|
||||
// overwrite the tilemode to a canonical value (since sweep ignores it)
|
||||
fTileMode = SkShader::kClamp_TileMode;
|
||||
SkASSERT(t0 < t1);
|
||||
}
|
||||
|
||||
SkShader::GradientType SkSweepGradient::asAGradient(GradientInfo* info) const {
|
||||
@ -39,14 +35,27 @@ sk_sp<SkFlattenable> SkSweepGradient::CreateProc(SkReadBuffer& buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
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,
|
||||
std::move(desc.fColorSpace), desc.fPos, desc.fCount,
|
||||
desc.fTileMode, startAngle, endAngle,
|
||||
desc.fGradFlags, desc.fLocalMatrix);
|
||||
}
|
||||
|
||||
void SkSweepGradient::flatten(SkWriteBuffer& buffer) const {
|
||||
this->INHERITED::flatten(buffer);
|
||||
buffer.writePoint(fCenter);
|
||||
buffer.writeScalar(fTBias);
|
||||
buffer.writeScalar(fTScale);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -62,8 +71,9 @@ class GrSweepGradient : public GrGradientEffect {
|
||||
public:
|
||||
class GLSLSweepProcessor;
|
||||
|
||||
static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args) {
|
||||
auto processor = sk_sp<GrSweepGradient>(new GrSweepGradient(args));
|
||||
static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar tBias,
|
||||
SkScalar tScale) {
|
||||
auto processor = sk_sp<GrSweepGradient>(new GrSweepGradient(args, tBias, tScale));
|
||||
return processor->isValid() ? std::move(processor) : nullptr;
|
||||
}
|
||||
|
||||
@ -74,12 +84,17 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
explicit GrSweepGradient(const CreateArgs& args)
|
||||
: INHERITED(args, args.fShader->colorsAreOpaque()) {
|
||||
explicit GrSweepGradient(const CreateArgs& args, SkScalar tBias, SkScalar tScale)
|
||||
: INHERITED(args, args.fShader->colorsAreOpaque())
|
||||
, fTBias(tBias)
|
||||
, fTScale(tScale){
|
||||
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>();
|
||||
}
|
||||
|
||||
@ -88,8 +103,18 @@ private:
|
||||
virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
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
|
||||
|
||||
SkScalar fTBias;
|
||||
SkScalar fTScale;
|
||||
|
||||
typedef GrGradientEffect INHERITED;
|
||||
};
|
||||
|
||||
@ -97,17 +122,38 @@ private:
|
||||
|
||||
class GrSweepGradient::GLSLSweepProcessor : public GrGradientEffect::GLSLProcessor {
|
||||
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));
|
||||
}
|
||||
|
||||
private:
|
||||
typedef GrGradientEffect::GLSLProcessor INHERITED;
|
||||
protected:
|
||||
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) {
|
||||
const GrSweepGradient& ge = args.fFp.cast<GrSweepGradient>();
|
||||
this->emitUniforms(args.fUniformHandler, ge);
|
||||
SkString coords2D = args.fFragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
|
||||
SkString t;
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
this->emitUniforms(uniformHandler, ge);
|
||||
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]
|
||||
if (args.fShaderCaps->atan2ImplementedAsAtanYOverX()) {
|
||||
// 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.
|
||||
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());
|
||||
}
|
||||
const SkString t = SkStringPrintf("((%s * 0.1591549430918 + 0.5 + %s[0]) * %s[1])",
|
||||
atan.c_str(), tBiasScaleV, tBiasScaleV);
|
||||
|
||||
this->emitColor(args.fFragBuilder,
|
||||
args.fUniformHandler,
|
||||
args.fShaderCaps,
|
||||
@ -192,8 +244,9 @@ sk_sp<GrFragmentProcessor> SkSweepGradient::asFragmentProcessor(const AsFPArgs&
|
||||
sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
|
||||
args.fDstColorSpace);
|
||||
sk_sp<GrFragmentProcessor> inner(GrSweepGradient::Make(
|
||||
GrGradientEffect::CreateArgs(args.fContext, this, &matrix, SkShader::kClamp_TileMode,
|
||||
std::move(colorSpaceXform), SkToBool(args.fDstColorSpace))));
|
||||
GrGradientEffect::CreateArgs(args.fContext, this, &matrix, fTileMode,
|
||||
std::move(colorSpaceXform), SkToBool(args.fDstColorSpace)),
|
||||
fTBias, fTScale));
|
||||
if (!inner) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -224,9 +277,11 @@ void SkSweepGradient::toString(SkString* str) const {
|
||||
str->append(")");
|
||||
}
|
||||
|
||||
void SkSweepGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline* p,
|
||||
void SkSweepGradient::appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* p,
|
||||
SkRasterPipeline*) const {
|
||||
p->append(SkRasterPipeline::xy_to_unit_angle);
|
||||
p->append_matrix(alloc, SkMatrix::Concat(SkMatrix::MakeScale(fTScale, 1),
|
||||
SkMatrix::MakeTrans(fTBias , 0)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
class SkSweepGradient final : public SkGradientShaderBase {
|
||||
public:
|
||||
SkSweepGradient(SkScalar cx, SkScalar cy, const Descriptor&);
|
||||
SkSweepGradient(const SkPoint& center, SkScalar t0, SkScalar t1, const Descriptor&);
|
||||
|
||||
GradientType asAGradient(GradientInfo* info) const override;
|
||||
|
||||
@ -33,7 +33,9 @@ protected:
|
||||
bool onIsRasterPipelineOnly() const override { return true; }
|
||||
|
||||
private:
|
||||
const SkPoint fCenter;
|
||||
const SkPoint fCenter;
|
||||
const SkScalar fTBias,
|
||||
fTScale;
|
||||
|
||||
friend class SkGradientShader;
|
||||
typedef SkGradientShaderBase INHERITED;
|
||||
|
Loading…
Reference in New Issue
Block a user