gfx/skia/trunk/src/pathops/SkPathOpsCommon.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2012 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     7 #include "SkAddIntersections.h"
     8 #include "SkOpEdgeBuilder.h"
     9 #include "SkPathOpsCommon.h"
    10 #include "SkPathWriter.h"
    11 #include "SkTSort.h"
    13 static int contourRangeCheckY(const SkTArray<SkOpContour*, true>& contourList, SkOpSegment** currentPtr,
    14                               int* indexPtr, int* endIndexPtr, double* bestHit, SkScalar* bestDx,
    15                               bool* tryAgain, double* midPtr, bool opp) {
    16     const int index = *indexPtr;
    17     const int endIndex = *endIndexPtr;
    18     const double mid = *midPtr;
    19     const SkOpSegment* current = *currentPtr;
    20     double tAtMid = current->tAtMid(index, endIndex, mid);
    21     SkPoint basePt = current->ptAtT(tAtMid);
    22     int contourCount = contourList.count();
    23     SkScalar bestY = SK_ScalarMin;
    24     SkOpSegment* bestSeg = NULL;
    25     int bestTIndex = 0;
    26     bool bestOpp;
    27     bool hitSomething = false;
    28     for (int cTest = 0; cTest < contourCount; ++cTest) {
    29         SkOpContour* contour = contourList[cTest];
    30         bool testOpp = contour->operand() ^ current->operand() ^ opp;
    31         if (basePt.fY < contour->bounds().fTop) {
    32             continue;
    33         }
    34         if (bestY > contour->bounds().fBottom) {
    35             continue;
    36         }
    37         int segmentCount = contour->segments().count();
    38         for (int test = 0; test < segmentCount; ++test) {
    39             SkOpSegment* testSeg = &contour->segments()[test];
    40             SkScalar testY = bestY;
    41             double testHit;
    42             int testTIndex = testSeg->crossedSpanY(basePt, &testY, &testHit, &hitSomething, tAtMid,
    43                     testOpp, testSeg == current);
    44             if (testTIndex < 0) {
    45                 if (testTIndex == SK_MinS32) {
    46                     hitSomething = true;
    47                     bestSeg = NULL;
    48                     goto abortContours;  // vertical encountered, return and try different point
    49                 }
    50                 continue;
    51             }
    52             if (testSeg == current && current->betweenTs(index, testHit, endIndex)) {
    53                 double baseT = current->t(index);
    54                 double endT = current->t(endIndex);
    55                 double newMid = (testHit - baseT) / (endT - baseT);
    56 #if DEBUG_WINDING
    57                 double midT = current->tAtMid(index, endIndex, mid);
    58                 SkPoint midXY = current->xyAtT(midT);
    59                 double newMidT = current->tAtMid(index, endIndex, newMid);
    60                 SkPoint newXY = current->xyAtT(newMidT);
    61                 SkDebugf("%s [%d] mid=%1.9g->%1.9g s=%1.9g (%1.9g,%1.9g) m=%1.9g (%1.9g,%1.9g)"
    62                         " n=%1.9g (%1.9g,%1.9g) e=%1.9g (%1.9g,%1.9g)\n", __FUNCTION__,
    63                         current->debugID(), mid, newMid,
    64                         baseT, current->xAtT(index), current->yAtT(index),
    65                         baseT + mid * (endT - baseT), midXY.fX, midXY.fY,
    66                         baseT + newMid * (endT - baseT), newXY.fX, newXY.fY,
    67                         endT, current->xAtT(endIndex), current->yAtT(endIndex));
    68 #endif
    69                 *midPtr = newMid * 2;  // calling loop with divide by 2 before continuing
    70                 return SK_MinS32;
    71             }
    72             bestSeg = testSeg;
    73             *bestHit = testHit;
    74             bestOpp = testOpp;
    75             bestTIndex = testTIndex;
    76             bestY = testY;
    77         }
    78     }
    79 abortContours:
    80     int result;
    81     if (!bestSeg) {
    82         result = hitSomething ? SK_MinS32 : 0;
    83     } else {
    84         if (bestSeg->windSum(bestTIndex) == SK_MinS32) {
    85             *currentPtr = bestSeg;
    86             *indexPtr = bestTIndex;
    87             *endIndexPtr = bestSeg->nextSpan(bestTIndex, 1);
    88             SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
    89             *tryAgain = true;
    90             return 0;
    91         }
    92         result = bestSeg->windingAtT(*bestHit, bestTIndex, bestOpp, bestDx);
    93         SkASSERT(result == SK_MinS32 || *bestDx);
    94     }
    95     double baseT = current->t(index);
    96     double endT = current->t(endIndex);
    97     *bestHit = baseT + mid * (endT - baseT);
    98     return result;
    99 }
   101 SkOpSegment* FindUndone(SkTArray<SkOpContour*, true>& contourList, int* start, int* end) {
   102     int contourCount = contourList.count();
   103     SkOpSegment* result;
   104     for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
   105         SkOpContour* contour = contourList[cIndex];
   106         result = contour->undoneSegment(start, end);
   107         if (result) {
   108             return result;
   109         }
   110     }
   111     return NULL;
   112 }
   114 SkOpSegment* FindChase(SkTDArray<SkOpSpan*>& chase, int& tIndex, int& endIndex) {
   115     while (chase.count()) {
   116         SkOpSpan* span;
   117         chase.pop(&span);
   118         const SkOpSpan& backPtr = span->fOther->span(span->fOtherIndex);
   119         SkOpSegment* segment = backPtr.fOther;
   120         tIndex = backPtr.fOtherIndex;
   121         SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
   122         int done = 0;
   123         if (segment->activeAngle(tIndex, &done, &angles)) {
   124             SkOpAngle* last = angles.end() - 1;
   125             tIndex = last->start();
   126             endIndex = last->end();
   127    #if TRY_ROTATE
   128             *chase.insert(0) = span;
   129    #else
   130             *chase.append() = span;
   131    #endif
   132             return last->segment();
   133         }
   134         if (done == angles.count()) {
   135             continue;
   136         }
   137         SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
   138         bool sortable = SkOpSegment::SortAngles(angles, &sorted,
   139                 SkOpSegment::kMayBeUnordered_SortAngleKind);
   140         int angleCount = sorted.count();
   141 #if DEBUG_SORT
   142         sorted[0]->segment()->debugShowSort(__FUNCTION__, sorted, 0, 0, 0, sortable);
   143 #endif
   144         if (!sortable) {
   145             continue;
   146         }
   147         // find first angle, initialize winding to computed fWindSum
   148         int firstIndex = -1;
   149         const SkOpAngle* angle;
   150         int winding;
   151         do {
   152             angle = sorted[++firstIndex];
   153             segment = angle->segment();
   154             winding = segment->windSum(angle);
   155         } while (winding == SK_MinS32);
   156         int spanWinding = segment->spanSign(angle->start(), angle->end());
   157     #if DEBUG_WINDING
   158         SkDebugf("%s winding=%d spanWinding=%d\n",
   159                 __FUNCTION__, winding, spanWinding);
   160     #endif
   161         // turn span winding into contour winding
   162         if (spanWinding * winding < 0) {
   163             winding += spanWinding;
   164         }
   165     #if DEBUG_SORT
   166         segment->debugShowSort(__FUNCTION__, sorted, firstIndex, winding, 0, sortable);
   167     #endif
   168         // we care about first sign and whether wind sum indicates this
   169         // edge is inside or outside. Maybe need to pass span winding
   170         // or first winding or something into this function?
   171         // advance to first undone angle, then return it and winding
   172         // (to set whether edges are active or not)
   173         int nextIndex = firstIndex + 1;
   174         int lastIndex = firstIndex != 0 ? firstIndex : angleCount;
   175         angle = sorted[firstIndex];
   176         winding -= angle->segment()->spanSign(angle);
   177         do {
   178             SkASSERT(nextIndex != firstIndex);
   179             if (nextIndex == angleCount) {
   180                 nextIndex = 0;
   181             }
   182             angle = sorted[nextIndex];
   183             segment = angle->segment();
   184             int maxWinding = winding;
   185             winding -= segment->spanSign(angle);
   186     #if DEBUG_SORT
   187             SkDebugf("%s id=%d maxWinding=%d winding=%d sign=%d\n", __FUNCTION__,
   188                     segment->debugID(), maxWinding, winding, angle->sign());
   189     #endif
   190             tIndex = angle->start();
   191             endIndex = angle->end();
   192             int lesser = SkMin32(tIndex, endIndex);
   193             const SkOpSpan& nextSpan = segment->span(lesser);
   194             if (!nextSpan.fDone) {
   195             // FIXME: this be wrong? assign startWinding if edge is in
   196             // same direction. If the direction is opposite, winding to
   197             // assign is flipped sign or +/- 1?
   198                 if (SkOpSegment::UseInnerWinding(maxWinding, winding)) {
   199                     maxWinding = winding;
   200                 }
   201                 segment->markAndChaseWinding(angle, maxWinding, 0);
   202                 break;
   203             }
   204         } while (++nextIndex != lastIndex);
   205         *chase.insert(0) = span;
   206         return segment;
   207     }
   208     return NULL;
   209 }
   211 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
   212 void DebugShowActiveSpans(SkTArray<SkOpContour*, true>& contourList) {
   213     int index;
   214     for (index = 0; index < contourList.count(); ++ index) {
   215         contourList[index]->debugShowActiveSpans();
   216     }
   217 }
   218 #endif
   220 static SkOpSegment* findSortableTop(const SkTArray<SkOpContour*, true>& contourList,
   221                                     int* index, int* endIndex, SkPoint* topLeft, bool* unsortable,
   222                                     bool* done, bool onlySortable) {
   223     SkOpSegment* result;
   224     do {
   225         SkPoint bestXY = {SK_ScalarMax, SK_ScalarMax};
   226         int contourCount = contourList.count();
   227         SkOpSegment* topStart = NULL;
   228         *done = true;
   229         for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
   230             SkOpContour* contour = contourList[cIndex];
   231             if (contour->done()) {
   232                 continue;
   233             }
   234             const SkPathOpsBounds& bounds = contour->bounds();
   235             if (bounds.fBottom < topLeft->fY) {
   236                 *done = false;
   237                 continue;
   238             }
   239             if (bounds.fBottom == topLeft->fY && bounds.fRight < topLeft->fX) {
   240                 *done = false;
   241                 continue;
   242             }
   243             contour->topSortableSegment(*topLeft, &bestXY, &topStart);
   244             if (!contour->done()) {
   245                 *done = false;
   246             }
   247         }
   248         if (!topStart) {
   249             return NULL;
   250         }
   251         *topLeft = bestXY;
   252         result = topStart->findTop(index, endIndex, unsortable, onlySortable);
   253     } while (!result);
   254     if (result) {
   255         *unsortable = false;
   256     }
   257     return result;
   258 }
   260 static int rightAngleWinding(const SkTArray<SkOpContour*, true>& contourList,
   261                              SkOpSegment** current, int* index, int* endIndex, double* tHit,
   262                              SkScalar* hitDx, bool* tryAgain, bool opp) {
   263     double test = 0.9;
   264     int contourWinding;
   265     do {
   266         contourWinding = contourRangeCheckY(contourList, current, index, endIndex, tHit, hitDx,
   267                 tryAgain, &test, opp);
   268         if (contourWinding != SK_MinS32 || *tryAgain) {
   269             return contourWinding;
   270         }
   271         test /= 2;
   272     } while (!approximately_negative(test));
   273     SkASSERT(0);  // should be OK to comment out, but interested when this hits
   274     return contourWinding;
   275 }
   277 static void skipVertical(const SkTArray<SkOpContour*, true>& contourList,
   278         SkOpSegment** current, int* index, int* endIndex) {
   279     if (!(*current)->isVertical(*index, *endIndex)) {
   280         return;
   281     }
   282     int contourCount = contourList.count();
   283     for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
   284         SkOpContour* contour = contourList[cIndex];
   285         if (contour->done()) {
   286             continue;
   287         }
   288         *current = contour->nonVerticalSegment(index, endIndex);
   289         if (*current) {
   290             return;
   291         }
   292     }
   293 }
   295 SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
   296         SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexPtr,
   297         int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done) {
   298     SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, topLeft, unsortable,
   299             done, true);
   300     if (!current) {
   301         return NULL;
   302     }
   303     const int index = *indexPtr;
   304     const int endIndex = *endIndexPtr;
   305     if (*firstContour) {
   306         current->initWinding(index, endIndex);
   307         *firstContour = false;
   308         return current;
   309     }
   310     int minIndex = SkMin32(index, endIndex);
   311     int sumWinding = current->windSum(minIndex);
   312     if (sumWinding != SK_MinS32) {
   313         return current;
   314     }
   315     SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32);
   316     SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
   317     SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
   318     sumWinding = current->computeSum(index, endIndex, angleIncludeType, &angles, &sorted);
   319     if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) {
   320         return current;
   321     }
   322     int contourWinding;
   323     int oppContourWinding = 0;
   324     // the simple upward projection of the unresolved points hit unsortable angles
   325     // shoot rays at right angles to the segment to find its winding, ignoring angle cases
   326     bool tryAgain;
   327     double tHit;
   328     SkScalar hitDx = 0;
   329     SkScalar hitOppDx = 0;
   330     do {
   331         // if current is vertical, find another candidate which is not
   332         // if only remaining candidates are vertical, then they can be marked done
   333         SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
   334         skipVertical(contourList, &current, indexPtr, endIndexPtr);
   336         SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
   337         tryAgain = false;
   338         contourWinding = rightAngleWinding(contourList, &current, indexPtr, endIndexPtr, &tHit,
   339                 &hitDx, &tryAgain, false);
   340         if (tryAgain) {
   341             continue;
   342         }
   343         if (angleIncludeType < SkOpAngle::kBinarySingle) {
   344             break;
   345         }
   346         oppContourWinding = rightAngleWinding(contourList, &current, indexPtr, endIndexPtr, &tHit,
   347                 &hitOppDx, &tryAgain, true);
   348     } while (tryAgain);
   349     current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, oppContourWinding,
   350             hitOppDx);
   351     return current;
   352 }
   354 static void checkEnds(SkTArray<SkOpContour*, true>* contourList) {
   355     // it's hard to determine if the end of a cubic or conic nearly intersects another curve.
   356     // instead, look to see if the connecting curve intersected at that same end.
   357     int contourCount = (*contourList).count();
   358     for (int cTest = 0; cTest < contourCount; ++cTest) {
   359         SkOpContour* contour = (*contourList)[cTest];
   360         contour->checkEnds();
   361     }
   362 }
   364 // A tiny interval may indicate an undiscovered coincidence. Find and fix.
   365 static void checkTiny(SkTArray<SkOpContour*, true>* contourList) {
   366     int contourCount = (*contourList).count();
   367     for (int cTest = 0; cTest < contourCount; ++cTest) {
   368         SkOpContour* contour = (*contourList)[cTest];
   369         contour->checkTiny();
   370     }
   371 }
   373 static void fixOtherTIndex(SkTArray<SkOpContour*, true>* contourList) {
   374     int contourCount = (*contourList).count();
   375     for (int cTest = 0; cTest < contourCount; ++cTest) {
   376         SkOpContour* contour = (*contourList)[cTest];
   377         contour->fixOtherTIndex();
   378     }
   379 }
   381 static void joinCoincidence(SkTArray<SkOpContour*, true>* contourList) {
   382     int contourCount = (*contourList).count();
   383     for (int cTest = 0; cTest < contourCount; ++cTest) {
   384         SkOpContour* contour = (*contourList)[cTest];
   385         contour->joinCoincidence();
   386     }
   387 }
   389 static void sortSegments(SkTArray<SkOpContour*, true>* contourList) {
   390     int contourCount = (*contourList).count();
   391     for (int cTest = 0; cTest < contourCount; ++cTest) {
   392         SkOpContour* contour = (*contourList)[cTest];
   393         contour->sortSegments();
   394     }
   395 }
   397 void MakeContourList(SkTArray<SkOpContour>& contours, SkTArray<SkOpContour*, true>& list,
   398                      bool evenOdd, bool oppEvenOdd) {
   399     int count = contours.count();
   400     if (count == 0) {
   401         return;
   402     }
   403     for (int index = 0; index < count; ++index) {
   404         SkOpContour& contour = contours[index];
   405         contour.setOppXor(contour.operand() ? evenOdd : oppEvenOdd);
   406         list.push_back(&contour);
   407     }
   408     SkTQSort<SkOpContour>(list.begin(), list.end() - 1);
   409 }
   411 class DistanceLessThan {
   412 public:
   413     DistanceLessThan(double* distances) : fDistances(distances) { }
   414     double* fDistances;
   415     bool operator()(const int one, const int two) {
   416         return fDistances[one] < fDistances[two];
   417     }
   418 };
   420     /*
   421         check start and end of each contour
   422         if not the same, record them
   423         match them up
   424         connect closest
   425         reassemble contour pieces into new path
   426     */
   427 void Assemble(const SkPathWriter& path, SkPathWriter* simple) {
   428 #if DEBUG_PATH_CONSTRUCTION
   429     SkDebugf("%s\n", __FUNCTION__);
   430 #endif
   431     SkTArray<SkOpContour> contours;
   432     SkOpEdgeBuilder builder(path, contours);
   433     builder.finish();
   434     int count = contours.count();
   435     int outer;
   436     SkTArray<int, true> runs(count);  // indices of partial contours
   437     for (outer = 0; outer < count; ++outer) {
   438         const SkOpContour& eContour = contours[outer];
   439         const SkPoint& eStart = eContour.start();
   440         const SkPoint& eEnd = eContour.end();
   441 #if DEBUG_ASSEMBLE
   442         SkDebugf("%s contour", __FUNCTION__);
   443         if (!SkDPoint::ApproximatelyEqual(eStart, eEnd)) {
   444             SkDebugf("[%d]", runs.count());
   445         } else {
   446             SkDebugf("   ");
   447         }
   448         SkDebugf(" start=(%1.9g,%1.9g) end=(%1.9g,%1.9g)\n",
   449                 eStart.fX, eStart.fY, eEnd.fX, eEnd.fY);
   450 #endif
   451         if (SkDPoint::ApproximatelyEqual(eStart, eEnd)) {
   452             eContour.toPath(simple);
   453             continue;
   454         }
   455         runs.push_back(outer);
   456     }
   457     count = runs.count();
   458     if (count == 0) {
   459         return;
   460     }
   461     SkTArray<int, true> sLink, eLink;
   462     sLink.push_back_n(count);
   463     eLink.push_back_n(count);
   464     int rIndex, iIndex;
   465     for (rIndex = 0; rIndex < count; ++rIndex) {
   466         sLink[rIndex] = eLink[rIndex] = SK_MaxS32;
   467     }
   468     const int ends = count * 2;  // all starts and ends
   469     const int entries = (ends - 1) * count;  // folded triangle : n * (n - 1) / 2
   470     SkTArray<double, true> distances;
   471     distances.push_back_n(entries);
   472     for (rIndex = 0; rIndex < ends - 1; ++rIndex) {
   473         outer = runs[rIndex >> 1];
   474         const SkOpContour& oContour = contours[outer];
   475         const SkPoint& oPt = rIndex & 1 ? oContour.end() : oContour.start();
   476         const int row = rIndex < count - 1 ? rIndex * ends : (ends - rIndex - 2)
   477                 * ends - rIndex - 1;
   478         for (iIndex = rIndex + 1; iIndex < ends; ++iIndex) {
   479             int inner = runs[iIndex >> 1];
   480             const SkOpContour& iContour = contours[inner];
   481             const SkPoint& iPt = iIndex & 1 ? iContour.end() : iContour.start();
   482             double dx = iPt.fX - oPt.fX;
   483             double dy = iPt.fY - oPt.fY;
   484             double dist = dx * dx + dy * dy;
   485             distances[row + iIndex] = dist;  // oStart distance from iStart
   486         }
   487     }
   488     SkTArray<int, true> sortedDist;
   489     sortedDist.push_back_n(entries);
   490     for (rIndex = 0; rIndex < entries; ++rIndex) {
   491         sortedDist[rIndex] = rIndex;
   492     }
   493     SkTQSort<int>(sortedDist.begin(), sortedDist.end() - 1, DistanceLessThan(distances.begin()));
   494     int remaining = count;  // number of start/end pairs
   495     for (rIndex = 0; rIndex < entries; ++rIndex) {
   496         int pair = sortedDist[rIndex];
   497         int row = pair / ends;
   498         int col = pair - row * ends;
   499         int thingOne = row < col ? row : ends - row - 2;
   500         int ndxOne = thingOne >> 1;
   501         bool endOne = thingOne & 1;
   502         int* linkOne = endOne ? eLink.begin() : sLink.begin();
   503         if (linkOne[ndxOne] != SK_MaxS32) {
   504             continue;
   505         }
   506         int thingTwo = row < col ? col : ends - row + col - 1;
   507         int ndxTwo = thingTwo >> 1;
   508         bool endTwo = thingTwo & 1;
   509         int* linkTwo = endTwo ? eLink.begin() : sLink.begin();
   510         if (linkTwo[ndxTwo] != SK_MaxS32) {
   511             continue;
   512         }
   513         SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]);
   514         bool flip = endOne == endTwo;
   515         linkOne[ndxOne] = flip ? ~ndxTwo : ndxTwo;
   516         linkTwo[ndxTwo] = flip ? ~ndxOne : ndxOne;
   517         if (!--remaining) {
   518             break;
   519         }
   520     }
   521     SkASSERT(!remaining);
   522 #if DEBUG_ASSEMBLE
   523     for (rIndex = 0; rIndex < count; ++rIndex) {
   524         int s = sLink[rIndex];
   525         int e = eLink[rIndex];
   526         SkDebugf("%s %c%d <- s%d - e%d -> %c%d\n", __FUNCTION__, s < 0 ? 's' : 'e',
   527                 s < 0 ? ~s : s, rIndex, rIndex, e < 0 ? 'e' : 's', e < 0 ? ~e : e);
   528     }
   529 #endif
   530     rIndex = 0;
   531     do {
   532         bool forward = true;
   533         bool first = true;
   534         int sIndex = sLink[rIndex];
   535         SkASSERT(sIndex != SK_MaxS32);
   536         sLink[rIndex] = SK_MaxS32;
   537         int eIndex;
   538         if (sIndex < 0) {
   539             eIndex = sLink[~sIndex];
   540             sLink[~sIndex] = SK_MaxS32;
   541         } else {
   542             eIndex = eLink[sIndex];
   543             eLink[sIndex] = SK_MaxS32;
   544         }
   545         SkASSERT(eIndex != SK_MaxS32);
   546 #if DEBUG_ASSEMBLE
   547         SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e',
   548                     sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
   549                     eIndex < 0 ? ~eIndex : eIndex);
   550 #endif
   551         do {
   552             outer = runs[rIndex];
   553             const SkOpContour& contour = contours[outer];
   554             if (first) {
   555                 first = false;
   556                 const SkPoint* startPtr = &contour.start();
   557                 simple->deferredMove(startPtr[0]);
   558             }
   559             if (forward) {
   560                 contour.toPartialForward(simple);
   561             } else {
   562                 contour.toPartialBackward(simple);
   563             }
   564 #if DEBUG_ASSEMBLE
   565             SkDebugf("%s rIndex=%d eIndex=%s%d close=%d\n", __FUNCTION__, rIndex,
   566                 eIndex < 0 ? "~" : "", eIndex < 0 ? ~eIndex : eIndex,
   567                 sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex));
   568 #endif
   569             if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) {
   570                 simple->close();
   571                 break;
   572             }
   573             if (forward) {
   574                 eIndex = eLink[rIndex];
   575                 SkASSERT(eIndex != SK_MaxS32);
   576                 eLink[rIndex] = SK_MaxS32;
   577                 if (eIndex >= 0) {
   578                     SkASSERT(sLink[eIndex] == rIndex);
   579                     sLink[eIndex] = SK_MaxS32;
   580                 } else {
   581                     SkASSERT(eLink[~eIndex] == ~rIndex);
   582                     eLink[~eIndex] = SK_MaxS32;
   583                 }
   584             } else {
   585                 eIndex = sLink[rIndex];
   586                 SkASSERT(eIndex != SK_MaxS32);
   587                 sLink[rIndex] = SK_MaxS32;
   588                 if (eIndex >= 0) {
   589                     SkASSERT(eLink[eIndex] == rIndex);
   590                     eLink[eIndex] = SK_MaxS32;
   591                 } else {
   592                     SkASSERT(sLink[~eIndex] == ~rIndex);
   593                     sLink[~eIndex] = SK_MaxS32;
   594                 }
   595             }
   596             rIndex = eIndex;
   597             if (rIndex < 0) {
   598                 forward ^= 1;
   599                 rIndex = ~rIndex;
   600             }
   601         } while (true);
   602         for (rIndex = 0; rIndex < count; ++rIndex) {
   603             if (sLink[rIndex] != SK_MaxS32) {
   604                 break;
   605             }
   606         }
   607     } while (rIndex < count);
   608 #if DEBUG_ASSEMBLE
   609     for (rIndex = 0; rIndex < count; ++rIndex) {
   610        SkASSERT(sLink[rIndex] == SK_MaxS32);
   611        SkASSERT(eLink[rIndex] == SK_MaxS32);
   612     }
   613 #endif
   614 }
   616 void HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) {
   617 #if DEBUG_SHOW_WINDING
   618     SkOpContour::debugShowWindingValues(contourList);
   619 #endif
   620     CoincidenceCheck(contourList, total);
   621 #if DEBUG_SHOW_WINDING
   622     SkOpContour::debugShowWindingValues(contourList);
   623 #endif
   624     fixOtherTIndex(contourList);
   625     checkEnds(contourList);
   626     checkTiny(contourList);
   627     joinCoincidence(contourList);
   628     sortSegments(contourList);
   629 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
   630     DebugShowActiveSpans(*contourList);
   631 #endif
   632 }

mercurial