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