49 "Please keep an eye on SkPath packing.");
52 return (
A * t +
B) * t +
C;
56 return ((
A * t +
B) * t +
C) * t +
D;
84 fPath->setFirstDirection(fSaved);
111 fHasValidBounds =
path->hasComputedBounds() &&
path->isFinite();
112 fEmpty =
path->isEmpty();
113 if (fHasValidBounds && !fEmpty) {
122 if ((fEmpty || fHasValidBounds) && fRect.
isFinite()) {
123 fPath->setBounds(fRect);
130 bool fHasValidBounds;
154#define INITIAL_LASTMOVETOINDEX_VALUE ~0
164 : fPathRef(
std::move(pr))
166 , fConvexity((uint8_t)ct)
167 , fFirstDirection((uint8_t)firstDirection)
168 , fFillType((unsigned)ft)
169 , fIsVolatile(isVolatile)
172void SkPath::resetFields() {
181 : fPathRef(
SkRef(that.fPathRef.
get())) {
182 this->copyFields(that);
195 this->copyFields(that);
201void SkPath::copyFields(
const SkPath& that) {
203 fLastMoveToIndex = that.fLastMoveToIndex;
204 fFillType = that.fFillType;
205 fIsVolatile = that.fIsVolatile;
208 this->setConvexity(that.getConvexityOrUnknown());
209 this->setFirstDirection(that.getFirstDirection());
216 (
a.fFillType ==
b.fFillType && *
a.fPathRef == *
b.fPathRef);
221 fPathRef.
swap(that.fPathRef);
222 std::swap(fLastMoveToIndex, that.fLastMoveToIndex);
224 const auto ft = fFillType;
225 fFillType = that.fFillType;
228 const auto iv = fIsVolatile;
229 fIsVolatile = that.fIsVolatile;
230 that.fIsVolatile = iv;
234 this->setConvexity(that.getConvexityOrUnknown());
235 that.setConvexity(c);
238 this->setFirstDirection(that.getFirstDirection());
239 that.setFirstDirection(fd);
245 return fPathRef->fPoints.
size() ==
compare.fPathRef->fPoints.size() &&
246 fPathRef->fVerbs ==
compare.fPathRef->fVerbs &&
247 fPathRef->fConicWeights ==
compare.fPathRef->fConicWeights;
252 if (pointCount != ending.fPathRef->
countPoints()) {
261 fPathRef->
interpolate(*ending.fPathRef, weight,
out->fPathRef.get());
284 if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
304 int segmentCount = 0;
319 firstPt = prevPt = pts[0];
326 int nextPt = pointCount;
329 if (prevPt == pts[nextPt]) {
339 orig.
set(pts, *weight);
355 prevPt = pts[nextPt];
367 return fPathRef->
genID(fFillType);
392 if (0 == verbCount) {
401 if (2 == verbCount) {
439 return this->isValidImpl() && fPathRef->
isValid();
442bool SkPath::hasComputedBounds()
const {
457void SkPath::validate()
const {
461void SkPath::validateRef()
const {
463 fPathRef->validate();
513 return ((0 !=
dx) << 0) | ((
dx > 0 || dy > 0) << 1);
532 return fPathRef->
isArc(arc);
550 if ((
unsigned)index < (
unsigned)fPathRef->
countPoints()) {
551 return fPathRef->
atPoint(index);
574 if (fPathRef !=
nullptr) {
600 if (
count <= index) {
604 ed.atPoint(index)->set(
x,
y);
622 fConvexity.store((uint8_t)c, std::memory_order_relaxed);
627 fConvexity.store((uint8_t)c, std::memory_order_relaxed);
630 fFirstDirection.store((uint8_t)
d, std::memory_order_relaxed);
636bool SkPath::isConvexityAccurate()
const {
639 auto conv = this->computeConvexity();
640 if (conv != convexity) {
653 convexity = this->computeConvexity();
662SkPath& SkPath::dirtyAfterEdit() {
680 if (extraPtCount > 0) {
683 SkPathRef::Editor(&fPathRef, extraVerbCount == 0 ? extraPtCount : extraVerbCount, extraPtCount, extraConicCount);
698 return this->dirtyAfterEdit();
705 if (fLastMoveToIndex >= 0) {
708 pt = fPathRef->
atPoint(~fLastMoveToIndex);
714void SkPath::injectMoveToIfNeeded() {
715 if (fLastMoveToIndex < 0) {
731 this->injectMoveToIfNeeded();
736 return this->dirtyAfterEdit();
740 this->injectMoveToIfNeeded();
749 this->injectMoveToIfNeeded();
756 return this->dirtyAfterEdit();
760 this->injectMoveToIfNeeded();
763 return this->
quadTo(pt.
fX + x1, pt.
fY + y1, pt.
fX + x2, pt.
fY + y2);
775 this->
quadTo(x1, y1, x2, y2);
779 this->injectMoveToIfNeeded();
786 (void)this->dirtyAfterEdit();
793 this->injectMoveToIfNeeded();
796 return this->
conicTo(pt.
fX + dx1, pt.
fY + dy1, pt.
fX + dx2, pt.
fY + dy2,
w);
803 this->injectMoveToIfNeeded();
811 return this->dirtyAfterEdit();
816 this->injectMoveToIfNeeded();
820 pt.
fX + x3, pt.
fY + y3);
849 if (fLastMoveToIndex >= 0) {
850 fLastMoveToIndex = ~fLastMoveToIndex;
853 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 *
sizeof(fLastMoveToIndex) - 1);
873 const int kVerbs = 5;
884 (void)this->dirtyAfterEdit();
909 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 *
sizeof(fLastMoveToIndex) - 1);
912 (void)this->dirtyAfterEdit();
958 if (*startV == *stopV) {
968 }
while (*startV == *stopV);
988 matrix.mapXY(stop.
x(), stop.
y(), singlePt);
1008 bool isRRect = hasOnlyMoveTos();
1013 this->
addRect(bounds,
dir, (startIndex + 1) / 2);
1031 const int kVerbs = startsWithConic
1034 const int kPoints = startsWithConic
1037 const int kWeights = 4;
1047 if (startsWithConic) {
1048 for (
unsigned i = 0;
i < 3; ++
i) {
1055 for (
unsigned i = 0;
i < 4; ++
i) {
1076bool SkPath::hasOnlyMoveTos()
const {
return this->
getSegmentMasks() == 0; }
1078bool SkPath::isZeroLengthSincePoint(
int startPtIndex)
const {
1085 for (
int index = 1; index <
count; ++index) {
1086 if (first != pts[index]) {
1097 if (rx < 0 || ry < 0) {
1120 bool isOval = hasOnlyMoveTos();
1133 const int kVerbs = 6;
1135 const int kWeights = 4;
1145 for (
unsigned i = 0;
i < 4; ++
i) {
1168 bool wasEmpty = this->
isEmpty();
1182 const int kVerbs = 6;
1184 const int kWeights = 4;
1198 for (
unsigned i = 0;
i < 4; ++
i) {
1234 return forceMoveTo ? this->
moveTo(lonePt) : this->
lineTo(lonePt);
1243 bool isArc = this->hasOnlyMoveTos();
1248 auto addPt = [&forceMoveTo, &
isArc,
this](
const SkPoint& pt) {
1263 if (startV == stopV) {
1304 this->injectMoveToIfNeeded();
1315 srcPts[1].
set(
x,
y);
1316 if (srcPts[0] == srcPts[1]) {
1321 SkVector midPointDistance = srcPts[0] - srcPts[1];
1322 midPointDistance *= 0.5f;
1328 pointTransform.
mapPoints(&transformedMidPoint, &midPointDistance, 1);
1331 SkScalar squareX = transformedMidPoint.
fX * transformedMidPoint.
fX;
1332 SkScalar squareY = transformedMidPoint.
fY * transformedMidPoint.
fY;
1336 SkScalar radiiScale = squareX / squareRx + squareY / squareRy;
1337 if (radiiScale > 1) {
1343 pointTransform.
setScale(1 / rx, 1 / ry);
1355 scaleFactor = -scaleFactor;
1357 delta.scale(scaleFactor);
1358 SkPoint centerPoint = unitPts[0] + unitPts[1];
1359 centerPoint *= 0.5f;
1361 unitPts[0] -= centerPoint;
1362 unitPts[1] -= centerPoint;
1365 SkScalar thetaArc = theta2 - theta1;
1385 SkScalar thetaWidth = thetaArc / segments;
1392 auto scalar_is_integer = [](
SkScalar scalar) ->
bool {
1396 scalar_is_integer(rx) && scalar_is_integer(ry) &&
1397 scalar_is_integer(
x) && scalar_is_integer(
y);
1399 for (
int i = 0;
i < segments; ++
i) {
1400 SkScalar endTheta = startTheta + thetaWidth,
1404 unitPts[1].
set(cosEndTheta, sinEndTheta);
1405 unitPts[1] += centerPoint;
1406 unitPts[0] = unitPts[1];
1407 unitPts[0].
offset(t * sinEndTheta, -t * cosEndTheta);
1415 if (expectIntegers) {
1416 for (
SkPoint& point : mapped) {
1421 this->
conicTo(mapped[0], mapped[1],
w);
1422 startTheta = endTheta;
1435 return this->
arcTo(rx, ry, xAxisRotate, largeArc, sweep,
1436 currentPoint.
fX +
dx, currentPoint.
fY + dy);
1454 SkScalar startIndex = std::fmod(startOver90I + 1.f, 4.f);
1455 startIndex = startIndex < 0 ? startIndex + 4.f : startIndex;
1457 (
unsigned) startIndex);
1468 this->injectMoveToIfNeeded();
1471 return this->
lineTo(x1, y1);
1481 double cosh =
dot(befored, afterd);
1482 double sinh =
cross(befored, afterd);
1489 return this->
lineTo(x1, y1);
1494 SkScalar xx = x1 - dist * befored[0];
1495 SkScalar yy = y1 - dist * befored[1];
1501 return this->
conicTo(x1, y1, x1 + after.
fX, y1 + after.
fY, weight);
1519 const uint8_t fillType = fFillType;
1521 fFillType = fillType;
1533 if (
src->fLastMoveToIndex >= 0) {
1540 matrix.mapPoints(newPts,
src->fPathRef->points(),
src->countPoints());
1541 if (
int numWeights =
src->fPathRef->countWeights()) {
1542 memcpy(newWeights,
src->fPathRef->conicWeights(), numWeights *
sizeof(newWeights[0]));
1544 return this->dirtyAfterEdit();
1548 bool firstVerb =
true;
1553 mapPtsProc(
matrix, mappedPts, &pts[0], 1);
1555 injectMoveToIfNeeded();
1558 if (!this->
getLastPt(&lastPt) || lastPt != mappedPts[0]) {
1559 this->
lineTo(mappedPts[0]);
1562 this->
moveTo(mappedPts[0]);
1566 mapPtsProc(
matrix, mappedPts, &pts[1], 1);
1567 this->
lineTo(mappedPts[0]);
1570 mapPtsProc(
matrix, mappedPts, &pts[1], 2);
1571 this->
quadTo(mappedPts[0], mappedPts[1]);
1574 mapPtsProc(
matrix, mappedPts, &pts[1], 2);
1575 this->
conicTo(mappedPts[0], mappedPts[1], *
w);
1578 mapPtsProc(
matrix, mappedPts, &pts[1], 3);
1579 this->
cubicTo(mappedPts[0], mappedPts[1], mappedPts[2]);
1594 if (
path.fPathRef->fVerbs.empty()) {
1598 const uint8_t* verbs =
path.fPathRef->verbsEnd();
1599 const uint8_t* verbsBegin =
path.fPathRef->verbsBegin();
1601 const SkPoint* pts =
path.fPathRef->pointsEnd() - 1;
1602 const SkScalar* conicWeights =
path.fPathRef->conicWeightsEnd();
1604 while (verbs > verbsBegin) {
1605 uint8_t v = *--verbs;
1615 this->
quadTo(pts[1], pts[0]);
1618 this->
conicTo(pts[1], pts[0], *--conicWeights);
1621 this->
cubicTo(pts[2], pts[1], pts[0]);
1641 const uint8_t* verbsBegin =
src->fPathRef->verbsBegin();
1642 const uint8_t* verbs =
src->fPathRef->verbsEnd();
1643 const SkPoint* pts =
src->fPathRef->pointsEnd();
1644 const SkScalar* conicWeights =
src->fPathRef->conicWeightsEnd();
1646 bool needMove =
true;
1647 bool needClose =
false;
1648 while (verbs > verbsBegin) {
1649 uint8_t v = *--verbs;
1671 this->
quadTo(pts[1], pts[0]);
1674 this->
conicTo(pts[1], pts[0], *--conicWeights);
1677 this->
cubicTo(pts[2], pts[1], pts[0]);
1707 path->cubicTo(pts[1], pts[2], pts[3]);
1712 if (
matrix.isIdentity()) {
1713 if (
dst !=
nullptr &&
dst !=
this) {
1720 if (
dst ==
nullptr) {
1724 if (
matrix.hasPerspective()) {
1726 tmp.fFillType = fFillType;
1779 dst->fLastMoveToIndex = fLastMoveToIndex;
1780 dst->fFillType = fFillType;
1781 dst->fIsVolatile = fIsVolatile;
1794 dst->setConvexity(convexity);
1803 dst->setFirstDirection(
1806 }
else if (det2x2 > 0) {
1807 dst->setFirstDirection(this->getFirstDirection());
1823 fConicWeights =
nullptr;
1824 fMoveTo.
fX = fMoveTo.
fY = fLastPt.
fX = fLastPt.
fY = 0;
1825 fForceClose = fCloseLine =
false;
1829 fVerbStop =
nullptr;
1834 this->setPath(
path, forceClose);
1839 fVerbs =
path.fPathRef->verbsBegin();
1840 fVerbStop =
path.fPathRef->verbsEnd();
1841 fConicWeights =
path.fPathRef->conicWeights();
1842 if (fConicWeights) {
1845 fLastPt.fX = fLastPt.fY = 0;
1846 fMoveTo.fX = fMoveTo.fY = 0;
1847 fForceClose =
SkToU8(forceClose);
1852 if (fVerbs ==
nullptr || fVerbs == fVerbStop) {
1859 const uint8_t* verbs = fVerbs;
1860 const uint8_t* stop = fVerbStop;
1866 while (verbs < stop) {
1868 unsigned v = *verbs++;
1881 if (fLastPt != fMoveTo) {
1904 if (fVerbs == fVerbStop) {
1907 if (
kLine_Verb == this->autoClose(ptsParam)) {
1916 unsigned verb = *fVerbs++;
1924 verb = this->autoClose(pts);
1930 if (fVerbs == fVerbStop) {
1937 fNeedClose = fForceClose;
1942 fLastPt = srcPts[0];
1951 memcpy(&pts[1], srcPts, 2 *
sizeof(
SkPoint));
1952 fLastPt = srcPts[1];
1957 memcpy(&pts[1], srcPts, 3 *
sizeof(
SkPoint));
1958 fLastPt = srcPts[2];
1962 verb = this->autoClose(pts);
1978 fEnd = iterate.
end();
1982 if (!(
fIter != fEnd)) {
1985 auto [verb, iterPts, weights] = *
fIter;
1993 fConicWeight = *weights;
1998 memcpy(pts, iterPts,
sizeof(
SkPoint) * numPts);
2019 if (conicWeight != -12345) {
2032 if (conicWeight >= 0) {
2042 Iter iter(*
this,
false);
2047 char const *
const gFillTypeStrs[] = {
2053 builder.printf(
"path.setFillType(SkPathFillType::k%s);\n",
2073 builder.append(
"path.close();\n");
2076 SkDebugf(
" path: UNKNOWN VERB %d, aborting dump...\n", verb);
2080 if (!wStream &&
builder.size()) {
2093 auto bool_str = [](
bool v) {
return v ?
"true" :
"false"; };
2095 builder.appendf(
"// fBoundsIsDirty = %s\n", bool_str(fPathRef->fBoundsIsDirty));
2096 builder.appendf(
"// fGenerationID = %u\n", fPathRef->fGenerationID);
2097 builder.appendf(
"// fSegmentMask = %d\n", fPathRef->fSegmentMask);
2099 const char* gTypeStrs[] = {
2100 "General",
"Oval",
"RRect",
2102 builder.appendf(
"// fType = %s\n", gTypeStrs[
static_cast<int>(fPathRef->fType)]);
2104 auto append_scalar = [&](
SkScalar v) {
2112 builder.append(
"const SkPoint path_points[] = {\n");
2116 append_scalar(
p.fX);
2118 append_scalar(
p.fY);
2123 const char* gVerbStrs[] = {
2124 "Move",
"Line",
"Quad",
"Conic",
"Cubic",
"Close"
2126 builder.append(
"const uint8_t path_verbs[] = {\n ");
2128 builder.appendf(
"(uint8_t)SkPathVerb::k%s, ", gVerbStrs[*v]);
2134 builder.append(
"const SkScalar path_conics[] = {\n ");
2142 char const *
const gFillTypeStrs[] = {
2149 builder.appendf(
"SkPath path = SkPath::Make(path_points, %d, path_verbs, %d, %s, %d,\n",
2151 nConics ?
"path_conics" :
"nullptr", nConics);
2152 builder.appendf(
" SkPathFillType::k%s, %s);\n",
2154 bool_str(fIsVolatile));
2163bool SkPath::isValidImpl()
const {
2164 if ((fFillType & ~3) != 0) {
2169 if (!fBoundsIsDirty) {
2206#define kValueNeverReturnedBySign 2
2224 fFirstPt = fLastPt = pt;
2229 if (fLastPt == pt) {
2234 if (fFirstPt == fLastPt && fExpectedDir ==
kInvalid_DirChange && fLastVec.equals(0,0)) {
2235 fLastVec = pt - fLastPt;
2236 fFirstVec = fLastVec;
2237 }
else if (!this->addVec(pt - fLastPt)) {
2257 for (
int outerLoop = 0; outerLoop < 2; ++outerLoop ) {
2267 dxes += (sx != lastSx);
2268 dyes += (sy != lastSy);
2269 if (dxes > 3 || dyes > 3) {
2289 return this->addPt(fFirstPt) && this->addVec(fFirstVec);
2312 bool addVec(
const SkVector& curVec) {
2321 }
else if (
dir != fExpectedDir) {
2335 return ++fReversals < 3;
2337 return (fIsFinite =
false);
2339 SK_ABORT(
"Use of invalid direction change flag");
2353 int fReversals { 0 };
2354 bool fIsFinite {
true };
2360 this->setConvexity(convexity);
2375 if (fLastMoveToIndex >= 0) {
2376 if (fLastMoveToIndex == pointCount - 1) {
2378 auto verbs = fPathRef->
verbsEnd() - 1;
2379 while(verbs > fPathRef->
verbsBegin() && *verbs == Verb::kMove_Verb) {
2383 }
else if (fLastMoveToIndex != skipCount) {
2390 if (skipCount > 0) {
2392 pointCount -= skipCount;
2401 int contourCount = 0;
2402 bool needsClose =
false;
2407 if (contourCount == 0) {
2409 state.setMovePt(pts[0]);
2417 if (contourCount == 1) {
2419 if (!
state.close()) {
2429 if (!
state.addPt(pts[
i])) {
2444 if (needsClose && !
state.close()) {
2450 && !this->getBounds().isEmpty()) {
2451 return setComputedConvexity(
state.reversals() < 3 ?
2454 this->setFirstDirection(
state.getFirstDirection());
2465 bool done()
const {
return fDone; }
2467 int count()
const {
return fCurrPtCount; }
2474 const uint8_t* fCurrVerb;
2475 const uint8_t* fStopVerbs;
2484 fCurrPt = pathRef.
points();
2493 if (fCurrVerb >= fStopVerbs) {
2501 fCurrPt += fCurrPtCount;
2505 const uint8_t* verbs = fCurrVerb;
2507 for (verbs++; verbs < fStopVerbs; verbs++) {
2515 fCurrConicWeight += 1;
2531 fCurrPtCount = ptCount;
2552 (p1y - p0y) * (p2x - p0x));
2580 if (pts[index] != pts[
i]) {
2596 int minIndex = index;
2597 int maxIndex = index;
2598 for (
int i = index + 1;
i < n; ++
i) {
2599 if (pts[
i].fY !=
y) {
2606 }
else if (
x >
max) {
2611 *maxIndexPtr = maxIndex;
2628 auto d =
path.getFirstDirection();
2646 for (; !iter.
done(); iter.
next()) {
2647 int n = iter.
count();
2655 if (pts[index].fY < ymax) {
2661 if (pts[(index + 1) % n].fY == pts[index].fY) {
2664 if (minIndex == maxIndex) {
2667 SkASSERT(pts[minIndex].fY == pts[index].fY);
2668 SkASSERT(pts[maxIndex].fY == pts[index].fY);
2669 SkASSERT(pts[minIndex].fX <= pts[maxIndex].fX);
2672 cross = minIndex - maxIndex;
2685 if (
prev == index) {
2695 if (0 ==
cross && pts[
prev].fY == pts[index].fY && pts[
next].fY == pts[index].fY) {
2703 ymax = pts[index].
fY;
2709 path.setFirstDirection(
d);
2719 return (
a -
b) * (c -
b) <= 0;
2735 for (
size_t i = 1;
i <
N; ++
i) {
2761 if (y < y0 || y > y3) {
2774 find_minmax<4>(pts, &
min, &
max);
2789 if (
x != pts[3].fX ||
y != pts[3].fY) {
2794 return xt <
x ?
dir : 0;
2801 for (
int i = 0;
i <= n; ++
i) {
2836 if (y < y0 || y > y2) {
2861 xt = pts[1 -
dir].
fX;
2867 if (
x != pts[2].fX ||
y != pts[2].fY) {
2872 return xt <
x ?
dir : 0;
2888 int* onCurveCount) {
2893 bool isMono =
is_mono_quad(pts[0].fY, pts[1].fY, pts[2].fY) || !
conic.chopAtYExtrema(chopped);
2911 if (y < y0 || y > y2) {
2923 if (pts[0].fX >
x && pts[1].fX >
x && pts[2].fX >
x) {
2930 2 * (pts[1].fY - pts[0].fY),
2939 xt = pts[1 -
dir].
fX;
2948 if (
x != pts[2].fX ||
y != pts[2].fY) {
2953 return xt <
x ?
dir : 0;
2985 if (y < y0 || y > y1) {
3001 if (
x != x1 ||
y != pts[1].fY) {
3014 && !
between(pts[2].fY,
y, pts[3].fY)) {
3018 && !
between(pts[2].fX,
x, pts[3].fX)) {
3023 for (
int i = 0;
i <= n; ++
i) {
3041 if (!
between(pts[0].fY,
y, pts[1].fY) && !
between(pts[1].fY,
y, pts[2].fY)) {
3044 if (!
between(pts[0].fX,
x, pts[1].fX) && !
between(pts[1].fX,
x, pts[2].fX)) {
3055 for (
int index = 0; index < n; ++index) {
3068 if (!
between(pts[0].fY,
y, pts[1].fY) && !
between(pts[1].fY,
y, pts[2].fY)) {
3071 if (!
between(pts[0].fX,
x, pts[1].fX) && !
between(pts[1].fX,
x, pts[2].fX)) {
3076 2 * (pts[1].fY - pts[0].fY),
3079 for (
int index = 0; index < n; ++index) {
3131 int onCurveCount = 0;
3134 switch (iter.
next(pts)) {
3163 if (onCurveCount <= 1) {
3164 return SkToBool(onCurveCount) ^ isInverse;
3166 if ((onCurveCount & 1) || evenOddFill) {
3167 return SkToBool(onCurveCount & 1) ^ isInverse;
3176 int oldCount = tangents.
size();
3177 switch (iter.
next(pts)) {
3197 if (tangents.
size() > oldCount) {
3198 int last = tangents.
size() - 1;
3199 const SkVector& tangent = tangents[last];
3203 for (
int index = 0; index < last; ++index) {
3222void SkPath::shrinkToFit() {
3226 if (!fPathRef->
unique()) {
3228 pr->copy(*fPathRef, 0, 0, 0);
3241 return conic.chopIntoQuadsPOW2(pts, pow2);
3251 bool needsClose = !isSimpleFill;
3255 if (0 != rectPtCnt) {
3258 rectPts[0] = verbPts[0];
3262 if (5 == rectPtCnt) {
3265 rectPts[rectPtCnt] = verbPts[1];
3269 if (4 == rectPtCnt) {
3270 rectPts[4] = rectPts[0];
3284 if (rectPtCnt < 5) {
3287 if (rectPts[0] != rectPts[4]) {
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) {
3296 if (rectPts[0].fX == rectPts[1].fX || rectPts[0].fY == rectPts[3].fY) {
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) {
3303 if (rectPts[0].fY == rectPts[1].fY || rectPts[0].fX == rectPts[3].fX) {
3306 vec03IsVertical =
false;
3312 unsigned sortFlags =
3313 ((rectPts[0].
fX < rectPts[2].
fX) ? 0b00 : 0b01) |
3314 ((rectPts[0].
fY < rectPts[2].
fY) ? 0b00 : 0b10);
3315 switch (sortFlags) {
3317 rect->setLTRB(rectPts[0].fX, rectPts[0].fY, rectPts[2].fX, rectPts[2].fY);
3322 rect->setLTRB(rectPts[2].fX, rectPts[0].fY, rectPts[0].fX, rectPts[2].fY);
3327 rect->setLTRB(rectPts[0].fX, rectPts[2].fY, rectPts[2].fX, rectPts[0].fY);
3332 rect->setLTRB(rectPts[2].fX, rectPts[2].fY, rectPts[0].fX, rectPts[0].fY);
3342 bool isFillNoPathEffect) {
3367 path->setIsVolatile(
true);
3380 bool convex = DrawArcIsConvex(
sweepAngle, arc.
fType, isFillNoPathEffect);
3382 bool forceMoveTo = !arc.
isWedge();
3388 forceMoveTo =
false;
3396 forceMoveTo =
false;
3404 path->setFirstDirection(firstDir);
3414 for (
int i = 0;
i < n; ++
i) {
3417 extremas[n] =
src[2];
3424 int n =
conic.findXExtrema(ts);
3425 n +=
conic.findYExtrema(&ts[n]);
3427 for (
int i = 0;
i < n; ++
i) {
3428 extremas[
i] =
conic.evalAt(ts[
i]);
3430 extremas[n] =
src[2];
3439 for (
int i = 0;
i < n; ++
i) {
3442 extremas[n] =
src[3];
3464 extremas[0] = pts[0];
3468 extremas[0] = pts[1];
3500 const SkPoint& p3,
bool exact) {
3507 return exact ? p1 == p2 && p2 == p3 && p3 == p4 :
3517 bool needMove =
true;
3528 for (
int i = 0;
i < verbCount; ++
i) {
3570 const uint8_t vbs[],
int verbCount,
3573 if (verbCount <= 0) {
3578 if (!
info.valid ||
info.points > pointCount ||
info.weights > wCount) {
3579 SkDEBUGFAIL(
"invalid verbs and number of points/weights");
3583 return MakeInternal(
info, pts, vbs, verbCount, ws, ft,
isVolatile);
3624 const uint8_t verbs[],
3631 SkSpan(verbs, verbCount),
3645 const SkPoint* firstPt =
nullptr;
3646 const SkPoint* lastPt =
nullptr;
3650 const SkPoint* savePts =
nullptr;
3651 lineStart.
set(0, 0);
3652 signed char directions[] = {-1, -1, -1, -1, -1};
3653 bool closedOrMoved =
false;
3654 bool autoClose =
false;
3655 bool insertClose =
false;
3656 int verbCnt =
path.fPathRef->countVerbs();
3657 while (*currVerb < verbCnt && (!allowPartial || !autoClose)) {
3663 insertClose =
false;
3670 SkVector lineDelta = lineEnd - lineStart;
3671 if (lineDelta.
fX && lineDelta.
fY) {
3677 if (lineStart == lineEnd) {
3682 directions[0] = nextDirection;
3684 closedOrMoved =
false;
3685 lineStart = lineEnd;
3688 if (closedOrMoved) {
3691 if (autoClose && nextDirection == directions[0]) {
3694 closedOrMoved = autoClose;
3695 if (directions[corners - 1] == nextDirection) {
3697 thirdCorner = lineEnd;
3699 lineStart = lineEnd;
3702 directions[corners++] = nextDirection;
3706 firstCorner = lineStart;
3709 if ((directions[0] ^ directions[2]) != 2) {
3712 thirdCorner = lineEnd;
3715 if ((directions[1] ^ directions[3]) != 2) {
3722 lineStart = lineEnd;
3730 if (allowPartial && !autoClose && directions[0] >= 0) {
3733 goto addMissingClose;
3738 closeXY = *firstPt - *lastPt;
3739 if (closeXY.
fX && closeXY.
fY) {
3744 closedOrMoved =
true;
3755 if (corners < 3 || corners > 4) {
3762 closeXY = *firstPt - *lastPt;
3763 if (closeXY.
fX && closeXY.
fY) {
3767 rect->set(firstCorner, thirdCorner);
3770 *isClosed = autoClose;
3773 *direction = directions[0] == ((directions[1] + 1) & 3) ?
3786 if (!IsRectContour(
path,
true, &currVerb, &pts,
nullptr, &testDirs[0], &testRects[0])) {
3789 if (IsRectContour(
path,
false, &currVerb, &pts,
nullptr, &testDirs[1], &testRects[1])) {
3790 if (testRects[0].
contains(testRects[1])) {
3792 rects[0] = testRects[0];
3793 rects[1] = testRects[1];
3796 dirs[0] = testDirs[0];
3797 dirs[1] = testDirs[1];
3801 if (testRects[1].
contains(testRects[0])) {
3803 rects[0] = testRects[1];
3804 rects[1] = testRects[0];
3807 dirs[0] = testDirs[1];
3808 dirs[1] = testDirs[0];
3822 return fA *
x + fB *
y + fC;
3843 (
a == 0 &&
b == 0)) {
3881 return kAllNegative;
3883 return kAllPositive;
3896 -plane.
fA, plane.
fB, p0.
fY,
3903 path.transform(
inv, &rotated);
3918 Rec* rec = (Rec*)ctx;
3920 bool addLineTo =
false;
3925 rec->fResult.moveTo(pts[0]);
3926 rec->fPrev = pts[0];
3930 if (addLineTo || pts[0] != rec->fPrev) {
3931 rec->fResult.lineTo(pts[0]);
3936 rec->fResult.lineTo(pts[1]);
3937 rec->fPrev = pts[1];
3940 rec->fResult.quadTo(pts[1], pts[2]);
3941 rec->fPrev = pts[2];
3944 rec->fResult.cubicTo(pts[1], pts[2], pts[3]);
3945 rec->fPrev = pts[3];
3953 rec.fResult.setFillType(
path.getFillType());
3954 SkPath result = rec.fResult.detach().makeTransform(mx);
3955 if (!
result.isFinite()) {
3963 if (!
matrix.hasPerspective()) {
3972 if (plane.normalize()) {
3973 switch (plane.test(
path.getBounds())) {
3989 return path.fPathRef->genIDChangeListenerCount();
3998 const int count =
path.fPathRef->countPoints();
4001 if (pts[
i-1].fX != pts[
i].fX && pts[
i-1].fY != pts[
i].fY) {
4011 fMoveToPtr =
fPts =
path.fPathRef->points();
4012 fVerbs =
path.fPathRef->verbsBegin();
4013 fVerbsStop =
path.fPathRef->verbsEnd();
4014 fConicWeights =
path.fPathRef->conicWeights();
4015 if (fConicWeights) {
4019 fNeedsCloseLine =
false;
4020 fNextIsNewContour =
false;
static SkM44 inv(const SkM44 &m)
static bool invalid(const SkISize &size)
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static const int points[]
std::unique_ptr< SkLatticeIter > fIter
static float next(float f)
static float prev(float f)
#define SkDEBUGFAIL(message)
#define SK_ABORT(message,...)
#define SkASSERT_RELEASE(cond)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static uint32_t SkFloat2Bits(float value)
static constexpr bool SkIsNaN(T x)
static bool SkIsFinite(T x, Pack... values)
static constexpr double sk_ieee_double_divide(double numer, double denom)
int SkChopCubicAtYExtrema(const SkPoint src[4], SkPoint dst[10])
void SkChopCubicAtHalf(const SkPoint src[4], SkPoint dst[7])
void SkEvalCubicAt(const SkPoint src[4], SkScalar t, SkPoint *loc, SkVector *tangent, SkVector *curvature)
int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2])
SkVector SkEvalQuadTangentAt(const SkPoint src[3], SkScalar t)
void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint *pt, SkVector *tangent)
int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1])
int SkChopQuadAtYExtrema(const SkPoint src[3], SkPoint dst[5])
@ kCW_SkRotationDirection
@ kCCW_SkRotationDirection
static skvx::float2 from_point(const SkPoint &point)
static void * sk_careful_memcpy(void *dst, const void *src, size_t len)
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kCubic_SkPathSegmentMask
@ kConic_SkPathSegmentMask
@ kQuad_SkPathSegmentMask
@ kLine_SkPathSegmentMask
@ 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.
static void tangent_line(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
static bool is_degenerate(const SkPath &path)
#define INITIAL_LASTMOVETOINDEX_VALUE
static SkScalar cross_prod(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2)
static bool checkOnCurve(SkScalar x, SkScalar y, const SkPoint &start, const SkPoint &end)
static int winding_mono_conic(const SkConic &conic, SkScalar x, SkScalar y, int *onCurveCount)
static bool is_mono_quad(SkScalar y0, SkScalar y1, SkScalar y2)
static int build_arc_conics(const SkRect &oval, const SkVector &start, const SkVector &stop, SkRotationDirection dir, SkConic conics[SkConic::kMaxConicsForArc], SkPoint *singlePt)
#define kValueNeverReturnedBySign
static void assert_known_direction(SkPathDirection dir)
static float poly_eval(float A, float B, float C, float t)
static bool arc_is_lone_point(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, SkPoint *pt)
static bool check_edge_against_rect(const SkPoint &p0, const SkPoint &p1, const SkRect &rect, SkPathFirstDirection dir)
static int winding_mono_cubic(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
static int winding_mono_quad(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
static int winding_quad(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
static int find_diff_pt(const SkPoint pts[], int index, int n, int inc)
static int rect_make_dir(SkScalar dx, SkScalar dy)
static int compute_cubic_extremas(const SkPoint src[4], SkPoint extremas[5])
static int winding_line(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
static bool contains_inclusive(const SkRect &r, SkScalar x, SkScalar y)
static int sign(SkScalar x)
static int compute_conic_extremas(const SkPoint src[3], SkScalar w, SkPoint extremas[3])
static void subdivide_cubic_to(SkPath *path, const SkPoint pts[4], int level=2)
static void tangent_cubic(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
static void angles_to_unit_vectors(SkScalar startAngle, SkScalar sweepAngle, SkVector *startV, SkVector *stopV, SkRotationDirection *dir)
static int winding_conic(const SkPoint pts[], SkScalar x, SkScalar y, SkScalar weight, int *onCurveCount)
bool operator==(const SkPath &a, const SkPath &b)
static int find_max_y(const SkPoint pts[], int count)
static void tangent_conic(const SkPoint pts[], SkScalar x, SkScalar y, SkScalar w, SkTDArray< SkVector > *tangents)
static double conic_eval_numerator(const SkScalar src[], SkScalar w, SkScalar t)
static SkScalar eval_cubic_pts(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3, SkScalar t)
static SkPathFirstDirection crossToDir(SkScalar cross)
static double conic_eval_denominator(SkScalar w, SkScalar t)
static int compute_quad_extremas(const SkPoint src[3], SkPoint extremas[3])
static bool between(SkScalar a, SkScalar b, SkScalar c)
static void append_params(SkString *str, const char label[], const SkPoint pts[], int count, SkScalarAsStringType strType, SkScalar conicWeight=-12345)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
static int find_min_max_x_at_y(const SkPoint pts[], int index, int n, int *maxIndexPtr)
static void tangent_quad(const SkPoint pts[], SkScalar x, SkScalar y, SkTDArray< SkVector > *tangents)
static void joinNoEmptyChecks(SkRect *dst, const SkRect &src)
static int winding_cubic(const SkPoint pts[], SkScalar x, SkScalar y, int *onCurveCount)
static void find_minmax(const SkPoint pts[], SkScalar *minPtr, SkScalar *maxPtr)
SkPathVerbAnalysis sk_path_analyze_verbs(const uint8_t vbs[], int verbCount)
void swap(sk_sp< T > &a, sk_sp< T > &b)
LoopControlFlowInfo fResult
#define SkDegreesToRadians(degrees)
#define SkScalarCopySign(x, y)
#define SkScalarFloorToScalar(x)
static float SkScalarSinSnapToZero(SkScalar radians)
#define SkScalarTan(radians)
#define SkScalarToDouble(x)
#define SkScalarMod(x, y)
#define SkScalarATan2(y, x)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
static int SkScalarSignAsInt(SkScalar x)
#define SkScalarSin(radians)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkDoubleToScalar(x)
#define SkScalarCeilToInt(x)
#define SkScalarRoundToScalar(x)
#define SkScalarCos(radians)
#define SK_ScalarRoot2Over2
static float SkScalarCosSnapToZero(SkScalar radians)
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
void SkAppendScalar(SkString *str, SkScalar value, SkScalarAsStringType asType)
@ kHex_SkScalarAsStringType
@ kDec_SkScalarAsStringType
static void SkAppendScalarDec(SkString *str, SkScalar value)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr bool SkToBool(const T &x)
constexpr uint8_t SkToU8(S x)
ContourIter(const SkPathRef &pathRef)
const SkPoint * pts() const
SkAutoDisableDirectionCheck(SkPath *path)
~SkAutoDisableDirectionCheck()
~SkAutoPathBoundsUpdate()
SkAutoPathBoundsUpdate(SkPath *path, const SkRect &r)
static bool ChopMonoAtY(const SkPoint pts[4], SkScalar y, SkScalar *t)
static void ClipPath(const SkPath &path, const SkRect &clip, bool canCullToTheRight, void(*consume)(SkEdgeClipper *, bool newCtr, void *ctx), void *ctx)
SkPath::Verb next(SkPoint pts[])
static MapPtsProc GetMapPtsProc(const SkMatrix &matrix)
SkMatrix::MapPtsProc MapPtsProc
static constexpr int kMScaleX
horizontal scale factor
static constexpr int kMPersp1
input y perspective factor
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
bool invert(SkMatrix *inverse) const
SkMatrix & setRotate(SkScalar degrees, SkScalar px, SkScalar py)
static constexpr int kMPersp0
input x perspective factor
SkMatrix & preRotate(SkScalar degrees, SkScalar px, SkScalar py)
static constexpr int kMPersp2
perspective bias
static constexpr int kMSkewY
vertical skew factor
static constexpr int kMScaleY
vertical scale factor
static constexpr int kMSkewX
horizontal skew factor
SkMatrix & preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
SkPathEdgeIter(const SkPath &path)
static int PtsInVerb(unsigned verb)
static bool IsRRect(const SkPath &path, SkRRect *rrect, SkPathDirection *dir, unsigned *start)
static bool IsNestedFillRects(const SkPath &, SkRect rect[2], SkPathDirection dirs[2]=nullptr)
static bool IsSimpleRect(const SkPath &path, bool isSimpleFill, SkRect *rect, SkPathDirection *direction, unsigned *start)
static int GenIDChangeListenersCount(const SkPath &)
static bool IsOval(const SkPath &path, SkRect *rect, SkPathDirection *dir, unsigned *start)
static bool IsAxisAligned(const SkPath &path)
static void CreateDrawArcPath(SkPath *path, const SkArc &arc, bool isFillNoPathEffect)
static SkPathFirstDirection ComputeFirstDirection(const SkPath &)
static bool DrawArcIsConvex(SkScalar sweepAngle, SkArc::Type arcType, bool isFillNoPathEffect)
static int LeadingMoveToCount(const SkPath &path)
static bool PerspectiveClip(const SkPath &src, const SkMatrix &, SkPath *result)
static bool IsRectContour(const SkPath &, bool allowPartial, int *currVerb, const SkPoint **ptsPtr, bool *isClosed, SkPathDirection *direction, SkRect *rect)
static bool AllPointsEq(const SkPoint pts[], int count)
static SkPathFirstDirection OppositeFirstDirection(SkPathFirstDirection dir)
void setIsOval(bool isCCW, unsigned start, bool isClosed)
std::tuple< SkPoint *, SkScalar * > growForVerbsInPath(const SkPathRef &path)
SkPoint * growForRepeatedVerb(int verb, int numVbs, SkScalar **weights=nullptr)
SkPoint * growForVerb(int verb, SkScalar weight=0)
void setIsRRect(bool isCCW, unsigned start)
SkPoint * writablePoints()
void setIsArc(const SkArc &arc)
uint32_t genID(uint8_t fillType) const
const SkPoint & atPoint(int index) const
const SkRect & getBounds() const
static void Rewind(sk_sp< SkPathRef > *pathRef)
static void CreateTransformedCopy(sk_sp< SkPathRef > *dst, const SkPathRef &src, const SkMatrix &matrix)
const uint8_t * verbsEnd() const
const SkScalar * conicWeightsEnd() const
uint8_t atVerb(int index) const
static SkPathRef * CreateEmpty()
const SkPoint * points() const
size_t approximateBytesUsed() const
bool hasComputedBounds() const
const SkScalar * conicWeights() const
const uint8_t * verbsBegin() const
bool dataMatchesVerbs() const
bool isArc(SkArc *arc) const
void interpolate(const SkPathRef &ending, SkScalar weight, SkPathRef *out) const
uint32_t getSegmentMasks() const
bool isClosedContour() const
void setPath(const SkPath &path, bool forceClose)
Verb next(SkPoint pts[4])
SkScalar conicWeight() const
void setPath(const SkPath &)
const SkPoint & current() const
SkPath & rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, SkScalar dx, SkScalar dy)
bool isInverseFillType() const
SkPath & reverseAddPath(const SkPath &src)
uint32_t getGenerationID() const
void offset(SkScalar dx, SkScalar dy, SkPath *dst) const
static bool IsLineDegenerate(const SkPoint &p1, const SkPoint &p2, bool exact)
static SkPath RRect(const SkRRect &, SkPathDirection dir=SkPathDirection::kCW)
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
bool conservativelyContainsRect(const SkRect &rect) const
void setLastPt(SkScalar x, SkScalar y)
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
SkPath & arcTo(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
SkPath & rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w)
SkPath & operator=(const SkPath &path)
SkPoint getPoint(int index) const
SkPath & moveTo(SkScalar x, SkScalar y)
bool isLine(SkPoint line[2]) const
bool getLastPt(SkPoint *lastPt) const
static bool IsQuadDegenerate(const SkPoint &p1, const SkPoint &p2, const SkPoint &p3, bool exact)
SkPathFillType getFillType() const
int getPoints(SkPoint points[], int max) const
SkPath & addPoly(const SkPoint pts[], int count, bool close)
SkPath & lineTo(SkScalar x, SkScalar y)
static bool IsCubicDegenerate(const SkPoint &p1, const SkPoint &p2, const SkPoint &p3, const SkPoint &p4, bool exact)
SkPath & addRRect(const SkRRect &rrect, SkPathDirection dir=SkPathDirection::kCW)
SkPath & rCubicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar dx3, SkScalar dy3)
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
SkRect computeTightBounds() const
size_t approximateBytesUsed() const
bool isInterpolatable(const SkPath &compare) const
SkPath & rMoveTo(SkScalar dx, SkScalar dy)
bool interpolate(const SkPath &ending, SkScalar weight, SkPath *out) const
SkPath & addArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle)
static SkPath Make(const SkPoint[], int pointCount, const uint8_t[], int verbCount, const SkScalar[], int conicWeightCount, SkPathFillType, bool isVolatile=false)
bool isOval(SkRect *bounds) const
int getVerbs(uint8_t verbs[], int max) const
static SkPath Circle(SkScalar center_x, SkScalar center_y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
SkPath & quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
SkPath & addRoundRect(const SkRect &rect, SkScalar rx, SkScalar ry, SkPathDirection dir=SkPathDirection::kCW)
static int ConvertConicToQuads(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkScalar w, SkPoint pts[], int pow2)
const SkRect & getBounds() const
uint32_t getSegmentMasks() const
static SkPath Oval(const SkRect &, SkPathDirection=SkPathDirection::kCW)
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
static SkPath Polygon(const SkPoint pts[], int count, bool isClosed, SkPathFillType=SkPathFillType::kWinding, bool isVolatile=false)
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
bool isLastContourClosed() const
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
SkPath & addOpenOval(const SkRect &oval, SkPathDirection dir, unsigned start)
SkPath & rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2)
bool isRect(SkRect *rect, bool *isClosed=nullptr, SkPathDirection *direction=nullptr) const
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
bool isRRect(SkRRect *rrect) const
bool isArc(SkArc *arc) const
SkPath & rLineTo(SkScalar dx, SkScalar dy)
bool contains(SkScalar x, SkScalar y) const
friend class SkPathBuilder
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
void incReserve(int extraPtCount, int extraVerbCount=0, int extraConicCount=0)
static SkScalar LengthSqd(const SkPoint &pt)
static bool EqualsWithinTolerance(const SkPoint &p1, const SkPoint &p2)
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
void setRectRadii(const SkRect &rect, const SkVector radii[4])
void setRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
const SkRect & getBounds() const
void append(const char text[])
void push_back(const T &v)
void remove(int index, int count=1)
void removeShuffle(int index)
bool writeText(const char text[])
void swap(sk_sp< T > &that)
void reset(T *ptr=nullptr)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
const uint8_t uint32_t uint32_t GError ** error
static float max(float r, float g, float b)
static float min(float r, float g, float b)
unsigned useCenter Optional< SkMatrix > matrix
Optional< SkRect > bounds
sk_sp< SkBlender > blender SkRect rect
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
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
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
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 mode
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
int64_t cross(Point d0, Point d1)
const myers::Point & get(const myers::Segment &)
SINT bool isfinite(const Vec< N, T > &v)
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
SIN Vec< N, float > normalize(const Vec< N, float > &v)
SIT T max(const Vec< 1, T > &x)
SIT T min(const Vec< 1, T > &x)
int compare(const void *untyped_lhs, const void *untyped_rhs)
SkPathFirstDirection getFirstDirection() const
bool addPt(const SkPoint &pt)
static SkPathConvexity BySign(const SkPoint points[], int count)
void setMovePt(const SkPoint &pt)
static SkArc Make(const SkRect &oval, SkScalar startAngleDegrees, SkScalar sweepAngleDegrees, Type type)
int SK_SPI chopIntoQuadsPOW2(SkPoint pts[], int pow2) const
static SkScalar TransformW(const SkPoint[3], SkScalar w, const SkMatrix &)
void set(const SkPoint pts[3], SkScalar w)
static int BuildUnitArc(const SkVector &start, const SkVector &stop, SkRotationDirection, const SkMatrix *, SkConic conics[kMaxConicsForArc])
Result test(const SkRect &bounds) const
SkScalar operator()(SkScalar x, SkScalar y) const
SkScalar eval(SkScalar x, SkScalar y) const
SkPath::RangeIter begin()
static float CrossProduct(const SkVector &a, const SkVector &b)
bool setLength(float length)
void offset(float dx, float dy)
static constexpr SkPoint Make(float x, float y)
void set(float x, float y)
constexpr float y() const
constexpr float x() const
static constexpr SkRect MakeEmpty()
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
bool contains(SkScalar x, SkScalar y) const
constexpr float centerX() const
constexpr float height() const
constexpr float centerY() const
constexpr float width() const
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
SkScalar fTop
smaller y-axis bounds