32 SkDebugf(
"%sPart %s\n", func, bugPart[0].c_str());
33 SkDebugf(
"%sPart %s\n", func, bugPart[1].c_str());
34 SkDebugf(
"%sPart %s\n", func, bugPart[2].c_str());
38 #define COMPARE_RESULT(append, compare) CompareResult(__FUNCTION__, &bugOut, bugPart, append, \
41 #define COMPARE_RESULT(append, compare) compare
78 fPart.
fCurve = fOriginalCurvePart;
81 lh->fPart.
fCurve = lh->fOriginalCurvePart;
83 rh->fPart.
fCurve = rh->fOriginalCurvePart;
88 bugOut.
printf(
"%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
89 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
90 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
92 lh->fStart->
t(), lh->fEnd->
t(),
95 rh->fStart->
t(), rh->fEnd->
t());
96 SkString bugPart[3] = { lh->debugPart(), this->debugPart(), rh->debugPart() };
98 if (lh->fComputeSector && !lh->computeSector()) {
101 if (fComputeSector && !this->computeSector()) {
104 if (rh->fComputeSector && !rh->computeSector()) {
108 bugOut.
printf(
"%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
109 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g"
110 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__,
112 lh->fStart->
t(), lh->fEnd->
t(),
115 rh->fStart->
t(), rh->fEnd->
t());
117 bool ltrOverlap = (lh->fSectorMask | rh->fSectorMask) & fSectorMask;
118 bool lrOverlap = lh->fSectorMask & rh->fSectorMask;
123 ^ (fSectorStart > lh->fSectorEnd) ^ (fSectorStart > rh->fSectorStart));
125 int lrGap = (rh->fSectorStart - lh->fSectorStart + 32) & 0x1f;
136 lrOrder = lrGap > 20 ? 0 : lrGap > 11 ? -1 : 1;
138 lrOrder = lh->orderable(rh);
139 if (!ltrOverlap && lrOrder >= 0) {
144 SkASSERT((lh->fSectorMask & fSectorMask) || (rh->fSectorMask & fSectorMask) || -1 == lrOrder);
145 if (lh->fSectorMask & fSectorMask) {
146 ltOrder = lh->orderable(
this);
148 int ltGap = (fSectorStart - lh->fSectorStart + 32) & 0x1f;
149 ltOrder = ltGap > 20 ? 0 : ltGap > 11 ? -1 : 1;
152 if (rh->fSectorMask & fSectorMask) {
153 trOrder = this->orderable(rh);
155 int trGap = (rh->fSectorStart - fSectorStart + 32) & 0x1f;
156 trOrder = trGap > 20 ? 0 : trGap > 11 ? -1 : 1;
158 this->alignmentSameSide(lh, <Order);
159 this->alignmentSameSide(rh, &trOrder);
160 if (lrOrder >= 0 && ltOrder >= 0 && trOrder >= 0) {
161 return COMPARE_RESULT(7, lrOrder ? (ltOrder & trOrder) : (ltOrder | trOrder));
167 if (ltOrder == 0 && lrOrder == 0) {
170 SkDEBUGCODE(
bool lrOpposite = lh->oppositePlanes(rh));
171 bool ltOpposite = lh->oppositePlanes(
this);
174 }
else if (ltOrder == 1 && trOrder == 0) {
176 bool trOpposite = oppositePlanes(rh);
178 }
else if (lrOrder == 1 && trOrder == 1) {
181 bool lrOpposite = lh->oppositePlanes(rh);
187 if (fUnorderable || lh->fUnorderable || rh->fUnorderable) {
192 int ltShare = lh->fOriginalCurvePart[0] == fOriginalCurvePart[0];
193 int lrShare = lh->fOriginalCurvePart[0] == rh->fOriginalCurvePart[0];
194 int trShare = fOriginalCurvePart[0] == rh->fOriginalCurvePart[0];
196 if (ltShare + lrShare + trShare == 1) {
198 int ltOOrder = lh->linesOnOriginalSide(
this);
199 int rtOOrder = rh->linesOnOriginalSide(
this);
200 if ((rtOOrder ^ ltOOrder) == 1) {
203 }
else if (trShare) {
204 int tlOOrder = this->linesOnOriginalSide(lh);
205 int rlOOrder = rh->linesOnOriginalSide(lh);
206 if ((tlOOrder ^ rlOOrder) == 1) {
211 int trOOrder = rh->linesOnOriginalSide(
this);
212 int lrOOrder = lh->linesOnOriginalSide(rh);
214 if ((lrOOrder ^ trOOrder) == 1) {
231 bool useOriginal)
const {
236 const SkDCurve& testCurve = useOriginal ?
test->fOriginalCurvePart :
test->fPart.fCurve;
237 for (
int index = 1; index <= iMax; ++index) {
238 double xy1 =
line.fX * (testCurve[index].fY - origin.
fY);
239 double xy2 =
line.fY * (testCurve[index].fX - origin.
fX);
242 if (crosses[0] * crosses[1] < 0) {
246 if (crosses[0] * crosses[2] < 0 || crosses[1] * crosses[2] < 0) {
251 return crosses[0] < 0;
254 return crosses[1] < 0;
257 return crosses[2] < 0;
264int SkOpAngle::lineOnOneSide(
const SkOpAngle*
test,
bool useOriginal) {
269 int result = this->lineOnOneSide(origin,
line,
test, useOriginal);
281 SkDPoint origin = fOriginalCurvePart[0];
286 for (
int index = 0; index < 2; ++index) {
287 SkDVector testLine = testCurve[index] - origin;
288 double xy1 =
line.fX * testLine.
fY;
289 double xy2 =
line.fY * testLine.
fX;
290 dots[index] =
line.fX * testLine.
fX +
line.fY * testLine.
fY;
293 if (crosses[0] * crosses[1] < 0) {
297 return crosses[0] < 0;
300 return crosses[1] < 0;
302 if ((!dots[0] && dots[1] < 0) || (dots[0] < 0 && !dots[1])) {
312void SkOpAngle::alignmentSameSide(
const SkOpAngle*
test,
int* order)
const {
321 if (
test->fPart.isCurve()) {
325 const SkDPoint& oOrigin =
test->fOriginalCurvePart.fLine[0];
326 if (xOrigin == oOrigin) {
331 SkDVector oLine =
test->fOriginalCurvePart.fLine[1] - oOrigin;
332 for (
int index = 1; index <= iMax; ++index) {
334 double xCross = oLine.
crossCheck(testPt - xOrigin);
335 double oCross = xLine.
crossCheck(testPt - oOrigin);
336 if (oCross * xCross < 0) {
343bool SkOpAngle::checkCrossesZero()
const {
346 bool crossesZero =
end -
start > 16;
350bool SkOpAngle::checkParallel(
SkOpAngle* rh) {
354 sweep = this->fPart.
fSweep;
356 scratch[0] = this->fPart.
fCurve[1] - this->fPart.
fCurve[0];
366 if (tangentsDiverge(rh, s0xt0)) {
373 if (this->endToSide(rh, &inside)) {
376 if (rh->endToSide(
this, &inside)) {
380 if (this->midToSide(rh, &inside)) {
383 if (rh->midToSide(
this, &inside)) {
391 this->fUnorderable =
true;
392 rh->fUnorderable =
true;
401bool SkOpAngle::computeSector() {
402 if (fComputedSector) {
403 return !fUnorderable;
405 fComputedSector =
true;
406 bool stepUp = fStart->
t() < fEnd->
t();
408 if (checkEnd->
final() && stepUp) {
420 if (oSpan == checkEnd) {
426 goto recomputeSector;
428 checkEnd = stepUp ? !checkEnd->
final()
435 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) {
439 if (stepUp != (fStart->
t() < computedEnd->
t())) {
444 fComputedEnd = fEnd = computedEnd;
448 return !fUnorderable;
451int SkOpAngle::convexHullOverlaps(
const SkOpAngle* rh) {
457 bool tBetweenS = s0xs1 > 0 ? s0xt0 > 0 && s1xt0 < 0 : s0xt0 < 0 && s1xt0 > 0;
460 tBetweenS |= s0xs1 > 0 ? s0xt1 > 0 && s1xt1 < 0 : s0xt1 < 0 && s1xt1 > 0;
465 if ((s0xt0 == 0 && s1xt1 == 0) || (s1xt0 == 0 && s0xt1 == 0)) {
468 bool sBetweenT = t0xt1 > 0 ? s0xt0 < 0 && s0xt1 > 0 : s0xt0 > 0 && s0xt1 < 0;
469 sBetweenT |= t0xt1 > 0 ? s1xt0 < 0 && s1xt1 > 0 : s1xt0 > 0 && s1xt1 < 0;
474 if (s0xt0 >= 0 && s0xt1 >= 0 && s1xt0 >= 0 && s1xt1 >= 0) {
477 if (s0xt0 <= 0 && s0xt1 <= 0 && s1xt0 <= 0 && s1xt1 <= 0) {
486 if (s0xt0 > 0 && m0xm1 > 0) {
489 if (s0xt0 < 0 && m0xm1 < 0) {
492 if (tangentsDiverge(rh, s0xt0)) {
504 for (
int idx1 = 0; idx1 <= ptCount - 1; ++idx1) {
505 for (
int idx2 = idx1 + 1; idx2 <= ptCount; ++idx2) {
510 v.
set(pts[idx2] - pts[idx1]);
515 return sqrt(longest) / dist;
518bool SkOpAngle::endsIntersect(
SkOpAngle* rh) {
525 if (this->fEnd->
contains(rh->fEnd)) {
526 return checkParallel(rh);
528 double smallTs[2] = {-1, -1};
529 bool limited[2] = {
false,
false};
530 for (
int index = 0; index < 2; ++index) {
539 double tStart = index ? rh->fStart->
t() : this->fStart->
t();
540 double tEnd = index ? rh->fComputedEnd->
t() : this->fComputedEnd->
t();
541 bool testAscends = tStart < (index ? rh->fComputedEnd->
t() : this->fComputedEnd->
t());
542 double t = testAscends ? 0 : 1;
543 for (
int idx2 = 0; idx2 <
i.used(); ++idx2) {
544 double testT =
i[0][idx2];
551 smallTs[index] = t = testAscends ?
std::max(t, testT) :
std::
min(t, testT);
555 bool sRayLonger =
false;
559 bool useIntersect =
false;
560 for (
int index = 0; index < 2; ++index) {
561 if (smallTs[index] < 0) {
570 if ((index ? lPts : rPts) == 1) {
571 SkDVector total = rays[index][1] - rays[index][0];
577 if (cept.
fX *
end.fX < 0 || cept.
fY *
end.fY < 0) {
580 double rayDist = cept.
length();
581 double endDist =
end.length();
582 bool rayLonger = rayDist > endDist;
583 if (limited[0] && limited[1] && rayLonger) {
585 sRayLonger = rayLonger;
587 sCeptT = smallTs[index];
591 double delta = fabs(rayDist - endDist);
592 double minX, minY, maxX, maxY;
596 int ptCount = index ? rPts : lPts;
597 for (
int idx2 = 0; idx2 <= ptCount; ++idx2) {
598 minX =
std::min(minX, curve[idx2].fX);
599 minY =
std::min(minY, curve[idx2].fY);
600 maxX =
std::max(maxX, curve[idx2].fX);
601 maxY =
std::max(maxY, curve[idx2].fY);
603 double maxWidth =
std::max(maxX - minX, maxY - minY);
616 if (delta < 4e-3 && delta > 1
e-3 && !useIntersect && fPart.
isCurve()
619 const SkDPoint& origin = rh->fOriginalCurvePart[0];
622 int originalSide = rh->lineOnOneSide(origin,
line,
this,
true);
623 if (originalSide >= 0) {
624 int translatedSide = rh->lineOnOneSide(origin,
line,
this,
false);
625 if (originalSide != translatedSide) {
630 if (
delta > 1
e-3 && (useIntersect ^=
true)) {
631 sRayLonger = rayLonger;
633 sCeptT = smallTs[index];
640 double tStart = sIndex ? rh->fStart->
t() : fStart->
t();
644 return checkParallel(rh);
646 return sRayLonger ^ (sIndex == 0) ^ (septDir < 0);
648 return checkParallel(rh);
652bool SkOpAngle::endToSide(
const SkOpAngle* rh,
bool* inside)
const {
656 rayEnd[0].
set(this->fEnd->
pt());
657 rayEnd[1] = rayEnd[0];
660 rayEnd[1].fX += slopeAtEnd.
fY;
661 rayEnd[1].fY -= slopeAtEnd.
fX;
667 int closestEnd = iEnd.
closestTo(rh->fStart->
t(), rh->fEnd->
t(), rayEnd[0], &endDist);
668 if (closestEnd < 0) {
677 double minX, minY, maxX, maxY;
682 for (
int idx2 = 0; idx2 <= oppPts; ++idx2) {
683 minX =
std::min(minX, curve[idx2].fX);
684 minY =
std::min(minY, curve[idx2].fY);
685 maxX =
std::max(maxX, curve[idx2].fX);
686 maxY =
std::max(maxY, curve[idx2].fY);
688 double maxWidth =
std::max(maxX - minX, maxY - minY);
690 if (!(endDist >= 5
e-12)) {
723int SkOpAngle::findSector(
SkPath::Verb verb,
double x,
double y)
const {
724 double absX = fabs(
x);
725 double absY = fabs(
y);
730 static const int sedecimant[3][3][3] = {
733 {{ 4, 3, 2}, { 7, -1, 15}, {10, 11, 12}},
734 {{ 5, -1, 1}, {-1, -1, -1}, { 9, -1, 13}},
735 {{ 6, 3, 0}, { 7, -1, 15}, { 8, 11, 14}},
737 int sector = sedecimant[(xy >= 0) + (xy > 0)][(
y >= 0) + (
y > 0)][(
x >= 0) + (
x > 0)] * 2 + 1;
756 if (!angle->merge(
this)) {
764 bool singleton =
nullptr == fNext;
769 if (
next->fNext ==
this) {
770 if (singleton || angle->after(
this)) {
781 bool flipAmbiguity =
false;
794 flipAmbiguity =
true;
803 if (fLastMarked->
chased()) {
818 double tStart = angle->fStart->
t();
819 double tEnd = angle->fEnd->
t();
822 if (lSegment != tSegment) {
825 double lStart = loop->fStart->
t();
826 if (lStart != tEnd) {
829 double lEnd = loop->fEnd->
t();
830 if (lEnd == tStart) {
833 }
while ((loop = loop->fNext) != first);
853 if (
this == working) {
856 working = working->fNext;
857 }
while (working != angle);
860 working->fNext =
nullptr;
863 }
while (working != angle);
869double SkOpAngle::midT()
const {
870 return (fStart->
t() + fEnd->
t()) / 2;
873bool SkOpAngle::midToSide(
const SkOpAngle* rh,
bool* inside)
const {
876 const SkPoint& startPt = this->fStart->
pt();
879 dStartPt.
set(startPt);
881 rayMid[0].fX = (startPt.
fX + endPt.
fX) / 2;
882 rayMid[0].fY = (startPt.
fY + endPt.
fY) / 2;
883 rayMid[1].fX = rayMid[0].fX + (endPt.
fY - startPt.
fY);
884 rayMid[1].fY = rayMid[0].fY - (endPt.
fX - startPt.
fX);
887 int iOutside = iMid.
mostOutside(this->fStart->
t(), this->fEnd->
t(), dStartPt);
895 int oppOutside = oppMid.
mostOutside(rh->fStart->
t(), rh->fEnd->
t(), dStartPt);
896 if (oppOutside < 0) {
900 SkDVector oppSide = oppMid.
pt(oppOutside) - dStartPt;
909bool SkOpAngle::oppositePlanes(
const SkOpAngle* rh)
const {
910 int startSpan =
SkTAbs(rh->fSectorStart - fSectorStart);
911 return startSpan >= 8;
918 double leftX = fTangentHalf.
dx();
919 double leftY = fTangentHalf.
dy();
920 double rightX = rh->fTangentHalf.
dx();
921 double rightY = rh->fTangentHalf.
dy();
922 double x_ry = leftX * rightY;
923 double rx_y = rightX * leftY;
925 if (leftX * rightX < 0 || leftY * rightY < 0) {
931 return x_ry < rx_y ? 1 : 0;
933 if ((
result = this->lineOnOneSide(rh,
false)) >= 0) {
939 }
else if (!rh->fPart.
isCurve()) {
940 if ((
result = rh->lineOnOneSide(
this,
false)) >= 0) {
946 }
else if ((
result = this->convexHullOverlaps(rh)) >= 0) {
949 return this->endsIntersect(rh) ? 1 : 0;
952 rh->fUnorderable =
true;
975 fComputedEnd = fEnd =
end;
978 fComputeSector = fComputedSector = fCheckCoincidence = fTangentsAmbiguous =
false;
984void SkOpAngle::setSpans() {
985 fUnorderable =
false;
986 fLastMarked =
nullptr;
998 fOriginalCurvePart = fPart.
fCurve;
1004 fOriginalCurvePart[1] = fPart.
fCurve[1];
1005 lineHalf[0].
set(fPart.
fCurve[0].asSkPoint());
1006 lineHalf[1].
set(fPart.
fCurve[1].asSkPoint());
1013 const SkPoint& cP1 = pts[fStart->
t() < fEnd->
t()];
1015 lineHalf[0].
set(fStart->
pt());
1016 lineHalf[1].
set(cP1);
1033 double startT = fStart->
t();
1034 double endT = fEnd->
t();
1035 double limitT = endT;
1037 for (index = 0; index <
testCount; ++index) {
1038 if (!
::between(startT, testTs[index], limitT)) {
1044 SkTQSort<double>(testTs, testTs +
testCount);
1045 double bestSide = 0;
1048 while (testTs[index] < 0) {
1053 int testIndex = index >> 1;
1054 double testT = testTs[testIndex];
1056 testT = (testT + testTs[testIndex + 1]) / 2;
1063 if (fabs(bestSide) < fabs(testSide)) {
1064 bestSide = testSide;
1074void SkOpAngle::setSector() {
1076 fUnorderable =
true;
1081 fSectorStart = this->findSector(verb, fPart.
fSweep[0].
fX, fPart.
fSweep[0].
fY);
1082 if (fSectorStart < 0) {
1087 fSectorEnd = fSectorStart;
1088 fSectorMask = 1 << fSectorStart;
1092 fSectorEnd = this->findSector(verb, fPart.
fSweep[1].
fX, fPart.
fSweep[1].
fY);
1093 if (fSectorEnd < 0) {
1095 fSectorStart = fSectorEnd = -1;
1097 fComputeSector =
true;
1100 if (fSectorEnd == fSectorStart
1101 && (fSectorStart & 3) != 3) {
1102 fSectorMask = 1 << fSectorStart;
1105 bool crossesZero = this->checkCrossesZero();
1107 bool curveBendsCCW = (fSectorStart ==
start) ^ crossesZero;
1109 if ((fSectorStart & 3) == 3) {
1110 fSectorStart = (fSectorStart + (curveBendsCCW ? 1 : 31)) & 0x1f;
1112 if ((fSectorEnd & 3) == 3) {
1113 fSectorEnd = (fSectorEnd + (curveBendsCCW ? 31 : 1)) & 0x1f;
1115 crossesZero = this->checkCrossesZero();
1121 fSectorMask = (unsigned) -1 >> (31 -
start) | ((unsigned) -1 <<
end);
1129bool SkOpAngle::tangentsDiverge(
const SkOpAngle* rh,
double s0xt0) {
1144 double s0dt0 = sweep[0].
dot(tweep[0]);
1149 double m = s0xt0 / s0dt0;
1150 double sDist = sweep[0].
length() *
m;
1151 double tDist = tweep[0].
length() *
m;
1152 bool useS = fabs(sDist) < fabs(tDist);
1154 fTangentsAmbiguous = mFactor >= 50 && mFactor < 200;
1155 return mFactor < 50;
static const size_t testCount
static bool approximately_zero(double x)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr double sk_ieee_double_divide(double numer, double denom)
#define COMPARE_RESULT(append, compare)
static SkDVector(*const CurveDSlopeAtT[])(const SkPoint[], SkScalar, double)
static SkDPoint dcubic_xy_at_t(const SkPoint a[4], SkScalar, double t)
static void(*const CurveIntersectRay[])(const SkPoint[], SkScalar, const SkDLine &, SkIntersections *)
bool AlmostEqualUlps(const SkPoint &pt1, const SkPoint &pt2)
bool AlmostBequalUlps(float a, float b)
bool approximately_equal(double x, double y)
bool approximately_between_orderable(double a, double b, double c)
bool between(double a, double b, double c)
bool approximately_equal_orderable(double x, double y)
int SkPathOpsVerbToPoints(SkPath::Verb verb)
#define SK_ScalarInfinity
void setCurveHullSweep(SkPath::Verb verb)
const SkDPoint & pt(int index) const
int closestTo(double rangeStart, double rangeEnd, const SkDPoint &testPt, double *dist) const
int mostOutside(double rangeStart, double rangeEnd, const SkDPoint &origin) const
bool cubicEndPoints(const SkDCubic &pts)
double cubicPart(const SkDCubic &part)
bool quadEndPoints(const SkDQuad &pts)
double pointDistance(const SkDPoint &pt) const
void lineEndPoints(const SkDLine &pts)
double distEndRatio(double dist) const
bool loopContains(const SkOpAngle *) const
SkOpSegment * segment() const
SkOpSpanBase * end() const
void debugValidateNext() const
bool tangentsAmbiguous() const
SkOpAngle * previous() const
void set(SkOpSpanBase *start, SkOpSpanBase *end)
SkOpSpanBase * start() const
SkOpSpanBase * lastMarked() const
SkPath::Verb verb() const
const SkOpSpanBase * tail() const
SkOpGlobalState * globalState() const
bool subDivide(const SkOpSpanBase *start, const SkOpSpanBase *end, SkDCurve *result) const
const SkOpSpan * head() const
SkDPoint dPtAtT(double mid) const
const SkPoint * pts() const
const SkPoint & pt() const
const SkOpSpan * prev() const
void setChased(bool chased)
SkOpGlobalState * globalState() const
bool contains(const SkOpSpanBase *) const
const SkOpSpan * starter(const SkOpSpanBase *end) const
SkOpSegment * segment() const
SkOpSpanBase * next() const
void printf(const char format[],...) SK_PRINTF_LIKE(2
const char * c_str() const
static void append(char **dst, size_t *count, const char *src, size_t n)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
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
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
int compare(const void *untyped_lhs, const void *untyped_rhs)
static int FindInflections(const SkPoint a[kPointCount], double tValues[2])
const SkDLine & set(const SkPoint pts[2])
void set(const SkPoint &pt)
SkDVector & set(const SkVector &pt)
double crossNoNormalCheck(const SkDVector &a) const
double dot(const SkDVector &a) const
double crossCheck(const SkDVector &a) const
double lengthSquared() const