Generates a simple polygon (if possible) that is offset a constant distance from the boundary of a given simple polygon. The input polygon must be simple, have no coincident vertices or collinear edges, and have values clamped to the nearest 1/16th.
1197 {
1198 if (inputPolygonSize < 3) {
1199 return false;
1200 }
1201
1202
1204 return false;
1205 }
1206
1208 return false;
1209 }
1210
1211
1214 return false;
1215 }
1216
1217
1219 for (
int i = 0;
i < inputPolygonSize; ++
i) {
1220 *offsetPolygon->
append() = inputPolygonVerts[
i];
1221 if (polygonIndices) {
1222 *polygonIndices->
append() =
i;
1223 }
1224 }
1225 return true;
1226 }
1227
1228
1230 if (0 == winding) {
1231 return false;
1232 }
1233
1234
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()) {
1241 return false;
1242 }
1243 int nextIndex = (currIndex + 1) % inputPolygonSize;
1246 return false;
1247 }
1248 if (currIndex > 0) {
1249
1251 prevIndex, currIndex, nextIndex)) {
1253 int numSteps;
1255 &rotSin, &rotCos, &numSteps)) {
1256 return false;
1257 }
1259 }
1260 }
1261 numEdges++;
1262 }
1263
1266 int numSteps;
1268 &rotSin, &rotCos, &numSteps)) {
1269 return false;
1270 }
1272 }
1273
1274
1275
1276
1278 return false;
1279 }
1280
1281
1284 for (int currIndex = 0, prevIndex = inputPolygonSize - 1;
1285 currIndex < inputPolygonSize;
1286 prevIndex = currIndex, ++currIndex) {
1287 int nextIndex = (currIndex + 1) % inputPolygonSize;
1288
1290 prevIndex, currIndex, nextIndex)) {
1292 int numSteps;
1295 &rotSin, &rotCos, &numSteps)) {
1296 return false;
1297 }
1298 auto currEdge = edgeData.push_back_n(
std::max(numSteps, 1));
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;
1308 if (prevEdge) {
1309 prevEdge->
fNext = currEdge;
1310 }
1311 prevEdge = currEdge;
1312 ++currEdge;
1313 }
1315 inputPolygonVerts[currIndex] + prevNormal,
1316 inputPolygonVerts[currIndex] +
normals[currIndex],
1317 currIndex, currIndex);
1318 currEdge->fPrev = prevEdge;
1319 if (prevEdge) {
1320 prevEdge->
fNext = currEdge;
1321 }
1322 prevEdge = currEdge;
1323 }
1324
1325
1326 auto currEdge = edgeData.push_back_n(1);
1328 inputPolygonVerts[currIndex] +
normals[currIndex],
1329 inputPolygonVerts[nextIndex] +
normals[currIndex],
1330 currIndex, nextIndex);
1331 currEdge->fPrev = prevEdge;
1332 if (prevEdge) {
1333 prevEdge->
fNext = currEdge;
1334 }
1335 prevEdge = currEdge;
1336 }
1337
1339 prevEdge->
fNext = &edgeData[0];
1340 edgeData[0].
fPrev = prevEdge;
1341
1342
1343 SkASSERT(edgeData.size() == (
int)numEdges);
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) {
1350 ++iterations;
1351
1352 if (iterations > maxIterations) {
1353 return false;
1354 }
1355
1359
1360 if (s < prevEdge->fTValue) {
1361
1363 --offsetVertexCount;
1364
1365 prevEdge = prevEdge->
fPrev;
1366
1369 currEdge->fIntersection,
1370 1.0e-6f)) {
1371 break;
1372 } else {
1373
1375 currEdge->fTValue = t;
1376 currEdge->fIndex = prevEdge->
fEnd;
1377
1378
1379 prevEdge = currEdge;
1380 currEdge = currEdge->
fNext;
1381 }
1382 } else {
1383
1384
1389
1390 if (dist0 < 0 && dist1 < 0) {
1391
1395 p1 = currEdge->fOffset.fP0 + currEdge->fOffset.fV;
1398
1399
1400 if (currSameContour && !prevSameContour) {
1402 currEdge = currNextEdge;
1403 --offsetVertexCount;
1404 continue;
1405 } else if (prevSameContour && !currSameContour) {
1407 prevEdge = prevPrevEdge;
1408 --offsetVertexCount;
1409 continue;
1410 }
1411 }
1412
1413
1414 if (dist0 < dist1) {
1416 prevEdge = prevPrevEdge;
1417 } else {
1419 currEdge = currNextEdge;
1420 }
1421 --offsetVertexCount;
1422 }
1423 }
1424
1425
1426
1427 offsetPolygon->
reset();
1428 if (!
head || offsetVertexCount == 0 ||
1430 return false;
1431 }
1432
1433 static constexpr SkScalar kCleanupTolerance = 0.01f;
1434 offsetPolygon->
reserve(offsetVertexCount);
1435 int currIndex = 0;
1436 *offsetPolygon->
append() =
head->fIntersection;
1437 if (polygonIndices) {
1439 }
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;
1448 }
1449 currIndex++;
1450 }
1451 currEdge = currEdge->fNext;
1452 }
1453
1454 if (currIndex >= 1 &&
1456 kCleanupTolerance)) {
1458 if (polygonIndices) {
1460 }
1461 }
1462
1463
1465
1466 return (winding*offsetWinding > 0 &&
1468}
static SkM44 normals(SkM44 m)
bool SkComputeRadialSteps(const SkVector &v1, const SkVector &v2, SkScalar offset, SkScalar *rotSin, SkScalar *rotCos, int *n)
bool compute_offset_vector(const SkPoint &p0, const SkPoint &p1, SkScalar offset, int side, SkPoint *vector)
static void setup_offset_edge(OffsetEdge *currEdge, const SkPoint &endpoint0, const SkPoint &endpoint1, uint16_t startIndex, uint16_t endIndex)
bool SkIsSimplePolygon(const SkPoint *polygon, int polygonSize)
static bool is_reflex_vertex(const SkPoint *inputPolygonVerts, int winding, SkScalar offset, uint16_t prevIndex, uint16_t currIndex, uint16_t nextIndex)
static constexpr float HalfWidth(const SkRect &r)
static constexpr float HalfHeight(const SkRect &r)
bool checkIntersection(const OffsetEdge *that, SkPoint *p, SkScalar *s, SkScalar *t)
SkScalar computeCrossingDistance(const OffsetEdge *that)