Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect)
 
static bool DrawArcIsConvex (SkScalar sweepAngle, bool useCenter, 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 36 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 105 of file SkPathPriv.h.

105 {
106 path.fPathRef->addGenIDChangeListener(std::move(listener));
107 }
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

◆ AsFirstDirection()

static SkPathFirstDirection SkPathPriv::AsFirstDirection ( SkPathDirection  dir)
inlinestatic

Definition at line 42 of file SkPathPriv.h.

42 {
43 // since we agree numerically for the values in Direction, we can just cast.
45 }
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 2563 of file SkPath.cpp.

2563 {
2564 auto d = path.getFirstDirection();
2566 return d;
2567 }
2568
2569 // We don't want to pay the cost for computing convexity if it is unknown,
2570 // so we call getConvexityOrUnknown() instead of isConvex().
2571 if (path.getConvexityOrUnknown() == SkPathConvexity::kConvex) {
2573 return d;
2574 }
2575
2576 ContourIter iter(*path.fPathRef);
2577
2578 // initialize with our logical y-min
2579 SkScalar ymax = path.getBounds().fTop;
2580 SkScalar ymaxCross = 0;
2581
2582 for (; !iter.done(); iter.next()) {
2583 int n = iter.count();
2584 if (n < 3) {
2585 continue;
2586 }
2587
2588 const SkPoint* pts = iter.pts();
2589 SkScalar cross = 0;
2590 int index = find_max_y(pts, n);
2591 if (pts[index].fY < ymax) {
2592 continue;
2593 }
2594
2595 // If there is more than 1 distinct point at the y-max, we take the
2596 // x-min and x-max of them and just subtract to compute the dir.
2597 if (pts[(index + 1) % n].fY == pts[index].fY) {
2598 int maxIndex;
2599 int minIndex = find_min_max_x_at_y(pts, index, n, &maxIndex);
2600 if (minIndex == maxIndex) {
2601 goto TRY_CROSSPROD;
2602 }
2603 SkASSERT(pts[minIndex].fY == pts[index].fY);
2604 SkASSERT(pts[maxIndex].fY == pts[index].fY);
2605 SkASSERT(pts[minIndex].fX <= pts[maxIndex].fX);
2606 // we just subtract the indices, and let that auto-convert to
2607 // SkScalar, since we just want - or + to signal the direction.
2608 cross = minIndex - maxIndex;
2609 } else {
2610 TRY_CROSSPROD:
2611 // Find a next and prev index to use for the cross-product test,
2612 // but we try to find pts that form non-zero vectors from pts[index]
2613 //
2614 // Its possible that we can't find two non-degenerate vectors, so
2615 // we have to guard our search (e.g. all the pts could be in the
2616 // same place).
2617
2618 // we pass n - 1 instead of -1 so we don't foul up % operator by
2619 // passing it a negative LH argument.
2620 int prev = find_diff_pt(pts, index, n, n - 1);
2621 if (prev == index) {
2622 // completely degenerate, skip to next contour
2623 continue;
2624 }
2625 int next = find_diff_pt(pts, index, n, 1);
2626 SkASSERT(next != index);
2627 cross = cross_prod(pts[prev], pts[index], pts[next]);
2628 // if we get a zero and the points are horizontal, then we look at the spread in
2629 // x-direction. We really should continue to walk away from the degeneracy until
2630 // there is a divergence.
2631 if (0 == cross && pts[prev].fY == pts[index].fY && pts[next].fY == pts[index].fY) {
2632 // construct the subtract so we get the correct Direction below
2633 cross = pts[index].fX - pts[next].fX;
2634 }
2635 }
2636
2637 if (cross) {
2638 // record our best guess so far
2639 ymax = pts[index].fY;
2640 ymaxCross = cross;
2641 }
2642 }
2643 if (ymaxCross) {
2644 d = crossToDir(ymaxCross);
2645 path.setFirstDirection(d);
2646 }
2647 return d; // may still be kUnknown
2648}
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:2473
static int find_diff_pt(const SkPoint pts[], int index, int n, int inc)
Definition SkPath.cpp:2509
static int find_max_y(const SkPoint pts[], int count)
Definition SkPath.cpp:2495
static SkPathFirstDirection crossToDir(SkScalar cross)
Definition SkPath.cpp:2551
static int find_min_max_x_at_y(const SkPoint pts[], int index, int n, int *maxIndexPtr)
Definition SkPath.cpp:2527
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
float fY
y-axis value

◆ 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 SkRect oval,
SkScalar  startAngle,
SkScalar  sweepAngle,
bool  useCenter,
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 3290 of file SkPath.cpp.

3291 {
3292 SkASSERT(!oval.isEmpty());
3293 SkASSERT(sweepAngle);
3294 // We cap the number of total rotations. This keeps the resulting paths simpler. More important,
3295 // it prevents values so large that the loops below never terminate (once ULP > 360).
3296 if (SkScalarAbs(sweepAngle) > 3600.0f) {
3297 sweepAngle = std::copysign(3600.0f, sweepAngle) + std::fmod(sweepAngle, 360.0f);
3298 }
3299 path->reset();
3300 path->setIsVolatile(true);
3301 path->setFillType(SkPathFillType::kWinding);
3302 if (isFillNoPathEffect && SkScalarAbs(sweepAngle) >= 360.f) {
3303 path->addOval(oval);
3304 SkASSERT(path->isConvex() && DrawArcIsConvex(sweepAngle, false, isFillNoPathEffect));
3305 return;
3306 }
3307 if (useCenter) {
3308 path->moveTo(oval.centerX(), oval.centerY());
3309 }
3310 auto firstDir =
3312 bool convex = DrawArcIsConvex(sweepAngle, useCenter, isFillNoPathEffect);
3313 // Arc to mods at 360 and drawArc is not supposed to.
3314 bool forceMoveTo = !useCenter;
3315 while (sweepAngle <= -360.f) {
3316 path->arcTo(oval, startAngle, -180.f, forceMoveTo);
3317 startAngle -= 180.f;
3318 path->arcTo(oval, startAngle, -180.f, false);
3319 startAngle -= 180.f;
3320 forceMoveTo = false;
3321 sweepAngle += 360.f;
3322 }
3323 while (sweepAngle >= 360.f) {
3324 path->arcTo(oval, startAngle, 180.f, forceMoveTo);
3325 startAngle += 180.f;
3326 path->arcTo(oval, startAngle, 180.f, false);
3327 startAngle += 180.f;
3328 forceMoveTo = false;
3329 sweepAngle -= 360.f;
3330 }
3331 path->arcTo(oval, startAngle, sweepAngle, forceMoveTo);
3332 if (useCenter) {
3333 path->close();
3334 }
3335 path->setConvexity(convex ? SkPathConvexity::kConvex : SkPathConvexity::kConcave);
3336 path->setFirstDirection(firstDir);
3337}
SkPathConvexity
Definition SkPathEnums.h:13
#define SkScalarAbs(x)
Definition SkScalar.h:39
static bool DrawArcIsConvex(SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect)
Definition SkPath.cpp:3276
SkRect oval
Definition SkRecords.h:249
SkScalar startAngle
Definition SkRecords.h:250
SkScalar sweepAngle
Definition SkRecords.h:251
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,
bool  useCenter,
bool  isFillNoPathEffect 
)
static

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

Definition at line 3276 of file SkPath.cpp.

3276 {
3277 if (isFillNoPathEffect && SkScalarAbs(sweepAngle) >= 360.f) {
3278 // This gets converted to an oval.
3279 return true;
3280 }
3281 if (useCenter) {
3282 // This is a pie wedge. It's convex if the angle is <= 180.
3283 return SkScalarAbs(sweepAngle) <= 180.f;
3284 }
3285 // When the angle exceeds 360 this wraps back on top of itself. Otherwise it is a circle clipped
3286 // to a secant, i.e. convex.
3287 return SkScalarAbs(sweepAngle) <= 360.f;
3288}

◆ 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 3920 of file SkPath.cpp.

3920 {
3921 return path.fPathRef->genIDChangeListenerCount();
3922}

◆ 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 3924 of file SkPath.cpp.

3924 {
3925 // Conservative (quick) test to see if all segments are axis-aligned.
3926 // Multiple contours might give a false-negative, but for speed, we ignore that
3927 // and just look at the raw points.
3928
3929 const SkPoint* pts = path.fPathRef->points();
3930 const int count = path.fPathRef->countPoints();
3931
3932 for (int i = 1; i < count; ++i) {
3933 if (pts[i-1].fX != pts[i].fX && pts[i-1].fY != pts[i].fY) {
3934 return false;
3935 }
3936 }
3937 return true;
3938}

◆ IsClosedSingleContour()

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

Definition at line 66 of file SkPathPriv.h.

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

◆ 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 3712 of file SkPath.cpp.

3712 {
3713 SkDEBUGCODE(path.validate();)
3714 int currVerb = 0;
3715 const SkPoint* pts = path.fPathRef->points();
3716 SkPathDirection testDirs[2];
3717 SkRect testRects[2];
3718 if (!IsRectContour(path, true, &currVerb, &pts, nullptr, &testDirs[0], &testRects[0])) {
3719 return false;
3720 }
3721 if (IsRectContour(path, false, &currVerb, &pts, nullptr, &testDirs[1], &testRects[1])) {
3722 if (testRects[0].contains(testRects[1])) {
3723 if (rects) {
3724 rects[0] = testRects[0];
3725 rects[1] = testRects[1];
3726 }
3727 if (dirs) {
3728 dirs[0] = testDirs[0];
3729 dirs[1] = testDirs[1];
3730 }
3731 return true;
3732 }
3733 if (testRects[1].contains(testRects[0])) {
3734 if (rects) {
3735 rects[0] = testRects[1];
3736 rects[1] = testRects[0];
3737 }
3738 if (dirs) {
3739 dirs[0] = testDirs[1];
3740 dirs[1] = testDirs[0];
3741 }
3742 return true;
3743 }
3744 }
3745 return false;
3746}
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static bool contains(const SkRect &r, SkPoint p)
SkPathDirection
Definition SkPathTypes.h:34
static bool IsRectContour(const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
Definition SkPath.cpp:3571

◆ 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

◆ IsRectContour()

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

Definition at line 3571 of file SkPath.cpp.

3573 {
3574 int corners = 0;
3575 SkPoint closeXY; // used to determine if final line falls on a diagonal
3576 SkPoint lineStart; // used to construct line from previous point
3577 const SkPoint* firstPt = nullptr; // first point in the rect (last of first moves)
3578 const SkPoint* lastPt = nullptr; // last point in the rect (last of lines or first if closed)
3579 SkPoint firstCorner;
3580 SkPoint thirdCorner;
3581 const SkPoint* pts = *ptsPtr;
3582 const SkPoint* savePts = nullptr; // used to allow caller to iterate through a pair of rects
3583 lineStart.set(0, 0);
3584 signed char directions[] = {-1, -1, -1, -1, -1}; // -1 to 3; -1 is uninitialized
3585 bool closedOrMoved = false;
3586 bool autoClose = false;
3587 bool insertClose = false;
3588 int verbCnt = path.fPathRef->countVerbs();
3589 while (*currVerb < verbCnt && (!allowPartial || !autoClose)) {
3590 uint8_t verb = insertClose ? (uint8_t) SkPath::kClose_Verb : path.fPathRef->atVerb(*currVerb);
3591 switch (verb) {
3593 savePts = pts;
3594 autoClose = true;
3595 insertClose = false;
3596 [[fallthrough]];
3597 case SkPath::kLine_Verb: {
3598 if (SkPath::kClose_Verb != verb) {
3599 lastPt = pts;
3600 }
3601 SkPoint lineEnd = SkPath::kClose_Verb == verb ? *firstPt : *pts++;
3602 SkVector lineDelta = lineEnd - lineStart;
3603 if (lineDelta.fX && lineDelta.fY) {
3604 return false; // diagonal
3605 }
3606 if (!lineDelta.isFinite()) {
3607 return false; // path contains infinity or NaN
3608 }
3609 if (lineStart == lineEnd) {
3610 break; // single point on side OK
3611 }
3612 int nextDirection = rect_make_dir(lineDelta.fX, lineDelta.fY); // 0 to 3
3613 if (0 == corners) {
3614 directions[0] = nextDirection;
3615 corners = 1;
3616 closedOrMoved = false;
3617 lineStart = lineEnd;
3618 break;
3619 }
3620 if (closedOrMoved) {
3621 return false; // closed followed by a line
3622 }
3623 if (autoClose && nextDirection == directions[0]) {
3624 break; // colinear with first
3625 }
3626 closedOrMoved = autoClose;
3627 if (directions[corners - 1] == nextDirection) {
3628 if (3 == corners && SkPath::kLine_Verb == verb) {
3629 thirdCorner = lineEnd;
3630 }
3631 lineStart = lineEnd;
3632 break; // colinear segment
3633 }
3634 directions[corners++] = nextDirection;
3635 // opposite lines must point in opposite directions; xoring them should equal 2
3636 switch (corners) {
3637 case 2:
3638 firstCorner = lineStart;
3639 break;
3640 case 3:
3641 if ((directions[0] ^ directions[2]) != 2) {
3642 return false;
3643 }
3644 thirdCorner = lineEnd;
3645 break;
3646 case 4:
3647 if ((directions[1] ^ directions[3]) != 2) {
3648 return false;
3649 }
3650 break;
3651 default:
3652 return false; // too many direction changes
3653 }
3654 lineStart = lineEnd;
3655 break;
3656 }
3657 case SkPath::kQuad_Verb:
3660 return false; // quadratic, cubic not allowed
3661 case SkPath::kMove_Verb:
3662 if (allowPartial && !autoClose && directions[0] >= 0) {
3663 insertClose = true;
3664 *currVerb -= 1; // try move again afterwards
3665 goto addMissingClose;
3666 }
3667 if (!corners) {
3668 firstPt = pts;
3669 } else {
3670 closeXY = *firstPt - *lastPt;
3671 if (closeXY.fX && closeXY.fY) {
3672 return false; // we're diagonal, abort
3673 }
3674 }
3675 lineStart = *pts++;
3676 closedOrMoved = true;
3677 break;
3678 default:
3679 SkDEBUGFAIL("unexpected verb");
3680 break;
3681 }
3682 *currVerb += 1;
3683 addMissingClose:
3684 ;
3685 }
3686 // Success if 4 corners and first point equals last
3687 if (corners < 3 || corners > 4) {
3688 return false;
3689 }
3690 if (savePts) {
3691 *ptsPtr = savePts;
3692 }
3693 // check if close generates diagonal
3694 closeXY = *firstPt - *lastPt;
3695 if (closeXY.fX && closeXY.fY) {
3696 return false;
3697 }
3698 if (rect) {
3699 rect->set(firstCorner, thirdCorner);
3700 }
3701 if (isClosed) {
3702 *isClosed = autoClose;
3703 }
3704 if (direction) {
3705 *direction = directions[0] == ((directions[1] + 1) & 3) ?
3707 }
3708 return true;
3709}
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
static int rect_make_dir(SkScalar dx, SkScalar dy)
Definition SkPath.cpp:502
@ kConic_Verb
Definition SkPath.h:1461
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
bool isFinite() const
void set(float x, float y)

◆ 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 }

◆ 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 3180 of file SkPath.cpp.

3181 {
3182 if (path.getSegmentMasks() != SkPath::kLine_SegmentMask) {
3183 return false;
3184 }
3185 SkPoint rectPts[5];
3186 int rectPtCnt = 0;
3187 bool needsClose = !isSimpleFill;
3188 for (auto [v, verbPts, w] : SkPathPriv::Iterate(path)) {
3189 switch (v) {
3190 case SkPathVerb::kMove:
3191 if (0 != rectPtCnt) {
3192 return false;
3193 }
3194 rectPts[0] = verbPts[0];
3195 ++rectPtCnt;
3196 break;
3197 case SkPathVerb::kLine:
3198 if (5 == rectPtCnt) {
3199 return false;
3200 }
3201 rectPts[rectPtCnt] = verbPts[1];
3202 ++rectPtCnt;
3203 break;
3204 case SkPathVerb::kClose:
3205 if (4 == rectPtCnt) {
3206 rectPts[4] = rectPts[0];
3207 rectPtCnt = 5;
3208 }
3209 needsClose = false;
3210 break;
3211 case SkPathVerb::kQuad:
3212 case SkPathVerb::kConic:
3213 case SkPathVerb::kCubic:
3214 return false;
3215 }
3216 }
3217 if (needsClose) {
3218 return false;
3219 }
3220 if (rectPtCnt < 5) {
3221 return false;
3222 }
3223 if (rectPts[0] != rectPts[4]) {
3224 return false;
3225 }
3226 // Check for two cases of rectangles: pts 0 and 3 form a vertical edge or a horizontal edge (
3227 // and pts 1 and 2 the opposite vertical or horizontal edge).
3228 bool vec03IsVertical;
3229 if (rectPts[0].fX == rectPts[3].fX && rectPts[1].fX == rectPts[2].fX &&
3230 rectPts[0].fY == rectPts[1].fY && rectPts[3].fY == rectPts[2].fY) {
3231 // Make sure it has non-zero width and height
3232 if (rectPts[0].fX == rectPts[1].fX || rectPts[0].fY == rectPts[3].fY) {
3233 return false;
3234 }
3235 vec03IsVertical = true;
3236 } else if (rectPts[0].fY == rectPts[3].fY && rectPts[1].fY == rectPts[2].fY &&
3237 rectPts[0].fX == rectPts[1].fX && rectPts[3].fX == rectPts[2].fX) {
3238 // Make sure it has non-zero width and height
3239 if (rectPts[0].fY == rectPts[1].fY || rectPts[0].fX == rectPts[3].fX) {
3240 return false;
3241 }
3242 vec03IsVertical = false;
3243 } else {
3244 return false;
3245 }
3246 // Set sortFlags so that it has the low bit set if pt index 0 is on right edge and second bit
3247 // set if it is on the bottom edge.
3248 unsigned sortFlags =
3249 ((rectPts[0].fX < rectPts[2].fX) ? 0b00 : 0b01) |
3250 ((rectPts[0].fY < rectPts[2].fY) ? 0b00 : 0b10);
3251 switch (sortFlags) {
3252 case 0b00:
3253 rect->setLTRB(rectPts[0].fX, rectPts[0].fY, rectPts[2].fX, rectPts[2].fY);
3254 *direction = vec03IsVertical ? SkPathDirection::kCW : SkPathDirection::kCCW;
3255 *start = 0;
3256 break;
3257 case 0b01:
3258 rect->setLTRB(rectPts[2].fX, rectPts[0].fY, rectPts[0].fX, rectPts[2].fY);
3259 *direction = vec03IsVertical ? SkPathDirection::kCCW : SkPathDirection::kCW;
3260 *start = 1;
3261 break;
3262 case 0b10:
3263 rect->setLTRB(rectPts[0].fX, rectPts[2].fY, rectPts[2].fX, rectPts[0].fY);
3264 *direction = vec03IsVertical ? SkPathDirection::kCCW : SkPathDirection::kCW;
3265 *start = 3;
3266 break;
3267 case 0b11:
3268 rect->setLTRB(rectPts[2].fX, rectPts[2].fY, rectPts[0].fX, rectPts[0].fY);
3269 *direction = vec03IsVertical ? SkPathDirection::kCW : SkPathDirection::kCCW;
3270 *start = 2;
3271 break;
3272 }
3273 return true;
3274}
@ 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:1437
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 94 of file SkPathPriv.h.

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

◆ 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 }
static const int points[]

◆ OppositeFirstDirection()

static SkPathFirstDirection SkPathPriv::OppositeFirstDirection ( SkPathFirstDirection  dir)
inlinestatic

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

Definition at line 51 of file SkPathPriv.h.

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

◆ 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 3894 of file SkPath.cpp.

3894 {
3895 if (!matrix.hasPerspective()) {
3896 return false;
3897 }
3898
3899 SkHalfPlane plane {
3903 };
3904 if (plane.normalize()) {
3905 switch (plane.test(path.getBounds())) {
3907 return false;
3908 case SkHalfPlane::kMixed: {
3909 *clippedPath = clip(path, plane);
3910 return true;
3911 }
3912 default: break; // handled outside of the switch
3913 }
3914 }
3915 // clipped out (or failed)
3916 *clippedPath = SkPath();
3917 return true;
3918}
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
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:40
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 }

◆ 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 40 of file SkPathPriv.h.


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