207 {
208 if (!this->someAssemblyRequired()) {
209 return;
210 }
211#if DEBUG_PATH_CONSTRUCTION
213#endif
215 int endCount = fEndPtTs.
size();
218#if DEBUG_ASSEMBLE
219 for (int index = 0; index < endCount; index += 2) {
220 const SkOpPtT* eStart = runs[index];
221 const SkOpPtT* eEnd = runs[index + 1];
224 SkDebugf(
"%s contour start=(%1.9g,%1.9g) end=(%1.9g,%1.9g)\n", __FUNCTION__,
226 }
227#endif
228
229 for (int pIndex = 0; pIndex < endCount; pIndex++) {
233 do {
235 break;
236 }
239 int step = opPtT->
fT ? 1 : -1;
242 if (!nextSegment) {
243 break;
244 }
246 if (
start->starter(opSpanEnd)->alreadyAdded()) {
247 break;
248 }
250 opPtT = opSpanEnd->
ptT();
252 *runsPtr = opPtT;
253 } while (true);
254 partWriter.finishContour();
256 if (partPartials.
empty()) {
257 continue;
258 }
259
260 SkPath& partial =
const_cast<SkPath&
>(fPartials[pIndex >> 1]);
261 const SkPath& part = partPartials[0];
262 if (pIndex & 1) {
264 } else {
269 }
270 }
272 int linkCount = endCount / 2;
275 int rIndex, iIndex;
276 for (rIndex = 0; rIndex < linkCount; ++rIndex) {
277 sLink[rIndex] = eLink[rIndex] =
SK_MaxS32;
278 }
279 const int entries = endCount * (endCount - 1) / 2;
283 int rRow = 0;
284 int dIndex = 0;
285 for (rIndex = 0; rIndex < endCount - 1; ++rIndex) {
286 const SkOpPtT* oPtT = runs[rIndex];
287 for (iIndex = rIndex + 1; iIndex < endCount; ++iIndex) {
288 const SkOpPtT* iPtT = runs[iIndex];
291 double dist =
dx *
dx + dy * dy;
292 distLookup.push_back(rRow + iIndex);
293 distances.push_back(dist);
294 sortedDist.push_back(dIndex++);
295 }
296 rRow += endCount;
297 }
299 SkTQSort<int>(sortedDist.begin(), sortedDist.end(),
DistanceLessThan(distances.begin()));
300 int remaining = linkCount;
301 for (rIndex = 0; rIndex < entries; ++rIndex) {
302 int pair = sortedDist[rIndex];
303 pair = distLookup[pair];
304 int row = pair / endCount;
305 int col = pair - row * endCount;
306 int ndxOne = row >> 1;
307 bool endOne = row & 1;
308 int* linkOne = endOne ? eLink.
begin() : sLink.
begin();
310 continue;
311 }
312 int ndxTwo = col >> 1;
313 bool endTwo = col & 1;
314 int* linkTwo = endTwo ? eLink.
begin() : sLink.
begin();
316 continue;
317 }
318 SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]);
319 bool flip = endOne == endTwo;
320 linkOne[ndxOne] = flip ? ~ndxTwo : ndxTwo;
321 linkTwo[ndxTwo] = flip ? ~ndxOne : ndxOne;
322 if (!--remaining) {
323 break;
324 }
325 }
327#if DEBUG_ASSEMBLE
328 for (rIndex = 0; rIndex < linkCount; ++rIndex) {
329 int s = sLink[rIndex];
330 int e = eLink[rIndex];
331 SkDebugf(
"%s %c%d <- s%d - e%d -> %c%d\n", __FUNCTION__,
s < 0 ?
's' :
'e',
332 s < 0 ? ~
s :
s, rIndex, rIndex,
e < 0 ?
'e' :
's',
e < 0 ? ~
e :
e);
333 }
334#endif
335 rIndex = 0;
336 do {
337 bool forward = true;
338 bool first = true;
339 int sIndex = sLink[rIndex];
342 int eIndex;
343 if (sIndex < 0) {
344 eIndex = sLink[~sIndex];
346 } else {
347 eIndex = eLink[sIndex];
349 }
351#if DEBUG_ASSEMBLE
352 SkDebugf(
"%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ?
's' :
'e',
353 sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
354 eIndex < 0 ? ~eIndex : eIndex);
355#endif
356 do {
358 if (!first) {
361 return;
362 }
363 if (forward) {
365 } else {
367 }
369
370
371
372
373 }
374 }
375 if (forward) {
378 } else {
380 fPathPtr->reversePathTo(
contour);
381 }
382 if (first) {
383 first = false;
384 }
385#if DEBUG_ASSEMBLE
386 SkDebugf(
"%s rIndex=%d eIndex=%s%d close=%d\n", __FUNCTION__, rIndex,
387 eIndex < 0 ? "~" : "", eIndex < 0 ? ~eIndex : eIndex,
388 sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex));
389#endif
390 if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) {
392 break;
393 }
394 if (forward) {
395 eIndex = eLink[rIndex];
398 if (eIndex >= 0) {
401 } else {
402 SkASSERT(eLink[~eIndex] == ~rIndex);
404 }
405 } else {
406 eIndex = sLink[rIndex];
409 if (eIndex >= 0) {
412 } else {
413 SkASSERT(sLink[~eIndex] == ~rIndex);
415 }
416 }
417 rIndex = eIndex;
418 if (rIndex < 0) {
419 forward ^= 1;
420 rIndex = ~rIndex;
421 }
422 } while (true);
423 for (rIndex = 0; rIndex < linkCount; ++rIndex) {
425 break;
426 }
427 }
428 } while (rIndex < linkCount);
429#if DEBUG_ASSEMBLE
430 for (rIndex = 0; rIndex < linkCount; ++rIndex) {
433 }
434#endif
435}
static int step(int x, SkScalar min, SkScalar max)
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static float next(float f)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr int32_t SK_MaxS32
bool zero_or_one(double x)
const SkOpSpanBase * span() const
bool contains(const SkOpPtT *) const
SkOpSegment * isSimple(SkOpSpanBase **end, int *step) const
bool addCurveTo(const SkOpSpanBase *start, const SkOpSpanBase *end, SkPathWriter *path) const
const SkOpSpan * prev() const
SkOpSegment * segment() const
const SkOpPtT * ptT() const
SkOpSpanBase * next() const
bool getLastPt(SkPoint *lastPt) const
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx