50 kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag,
51 kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag,
52 kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag,
53 kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
55 kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag |
56 kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
64 uint32_t circularCornerFlags,
const SkRRect&);
66 ~CircularRRectEffect()
override {}
68 const char*
name()
const override {
return "CircularRRect"; }
70 std::unique_ptr<GrFragmentProcessor>
clone()
const override;
75 CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
77 CircularRRectEffect(
const CircularRRectEffect& that);
79 std::unique_ptr<ProgramImpl> onMakeProgramImpl()
const override;
87 uint32_t fCircularCornerFlags;
101 return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
102 new CircularRRectEffect(std::move(inputFP), edgeType, circularCornerFlags,
rrect)));
105CircularRRectEffect::CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
107 uint32_t circularCornerFlags,
109 :
INHERITED(kCircularRRectEffect_ClassID,
110 ProcessorOptimizationFlags(inputFP.
get()) &
111 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
113 , fEdgeType(edgeType)
114 , fCircularCornerFlags(circularCornerFlags) {
115 this->registerChild(std::move(inputFP));
118CircularRRectEffect::CircularRRectEffect(
const CircularRRectEffect& that)
121 , fEdgeType(that.fEdgeType)
122 , fCircularCornerFlags(that.fCircularCornerFlags) {}
124std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::clone()
const {
125 return std::unique_ptr<GrFragmentProcessor>(
new CircularRRectEffect(*
this));
129 const CircularRRectEffect& crre = other.
cast<CircularRRectEffect>();
131 return fEdgeType == crre.fEdgeType &&
fRRect == crre.fRRect;
138#if defined(GR_TEST_UTILS)
139std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::TestCreate(GrProcessorTestData*
d) {
140 SkScalar w =
d->fRandom->nextRangeScalar(20.f, 1000.f);
141 SkScalar h =
d->fRandom->nextRangeScalar(20.f, 1000.f);
145 std::unique_ptr<GrFragmentProcessor>
fp =
d->inputFP();
151 *
d->caps()->shaderCaps());
166 GrGLSLProgramDataManager::UniformHandle fInnerRectUniform;
167 GrGLSLProgramDataManager::UniformHandle fRadiusPlusHalfUniform;
172 const CircularRRectEffect& crre =
args.fFp.cast<CircularRRectEffect>();
174 const char *rectName;
175 const char *radiusPlusHalfName;
181 "innerRect", &rectName);
185 &radiusPlusHalfName);
189 if (!
args.fShaderCaps->fFloatIs32Bits) {
190 clampedCircleDistance.
printf(
"saturate(%s.x * (1.0 - length(dxy * %s.y)))",
191 radiusPlusHalfName, radiusPlusHalfName);
193 clampedCircleDistance.
printf(
"saturate(%s.x - length(dxy))", radiusPlusHalfName);
212 switch (crre.fCircularCornerFlags) {
213 case CircularRRectEffect::kAll_CornerFlags:
214 fragBuilder->
codeAppendf(
"float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
215 fragBuilder->
codeAppendf(
"float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
216 fragBuilder->
codeAppend(
"float2 dxy = max(max(dxy0, dxy1), 0.0);");
217 fragBuilder->
codeAppendf(
"half alpha = half(%s);", clampedCircleDistance.
c_str());
219 case CircularRRectEffect::kTopLeft_CornerFlag:
220 fragBuilder->
codeAppendf(
"float2 dxy = max(%s.LT - sk_FragCoord.xy, 0.0);",
222 fragBuilder->
codeAppendf(
"half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
224 fragBuilder->
codeAppendf(
"half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
226 fragBuilder->
codeAppendf(
"half alpha = bottomAlpha * rightAlpha * half(%s);",
227 clampedCircleDistance.
c_str());
229 case CircularRRectEffect::kTopRight_CornerFlag:
230 fragBuilder->
codeAppendf(
"float2 dxy = max(float2(sk_FragCoord.x - %s.R, "
231 "%s.T - sk_FragCoord.y), 0.0);",
233 fragBuilder->
codeAppendf(
"half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
235 fragBuilder->
codeAppendf(
"half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
237 fragBuilder->
codeAppendf(
"half alpha = bottomAlpha * leftAlpha * half(%s);",
238 clampedCircleDistance.
c_str());
240 case CircularRRectEffect::kBottomRight_CornerFlag:
241 fragBuilder->
codeAppendf(
"float2 dxy = max(sk_FragCoord.xy - %s.RB, 0.0);",
243 fragBuilder->
codeAppendf(
"half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
245 fragBuilder->
codeAppendf(
"half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
247 fragBuilder->
codeAppendf(
"half alpha = topAlpha * leftAlpha * half(%s);",
248 clampedCircleDistance.
c_str());
250 case CircularRRectEffect::kBottomLeft_CornerFlag:
251 fragBuilder->
codeAppendf(
"float2 dxy = max(float2(%s.L - sk_FragCoord.x, "
252 "sk_FragCoord.y - %s.B), 0.0);",
254 fragBuilder->
codeAppendf(
"half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
256 fragBuilder->
codeAppendf(
"half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
258 fragBuilder->
codeAppendf(
"half alpha = topAlpha * rightAlpha * half(%s);",
259 clampedCircleDistance.
c_str());
261 case CircularRRectEffect::kLeft_CornerFlags:
262 fragBuilder->
codeAppendf(
"float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
263 fragBuilder->
codeAppendf(
"float dy1 = sk_FragCoord.y - %s.B;", rectName);
264 fragBuilder->
codeAppend(
"float2 dxy = max(float2(dxy0.x, max(dxy0.y, dy1)), 0.0);");
265 fragBuilder->
codeAppendf(
"half rightAlpha = half(saturate(%s.R - sk_FragCoord.x));",
267 fragBuilder->
codeAppendf(
"half alpha = rightAlpha * half(%s);",
268 clampedCircleDistance.
c_str());
270 case CircularRRectEffect::kTop_CornerFlags:
271 fragBuilder->
codeAppendf(
"float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
272 fragBuilder->
codeAppendf(
"float dx1 = sk_FragCoord.x - %s.R;", rectName);
273 fragBuilder->
codeAppend(
"float2 dxy = max(float2(max(dxy0.x, dx1), dxy0.y), 0.0);");
274 fragBuilder->
codeAppendf(
"half bottomAlpha = half(saturate(%s.B - sk_FragCoord.y));",
276 fragBuilder->
codeAppendf(
"half alpha = bottomAlpha * half(%s);",
277 clampedCircleDistance.
c_str());
279 case CircularRRectEffect::kRight_CornerFlags:
280 fragBuilder->
codeAppendf(
"float dy0 = %s.T - sk_FragCoord.y;", rectName);
281 fragBuilder->
codeAppendf(
"float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
282 fragBuilder->
codeAppend(
"float2 dxy = max(float2(dxy1.x, max(dy0, dxy1.y)), 0.0);");
283 fragBuilder->
codeAppendf(
"half leftAlpha = half(saturate(sk_FragCoord.x - %s.L));",
285 fragBuilder->
codeAppendf(
"half alpha = leftAlpha * half(%s);",
286 clampedCircleDistance.
c_str());
288 case CircularRRectEffect::kBottom_CornerFlags:
289 fragBuilder->
codeAppendf(
"float dx0 = %s.L - sk_FragCoord.x;", rectName);
290 fragBuilder->
codeAppendf(
"float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
291 fragBuilder->
codeAppend(
"float2 dxy = max(float2(max(dx0, dxy1.x), dxy1.y), 0.0);");
292 fragBuilder->
codeAppendf(
"half topAlpha = half(saturate(sk_FragCoord.y - %s.T));",
294 fragBuilder->
codeAppendf(
"half alpha = topAlpha * half(%s);",
295 clampedCircleDistance.
c_str());
300 fragBuilder->
codeAppend(
"alpha = 1.0 - alpha;");
310 const CircularRRectEffect& crre = processor.
cast<CircularRRectEffect>();
312 if (
rrect != fPrevRRect) {
315 switch (crre.fCircularCornerFlags) {
316 case CircularRRectEffect::kAll_CornerFlags:
320 rect.inset(radius, radius);
322 case CircularRRectEffect::kTopLeft_CornerFlag:
324 rect.fLeft += radius;
327 rect.fBottom += 0.5f;
329 case CircularRRectEffect::kTopRight_CornerFlag:
333 rect.fRight -= radius;
334 rect.fBottom += 0.5f;
336 case CircularRRectEffect::kBottomRight_CornerFlag:
340 rect.fRight -= radius;
341 rect.fBottom -= radius;
343 case CircularRRectEffect::kBottomLeft_CornerFlag:
345 rect.fLeft += radius;
348 rect.fBottom -= radius;
350 case CircularRRectEffect::kLeft_CornerFlags:
352 rect.fLeft += radius;
355 rect.fBottom -= radius;
357 case CircularRRectEffect::kTop_CornerFlags:
359 rect.fLeft += radius;
361 rect.fRight -= radius;
362 rect.fBottom += 0.5f;
364 case CircularRRectEffect::kRight_CornerFlags:
368 rect.fRight -= radius;
369 rect.fBottom -= radius;
371 case CircularRRectEffect::kBottom_CornerFlags:
373 rect.fLeft += radius;
375 rect.fRight -= radius;
376 rect.fBottom -= radius;
379 SK_ABORT(
"Should have been one of the above cases.");
383 pdman.
set2f(fRadiusPlusHalfUniform, radius, 1.f / radius);
392 b->add32((fCircularCornerFlags << 3) |
static_cast<int>(fEdgeType));
395std::unique_ptr<GrFragmentProcessor::ProgramImpl> CircularRRectEffect::onMakeProgramImpl()
const {
396 return std::make_unique<Impl>();
406 ~EllipticalRRectEffect()
override {}
408 const char*
name()
const override {
return "EllipticalRRect"; }
410 std::unique_ptr<GrFragmentProcessor> clone()
const override;
416 EllipticalRRectEffect(
const EllipticalRRectEffect& that);
418 std::unique_ptr<ProgramImpl> onMakeProgramImpl()
const override;
438 return GrFPSuccess(std::unique_ptr<GrFragmentProcessor>(
439 new EllipticalRRectEffect(std::move(inputFP), edgeType,
rrect)));
442EllipticalRRectEffect::EllipticalRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
445 :
INHERITED(kEllipticalRRectEffect_ClassID,
446 ProcessorOptimizationFlags(inputFP.
get()) &
447 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
449 , fEdgeType(edgeType) {
450 this->registerChild(std::move(inputFP));
453EllipticalRRectEffect::EllipticalRRectEffect(
const EllipticalRRectEffect& that)
456 , fEdgeType(that.fEdgeType) {}
458std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::clone()
const {
459 return std::unique_ptr<GrFragmentProcessor>(
new EllipticalRRectEffect(*
this));
463 const EllipticalRRectEffect& erre = other.
cast<EllipticalRRectEffect>();
464 return fEdgeType == erre.fEdgeType &&
fRRect == erre.fRRect;
472#if defined(GR_TEST_UTILS)
473std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::TestCreate(GrProcessorTestData*
d) {
474 SkScalar w =
d->fRandom->nextRangeScalar(20.f, 1000.f);
475 SkScalar h =
d->fRandom->nextRangeScalar(20.f, 1000.f);
484 if (
d->fRandom->nextBool()) {
500 std::unique_ptr<GrFragmentProcessor>
fp =
d->inputFP();
505 *
d->caps()->shaderCaps());
539 GrGLSLProgramDataManager::UniformHandle fInnerRectUniform;
540 GrGLSLProgramDataManager::UniformHandle fInvRadiiSqdUniform;
541 GrGLSLProgramDataManager::UniformHandle fScaleUniform;
546 const EllipticalRRectEffect& erre =
args.fFp.cast<EllipticalRRectEffect>();
548 const char *rectName;
551 "innerRect", &rectName);
566 fragBuilder->
codeAppendf(
"float2 dxy0 = %s.LT - sk_FragCoord.xy;", rectName);
567 fragBuilder->
codeAppendf(
"float2 dxy1 = sk_FragCoord.xy - %s.RB;", rectName);
570 const char* scaleName =
nullptr;
573 "scale", &scaleName);
577 switch (erre.fRRect.getType()) {
579 const char *invRadiiXYSqdName;
580 fInvRadiiSqdUniform = uniformHandler->addUniform(&erre,
585 fragBuilder->
codeAppend(
"float2 dxy = max(max(dxy0, dxy1), 0.0);");
587 fragBuilder->
codeAppendf(
"dxy *= %s.y;", scaleName);
590 fragBuilder->
codeAppendf(
"float2 Z = dxy * %s.xy;", invRadiiXYSqdName);
594 const char *invRadiiLTRBSqdName;
595 fInvRadiiSqdUniform = uniformHandler->addUniform(&erre,
599 &invRadiiLTRBSqdName);
601 fragBuilder->
codeAppendf(
"dxy0 *= %s.y;", scaleName);
602 fragBuilder->
codeAppendf(
"dxy1 *= %s.y;", scaleName);
604 fragBuilder->
codeAppend(
"float2 dxy = max(max(dxy0, dxy1), 0.0);");
608 fragBuilder->
codeAppendf(
"float2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);",
609 invRadiiLTRBSqdName, invRadiiLTRBSqdName);
614 SK_ABORT(
"RRect should always be simple or nine-patch.");
617 fragBuilder->
codeAppend(
"half implicit = half(dot(Z, dxy) - 1.0);");
619 fragBuilder->
codeAppend(
"half grad_dot = half(4.0 * dot(Z, Z));");
621 fragBuilder->
codeAppend(
"grad_dot = max(grad_dot, 1.0e-4);");
622 fragBuilder->
codeAppend(
"half approx_dist = implicit * half(inversesqrt(grad_dot));");
624 fragBuilder->
codeAppendf(
"approx_dist *= %s.x;", scaleName);
628 fragBuilder->
codeAppend(
"half alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
630 fragBuilder->
codeAppend(
"half alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
640 const EllipticalRRectEffect& erre = effect.
cast<EllipticalRRectEffect>();
644 if (
rrect != fPrevRRect) {
652 if (fScaleUniform.isValid()) {
654 pdman.
set2f(fInvRadiiSqdUniform, 1.f, (r0.
fX * r0.
fX) / (r0.
fY * r0.
fY));
655 pdman.
set2f(fScaleUniform, r0.
fX, 1.f / r0.
fX);
657 pdman.
set2f(fInvRadiiSqdUniform, (r0.
fY * r0.
fY) / (r0.
fX * r0.
fX), 1.f);
658 pdman.
set2f(fScaleUniform, r0.
fY, 1.f / r0.
fY);
661 pdman.
set2f(fInvRadiiSqdUniform, 1.f / (r0.
fX * r0.
fX),
662 1.f / (r0.
fY * r0.
fY));
673 if (fScaleUniform.isValid()) {
676 pdman.
set4f(fInvRadiiSqdUniform, scaleSqd / (r0.
fX * r0.
fX),
677 scaleSqd / (r0.
fY * r0.
fY),
678 scaleSqd / (r1.
fX * r1.
fX),
679 scaleSqd / (r1.
fY * r1.
fY));
682 pdman.
set4f(fInvRadiiSqdUniform, 1.f / (r0.
fX * r0.
fX),
683 1.f / (r0.
fY * r0.
fY),
684 1.f / (r1.
fX * r1.
fX),
685 1.f / (r1.
fY * r1.
fY));
690 SK_ABORT(
"RRect should always be simple or nine-patch.");
702 b->addBits(2,
static_cast<int>(fEdgeType),
"edge_type");
707std::unique_ptr<GrFragmentProcessor::ProgramImpl> EllipticalRRectEffect::onMakeProgramImpl()
const {
708 return std::make_unique<Impl>();
735 CircularRRectEffect::kAll_CornerFlags,
rrect);
744 uint32_t cornerFlags = 0;
747 bool squashedRadii =
false;
748 for (
int c = 0; c < 4; ++c) {
751 if ((0 == radii[c].fX) != (0 == radii[c].fY)) {
754 if (0 == radii[c].fX) {
760 squashedRadii =
true;
763 if (radii[c].fX != radii[c].fY) {
768 circularRadius = radii[c].
fX;
769 cornerFlags = 1 << c;
771 if (radii[c].fX != circularRadius) {
775 cornerFlags |= 1 << c;
779 switch (cornerFlags) {
780 case CircularRRectEffect::kAll_CornerFlags:
785 case CircularRRectEffect::kTopLeft_CornerFlag:
786 case CircularRRectEffect::kTopRight_CornerFlag:
787 case CircularRRectEffect::kBottomRight_CornerFlag:
788 case CircularRRectEffect::kBottomLeft_CornerFlag:
789 case CircularRRectEffect::kLeft_CornerFlags:
790 case CircularRRectEffect::kTop_CornerFlags:
791 case CircularRRectEffect::kRight_CornerFlags:
792 case CircularRRectEffect::kBottom_CornerFlags: {
799 case CircularRRectEffect::kNone_CornerFlags: {
static GrFPResult GrFPSuccess(std::unique_ptr< GrFragmentProcessor > fp)
std::tuple< bool, std::unique_ptr< GrFragmentProcessor > > GrFPResult
static GrFPResult GrFPFailure(std::unique_ptr< GrFragmentProcessor > fp)
#define GR_DEFINE_FRAGMENT_PROCESSOR_TEST(...)
#define GR_DECLARE_FRAGMENT_PROCESSOR_TEST
static const SkScalar kRadiusMin
static bool elliptical_effect_uses_scale(const GrShaderCaps &caps, const SkRRect &rrect)
static const int kGrClipEdgeTypeCnt
#define SK_ABORT(message,...)
#define INHERITED(method,...)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
void emitCode(EmitArgs &) override
void emitCode(EmitArgs &) override
SkString invokeChild(int childIndex, EmitArgs &parentArgs, std::string_view skslCoords={})
virtual std::unique_ptr< GrFragmentProcessor > clone() const =0
static std::unique_ptr< GrFragmentProcessor > Rect(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, SkRect)
virtual void set2f(UniformHandle, float, float) const =0
virtual void set4f(UniformHandle, float, float, float, float) const =0
void codeAppend(const char *str)
void codeAppendf(const char format[],...) SK_PRINTF_LIKE(2
virtual const char * name() const =0
static bool IsSimpleCircular(const SkRRect &rr)
static SkVector GetSimpleRadii(const SkRRect &rr)
SkVector radii(Corner corner) const
@ kLastType
largest Type value
@ kSimple_Type
non-zero width and height with equal radii
@ kNinePatch_Type
non-zero width and height with axis-aligned radii
@ kUpperLeft_Corner
index of top-left corner radii
@ kLowerRight_Corner
index of bottom-right corner radii
@ kUpperRight_Corner
index of top-right corner radii
@ kLowerLeft_Corner
index of bottom-left corner radii
void setRectRadii(const SkRect &rect, const SkVector radii[4])
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
const SkRect & getBounds() const
void printf(const char format[],...) SK_PRINTF_LIKE(2
const char * c_str() const
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static float max(float r, float g, float b)
GrFPResult Make(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, const SkRect &, const GrShaderCaps &)
GrFPResult Make(std::unique_ptr< GrFragmentProcessor >, GrClipEdgeType, const SkRRect &, const GrShaderCaps &)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
sk_sp< SkBlender > blender SkRect rect
DEF_SWITCHES_START aot vmservice shared library name
const myers::Point & get(const myers::Segment &)
void set(float x, float y)
static constexpr SkRect MakeWH(float w, float h)