Home | History | Annotate | Download | only in pathops
      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 "SkOpCoincidence.h"
      9 #include "SkPathOpsBounds.h"
     10 
     11 #include <utility>
     12 
     13 #if DEBUG_ADD_INTERSECTING_TS
     14 
     15 static void debugShowLineIntersection(int pts, const SkIntersectionHelper& wt,
     16                                       const SkIntersectionHelper& wn, const SkIntersections& i) {
     17     SkASSERT(i.used() == pts);
     18     if (!pts) {
     19         SkDebugf("%s no intersect " LINE_DEBUG_STR " " LINE_DEBUG_STR "\n",
     20                 __FUNCTION__, LINE_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
     21         return;
     22     }
     23     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " LINE_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
     24             i[0][0], LINE_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
     25     if (pts == 2) {
     26         SkDebugf(" " T_DEBUG_STR(wtTs, 1) " " PT_DEBUG_STR, i[0][1], PT_DEBUG_DATA(i, 1));
     27     }
     28     SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
     29     if (pts == 2) {
     30         SkDebugf(" " T_DEBUG_STR(wnTs, 1), i[1][1]);
     31     }
     32     SkDebugf("\n");
     33 }
     34 
     35 static void debugShowQuadLineIntersection(int pts, const SkIntersectionHelper& wt,
     36                                           const SkIntersectionHelper& wn,
     37                                           const SkIntersections& i) {
     38     SkASSERT(i.used() == pts);
     39     if (!pts) {
     40         SkDebugf("%s no intersect " QUAD_DEBUG_STR " " LINE_DEBUG_STR "\n",
     41                 __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
     42         return;
     43     }
     44     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
     45             i[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
     46     for (int n = 1; n < pts; ++n) {
     47         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
     48     }
     49     SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
     50     for (int n = 1; n < pts; ++n) {
     51         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
     52     }
     53     SkDebugf("\n");
     54 }
     55 
     56 static void debugShowQuadIntersection(int pts, const SkIntersectionHelper& wt,
     57         const SkIntersectionHelper& wn, const SkIntersections& i) {
     58     SkASSERT(i.used() == pts);
     59     if (!pts) {
     60         SkDebugf("%s no intersect " QUAD_DEBUG_STR " " QUAD_DEBUG_STR "\n",
     61                 __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
     62         return;
     63     }
     64     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
     65             i[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
     66     for (int n = 1; n < pts; ++n) {
     67         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
     68     }
     69     SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
     70     for (int n = 1; n < pts; ++n) {
     71         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
     72     }
     73     SkDebugf("\n");
     74 }
     75 
     76 static void debugShowConicLineIntersection(int pts, const SkIntersectionHelper& wt,
     77         const SkIntersectionHelper& wn, const SkIntersections& i) {
     78     SkASSERT(i.used() == pts);
     79     if (!pts) {
     80         SkDebugf("%s no intersect " CONIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
     81                 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()), LINE_DEBUG_DATA(wn.pts()));
     82         return;
     83     }
     84     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
     85             i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
     86     for (int n = 1; n < pts; ++n) {
     87         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
     88     }
     89     SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
     90     for (int n = 1; n < pts; ++n) {
     91         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
     92     }
     93     SkDebugf("\n");
     94 }
     95 
     96 static void debugShowConicQuadIntersection(int pts, const SkIntersectionHelper& wt,
     97         const SkIntersectionHelper& wn, const SkIntersections& i) {
     98     SkASSERT(i.used() == pts);
     99     if (!pts) {
    100         SkDebugf("%s no intersect " CONIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
    101                 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()), QUAD_DEBUG_DATA(wn.pts()));
    102         return;
    103     }
    104     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
    105             i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
    106     for (int n = 1; n < pts; ++n) {
    107         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
    108     }
    109     SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
    110     for (int n = 1; n < pts; ++n) {
    111         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
    112     }
    113     SkDebugf("\n");
    114 }
    115 
    116 static void debugShowConicIntersection(int pts, const SkIntersectionHelper& wt,
    117         const SkIntersectionHelper& wn, const SkIntersections& i) {
    118     SkASSERT(i.used() == pts);
    119     if (!pts) {
    120         SkDebugf("%s no intersect " CONIC_DEBUG_STR " " CONIC_DEBUG_STR "\n",
    121                 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()),
    122                 CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
    123         return;
    124     }
    125     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
    126             i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
    127     for (int n = 1; n < pts; ++n) {
    128         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
    129     }
    130     SkDebugf(" wnTs[0]=%g " CONIC_DEBUG_STR, i[1][0], CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
    131     for (int n = 1; n < pts; ++n) {
    132         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
    133     }
    134     SkDebugf("\n");
    135 }
    136 
    137 static void debugShowCubicLineIntersection(int pts, const SkIntersectionHelper& wt,
    138         const SkIntersectionHelper& wn, const SkIntersections& i) {
    139     SkASSERT(i.used() == pts);
    140     if (!pts) {
    141         SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
    142                 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
    143         return;
    144     }
    145     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
    146             i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
    147     for (int n = 1; n < pts; ++n) {
    148         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
    149     }
    150     SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
    151     for (int n = 1; n < pts; ++n) {
    152         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
    153     }
    154     SkDebugf("\n");
    155 }
    156 
    157 static void debugShowCubicQuadIntersection(int pts, const SkIntersectionHelper& wt,
    158         const SkIntersectionHelper& wn, const SkIntersections& i) {
    159     SkASSERT(i.used() == pts);
    160     if (!pts) {
    161         SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
    162                 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
    163         return;
    164     }
    165     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
    166             i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
    167     for (int n = 1; n < pts; ++n) {
    168         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
    169     }
    170     SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
    171     for (int n = 1; n < pts; ++n) {
    172         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
    173     }
    174     SkDebugf("\n");
    175 }
    176 
    177 static void debugShowCubicConicIntersection(int pts, const SkIntersectionHelper& wt,
    178         const SkIntersectionHelper& wn, const SkIntersections& i) {
    179     SkASSERT(i.used() == pts);
    180     if (!pts) {
    181         SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CONIC_DEBUG_STR "\n",
    182                 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
    183         return;
    184     }
    185     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
    186             i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
    187     for (int n = 1; n < pts; ++n) {
    188         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
    189     }
    190     SkDebugf(" wnTs[0]=%g " CONIC_DEBUG_STR, i[1][0], CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
    191     for (int n = 1; n < pts; ++n) {
    192         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
    193     }
    194     SkDebugf("\n");
    195 }
    196 
    197 static void debugShowCubicIntersection(int pts, const SkIntersectionHelper& wt,
    198         const SkIntersectionHelper& wn, const SkIntersections& i) {
    199     SkASSERT(i.used() == pts);
    200     if (!pts) {
    201         SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CUBIC_DEBUG_STR "\n",
    202                 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CUBIC_DEBUG_DATA(wn.pts()));
    203         return;
    204     }
    205     SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
    206             i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
    207     for (int n = 1; n < pts; ++n) {
    208         SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
    209     }
    210     SkDebugf(" wnTs[0]=%g " CUBIC_DEBUG_STR, i[1][0], CUBIC_DEBUG_DATA(wn.pts()));
    211     for (int n = 1; n < pts; ++n) {
    212         SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
    213     }
    214     SkDebugf("\n");
    215 }
    216 
    217 #else
    218 static void debugShowLineIntersection(int , const SkIntersectionHelper& ,
    219         const SkIntersectionHelper& , const SkIntersections& ) {
    220 }
    221 
    222 static void debugShowQuadLineIntersection(int , const SkIntersectionHelper& ,
    223         const SkIntersectionHelper& , const SkIntersections& ) {
    224 }
    225 
    226 static void debugShowQuadIntersection(int , const SkIntersectionHelper& ,
    227         const SkIntersectionHelper& , const SkIntersections& ) {
    228 }
    229 
    230 static void debugShowConicLineIntersection(int , const SkIntersectionHelper& ,
    231         const SkIntersectionHelper& , const SkIntersections& ) {
    232 }
    233 
    234 static void debugShowConicQuadIntersection(int , const SkIntersectionHelper& ,
    235         const SkIntersectionHelper& , const SkIntersections& ) {
    236 }
    237 
    238 static void debugShowConicIntersection(int , const SkIntersectionHelper& ,
    239         const SkIntersectionHelper& , const SkIntersections& ) {
    240 }
    241 
    242 static void debugShowCubicLineIntersection(int , const SkIntersectionHelper& ,
    243         const SkIntersectionHelper& , const SkIntersections& ) {
    244 }
    245 
    246 static void debugShowCubicQuadIntersection(int , const SkIntersectionHelper& ,
    247         const SkIntersectionHelper& , const SkIntersections& ) {
    248 }
    249 
    250 static void debugShowCubicConicIntersection(int , const SkIntersectionHelper& ,
    251         const SkIntersectionHelper& , const SkIntersections& ) {
    252 }
    253 
    254 static void debugShowCubicIntersection(int , const SkIntersectionHelper& ,
    255         const SkIntersectionHelper& , const SkIntersections& ) {
    256 }
    257 #endif
    258 
    259 bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coincidence) {
    260     if (test != next) {
    261         if (AlmostLessUlps(test->bounds().fBottom, next->bounds().fTop)) {
    262             return false;
    263         }
    264         // OPTIMIZATION: outset contour bounds a smidgen instead?
    265         if (!SkPathOpsBounds::Intersects(test->bounds(), next->bounds())) {
    266             return true;
    267         }
    268     }
    269     SkIntersectionHelper wt;
    270     wt.init(test);
    271     do {
    272         SkIntersectionHelper wn;
    273         wn.init(next);
    274         test->debugValidate();
    275         next->debugValidate();
    276         if (test == next && !wn.startAfter(wt)) {
    277             continue;
    278         }
    279         do {
    280             if (!SkPathOpsBounds::Intersects(wt.bounds(), wn.bounds())) {
    281                 continue;
    282             }
    283             int pts = 0;
    284             SkIntersections ts { SkDEBUGCODE(test->globalState()) };
    285             bool swap = false;
    286             SkDQuad quad1, quad2;
    287             SkDConic conic1, conic2;
    288             SkDCubic cubic1, cubic2;
    289             switch (wt.segmentType()) {
    290                 case SkIntersectionHelper::kHorizontalLine_Segment:
    291                     swap = true;
    292                     switch (wn.segmentType()) {
    293                         case SkIntersectionHelper::kHorizontalLine_Segment:
    294                         case SkIntersectionHelper::kVerticalLine_Segment:
    295                         case SkIntersectionHelper::kLine_Segment:
    296                             pts = ts.lineHorizontal(wn.pts(), wt.left(),
    297                                     wt.right(), wt.y(), wt.xFlipped());
    298                             debugShowLineIntersection(pts, wn, wt, ts);
    299                             break;
    300                         case SkIntersectionHelper::kQuad_Segment:
    301                             pts = ts.quadHorizontal(wn.pts(), wt.left(),
    302                                     wt.right(), wt.y(), wt.xFlipped());
    303                             debugShowQuadLineIntersection(pts, wn, wt, ts);
    304                             break;
    305                         case SkIntersectionHelper::kConic_Segment:
    306                             pts = ts.conicHorizontal(wn.pts(), wn.weight(), wt.left(),
    307                                     wt.right(), wt.y(), wt.xFlipped());
    308                             debugShowConicLineIntersection(pts, wn, wt, ts);
    309                             break;
    310                         case SkIntersectionHelper::kCubic_Segment:
    311                             pts = ts.cubicHorizontal(wn.pts(), wt.left(),
    312                                     wt.right(), wt.y(), wt.xFlipped());
    313                             debugShowCubicLineIntersection(pts, wn, wt, ts);
    314                             break;
    315                         default:
    316                             SkASSERT(0);
    317                     }
    318                     break;
    319                 case SkIntersectionHelper::kVerticalLine_Segment:
    320                     swap = true;
    321                     switch (wn.segmentType()) {
    322                         case SkIntersectionHelper::kHorizontalLine_Segment:
    323                         case SkIntersectionHelper::kVerticalLine_Segment:
    324                         case SkIntersectionHelper::kLine_Segment: {
    325                             pts = ts.lineVertical(wn.pts(), wt.top(),
    326                                     wt.bottom(), wt.x(), wt.yFlipped());
    327                             debugShowLineIntersection(pts, wn, wt, ts);
    328                             break;
    329                         }
    330                         case SkIntersectionHelper::kQuad_Segment: {
    331                             pts = ts.quadVertical(wn.pts(), wt.top(),
    332                                     wt.bottom(), wt.x(), wt.yFlipped());
    333                             debugShowQuadLineIntersection(pts, wn, wt, ts);
    334                             break;
    335                         }
    336                         case SkIntersectionHelper::kConic_Segment: {
    337                             pts = ts.conicVertical(wn.pts(), wn.weight(), wt.top(),
    338                                     wt.bottom(), wt.x(), wt.yFlipped());
    339                             debugShowConicLineIntersection(pts, wn, wt, ts);
    340                             break;
    341                         }
    342                         case SkIntersectionHelper::kCubic_Segment: {
    343                             pts = ts.cubicVertical(wn.pts(), wt.top(),
    344                                     wt.bottom(), wt.x(), wt.yFlipped());
    345                             debugShowCubicLineIntersection(pts, wn, wt, ts);
    346                             break;
    347                         }
    348                         default:
    349                             SkASSERT(0);
    350                     }
    351                     break;
    352                 case SkIntersectionHelper::kLine_Segment:
    353                     switch (wn.segmentType()) {
    354                         case SkIntersectionHelper::kHorizontalLine_Segment:
    355                             pts = ts.lineHorizontal(wt.pts(), wn.left(),
    356                                     wn.right(), wn.y(), wn.xFlipped());
    357                             debugShowLineIntersection(pts, wt, wn, ts);
    358                             break;
    359                         case SkIntersectionHelper::kVerticalLine_Segment:
    360                             pts = ts.lineVertical(wt.pts(), wn.top(),
    361                                     wn.bottom(), wn.x(), wn.yFlipped());
    362                             debugShowLineIntersection(pts, wt, wn, ts);
    363                             break;
    364                         case SkIntersectionHelper::kLine_Segment:
    365                             pts = ts.lineLine(wt.pts(), wn.pts());
    366                             debugShowLineIntersection(pts, wt, wn, ts);
    367                             break;
    368                         case SkIntersectionHelper::kQuad_Segment:
    369                             swap = true;
    370                             pts = ts.quadLine(wn.pts(), wt.pts());
    371                             debugShowQuadLineIntersection(pts, wn, wt, ts);
    372                             break;
    373                         case SkIntersectionHelper::kConic_Segment:
    374                             swap = true;
    375                             pts = ts.conicLine(wn.pts(), wn.weight(), wt.pts());
    376                             debugShowConicLineIntersection(pts, wn, wt, ts);
    377                             break;
    378                         case SkIntersectionHelper::kCubic_Segment:
    379                             swap = true;
    380                             pts = ts.cubicLine(wn.pts(), wt.pts());
    381                             debugShowCubicLineIntersection(pts, wn, wt, ts);
    382                             break;
    383                         default:
    384                             SkASSERT(0);
    385                     }
    386                     break;
    387                 case SkIntersectionHelper::kQuad_Segment:
    388                     switch (wn.segmentType()) {
    389                         case SkIntersectionHelper::kHorizontalLine_Segment:
    390                             pts = ts.quadHorizontal(wt.pts(), wn.left(),
    391                                     wn.right(), wn.y(), wn.xFlipped());
    392                             debugShowQuadLineIntersection(pts, wt, wn, ts);
    393                             break;
    394                         case SkIntersectionHelper::kVerticalLine_Segment:
    395                             pts = ts.quadVertical(wt.pts(), wn.top(),
    396                                     wn.bottom(), wn.x(), wn.yFlipped());
    397                             debugShowQuadLineIntersection(pts, wt, wn, ts);
    398                             break;
    399                         case SkIntersectionHelper::kLine_Segment:
    400                             pts = ts.quadLine(wt.pts(), wn.pts());
    401                             debugShowQuadLineIntersection(pts, wt, wn, ts);
    402                             break;
    403                         case SkIntersectionHelper::kQuad_Segment: {
    404                             pts = ts.intersect(quad1.set(wt.pts()), quad2.set(wn.pts()));
    405                             debugShowQuadIntersection(pts, wt, wn, ts);
    406                             break;
    407                         }
    408                         case SkIntersectionHelper::kConic_Segment: {
    409                             swap = true;
    410                             pts = ts.intersect(conic2.set(wn.pts(), wn.weight()),
    411                                     quad1.set(wt.pts()));
    412                             debugShowConicQuadIntersection(pts, wn, wt, ts);
    413                             break;
    414                         }
    415                         case SkIntersectionHelper::kCubic_Segment: {
    416                             swap = true;
    417                             pts = ts.intersect(cubic2.set(wn.pts()), quad1.set(wt.pts()));
    418                             debugShowCubicQuadIntersection(pts, wn, wt, ts);
    419                             break;
    420                         }
    421                         default:
    422                             SkASSERT(0);
    423                     }
    424                     break;
    425                 case SkIntersectionHelper::kConic_Segment:
    426                     switch (wn.segmentType()) {
    427                         case SkIntersectionHelper::kHorizontalLine_Segment:
    428                             pts = ts.conicHorizontal(wt.pts(), wt.weight(), wn.left(),
    429                                     wn.right(), wn.y(), wn.xFlipped());
    430                             debugShowConicLineIntersection(pts, wt, wn, ts);
    431                             break;
    432                         case SkIntersectionHelper::kVerticalLine_Segment:
    433                             pts = ts.conicVertical(wt.pts(), wt.weight(), wn.top(),
    434                                     wn.bottom(), wn.x(), wn.yFlipped());
    435                             debugShowConicLineIntersection(pts, wt, wn, ts);
    436                             break;
    437                         case SkIntersectionHelper::kLine_Segment:
    438                             pts = ts.conicLine(wt.pts(), wt.weight(), wn.pts());
    439                             debugShowConicLineIntersection(pts, wt, wn, ts);
    440                             break;
    441                         case SkIntersectionHelper::kQuad_Segment: {
    442                             pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
    443                                     quad2.set(wn.pts()));
    444                             debugShowConicQuadIntersection(pts, wt, wn, ts);
    445                             break;
    446                         }
    447                         case SkIntersectionHelper::kConic_Segment: {
    448                             pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
    449                                     conic2.set(wn.pts(), wn.weight()));
    450                             debugShowConicIntersection(pts, wt, wn, ts);
    451                             break;
    452                         }
    453                         case SkIntersectionHelper::kCubic_Segment: {
    454                             swap = true;
    455                             pts = ts.intersect(cubic2.set(wn.pts()
    456                                     SkDEBUGPARAMS(ts.globalState())),
    457                                     conic1.set(wt.pts(), wt.weight()
    458                                     SkDEBUGPARAMS(ts.globalState())));
    459                             debugShowCubicConicIntersection(pts, wn, wt, ts);
    460                             break;
    461                         }
    462                     }
    463                     break;
    464                 case SkIntersectionHelper::kCubic_Segment:
    465                     switch (wn.segmentType()) {
    466                         case SkIntersectionHelper::kHorizontalLine_Segment:
    467                             pts = ts.cubicHorizontal(wt.pts(), wn.left(),
    468                                     wn.right(), wn.y(), wn.xFlipped());
    469                             debugShowCubicLineIntersection(pts, wt, wn, ts);
    470                             break;
    471                         case SkIntersectionHelper::kVerticalLine_Segment:
    472                             pts = ts.cubicVertical(wt.pts(), wn.top(),
    473                                     wn.bottom(), wn.x(), wn.yFlipped());
    474                             debugShowCubicLineIntersection(pts, wt, wn, ts);
    475                             break;
    476                         case SkIntersectionHelper::kLine_Segment:
    477                             pts = ts.cubicLine(wt.pts(), wn.pts());
    478                             debugShowCubicLineIntersection(pts, wt, wn, ts);
    479                             break;
    480                         case SkIntersectionHelper::kQuad_Segment: {
    481                             pts = ts.intersect(cubic1.set(wt.pts()), quad2.set(wn.pts()));
    482                             debugShowCubicQuadIntersection(pts, wt, wn, ts);
    483                             break;
    484                         }
    485                         case SkIntersectionHelper::kConic_Segment: {
    486                             pts = ts.intersect(cubic1.set(wt.pts()
    487                                     SkDEBUGPARAMS(ts.globalState())),
    488                                     conic2.set(wn.pts(), wn.weight()
    489                                     SkDEBUGPARAMS(ts.globalState())));
    490                             debugShowCubicConicIntersection(pts, wt, wn, ts);
    491                             break;
    492                         }
    493                         case SkIntersectionHelper::kCubic_Segment: {
    494                             pts = ts.intersect(cubic1.set(wt.pts()), cubic2.set(wn.pts()));
    495                             debugShowCubicIntersection(pts, wt, wn, ts);
    496                             break;
    497                         }
    498                         default:
    499                             SkASSERT(0);
    500                     }
    501                     break;
    502                 default:
    503                     SkASSERT(0);
    504             }
    505 #if DEBUG_T_SECT_LOOP_COUNT
    506             test->globalState()->debugAddLoopCount(&ts, wt, wn);
    507 #endif
    508             int coinIndex = -1;
    509             SkOpPtT* coinPtT[2];
    510             for (int pt = 0; pt < pts; ++pt) {
    511                 SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1);
    512                 SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1);
    513                 wt.segment()->debugValidate();
    514                 // if t value is used to compute pt in addT, error may creep in and
    515                 // rect intersections may result in non-rects. if pt value from intersection
    516                 // is passed in, current tests break. As a workaround, pass in pt
    517                 // value from intersection only if pt.x and pt.y is integral
    518                 SkPoint iPt = ts.pt(pt).asSkPoint();
    519                 bool iPtIsIntegral = iPt.fX == floor(iPt.fX) && iPt.fY == floor(iPt.fY);
    520                 SkOpPtT* testTAt = iPtIsIntegral ? wt.segment()->addT(ts[swap][pt], iPt)
    521                         : wt.segment()->addT(ts[swap][pt]);
    522                 wn.segment()->debugValidate();
    523                 SkOpPtT* nextTAt = iPtIsIntegral ? wn.segment()->addT(ts[!swap][pt], iPt)
    524                         : wn.segment()->addT(ts[!swap][pt]);
    525                 if (!testTAt->contains(nextTAt)) {
    526                     SkOpPtT* oppPrev = testTAt->oppPrev(nextTAt);  //  Returns nullptr if pair
    527                     if (oppPrev) {                                 //  already share a pt-t loop.
    528                         testTAt->span()->mergeMatches(nextTAt->span());
    529                         testTAt->addOpp(nextTAt, oppPrev);
    530                     }
    531                     if (testTAt->fPt != nextTAt->fPt) {
    532                         testTAt->span()->unaligned();
    533                         nextTAt->span()->unaligned();
    534                     }
    535                     wt.segment()->debugValidate();
    536                     wn.segment()->debugValidate();
    537                 }
    538                 if (!ts.isCoincident(pt)) {
    539                     continue;
    540                 }
    541                 if (coinIndex < 0) {
    542                     coinPtT[0] = testTAt;
    543                     coinPtT[1] = nextTAt;
    544                     coinIndex = pt;
    545                     continue;
    546                 }
    547                 if (coinPtT[0]->span() == testTAt->span()) {
    548                     coinIndex = -1;
    549                     continue;
    550                 }
    551                 if (coinPtT[1]->span() == nextTAt->span()) {
    552                     coinIndex = -1;  // coincidence span collapsed
    553                     continue;
    554                 }
    555                 if (swap) {
    556                     using std::swap;
    557                     swap(coinPtT[0], coinPtT[1]);
    558                     swap(testTAt, nextTAt);
    559                 }
    560                 SkASSERT(coincidence->globalState()->debugSkipAssert()
    561                         || coinPtT[0]->span()->t() < testTAt->span()->t());
    562                 if (coinPtT[0]->span()->deleted()) {
    563                     coinIndex = -1;
    564                     continue;
    565                 }
    566                 if (testTAt->span()->deleted()) {
    567                     coinIndex = -1;
    568                     continue;
    569                 }
    570                 coincidence->add(coinPtT[0], testTAt, coinPtT[1], nextTAt);
    571                 wt.segment()->debugValidate();
    572                 wn.segment()->debugValidate();
    573                 coinIndex = -1;
    574             }
    575             SkOPOBJASSERT(coincidence, coinIndex < 0);  // expect coincidence to be paired
    576         } while (wn.advance());
    577     } while (wt.advance());
    578     return true;
    579 }
    580