114static const uint16_t gRRectIndices[] = {
119 6, 18, 27, 6, 27, 25,
120 18, 12, 26, 18, 26, 27,
121 12, 0, 24, 12, 24, 26,
124 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5,
125 6, 11, 10, 6, 10, 9, 6, 9, 8, 6, 8, 7,
126 12, 17, 16, 12, 16, 15, 12, 15, 14, 12, 14, 13,
127 18, 19, 20, 18, 20, 21, 18, 21, 22, 18, 22, 23,
132 18, 23, 17, 18, 17, 12,
147static const int kVertsPerStrokeRRect = 24;
149static const int kVertsPerFillRRect = 24;
160 return kVertsPerFillRRect;
162 return kVertsPerStrokeRRect;
185 return gRRectIndices + 6*4;
187 return gRRectIndices;
194class ShadowCircularRRectOp final :
public GrMeshDrawOp {
200 float devRadius,
bool isCircle,
float blurRadius,
float insetWidth,
203 , fFalloffView(
std::move(falloffView)) {
214 umbraInset =
std::max(outerRadius, blurRadius);
220 innerRadius = devRadius - insetWidth;
226 innerRadius =
std::max(insetWidth - umbraInset, 0.0f);
231 this->
setBounds(bounds, HasAABloat::kNo, IsHairline::kNo);
233 fGeoData.emplace_back(Geometry{
color, outerRadius, umbraInset, innerRadius,
244 const char*
name()
const override {
return "ShadowCircularRRectOp"; }
264 struct CircleVertex {
271 void fillInCircleVerts(
const Geometry&
args,
bool isStroked, CircleVertex** verts)
const {
277 SkScalar distanceCorrection = outerRadius / blurRadius;
282 innerRadius = innerRadius / outerRadius;
286 SkScalar octOffset = 0.41421356237f;
289 (*verts)->fColor =
color;
291 (*verts)->fDistanceCorrection = distanceCorrection;
295 (*verts)->fColor =
color;
297 (*verts)->fDistanceCorrection = distanceCorrection;
301 (*verts)->fColor =
color;
303 (*verts)->fDistanceCorrection = distanceCorrection;
307 (*verts)->fColor =
color;
309 (*verts)->fDistanceCorrection = distanceCorrection;
313 (*verts)->fColor =
color;
315 (*verts)->fDistanceCorrection = distanceCorrection;
319 (*verts)->fColor =
color;
321 (*verts)->fDistanceCorrection = distanceCorrection;
325 (*verts)->fColor =
color;
327 (*verts)->fDistanceCorrection = distanceCorrection;
331 (*verts)->fColor =
color;
333 (*verts)->fDistanceCorrection = distanceCorrection;
345 (*verts)->fColor =
color;
346 (*verts)->fOffset =
SkPoint::Make(-
s * innerRadius, -c * innerRadius);
347 (*verts)->fDistanceCorrection = distanceCorrection;
351 (*verts)->fColor =
color;
352 (*verts)->fOffset =
SkPoint::Make(
s * innerRadius, -c * innerRadius);
353 (*verts)->fDistanceCorrection = distanceCorrection;
357 (*verts)->fColor =
color;
358 (*verts)->fOffset =
SkPoint::Make(c * innerRadius, -
s * innerRadius);
359 (*verts)->fDistanceCorrection = distanceCorrection;
363 (*verts)->fColor =
color;
364 (*verts)->fOffset =
SkPoint::Make(c * innerRadius,
s * innerRadius);
365 (*verts)->fDistanceCorrection = distanceCorrection;
369 (*verts)->fColor =
color;
370 (*verts)->fOffset =
SkPoint::Make(
s * innerRadius, c * innerRadius);
371 (*verts)->fDistanceCorrection = distanceCorrection;
375 (*verts)->fColor =
color;
376 (*verts)->fOffset =
SkPoint::Make(-
s * innerRadius, c * innerRadius);
377 (*verts)->fDistanceCorrection = distanceCorrection;
381 (*verts)->fColor =
color;
382 (*verts)->fOffset =
SkPoint::Make(-c * innerRadius,
s * innerRadius);
383 (*verts)->fDistanceCorrection = distanceCorrection;
387 (*verts)->fColor =
color;
388 (*verts)->fOffset =
SkPoint::Make(-c * innerRadius, -
s * innerRadius);
389 (*verts)->fDistanceCorrection = distanceCorrection;
394 (*verts)->fColor =
color;
396 (*verts)->fDistanceCorrection = distanceCorrection;
401 void fillInRRectVerts(
const Geometry&
args, CircleVertex** verts)
const {
409 if (umbraInset > minDim) {
414 bounds.fLeft + umbraInset,
bounds.fRight - umbraInset };
416 bounds.fLeft + outerRadius,
bounds.fRight - outerRadius };
420 bounds.fBottom - umbraInset,
bounds.fBottom - umbraInset };
422 bounds.fBottom - outerRadius,
bounds.fBottom - outerRadius };
446 SkScalar distanceCorrection = umbraInset / blurRadius;
449 for (
int i = 0;
i < 4; ++
i) {
452 (*verts)->fColor =
color;
454 (*verts)->fDistanceCorrection = distanceCorrection;
459 (*verts)->fColor =
color;
461 (*verts)->fDistanceCorrection = distanceCorrection;
465 (*verts)->fColor =
color;
466 (*verts)->fOffset = outerVec;
467 (*verts)->fDistanceCorrection = distanceCorrection;
471 (*verts)->fColor =
color;
472 (*verts)->fOffset = diagVec;
473 (*verts)->fDistanceCorrection = distanceCorrection;
477 (*verts)->fColor =
color;
478 (*verts)->fOffset = outerVec;
479 (*verts)->fDistanceCorrection = distanceCorrection;
483 (*verts)->fColor =
color;
485 (*verts)->fDistanceCorrection = distanceCorrection;
500 (*verts)->fColor =
color;
502 (*verts)->fDistanceCorrection = distanceCorrection;
507 (*verts)->fColor =
color;
509 (*verts)->fDistanceCorrection = distanceCorrection;
514 (*verts)->fColor =
color;
516 (*verts)->fDistanceCorrection = distanceCorrection;
521 (*verts)->fColor =
color;
523 (*verts)->fDistanceCorrection = distanceCorrection;
534 bool usesMSAASurface,
544 std::move(appliedClip),
548 renderPassXferBarriers,
555 int instanceCount = fGeoData.size();
559 CircleVertex* verts = (CircleVertex*)
target->makeVertexSpace(
560 sizeof(CircleVertex), fVertCount, &vertexBuffer, &firstVertex);
562 SkDebugf(
"Could not allocate vertices\n");
568 uint16_t* indices =
target->makeIndexSpace(fIndexCount, &indexBuffer, &firstIndex);
570 SkDebugf(
"Could not allocate indices\n");
574 int currStartVertex = 0;
575 for (
int i = 0;
i < instanceCount;
i++) {
576 const Geometry&
args = fGeoData[
i];
578 if (
args.fIsCircle) {
580 this->fillInCircleVerts(
args, isStroked, &verts);
584 for (
int j = 0; j < primIndexCount; ++j) {
585 *indices++ = primIndices[j] + currStartVertex;
591 this->fillInRRectVerts(
args, &verts);
595 for (
int j = 0; j < primIndexCount; ++j) {
596 *indices++ = primIndices[j] + currStartVertex;
603 fMesh =
target->allocMesh();
604 fMesh->
setIndexed(std::move(indexBuffer), fIndexCount, firstIndex, 0, fVertCount - 1,
613 if (!fProgramInfo || !fMesh) {
624 ShadowCircularRRectOp* that = t->
cast<ShadowCircularRRectOp>();
625 fGeoData.push_back_n(that->fGeoData.size(), that->fGeoData.begin());
626 fVertCount += that->fVertCount;
627 fIndexCount += that->fIndexCount;
628 return CombineResult::kMerged;
631#if defined(GR_TEST_UTILS)
632 SkString onDumpInfo()
const override {
634 for (
int i = 0;
i < fGeoData.size(); ++
i) {
636 "Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f],"
637 "OuterRad: %.2f, Umbra: %.2f, InnerRad: %.2f, BlurRad: %.2f\n",
638 fGeoData[
i].fColor, fGeoData[
i].fDevBounds.fLeft, fGeoData[
i].fDevBounds.fTop,
639 fGeoData[
i].fDevBounds.fRight, fGeoData[
i].fDevBounds.fBottom,
640 fGeoData[
i].fOuterRadius, fGeoData[
i].fUmbraInset,
641 fGeoData[
i].fInnerRadius, fGeoData[
i].fBlurRadius);
685 static const int kWidth = 128;
690 bitmap.allocPixels(ii, kRowBytes);
692 unsigned char*
values = (
unsigned char*)
bitmap.getPixels();
693 for (
int i = 0;
i < 128; ++
i) {
704 view = threadSafeCache->add(
key, view);
734 if (scaledInsetWidth <= 0) {
738 return GrOp::Make<ShadowCircularRRectOp>(context,
745 std::move(falloffView));
752#if defined(GR_TEST_UTILS)
756GR_DRAW_OP_TEST_DEFINE(ShadowRRectOp) {
762 SkScalar translateX = random->nextSScalar1() * 1000.f;
763 SkScalar translateY = random->nextSScalar1() * 1000.f;
769 SkScalar insetWidth = random->nextSScalar1() * 72.f;
770 SkScalar blurWidth = random->nextSScalar1() * 72.f;
771 bool isCircle = random->nextBool();
775 SkRect circle = GrTest::TestSquare(random);
778 context,
color, viewMatrix,
rrect, blurWidth, insetWidth)) {
785 rrect = GrTest::TestRRectSimple(random);
788 context,
color, viewMatrix,
rrect, blurWidth, insetWidth)) {
#define DEFINE_OP_CLASS_ID
static const uint16_t * circle_type_to_indices(bool stroked)
static int rrect_type_to_vert_count(RRectType type)
static int rrect_type_to_index_count(RRectType type)
static int circle_type_to_index_count(bool stroked)
static const int kVertsPerFillCircle
static const uint16_t gStrokeCircleIndices[]
static const int kIndicesPerFillRRect
static const int kIndicesPerStrokeCircle
static const uint16_t gFillCircleIndices[]
static const int kIndicesPerOverstrokeRRect
static const int kIndicesPerFillCircle
static const int kVertsPerOverstrokeRRect
static const uint16_t * rrect_type_to_indices(RRectType type)
static const int kIndicesPerStrokeRRect
static const int kVertsPerStrokeCircle
static int circle_type_to_vert_count(bool stroked)
static constexpr size_t GrColorTypeBytesPerPixel(GrColorType ct)
std::function< void(GrSurfaceProxy *, skgpu::Mipmapped)> GrVisitProxyFunc
@ kTopLeft_GrSurfaceOrigin
#define SK_ABORT(message,...)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
std::tuple< GrSurfaceProxyView, GrColorType > GrMakeUncachedBitmapProxyView(GrRecordingContext *rContext, const SkBitmap &bitmap, skgpu::Mipmapped mipmapped, SkBackingFit fit, skgpu::Budgeted budgeted)
static bool rotate(const SkDCubic &cubic, int zero, int index, SkDCubic &rotPath)
#define INHERITED(method,...)
#define SkScalarRoundToInt(x)
static constexpr bool SkToBool(const T &x)
static SkScalar center(float pos0, float pos1)
virtual FixedFunctionFlags fixedFunctionFlags() const
virtual GrProcessorSet::Analysis finalize(const GrCaps &, const GrAppliedClip *, GrClampType)=0
size_t vertexStride() const
virtual GrProgramInfo * programInfo()=0
void createProgramInfo(const GrCaps *caps, SkArenaAlloc *arena, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&appliedClip, const GrDstProxyView &dstProxyView, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)
virtual void onCreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrAppliedClip &&, const GrDstProxyView &, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp)=0
virtual void onPrepareDraws(GrMeshDrawTarget *)=0
void drawMesh(const GrSimpleMesh &mesh)
void bindPipelineAndScissorClip(const GrProgramInfo &programInfo, const SkRect &drawBounds)
void bindTextures(const GrGeometryProcessor &geomProc, const GrSurfaceProxy &singleGeomProcTexture, const GrPipeline &pipeline)
virtual void onExecute(GrOpFlushState *, const SkRect &chainBounds)=0
std::unique_ptr< GrOp > Owner
virtual const char * name() const =0
const SkRect & bounds() const
void setBounds(const SkRect &newBounds, HasAABloat aabloat, IsHairline zeroArea)
virtual CombineResult onCombineIfPossible(GrOp *, SkArenaAlloc *, const GrCaps &)
static constexpr Analysis EmptySetAnalysis()
static GrProcessorSet MakeEmptySet()
const GrPipeline & pipeline() const
const GrGeometryProcessor & geomProc() const
void visitFPProxies(const GrVisitProxyFunc &func) const
static GrGeometryProcessor * Make(SkArenaAlloc *arena, const GrSurfaceProxyView &lutView)
GrThreadSafeCache * threadSafeCache()
GrRecordingContextPriv priv()
static GrProgramInfo * CreateProgramInfo(const GrCaps *, SkArenaAlloc *, const GrPipeline *, const GrSurfaceProxyView &writeView, bool usesMSAASurface, GrGeometryProcessor *, GrPrimitiveType, GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp, const GrUserStencilSettings *=&GrUserStencilSettings::kUnused)
GrSurfaceOrigin origin() const
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
static constexpr int kMScaleX
horizontal scale factor
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
SkMatrix & setRotate(SkScalar degrees, SkScalar px, SkScalar py)
bool isSimilarity(SkScalar tol=SK_ScalarNearlyZero) const
static constexpr int kMSkewX
horizontal skew factor
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
static bool EqualRadii(const SkRRect &rr)
static bool IsSimpleCircular(const SkRRect &rr)
static SkVector GetSimpleRadii(const SkRRect &rr)
static SkRRect MakeOval(const SkRect &oval)
const SkRect & getBounds() const
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
static Domain GenerateDomain()
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)
static float min(float r, float g, float b)
Optional< SkRect > bounds
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
const myers::Point & get< 0 >(const myers::Segment &s)
static GrSurfaceProxyView create_falloff_texture(GrRecordingContext *rContext)
GrOp::Owner Make(GrRecordingContext *context, GrColor color, const SkMatrix &viewMatrix, const SkRRect &rrect, SkScalar blurWidth, SkScalar insetWidth)
static SkRect inset(const SkRect &r)
void setIndexed(sk_sp< const GrBuffer > indexBuffer, int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue, GrPrimitiveRestart, sk_sp< const GrBuffer > vertexBuffer, int baseVertex)
static const GrUserStencilSettings & kUnused
static SkImageInfo MakeA8(int width, int height)
static constexpr SkPoint Make(float x, float y)
constexpr float height() const
constexpr float width() const