31#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
50 return ((perpDot > 0) ? 1 : -1);
58 if (polygonSize < 3) {
64 SkVector v0 = polygonVerts[1] - polygonVerts[0];
65 for (
int curr = 2; curr < polygonSize; ++curr) {
66 SkVector v1 = polygonVerts[curr] - polygonVerts[0];
67 quadArea += v0.
cross(v1);
74 return (quadArea > 0) ? 1 : -1;
92 return (denomPositive && (numer < 0 || numer > denom)) ||
93 (!denomPositive && (numer > 0 || numer < denom));
112 bool denomPositive = (denom > 0);
160 sNumer = v0.
dot(
w + v1);
165 if (sNumer*oldSNumer > 0) {
176 sNumer =
w.cross(v1);
180 tNumer =
w.cross(v0);
189 *
p = s0.
fP0 + v0*localS;
197 if (polygonSize < 3) {
202 int xSignChangeCount = 0;
203 int ySignChangeCount = 0;
205 int prevIndex = polygonSize - 1;
208 SkVector v0 = polygonVerts[currIndex] - polygonVerts[prevIndex];
211 SkVector v1 = polygonVerts[nextIndex] - polygonVerts[currIndex];
212 for (
int i = 0;
i < polygonSize; ++
i) {
219 if (lastPerpDot*perpDot < 0) {
223 lastPerpDot = perpDot;
227 if (lastVx*v1.
fX < 0) {
230 if (lastVy*v1.
fY < 0) {
233 if (xSignChangeCount > 2 || ySignChangeCount > 2) {
236 prevIndex = currIndex;
237 currIndex = nextIndex;
238 nextIndex = (currIndex + 1) % polygonSize;
246 v1 = polygonVerts[nextIndex] - polygonVerts[currIndex];
271 if (this->fEnd == that->
fIndex) {
308 localS *= v0.
dot(v0);
340 if (inputPolygonSize < 3) {
357 for (
int i = 0;
i < inputPolygonSize; ++
i) {
358 *insetPolygon->
append() = inputPolygonVerts[
i];
371 int prev = inputPolygonSize - 1;
372 for (
int curr = 0; curr < inputPolygonSize;
prev = curr, ++curr) {
373 int next = (curr + 1) % inputPolygonSize;
374 if (!inputPolygonVerts[curr].
isFinite()) {
379 inputPolygonVerts[
next])*winding < 0) {
382 SkVector v = inputPolygonVerts[
next] - inputPolygonVerts[curr];
385 edgeData[curr].fPrev = &edgeData[
prev];
386 edgeData[curr].fNext = &edgeData[
next];
387 edgeData[curr].fOffset.fP0 = inputPolygonVerts[curr] + perp;
388 edgeData[curr].fOffset.fV = v;
389 edgeData[curr].init();
395 int insetVertexCount = inputPolygonSize;
396 unsigned int iterations = 0;
397 unsigned int maxIterations = inputPolygonSize * inputPolygonSize;
398 while (
head && prevEdge != currEdge) {
401 if (iterations > maxIterations) {
408 &intersection, &
s, &t)) {
410 if (s < prevEdge->fTValue) {
415 prevEdge = prevEdge->
fPrev;
429 currEdge = currEdge->
fNext;
444 prevEdge = prevEdge->
fPrev;
449 currEdge = currEdge->
fNext;
456 insetPolygon->
reset();
461 static constexpr SkScalar kCleanupTolerance = 0.01f;
462 if (insetVertexCount >= 0) {
463 insetPolygon->
reserve(insetVertexCount);
466 *insetPolygon->
append() =
head->fIntersection;
467 currEdge =
head->fNext;
468 while (currEdge !=
head) {
470 (*insetPolygon)[currIndex],
471 kCleanupTolerance)) {
475 currEdge = currEdge->
fNext;
478 if (currIndex >= 1 &&
480 kCleanupTolerance)) {
492 const SkScalar kRecipPixelsPerArcSegment = 0.25f;
512 SkScalar dTheta = steps > 0 ? theta / steps : 0;
517 if (steps > 0 && (*rotSin == 0 || *rotCos == 1)) {
528 return p0.
fX < p1.
fX || (!(p0.
fX > p1.
fX) && p0.
fY > p1.
fY);
533 return p0.
fX > p1.
fX || (!(p0.
fX < p1.
fX) && p0.
fY < p1.
fY);
607 return (p0.
fY >= q0.
fY);
608 }
else if (p0.
fY > q0.
fY) {
610 }
else if (p0.
fY < q0.
fY) {
617 return (p1.
fY >= q1.
fY);
619 return (p1.
fY > q1.
fY);
681 return this->
above(that);
684 bool equals(uint16_t index0, uint16_t index1)
const {
705 fTreeHead.
fChild[1] =
nullptr;
715 if (!fTreeHead.
fChild[1]) {
740 if ((pred && pred->
intersect(p0, v, index0, index1)) ||
741 (succ && succ->
intersect(p0, v, index0, index1))) {
745 parent->
fChild[
dir] = curr = this->allocate(p0, v, index0, index1);
767 int dir2 = (top->
fChild[1] == grandparent);
768 if (curr == parent->
fChild[last]) {
769 top->
fChild[dir2] = SingleRotation(grandparent, !last);
771 top->
fChild[dir2] = DoubleRotation(grandparent, !last);
775 }
else if (IsRed(curr->
fChild[0]) && IsRed(curr->
fChild[1])) {
781 int dir2 = (top->
fChild[1] == grandparent);
782 if (curr == parent->
fChild[last]) {
783 top->
fChild[dir2] = SingleRotation(grandparent, !last);
785 top->
fChild[dir2] = DoubleRotation(grandparent, !last);
813 grandparent = parent;
828 uint16_t index0, uint16_t index1, uint16_t index2) {
829 if (!fTreeHead.
fChild[1]) {
843 if (curr->
equals(index0, index1)) {
887 if (!fTreeHead.
fChild[1]) {
902 grandparent = parent;
906 if (curr->
equals(index0, index1)) {
924 if (!IsRed(curr) && !IsRed(curr->
fChild[
dir])) {
926 parent = parent->
fChild[last] = SingleRotation(curr,
dir);
931 if (!IsRed(
s->fChild[!last]) && !IsRed(
s->fChild[last])) {
933 parent->
fRed =
false;
937 int dir2 = (grandparent->
fChild[1] == parent);
939 if (IsRed(
s->fChild[last])) {
940 grandparent->
fChild[dir2] = DoubleRotation(parent, last);
941 }
else if (IsRed(
s->fChild[!last])) {
942 grandparent->
fChild[dir2] = SingleRotation(parent, last);
982 if (fTreeHead.
fChild[1]) {
988 if (fTreeHead.
fChild[1]) {
1000 if (fCurrFree >= fMaxFree) {
1003 char* bytes = fAllocation +
sizeof(
ActiveEdge)*fCurrFree;
1005 return new(bytes)
ActiveEdge(p0, p1, index0, index1);
1012 return node && node->
fRed;
1030 return SingleRotation(node,
dir);
1034 static int VerifyTree(
const ActiveEdge* tree) {
1043 if (IsRed(tree) && (IsRed(
left) || IsRed(
right))) {
1064 int leftCount = VerifyTree(
left);
1065 int rightCount = VerifyTree(
right);
1068 if (leftCount != 0 && rightCount != 0) {
1070 if (leftCount != rightCount) {
1074 return IsRed(tree) ? leftCount : leftCount + 1;
1093 if (polygonSize < 3) {
1103 if (polygonSize > 2048) {
1108 for (
int i = 0;
i < polygonSize; ++
i) {
1115 newVertex.
fPrevIndex = (
i - 1 + polygonSize) % polygonSize;
1128 vertexQueue.
insert(newVertex);
1134 while (vertexQueue.
count() > 0) {
1172 return (vertexQueue.
count() == 0);
1180 uint16_t startIndex, uint16_t endIndex) {
1182 currEdge->
fOffset.
fV = endpoint1 - endpoint0;
1183 currEdge->
init(startIndex, endIndex);
1187 uint16_t prevIndex, uint16_t currIndex, uint16_t nextIndex) {
1189 inputPolygonVerts[currIndex] - inputPolygonVerts[prevIndex],
1190 inputPolygonVerts[nextIndex]);
1198 if (inputPolygonSize < 3) {
1219 for (
int i = 0;
i < inputPolygonSize; ++
i) {
1220 *offsetPolygon->
append() = inputPolygonVerts[
i];
1221 if (polygonIndices) {
1222 *polygonIndices->
append() =
i;
1236 unsigned int numEdges = 0;
1237 for (
int currIndex = 0, prevIndex = inputPolygonSize - 1;
1238 currIndex < inputPolygonSize;
1239 prevIndex = currIndex, ++currIndex) {
1240 if (!inputPolygonVerts[currIndex].
isFinite()) {
1243 int nextIndex = (currIndex + 1) % inputPolygonSize;
1248 if (currIndex > 0) {
1251 prevIndex, currIndex, nextIndex)) {
1255 &rotSin, &rotCos, &numSteps)) {
1268 &rotSin, &rotCos, &numSteps)) {
1284 for (
int currIndex = 0, prevIndex = inputPolygonSize - 1;
1285 currIndex < inputPolygonSize;
1286 prevIndex = currIndex, ++currIndex) {
1287 int nextIndex = (currIndex + 1) % inputPolygonSize;
1290 prevIndex, currIndex, nextIndex)) {
1295 &rotSin, &rotCos, &numSteps)) {
1299 for (
int i = 0;
i < numSteps - 1; ++
i) {
1301 prevNormal.
fY*rotCos + prevNormal.
fX*rotSin);
1303 inputPolygonVerts[currIndex] + prevNormal,
1304 inputPolygonVerts[currIndex] + currNormal,
1305 currIndex, currIndex);
1306 prevNormal = currNormal;
1307 currEdge->fPrev = prevEdge;
1309 prevEdge->
fNext = currEdge;
1311 prevEdge = currEdge;
1315 inputPolygonVerts[currIndex] + prevNormal,
1316 inputPolygonVerts[currIndex] +
normals[currIndex],
1317 currIndex, currIndex);
1318 currEdge->fPrev = prevEdge;
1320 prevEdge->
fNext = currEdge;
1322 prevEdge = currEdge;
1328 inputPolygonVerts[currIndex] +
normals[currIndex],
1329 inputPolygonVerts[nextIndex] +
normals[currIndex],
1330 currIndex, nextIndex);
1331 currEdge->fPrev = prevEdge;
1333 prevEdge->
fNext = currEdge;
1335 prevEdge = currEdge;
1339 prevEdge->
fNext = &edgeData[0];
1340 edgeData[0].fPrev = prevEdge;
1344 auto head = &edgeData[0];
1345 auto currEdge =
head;
1346 unsigned int offsetVertexCount = numEdges;
1347 unsigned long long iterations = 0;
1348 unsigned long long maxIterations = (
unsigned long long)(numEdges) * numEdges;
1349 while (
head && prevEdge != currEdge && offsetVertexCount > 0) {
1352 if (iterations > maxIterations) {
1360 if (s < prevEdge->fTValue) {
1363 --offsetVertexCount;
1365 prevEdge = prevEdge->
fPrev;
1369 currEdge->fIntersection,
1375 currEdge->fTValue = t;
1376 currEdge->fIndex = prevEdge->
fEnd;
1379 prevEdge = currEdge;
1380 currEdge = currEdge->
fNext;
1390 if (dist0 < 0 && dist1 < 0) {
1395 p1 = currEdge->fOffset.fP0 + currEdge->fOffset.fV;
1400 if (currSameContour && !prevSameContour) {
1402 currEdge = currNextEdge;
1403 --offsetVertexCount;
1405 }
else if (prevSameContour && !currSameContour) {
1407 prevEdge = prevPrevEdge;
1408 --offsetVertexCount;
1414 if (dist0 < dist1) {
1416 prevEdge = prevPrevEdge;
1419 currEdge = currNextEdge;
1421 --offsetVertexCount;
1427 offsetPolygon->
reset();
1428 if (!
head || offsetVertexCount == 0 ||
1433 static constexpr SkScalar kCleanupTolerance = 0.01f;
1434 offsetPolygon->
reserve(offsetVertexCount);
1436 *offsetPolygon->
append() =
head->fIntersection;
1437 if (polygonIndices) {
1440 currEdge =
head->fNext;
1441 while (currEdge !=
head) {
1443 (*offsetPolygon)[currIndex],
1444 kCleanupTolerance)) {
1445 *offsetPolygon->
append() = currEdge->fIntersection;
1446 if (polygonIndices) {
1447 *polygonIndices->
append() = currEdge->fIndex;
1451 currEdge = currEdge->fNext;
1454 if (currIndex >= 1 &&
1456 kCleanupTolerance)) {
1458 if (polygonIndices) {
1466 return (winding*offsetWinding > 0 &&
1540 fVCount = vertexCount/fHCount;
1547 fGrid.
resize(fHCount*fVCount);
1548 for (
int i = 0;
i < fGrid.
size(); ++
i) {
1556 int index = hash(v);
1557 fGrid[index].addToTail(v);
1562 int index = hash(v);
1568 uint16_t ignoreIndex0, uint16_t ignoreIndex1)
const {
1575 int h0 = (triBounds.
fLeft - fBounds.
fLeft)*fGridConversion.
fX;
1576 int h1 = (triBounds.
fRight - fBounds.
fLeft)*fGridConversion.
fX;
1577 int v0 = (triBounds.
fTop - fBounds.
fTop)*fGridConversion.
fY;
1578 int v1 = (triBounds.
fBottom - fBounds.
fTop)*fGridConversion.
fY;
1580 for (
int v = v0; v <= v1; ++v) {
1581 for (
int h = h0;
h <= h1; ++
h) {
1582 int i = v * fHCount +
h;
1584 reflexIter != fGrid[
i].
end(); ++reflexIter) {
1586 if (reflexVertex->
fIndex != ignoreIndex0 &&
1587 reflexVertex->
fIndex != ignoreIndex1 &&
1604 return v*fHCount +
h;
1621 SkVector v0 =
p->fPosition - polygonVerts[
p->fPrevIndex];
1622 SkVector v1 = polygonVerts[
p->fNextIndex] -
p->fPosition;
1626 p->fPrev =
p->fNext =
nullptr;
1634 if (polygonSize < 3) {
1644 if (!
bounds.setBoundsCheck(polygonVerts, polygonSize)) {
1657 int prevIndex = polygonSize - 1;
1658 SkVector v0 = polygonVerts[0] - polygonVerts[prevIndex];
1659 for (
int currIndex = 0; currIndex < polygonSize; ++currIndex) {
1660 int nextIndex = (currIndex + 1) % polygonSize;
1663 triangulationVertices[currIndex].fPosition = polygonVerts[currIndex];
1664 triangulationVertices[currIndex].fIndex = currIndex;
1665 triangulationVertices[currIndex].fPrevIndex = prevIndex;
1666 triangulationVertices[currIndex].fNextIndex = nextIndex;
1667 SkVector v1 = polygonVerts[nextIndex] - polygonVerts[currIndex];
1674 prevIndex = currIndex;
1685 prevIndex = polygonSize - 1;
1686 for (
int currIndex = 0; currIndex < polygonSize; prevIndex = currIndex, ++currIndex) {
1689 int nextIndex = (currIndex + 1) % polygonSize;
1696 convexList.
addToHead(&triangulationVertices[currIndex]);
1698 convexList.
addToTail(&triangulationVertices[currIndex]);
1702 reflexHash.
add(&triangulationVertices[currIndex]);
1713 triangleIndices->
reserve(triangleIndices->
size() + 3 * (polygonSize - 2));
1714 int vertexCount = polygonSize;
1715 while (vertexCount > 3) {
1716 bool success =
false;
1722 convexIter != convexList.
end(); ++convexIter) {
1723 earVertex = *convexIter;
1726 p0 = &triangulationVertices[earVertex->
fPrevIndex];
1727 p2 = &triangulationVertices[earVertex->
fNextIndex];
1746 auto indices = triangleIndices->
append(3);
1747 indices[0] = indexMap[p0->
fIndex];
1748 indices[1] = indexMap[earVertex->
fIndex];
1749 indices[2] = indexMap[p2->
fIndex];
1752 convexList.
remove(earVertex);
1765 vertexIter != convexList.
end(); ++vertexIter) {
static SkM44 normals(SkM44 m)
static bool isFinite(const SkRect &r)
static float next(float f)
static float prev(float f)
static bool SkIsFinite(T x, Pack... values)
static constexpr float sk_ieee_float_divide(float numer, float denom)
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
static int side(double x)
static bool left(const SkPoint &p0, const SkPoint &p1)
bool SkComputeRadialSteps(const SkVector &v1, const SkVector &v2, SkScalar offset, SkScalar *rotSin, SkScalar *rotCos, int *n)
bool SkIsConvexPolygon(const SkPoint *polygonVerts, int polygonSize)
static void reclassify_vertex(TriangulationVertex *p, const SkPoint *polygonVerts, int winding, ReflexHash *reflexHash, SkTInternalLList< TriangulationVertex > *convexList)
bool SkTriangulateSimplePolygon(const SkPoint *polygonVerts, uint16_t *indexMap, int polygonSize, SkTDArray< uint16_t > *triangleIndices)
bool compute_offset_vector(const SkPoint &p0, const SkPoint &p1, SkScalar offset, int side, SkPoint *vector)
static bool right(const SkPoint &p0, const SkPoint &p1)
bool SkOffsetSimplePolygon(const SkPoint *inputPolygonVerts, int inputPolygonSize, const SkRect &bounds, SkScalar offset, SkTDArray< SkPoint > *offsetPolygon, SkTDArray< int > *polygonIndices)
static void setup_offset_edge(OffsetEdge *currEdge, const SkPoint &endpoint0, const SkPoint &endpoint1, uint16_t startIndex, uint16_t endIndex)
static bool zero_length(const SkPoint &v, SkScalar vdotv)
static bool compute_intersection(const OffsetSegment &s0, const OffsetSegment &s1, SkPoint *p, SkScalar *s, SkScalar *t)
bool SkIsSimplePolygon(const SkPoint *polygon, int polygonSize)
static void remove_node(const OffsetEdge *node, OffsetEdge **head)
static int compute_side(const SkPoint &p0, const SkVector &v, const SkPoint &p)
static void compute_triangle_bounds(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, SkRect *bounds)
constexpr SkScalar kCrossTolerance
static bool is_reflex_vertex(const SkPoint *inputPolygonVerts, int winding, SkScalar offset, uint16_t prevIndex, uint16_t currIndex, uint16_t nextIndex)
static bool point_in_triangle(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, const SkPoint &p)
static bool outside_interval(SkScalar numer, SkScalar denom, bool denomPositive)
int SkGetPolygonWinding(const SkPoint *polygonVerts, int polygonSize)
bool SkInsetConvexPolygon(const SkPoint *inputPolygonVerts, int inputPolygonSize, SkScalar inset, SkTDArray< SkPoint > *insetPolygon)
#define SkScalarATan2(y, x)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkScalarSin(radians)
#define SkScalarRoundToInt(x)
#define SK_ScalarNearlyZero
#define SkScalarCos(radians)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
bool insert(const SkPoint &p0, const SkPoint &p1, uint16_t index0, uint16_t index1)
bool remove(const SkPoint &p0, const SkPoint &p1, uint16_t index0, uint16_t index1)
ActiveEdgeList(int maxEdges)
bool replace(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, uint16_t index0, uint16_t index1, uint16_t index2)
void remove(TriangulationVertex *v)
bool init(const SkRect &bounds, int vertexCount)
bool checkTriangle(const SkPoint &p0, const SkPoint &p1, const SkPoint &p2, uint16_t ignoreIndex0, uint16_t ignoreIndex1) const
void add(TriangulationVertex *v)
static bool CanNormalize(SkScalar dx, SkScalar dy)
static bool EqualsWithinTolerance(const SkPoint &p1, const SkPoint &p2)
static constexpr float HalfWidth(const SkRect &r)
static constexpr float HalfHeight(const SkRect &r)
void remove(int index, int count=1)
static const char * begin(const StringSlice &s)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
static float max(float r, float g, float b)
static float min(float r, float g, float b)
Optional< SkRect > bounds
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
int64_t cross(Point d0, Point d1)
SIT T max(const Vec< 1, T > &x)
SIT T min(const Vec< 1, T > &x)
static SkRect inset(const SkRect &r)
bool aboveIfLeft(const ActiveEdge *that) const
bool intersect(const SkPoint &q0, const SkVector &w, uint16_t index0, uint16_t index1) const
ActiveEdge(const SkPoint &p0, const SkVector &v, uint16_t index0, uint16_t index1)
bool lessThan(const ActiveEdge *that) const
bool above(const ActiveEdge *that) const
bool intersect(const ActiveEdge *edge)
bool equals(uint16_t index0, uint16_t index1) const
bool checkIntersection(const OffsetEdge *that, SkPoint *p, SkScalar *s, SkScalar *t)
void init(uint16_t start=0, uint16_t end=0)
SkScalar computeCrossingDistance(const OffsetEdge *that)
bool setLength(float length)
float dot(const SkVector &vec) const
static constexpr SkPoint Make(float x, float y)
void set(float x, float y)
float cross(const SkVector &vec) const
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
SkScalar fTop
smaller y-axis bounds
SK_DECLARE_INTERNAL_LLIST_INTERFACE(TriangulationVertex)
static bool Left(const Vertex &qv0, const Vertex &qv1)