Flutter Engine
The Flutter Engine
Classes | Public Types | Static Public Member Functions | Static Public Attributes | List of all members
SkPathPriv Class Reference

#include <SkPathPriv.h>

Classes

struct  Iterate
 
struct  Verbs
 

Public Types

using RangeIter = SkPath::RangeIter
 

Static Public Member Functions

static SkPathFirstDirection AsFirstDirection (SkPathDirection dir)
 
static SkPathFirstDirection OppositeFirstDirection (SkPathFirstDirection dir)
 
static SkPathFirstDirection ComputeFirstDirection (const SkPath &)
 
static bool IsClosedSingleContour (const SkPath &path)
 
static int LeadingMoveToCount (const SkPath &path)
 
static void AddGenIDChangeListener (const SkPath &path, sk_sp< SkIDChangeListener > listener)
 
static bool IsSimpleRect (const SkPath &path, bool isSimpleFill, SkRect *rect, SkPathDirection *direction, unsigned *start)
 
static void CreateDrawArcPath (SkPath *path, const SkArc &arc, bool isFillNoPathEffect)
 
static bool DrawArcIsConvex (SkScalar sweepAngle, SkArc::Type arcType, bool isFillNoPathEffect)
 
static void ShrinkToFit (SkPath *path)
 
static const uint8_t * VerbData (const SkPath &path)
 
static const SkPointPointData (const SkPath &path)
 
static int ConicWeightCnt (const SkPath &path)
 
static const SkScalarConicWeightData (const SkPath &path)
 
static bool TestingOnly_unique (const SkPath &path)
 
static bool HasComputedBounds (const SkPath &path)
 
static bool IsOval (const SkPath &path, SkRect *rect, SkPathDirection *dir, unsigned *start)
 
static bool IsRRect (const SkPath &path, SkRRect *rrect, SkPathDirection *dir, unsigned *start)
 
static bool TooBigForMath (const SkRect &bounds)
 
static bool TooBigForMath (const SkPath &path)
 
static int PtsInIter (unsigned verb)
 
static int PtsInVerb (unsigned verb)
 
static bool IsAxisAligned (const SkPath &path)
 
static bool AllPointsEq (const SkPoint pts[], int count)
 
static int LastMoveToIndex (const SkPath &path)
 
static bool IsRectContour (const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
 
static bool IsNestedFillRects (const SkPath &, SkRect rect[2], SkPathDirection dirs[2]=nullptr)
 
static bool IsInverseFillType (SkPathFillType fill)
 
static SkPathFillType ConvertToNonInverseFillType (SkPathFillType fill)
 
static bool PerspectiveClip (const SkPath &src, const SkMatrix &, SkPath *result)
 
static int GenIDChangeListenersCount (const SkPath &)
 
static void UpdatePathPoint (SkPath *path, int index, const SkPoint &pt)
 
static SkPathConvexity GetConvexity (const SkPath &path)
 
static SkPathConvexity GetConvexityOrUnknown (const SkPath &path)
 
static void SetConvexity (const SkPath &path, SkPathConvexity c)
 
static void ForceComputeConvexity (const SkPath &path)
 
static void ReverseAddPath (SkPathBuilder *builder, const SkPath &reverseMe)
 
static SkPath MakePath (const SkPathVerbAnalysis &analysis, const SkPoint points[], const uint8_t verbs[], int verbCount, const SkScalar conics[], SkPathFillType fillType, bool isVolatile)
 

Static Public Attributes

static constexpr SkScalar kW0PlaneDistance = 1.f / (1 << 14)
 

Detailed Description

Definition at line 37 of file SkPathPriv.h.

Member Typedef Documentation

◆ RangeIter

using SkPathPriv::RangeIter = SkPath::RangeIter

Iterates through a raw range of path verbs, points, and conics. All values are returned unaltered.

NOTE: This class's definition will be moved into SkPathPriv once RangeIter is removed.

Definition at line 164 of file SkPathPriv.h.

Member Function Documentation

◆ AddGenIDChangeListener()

static void SkPathPriv::AddGenIDChangeListener ( const SkPath path,
sk_sp< SkIDChangeListener listener 
)
inlinestatic

Definition at line 106 of file SkPathPriv.h.

106 {
107 path.fPathRef->addGenIDChangeListener(std::move(listener));
108 }
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57

◆ AllPointsEq()

static bool SkPathPriv::AllPointsEq ( const SkPoint  pts[],
int  count 
)
inlinestatic

Definition at line 339 of file SkPathPriv.h.

339 {
340 for (int i = 1; i < count; ++i) {
341 if (pts[0] != pts[i]) {
342 return false;
343 }
344 }
345 return true;
346 }
int count
Definition: FontMgrTest.cpp:50

◆ AsFirstDirection()

static SkPathFirstDirection SkPathPriv::AsFirstDirection ( SkPathDirection  dir)
inlinestatic

Definition at line 43 of file SkPathPriv.h.

43 {
44 // since we agree numerically for the values in Direction, we can just cast.
46 }
SkPathFirstDirection
Definition: SkPathEnums.h:19
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145

◆ ComputeFirstDirection()

SkPathFirstDirection SkPathPriv::ComputeFirstDirection ( const SkPath path)
static

Tries to compute the direction of the outer-most non-degenerate contour. If it can be computed, return that direction. If it cannot be determined, or the contour is known to be convex, return kUnknown. If the direction was determined, it is cached to make subsequent calls return quickly.

Definition at line 2627 of file SkPath.cpp.

2627 {
2628 auto d = path.getFirstDirection();
2630 return d;
2631 }
2632
2633 // We don't want to pay the cost for computing convexity if it is unknown,
2634 // so we call getConvexityOrUnknown() instead of isConvex().
2635 if (path.getConvexityOrUnknown() == SkPathConvexity::kConvex) {
2637 return d;
2638 }
2639
2640 ContourIter iter(*path.fPathRef);
2641
2642 // initialize with our logical y-min
2643 SkScalar ymax = path.getBounds().fTop;
2644 SkScalar ymaxCross = 0;
2645
2646 for (; !iter.done(); iter.next()) {
2647 int n = iter.count();
2648 if (n < 3) {
2649 continue;
2650 }
2651
2652 const SkPoint* pts = iter.pts();
2653 SkScalar cross = 0;
2654 int index = find_max_y(pts, n);
2655 if (pts[index].fY < ymax) {
2656 continue;
2657 }
2658
2659 // If there is more than 1 distinct point at the y-max, we take the
2660 // x-min and x-max of them and just subtract to compute the dir.
2661 if (pts[(index + 1) % n].fY == pts[index].fY) {
2662 int maxIndex;
2663 int minIndex = find_min_max_x_at_y(pts, index, n, &maxIndex);
2664 if (minIndex == maxIndex) {
2665 goto TRY_CROSSPROD;
2666 }
2667 SkASSERT(pts[minIndex].fY == pts[index].fY);
2668 SkASSERT(pts[maxIndex].fY == pts[index].fY);
2669 SkASSERT(pts[minIndex].fX <= pts[maxIndex].fX);
2670 // we just subtract the indices, and let that auto-convert to
2671 // SkScalar, since we just want - or + to signal the direction.
2672 cross = minIndex - maxIndex;
2673 } else {
2674 TRY_CROSSPROD:
2675 // Find a next and prev index to use for the cross-product test,
2676 // but we try to find pts that form non-zero vectors from pts[index]
2677 //
2678 // Its possible that we can't find two non-degenerate vectors, so
2679 // we have to guard our search (e.g. all the pts could be in the
2680 // same place).
2681
2682 // we pass n - 1 instead of -1 so we don't foul up % operator by
2683 // passing it a negative LH argument.
2684 int prev = find_diff_pt(pts, index, n, n - 1);
2685 if (prev == index) {
2686 // completely degenerate, skip to next contour
2687 continue;
2688 }
2689 int next = find_diff_pt(pts, index, n, 1);
2690 SkASSERT(next != index);
2691 cross = cross_prod(pts[prev], pts[index], pts[next]);
2692 // if we get a zero and the points are horizontal, then we look at the spread in
2693 // x-direction. We really should continue to walk away from the degeneracy until
2694 // there is a divergence.
2695 if (0 == cross && pts[prev].fY == pts[index].fY && pts[next].fY == pts[index].fY) {
2696 // construct the subtract so we get the correct Direction below
2697 cross = pts[index].fX - pts[next].fX;
2698 }
2699 }
2700
2701 if (cross) {
2702 // record our best guess so far
2703 ymax = pts[index].fY;
2704 ymaxCross = cross;
2705 }
2706 }
2707 if (ymaxCross) {
2708 d = crossToDir(ymaxCross);
2709 path.setFirstDirection(d);
2710 }
2711 return d; // may still be kUnknown
2712}
static float next(float f)
static float prev(float f)
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkScalar cross_prod(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
Definition: SkPath.cpp:2537
static int find_diff_pt(const SkPoint pts[], int index, int n, int inc)
Definition: SkPath.cpp:2573
static int find_max_y(const SkPoint pts[], int count)
Definition: SkPath.cpp:2559
static SkPathFirstDirection crossToDir(SkScalar cross)
Definition: SkPath.cpp:2615
static int find_min_max_x_at_y(const SkPoint pts[], int index, int n, int *maxIndexPtr)
Definition: SkPath.cpp:2591
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
float SkScalar
Definition: extension.cpp:12
int64_t cross(Point d0, Point d1)
Definition: Myers.cpp:55
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ ConicWeightCnt()

static int SkPathPriv::ConicWeightCnt ( const SkPath path)
inlinestatic

Returns the number of conic weights in the path

Definition at line 208 of file SkPathPriv.h.

208 {
209 return path.fPathRef->countWeights();
210 }

◆ ConicWeightData()

static const SkScalar * SkPathPriv::ConicWeightData ( const SkPath path)
inlinestatic

Returns a raw pointer to the path conic weights.

Definition at line 213 of file SkPathPriv.h.

213 {
214 return path.fPathRef->conicWeights();
215 }

◆ ConvertToNonInverseFillType()

static SkPathFillType SkPathPriv::ConvertToNonInverseFillType ( SkPathFillType  fill)
inlinestatic

Returns equivalent SkPath::FillType representing SkPath fill inside its bounds.

Parameters
fillone of: kWinding_FillType, kEvenOdd_FillType, kInverseWinding_FillType, kInverseEvenOdd_FillType
Returns
fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted

Definition at line 379 of file SkPathPriv.h.

379 {
380 return (SkPathFillType)(static_cast<int>(fill) & 1);
381 }
SkPathFillType
Definition: SkPathTypes.h:11

◆ CreateDrawArcPath()

void SkPathPriv::CreateDrawArcPath ( SkPath path,
const SkArc arc,
bool  isFillNoPathEffect 
)
static

Creates a path from arc params using the semantics of SkCanvas::drawArc. This function assumes empty ovals and zero sweeps have already been filtered out.

Definition at line 3356 of file SkPath.cpp.

3356 {
3357 SkRect oval = arc.fOval;
3359 SkASSERT(!oval.isEmpty());
3361 // We cap the number of total rotations. This keeps the resulting paths simpler. More important,
3362 // it prevents values so large that the loops below never terminate (once ULP > 360).
3363 if (SkScalarAbs(sweepAngle) > 3600.0f) {
3364 sweepAngle = std::copysign(3600.0f, sweepAngle) + std::fmod(sweepAngle, 360.0f);
3365 }
3366 path->reset();
3367 path->setIsVolatile(true);
3368 path->setFillType(SkPathFillType::kWinding);
3369 if (isFillNoPathEffect && SkScalarAbs(sweepAngle) >= 360.f) {
3370 path->addOval(oval);
3371 SkASSERT(path->isConvex() &&
3372 DrawArcIsConvex(sweepAngle, SkArc::Type::kArc, isFillNoPathEffect));
3373 return;
3374 }
3375 if (arc.isWedge()) {
3376 path->moveTo(oval.centerX(), oval.centerY());
3377 }
3378 auto firstDir =
3380 bool convex = DrawArcIsConvex(sweepAngle, arc.fType, isFillNoPathEffect);
3381 // Arc to mods at 360 and drawArc is not supposed to.
3382 bool forceMoveTo = !arc.isWedge();
3383 while (sweepAngle <= -360.f) {
3384 path->arcTo(oval, startAngle, -180.f, forceMoveTo);
3385 startAngle -= 180.f;
3386 path->arcTo(oval, startAngle, -180.f, false);
3387 startAngle -= 180.f;
3388 forceMoveTo = false;
3389 sweepAngle += 360.f;
3390 }
3391 while (sweepAngle >= 360.f) {
3392 path->arcTo(oval, startAngle, 180.f, forceMoveTo);
3393 startAngle += 180.f;
3394 path->arcTo(oval, startAngle, 180.f, false);
3395 startAngle += 180.f;
3396 forceMoveTo = false;
3397 sweepAngle -= 360.f;
3398 }
3399 path->arcTo(oval, startAngle, sweepAngle, forceMoveTo);
3400 if (arc.isWedge()) {
3401 path->close();
3402 }
3404 path->setFirstDirection(firstDir);
3405}
#define SkScalarAbs(x)
Definition: SkScalar.h:39
static bool DrawArcIsConvex(SkScalar sweepAngle, SkArc::Type arcType, bool isFillNoPathEffect)
Definition: SkPath.cpp:3340
SkRect oval
Definition: SkRecords.h:249
SkScalar startAngle
Definition: SkRecords.h:250
SkScalar sweepAngle
Definition: SkRecords.h:251
Type fType
Definition: SkArc.h:62
SkScalar fSweepAngle
Definition: SkArc.h:60
SkScalar fStartAngle
Definition: SkArc.h:58
SkRect fOval
Definition: SkArc.h:55
bool isWedge() const
Definition: SkArc.h:28
constexpr float centerX() const
Definition: SkRect.h:776
constexpr float centerY() const
Definition: SkRect.h:785
bool isEmpty() const
Definition: SkRect.h:693

◆ DrawArcIsConvex()

bool SkPathPriv::DrawArcIsConvex ( SkScalar  sweepAngle,
SkArc::Type  arcType,
bool  isFillNoPathEffect 
)
static

Determines whether an arc produced by CreateDrawArcPath will be convex. Assumes a non-empty oval.

Definition at line 3340 of file SkPath.cpp.

3342 {
3343 if (isFillNoPathEffect && SkScalarAbs(sweepAngle) >= 360.f) {
3344 // This gets converted to an oval.
3345 return true;
3346 }
3347 if (arcType == SkArc::Type::kWedge) {
3348 // This is a pie wedge. It's convex if the angle is <= 180.
3349 return SkScalarAbs(sweepAngle) <= 180.f;
3350 }
3351 // When the angle exceeds 360 this wraps back on top of itself. Otherwise it is a circle clipped
3352 // to a secant, i.e. convex.
3353 return SkScalarAbs(sweepAngle) <= 360.f;
3354}

◆ ForceComputeConvexity()

static void SkPathPriv::ForceComputeConvexity ( const SkPath path)
inlinestatic

Definition at line 416 of file SkPathPriv.h.

416 {
417 path.setConvexity(SkPathConvexity::kUnknown);
418 (void)path.isConvex();
419 }

◆ GenIDChangeListenersCount()

int SkPathPriv::GenIDChangeListenersCount ( const SkPath path)
static

Gets the number of GenIDChangeListeners. If another thread has access to this path then this may be stale before return and only indicates that the count was the return value at some point during the execution of the function.

Definition at line 3988 of file SkPath.cpp.

3988 {
3989 return path.fPathRef->genIDChangeListenerCount();
3990}

◆ GetConvexity()

static SkPathConvexity SkPathPriv::GetConvexity ( const SkPath path)
inlinestatic

Definition at line 407 of file SkPathPriv.h.

407 {
408 return path.getConvexity();
409 }

◆ GetConvexityOrUnknown()

static SkPathConvexity SkPathPriv::GetConvexityOrUnknown ( const SkPath path)
inlinestatic

Definition at line 410 of file SkPathPriv.h.

410 {
411 return path.getConvexityOrUnknown();
412 }

◆ HasComputedBounds()

static bool SkPathPriv::HasComputedBounds ( const SkPath path)
inlinestatic

Definition at line 223 of file SkPathPriv.h.

223 {
224 return path.hasComputedBounds();
225 }

◆ IsAxisAligned()

bool SkPathPriv::IsAxisAligned ( const SkPath path)
static

Definition at line 3992 of file SkPath.cpp.

3992 {
3993 // Conservative (quick) test to see if all segments are axis-aligned.
3994 // Multiple contours might give a false-negative, but for speed, we ignore that
3995 // and just look at the raw points.
3996
3997 const SkPoint* pts = path.fPathRef->points();
3998 const int count = path.fPathRef->countPoints();
3999
4000 for (int i = 1; i < count; ++i) {
4001 if (pts[i-1].fX != pts[i].fX && pts[i-1].fY != pts[i].fY) {
4002 return false;
4003 }
4004 }
4005 return true;
4006}

◆ IsClosedSingleContour()

static bool SkPathPriv::IsClosedSingleContour ( const SkPath path)
inlinestatic

Definition at line 67 of file SkPathPriv.h.

67 {
68 int verbCount = path.countVerbs();
69 if (verbCount == 0)
70 return false;
71 int moveCount = 0;
72 auto verbs = path.fPathRef->verbsBegin();
73 for (int i = 0; i < verbCount; i++) {
74 switch (verbs[i]) {
75 case SkPath::Verb::kMove_Verb:
76 moveCount += 1;
77 if (moveCount > 1) {
78 return false;
79 }
80 break;
81 case SkPath::Verb::kClose_Verb:
82 if (i == verbCount - 1) {
83 return true;
84 }
85 return false;
86 default: break;
87 }
88 }
89 return false;
90 }

◆ IsInverseFillType()

static bool SkPathPriv::IsInverseFillType ( SkPathFillType  fill)
inlinestatic

Definition at line 368 of file SkPathPriv.h.

368 {
369 return (static_cast<int>(fill) & 2) != 0;
370 }

◆ IsNestedFillRects()

bool SkPathPriv::IsNestedFillRects ( const SkPath path,
SkRect  rect[2],
SkPathDirection  dirs[2] = nullptr 
)
static

Returns true if SkPath is equivalent to nested SkRect pair when filled. If false, rect and dirs are unchanged. If true, rect and dirs are written to if not nullptr: setting rect[0] to outer SkRect, and rect[1] to inner SkRect; setting dirs[0] to SkPathDirection of outer SkRect, and dirs[1] to SkPathDirection of inner SkRect.

Parameters
rectstorage for SkRect pair; may be nullptr
dirsstorage for SkPathDirection pair; may be nullptr
Returns
true if SkPath contains nested SkRect pair

Definition at line 3780 of file SkPath.cpp.

3780 {
3781 SkDEBUGCODE(path.validate();)
3782 int currVerb = 0;
3783 const SkPoint* pts = path.fPathRef->points();
3784 SkPathDirection testDirs[2];
3785 SkRect testRects[2];
3786 if (!IsRectContour(path, true, &currVerb, &pts, nullptr, &testDirs[0], &testRects[0])) {
3787 return false;
3788 }
3789 if (IsRectContour(path, false, &currVerb, &pts, nullptr, &testDirs[1], &testRects[1])) {
3790 if (testRects[0].contains(testRects[1])) {
3791 if (rects) {
3792 rects[0] = testRects[0];
3793 rects[1] = testRects[1];
3794 }
3795 if (dirs) {
3796 dirs[0] = testDirs[0];
3797 dirs[1] = testDirs[1];
3798 }
3799 return true;
3800 }
3801 if (testRects[1].contains(testRects[0])) {
3802 if (rects) {
3803 rects[0] = testRects[1];
3804 rects[1] = testRects[0];
3805 }
3806 if (dirs) {
3807 dirs[0] = testDirs[1];
3808 dirs[1] = testDirs[0];
3809 }
3810 return true;
3811 }
3812 }
3813 return false;
3814}
static const int points[]
SkPathDirection
Definition: SkPathTypes.h:34
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static bool IsRectContour(const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
Definition: SkPath.cpp:3639
if(end==-1)
constexpr bool contains(std::string_view str, std::string_view needle)
Definition: SkStringView.h:41

◆ IsOval()

static bool SkPathPriv::IsOval ( const SkPath path,
SkRect rect,
SkPathDirection dir,
unsigned *  start 
)
inlinestatic

Returns true if constructed by addCircle(), addOval(); and in some cases, addRoundRect(), addRRect(). SkPath constructed with conicTo() or rConicTo() will not return true though SkPath draws oval.

rect receives bounds of oval. dir receives SkPathDirection of oval: kCW_Direction if clockwise, kCCW_Direction if counterclockwise. start receives start of oval: 0 for top, 1 for right, 2 for bottom, 3 for left.

rect, dir, and start are unmodified if oval is not found.

Triggers performance optimizations on some GPU surface implementations.

Parameters
rectstorage for bounding SkRect of oval; may be nullptr
dirstorage for SkPathDirection; may be nullptr
startstorage for start of oval; may be nullptr
Returns
true if SkPath was constructed by method that reduces to oval

Definition at line 245 of file SkPathPriv.h.

245 {
246 bool isCCW = false;
247 bool result = path.fPathRef->isOval(rect, &isCCW, start);
248 if (dir && result) {
250 }
251 return result;
252 }
GAsyncResult * result
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350

◆ IsRectContour()

bool SkPathPriv::IsRectContour ( const SkPath path,
bool  allowPartial,
int currVerb,
const SkPoint **  ptsPtr,
bool *  isClosed,
SkPathDirection direction,
SkRect rect 
)
static

Definition at line 3639 of file SkPath.cpp.

3641 {
3642 int corners = 0;
3643 SkPoint closeXY; // used to determine if final line falls on a diagonal
3644 SkPoint lineStart; // used to construct line from previous point
3645 const SkPoint* firstPt = nullptr; // first point in the rect (last of first moves)
3646 const SkPoint* lastPt = nullptr; // last point in the rect (last of lines or first if closed)
3647 SkPoint firstCorner;
3648 SkPoint thirdCorner;
3649 const SkPoint* pts = *ptsPtr;
3650 const SkPoint* savePts = nullptr; // used to allow caller to iterate through a pair of rects
3651 lineStart.set(0, 0);
3652 signed char directions[] = {-1, -1, -1, -1, -1}; // -1 to 3; -1 is uninitialized
3653 bool closedOrMoved = false;
3654 bool autoClose = false;
3655 bool insertClose = false;
3656 int verbCnt = path.fPathRef->countVerbs();
3657 while (*currVerb < verbCnt && (!allowPartial || !autoClose)) {
3658 uint8_t verb = insertClose ? (uint8_t) SkPath::kClose_Verb : path.fPathRef->atVerb(*currVerb);
3659 switch (verb) {
3661 savePts = pts;
3662 autoClose = true;
3663 insertClose = false;
3664 [[fallthrough]];
3665 case SkPath::kLine_Verb: {
3666 if (SkPath::kClose_Verb != verb) {
3667 lastPt = pts;
3668 }
3669 SkPoint lineEnd = SkPath::kClose_Verb == verb ? *firstPt : *pts++;
3670 SkVector lineDelta = lineEnd - lineStart;
3671 if (lineDelta.fX && lineDelta.fY) {
3672 return false; // diagonal
3673 }
3674 if (!lineDelta.isFinite()) {
3675 return false; // path contains infinity or NaN
3676 }
3677 if (lineStart == lineEnd) {
3678 break; // single point on side OK
3679 }
3680 int nextDirection = rect_make_dir(lineDelta.fX, lineDelta.fY); // 0 to 3
3681 if (0 == corners) {
3682 directions[0] = nextDirection;
3683 corners = 1;
3684 closedOrMoved = false;
3685 lineStart = lineEnd;
3686 break;
3687 }
3688 if (closedOrMoved) {
3689 return false; // closed followed by a line
3690 }
3691 if (autoClose && nextDirection == directions[0]) {
3692 break; // colinear with first
3693 }
3694 closedOrMoved = autoClose;
3695 if (directions[corners - 1] == nextDirection) {
3696 if (3 == corners && SkPath::kLine_Verb == verb) {
3697 thirdCorner = lineEnd;
3698 }
3699 lineStart = lineEnd;
3700 break; // colinear segment
3701 }
3702 directions[corners++] = nextDirection;
3703 // opposite lines must point in opposite directions; xoring them should equal 2
3704 switch (corners) {
3705 case 2:
3706 firstCorner = lineStart;
3707 break;
3708 case 3:
3709 if ((directions[0] ^ directions[2]) != 2) {
3710 return false;
3711 }
3712 thirdCorner = lineEnd;
3713 break;
3714 case 4:
3715 if ((directions[1] ^ directions[3]) != 2) {
3716 return false;
3717 }
3718 break;
3719 default:
3720 return false; // too many direction changes
3721 }
3722 lineStart = lineEnd;
3723 break;
3724 }
3725 case SkPath::kQuad_Verb:
3728 return false; // quadratic, cubic not allowed
3729 case SkPath::kMove_Verb:
3730 if (allowPartial && !autoClose && directions[0] >= 0) {
3731 insertClose = true;
3732 *currVerb -= 1; // try move again afterwards
3733 goto addMissingClose;
3734 }
3735 if (!corners) {
3736 firstPt = pts;
3737 } else {
3738 closeXY = *firstPt - *lastPt;
3739 if (closeXY.fX && closeXY.fY) {
3740 return false; // we're diagonal, abort
3741 }
3742 }
3743 lineStart = *pts++;
3744 closedOrMoved = true;
3745 break;
3746 default:
3747 SkDEBUGFAIL("unexpected verb");
3748 break;
3749 }
3750 *currVerb += 1;
3751 addMissingClose:
3752 ;
3753 }
3754 // Success if 4 corners and first point equals last
3755 if (corners < 3 || corners > 4) {
3756 return false;
3757 }
3758 if (savePts) {
3759 *ptsPtr = savePts;
3760 }
3761 // check if close generates diagonal
3762 closeXY = *firstPt - *lastPt;
3763 if (closeXY.fX && closeXY.fY) {
3764 return false;
3765 }
3766 if (rect) {
3767 rect->set(firstCorner, thirdCorner);
3768 }
3769 if (isClosed) {
3770 *isClosed = autoClose;
3771 }
3772 if (direction) {
3773 *direction = directions[0] == ((directions[1] + 1) & 3) ?
3775 }
3776 return true;
3777}
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
static int rect_make_dir(SkScalar dx, SkScalar dy)
Definition: SkPath.cpp:512
@ kClose_Verb
Definition: SkPath.h:1471
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467
bool isFinite() const
Definition: SkPoint_impl.h:412
void set(float x, float y)
Definition: SkPoint_impl.h:200

◆ IsRRect()

static bool SkPathPriv::IsRRect ( const SkPath path,
SkRRect rrect,
SkPathDirection dir,
unsigned *  start 
)
inlinestatic

Returns true if constructed by addRoundRect(), addRRect(); and if construction is not empty, not SkRect, and not oval. SkPath constructed with other calls will not return true though SkPath draws SkRRect.

rrect receives bounds of SkRRect. dir receives SkPathDirection of oval: kCW_Direction if clockwise, kCCW_Direction if counterclockwise. start receives start of SkRRect: 0 for top, 1 for right, 2 for bottom, 3 for left.

rrect, dir, and start are unmodified if SkRRect is not found.

Triggers performance optimizations on some GPU surface implementations.

Parameters
rrectstorage for bounding SkRect of SkRRect; may be nullptr
dirstorage for SkPathDirection; may be nullptr
startstorage for start of SkRRect; may be nullptr
Returns
true if SkPath contains only SkRRect

Definition at line 272 of file SkPathPriv.h.

273 {
274 bool isCCW = false;
275 bool result = path.fPathRef->isRRect(rrect, &isCCW, start);
276 if (dir && result) {
278 }
279 return result;
280 }
SkRRect rrect
Definition: SkRecords.h:232

◆ IsSimpleRect()

bool SkPathPriv::IsSimpleRect ( const SkPath path,
bool  isSimpleFill,
SkRect rect,
SkPathDirection direction,
unsigned *  start 
)
static

This returns true for a rect that has a move followed by 3 or 4 lines and a close. If 'isSimpleFill' is true, an uncloseed rect will also be accepted as long as it starts and ends at the same corner. This does not permit degenerate line or point rectangles.

Definition at line 3244 of file SkPath.cpp.

3245 {
3246 if (path.getSegmentMasks() != SkPath::kLine_SegmentMask) {
3247 return false;
3248 }
3249 SkPoint rectPts[5];
3250 int rectPtCnt = 0;
3251 bool needsClose = !isSimpleFill;
3252 for (auto [v, verbPts, w] : SkPathPriv::Iterate(path)) {
3253 switch (v) {
3254 case SkPathVerb::kMove:
3255 if (0 != rectPtCnt) {
3256 return false;
3257 }
3258 rectPts[0] = verbPts[0];
3259 ++rectPtCnt;
3260 break;
3261 case SkPathVerb::kLine:
3262 if (5 == rectPtCnt) {
3263 return false;
3264 }
3265 rectPts[rectPtCnt] = verbPts[1];
3266 ++rectPtCnt;
3267 break;
3268 case SkPathVerb::kClose:
3269 if (4 == rectPtCnt) {
3270 rectPts[4] = rectPts[0];
3271 rectPtCnt = 5;
3272 }
3273 needsClose = false;
3274 break;
3275 case SkPathVerb::kQuad:
3276 case SkPathVerb::kConic:
3277 case SkPathVerb::kCubic:
3278 return false;
3279 }
3280 }
3281 if (needsClose) {
3282 return false;
3283 }
3284 if (rectPtCnt < 5) {
3285 return false;
3286 }
3287 if (rectPts[0] != rectPts[4]) {
3288 return false;
3289 }
3290 // Check for two cases of rectangles: pts 0 and 3 form a vertical edge or a horizontal edge (
3291 // and pts 1 and 2 the opposite vertical or horizontal edge).
3292 bool vec03IsVertical;
3293 if (rectPts[0].fX == rectPts[3].fX && rectPts[1].fX == rectPts[2].fX &&
3294 rectPts[0].fY == rectPts[1].fY && rectPts[3].fY == rectPts[2].fY) {
3295 // Make sure it has non-zero width and height
3296 if (rectPts[0].fX == rectPts[1].fX || rectPts[0].fY == rectPts[3].fY) {
3297 return false;
3298 }
3299 vec03IsVertical = true;
3300 } else if (rectPts[0].fY == rectPts[3].fY && rectPts[1].fY == rectPts[2].fY &&
3301 rectPts[0].fX == rectPts[1].fX && rectPts[3].fX == rectPts[2].fX) {
3302 // Make sure it has non-zero width and height
3303 if (rectPts[0].fY == rectPts[1].fY || rectPts[0].fX == rectPts[3].fX) {
3304 return false;
3305 }
3306 vec03IsVertical = false;
3307 } else {
3308 return false;
3309 }
3310 // Set sortFlags so that it has the low bit set if pt index 0 is on right edge and second bit
3311 // set if it is on the bottom edge.
3312 unsigned sortFlags =
3313 ((rectPts[0].fX < rectPts[2].fX) ? 0b00 : 0b01) |
3314 ((rectPts[0].fY < rectPts[2].fY) ? 0b00 : 0b10);
3315 switch (sortFlags) {
3316 case 0b00:
3317 rect->setLTRB(rectPts[0].fX, rectPts[0].fY, rectPts[2].fX, rectPts[2].fY);
3318 *direction = vec03IsVertical ? SkPathDirection::kCW : SkPathDirection::kCCW;
3319 *start = 0;
3320 break;
3321 case 0b01:
3322 rect->setLTRB(rectPts[2].fX, rectPts[0].fY, rectPts[0].fX, rectPts[2].fY);
3323 *direction = vec03IsVertical ? SkPathDirection::kCCW : SkPathDirection::kCW;
3324 *start = 1;
3325 break;
3326 case 0b10:
3327 rect->setLTRB(rectPts[0].fX, rectPts[2].fY, rectPts[2].fX, rectPts[0].fY);
3328 *direction = vec03IsVertical ? SkPathDirection::kCCW : SkPathDirection::kCW;
3329 *start = 3;
3330 break;
3331 case 0b11:
3332 rect->setLTRB(rectPts[2].fX, rectPts[2].fY, rectPts[0].fX, rectPts[0].fY);
3333 *direction = vec03IsVertical ? SkPathDirection::kCW : SkPathDirection::kCCW;
3334 *start = 2;
3335 break;
3336 }
3337 return true;
3338}
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
@ kLine_SegmentMask
Definition: SkPath.h:1445
SkScalar w

◆ LastMoveToIndex()

static int SkPathPriv::LastMoveToIndex ( const SkPath path)
inlinestatic

Definition at line 348 of file SkPathPriv.h.

348{ return path.fLastMoveToIndex; }

◆ LeadingMoveToCount()

static int SkPathPriv::LeadingMoveToCount ( const SkPath path)
inlinestatic

Definition at line 95 of file SkPathPriv.h.

95 {
96 int verbCount = path.countVerbs();
97 auto verbs = path.fPathRef->verbsBegin();
98 for (int i = 0; i < verbCount; i++) {
99 if (verbs[i] != SkPath::Verb::kMove_Verb) {
100 return i;
101 }
102 }
103 return verbCount; // path is all move verbs
104 }

◆ MakePath()

static SkPath SkPathPriv::MakePath ( const SkPathVerbAnalysis analysis,
const SkPoint  points[],
const uint8_t  verbs[],
int  verbCount,
const SkScalar  conics[],
SkPathFillType  fillType,
bool  isVolatile 
)
inlinestatic

Definition at line 425 of file SkPathPriv.h.

431 {
432 return SkPath::MakeInternal(analysis, points, verbs, verbCount, conics, fillType,
433 isVolatile);
434 }

◆ OppositeFirstDirection()

static SkPathFirstDirection SkPathPriv::OppositeFirstDirection ( SkPathFirstDirection  dir)
inlinestatic

Return the opposite of the specified direction. kUnknown is its own opposite.

Definition at line 52 of file SkPathPriv.h.

52 {
53 static const SkPathFirstDirection gOppositeDir[] = {
55 };
56 return gOppositeDir[(unsigned)dir];
57 }

◆ PerspectiveClip()

bool SkPathPriv::PerspectiveClip ( const SkPath src,
const SkMatrix matrix,
SkPath result 
)
static

If needed (to not blow-up under a perspective matrix), clip the path, returning the answer in "result", and return true.

Note result might be empty (if the path was completely clipped out).

If no clipping is needed, returns false and "result" is left unchanged.

Definition at line 3962 of file SkPath.cpp.

3962 {
3963 if (!matrix.hasPerspective()) {
3964 return false;
3965 }
3966
3967 SkHalfPlane plane {
3971 };
3972 if (plane.normalize()) {
3973 switch (plane.test(path.getBounds())) {
3975 return false;
3976 case SkHalfPlane::kMixed: {
3977 *clippedPath = clip(path, plane);
3978 return true;
3979 }
3980 default: break; // handled outside of the switch
3981 }
3982 }
3983 // clipped out (or failed)
3984 *clippedPath = SkPath();
3985 return true;
3986}
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
static constexpr int kMPersp1
input y perspective factor
Definition: SkMatrix.h:360
static constexpr int kMPersp0
input x perspective factor
Definition: SkMatrix.h:359
static constexpr int kMPersp2
perspective bias
Definition: SkMatrix.h:361
static constexpr SkScalar kW0PlaneDistance
Definition: SkPathPriv.h:41
Definition: SkPath.h:59
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258

◆ PointData()

static const SkPoint * SkPathPriv::PointData ( const SkPath path)
inlinestatic

Returns a raw pointer to the path points

Definition at line 203 of file SkPathPriv.h.

203 {
204 return path.fPathRef->points();
205 }

◆ PtsInIter()

static int SkPathPriv::PtsInIter ( unsigned  verb)
inlinestatic

Definition at line 305 of file SkPathPriv.h.

305 {
306 static const uint8_t gPtsInVerb[] = {
307 1, // kMove pts[0]
308 2, // kLine pts[0..1]
309 3, // kQuad pts[0..2]
310 3, // kConic pts[0..2]
311 4, // kCubic pts[0..3]
312 0, // kClose
313 0 // kDone
314 };
315
316 SkASSERT(verb < std::size(gPtsInVerb));
317 return gPtsInVerb[verb];
318 }
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
Definition: switches.h:259

◆ PtsInVerb()

static int SkPathPriv::PtsInVerb ( unsigned  verb)
inlinestatic

Definition at line 322 of file SkPathPriv.h.

322 {
323 static const uint8_t gPtsInVerb[] = {
324 1, // kMove pts[0]
325 1, // kLine pts[0..1]
326 2, // kQuad pts[0..2]
327 2, // kConic pts[0..2]
328 3, // kCubic pts[0..3]
329 0, // kClose
330 0 // kDone
331 };
332
333 SkASSERT(verb < std::size(gPtsInVerb));
334 return gPtsInVerb[verb];
335 }

◆ ReverseAddPath()

static void SkPathPriv::ReverseAddPath ( SkPathBuilder builder,
const SkPath reverseMe 
)
inlinestatic

Definition at line 421 of file SkPathPriv.h.

421 {
422 builder->privateReverseAddPath(reverseMe);
423 }

◆ SetConvexity()

static void SkPathPriv::SetConvexity ( const SkPath path,
SkPathConvexity  c 
)
inlinestatic

Definition at line 413 of file SkPathPriv.h.

413 {
414 path.setConvexity(c);
415 }

◆ ShrinkToFit()

static void SkPathPriv::ShrinkToFit ( SkPath path)
inlinestatic

Definition at line 130 of file SkPathPriv.h.

130 {
131 path->shrinkToFit();
132 }

◆ TestingOnly_unique()

static bool SkPathPriv::TestingOnly_unique ( const SkPath path)
inlinestatic

Returns true if the underlying SkPathRef has one single owner.

Definition at line 218 of file SkPathPriv.h.

218 {
219 return path.fPathRef->unique();
220 }

◆ TooBigForMath() [1/2]

static bool SkPathPriv::TooBigForMath ( const SkPath path)
inlinestatic

Definition at line 300 of file SkPathPriv.h.

300 {
301 return TooBigForMath(path.getBounds());
302 }
static bool TooBigForMath(const SkRect &bounds)
Definition: SkPathPriv.h:290

◆ TooBigForMath() [2/2]

static bool SkPathPriv::TooBigForMath ( const SkRect bounds)
inlinestatic

Sometimes in the drawing pipeline, we have to perform math on path coordinates, even after the path is in device-coordinates. Tessellation and clipping are two examples. Usually this is pretty modest, but it can involve subtracting/adding coordinates, or multiplying by small constants (e.g. 2,3,4). To try to preflight issues where these optionations could turn finite path values into infinities (or NaNs), we allow the upper drawing code to reject the path if its bounds (in device coordinates) is too close to max float.

Definition at line 290 of file SkPathPriv.h.

290 {
291 // This value is just a guess. smaller is safer, but we don't want to reject largish paths
292 // that we don't have to.
293 constexpr SkScalar scale_down_to_allow_for_small_multiplies = 0.25f;
294 constexpr SkScalar max = SK_ScalarMax * scale_down_to_allow_for_small_multiplies;
295
296 // use ! expression so we return true if bounds contains NaN
297 return !(bounds.fLeft >= -max && bounds.fTop >= -max &&
298 bounds.fRight <= max && bounds.fBottom <= max);
299 }
#define SK_ScalarMax
Definition: SkScalar.h:24
static float max(float r, float g, float b)
Definition: hsl.cpp:49
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ UpdatePathPoint()

static void SkPathPriv::UpdatePathPoint ( SkPath path,
int  index,
const SkPoint pt 
)
inlinestatic

Definition at line 400 of file SkPathPriv.h.

400 {
401 SkASSERT(index < path->countPoints());
402 SkPathRef::Editor ed(&path->fPathRef);
403 ed.writablePoints()[index] = pt;
404 path->dirtyAfterEdit();
405 }

◆ VerbData()

static const uint8_t * SkPathPriv::VerbData ( const SkPath path)
inlinestatic

Returns a pointer to the verb data.

Definition at line 198 of file SkPathPriv.h.

198 {
199 return path.fPathRef->verbsBegin();
200 }

Member Data Documentation

◆ kW0PlaneDistance

constexpr SkScalar SkPathPriv::kW0PlaneDistance = 1.f / (1 << 14)
inlinestaticconstexpr

Definition at line 41 of file SkPathPriv.h.


The documentation for this class was generated from the following files: