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 
      8 #include "SkIntersections.h"
      9 
     10 int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar, SkScalar, SkScalar, bool) = {
     11     NULL,
     12     &SkIntersections::verticalLine,
     13     &SkIntersections::verticalQuad,
     14     &SkIntersections::verticalCubic
     15 };
     16 
     17 int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine&) = {
     18     NULL,
     19     NULL,
     20     &SkIntersections::quadRay,
     21     &SkIntersections::cubicRay
     22 };
     23 
     24 int SkIntersections::coincidentUsed() const {
     25     if (!fIsCoincident[0]) {
     26         SkASSERT(!fIsCoincident[1]);
     27         return 0;
     28     }
     29     int count = 0;
     30     SkDEBUGCODE(int count2 = 0;)
     31     for (int index = 0; index < fUsed; ++index) {
     32         if (fIsCoincident[0] & (1 << index)) {
     33             ++count;
     34         }
     35 #ifdef SK_DEBUG
     36         if (fIsCoincident[1] & (1 << index)) {
     37             ++count2;
     38         }
     39 #endif
     40     }
     41     SkASSERT(count == count2);
     42     return count;
     43 }
     44 
     45 int SkIntersections::cubicRay(const SkPoint pts[4], const SkDLine& line) {
     46     SkDCubic cubic;
     47     cubic.set(pts);
     48     return intersectRay(cubic, line);
     49 }
     50 
     51 void SkIntersections::flip() {
     52     for (int index = 0; index < fUsed; ++index) {
     53         fT[1][index] = 1 - fT[1][index];
     54     }
     55 }
     56 
     57 int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
     58     if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) {
     59         // For now, don't allow a mix of coincident and non-coincident intersections
     60         return -1;
     61     }
     62     SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]);
     63     int index;
     64     for (index = 0; index < fUsed; ++index) {
     65         double oldOne = fT[0][index];
     66         double oldTwo = fT[1][index];
     67         if (one == oldOne && two == oldTwo) {
     68             return -1;
     69         }
     70         if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) {
     71             if ((precisely_zero(one) && !precisely_zero(oldOne))
     72                     || (precisely_equal(one, 1) && !precisely_equal(oldOne, 1))
     73                     || (precisely_zero(two) && !precisely_zero(oldTwo))
     74                     || (precisely_equal(two, 1) && !precisely_equal(oldTwo, 1))) {
     75                 fT[0][index] = one;
     76                 fT[1][index] = two;
     77                 fPt[index] = pt;
     78             }
     79             return -1;
     80         }
     81     #if ONE_OFF_DEBUG
     82         if (pt.roughlyEqual(fPt[index])) {
     83             SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
     84         }
     85     #endif
     86         if (fT[0][index] > one) {
     87             break;
     88         }
     89     }
     90     SkASSERT(fUsed < 9);
     91     int remaining = fUsed - index;
     92     if (remaining > 0) {
     93         memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
     94         memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
     95         memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
     96         fIsCoincident[0] += fIsCoincident[0] & ~((1 << index) - 1);
     97         fIsCoincident[1] += fIsCoincident[1] & ~((1 << index) - 1);
     98     }
     99     fPt[index] = pt;
    100     fT[0][index] = one;
    101     fT[1][index] = two;
    102     ++fUsed;
    103     return index;
    104 }
    105 
    106 void SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt) {
    107     int index = insertSwap(one, two, pt);
    108     int bit = 1 << index;
    109     fIsCoincident[0] |= bit;
    110     fIsCoincident[1] |= bit;
    111 }
    112 
    113 void SkIntersections::offset(int base, double start, double end) {
    114     for (int index = base; index < fUsed; ++index) {
    115         double val = fT[fSwap][index];
    116         val *= end - start;
    117         val += start;
    118         fT[fSwap][index] = val;
    119     }
    120 }
    121 
    122 int SkIntersections::quadRay(const SkPoint pts[3], const SkDLine& line) {
    123     SkDQuad quad;
    124     quad.set(pts);
    125     return intersectRay(quad, line);
    126 }
    127 
    128 void SkIntersections::quickRemoveOne(int index, int replace) {
    129     if (index < replace) {
    130         fT[0][index] = fT[0][replace];
    131     }
    132 }
    133 
    134 #if 0
    135 void SkIntersections::remove(double one, double two, const SkDPoint& startPt,
    136         const SkDPoint& endPt) {
    137     for (int index = fUsed - 1; index >= 0; --index) {
    138         if (!(fIsCoincident[0] & (1 << index)) && (between(one, fT[fSwap][index], two)
    139                 || startPt.approximatelyEqual(fPt[index])
    140                 || endPt.approximatelyEqual(fPt[index]))) {
    141             SkASSERT(fUsed > 0);
    142             removeOne(index);
    143         }
    144     }
    145 }
    146 #endif
    147 
    148 void SkIntersections::removeOne(int index) {
    149     int remaining = --fUsed - index;
    150     if (remaining <= 0) {
    151         return;
    152     }
    153     memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
    154     memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
    155     memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
    156     SkASSERT(fIsCoincident[0] == 0);
    157     int coBit = fIsCoincident[0] & (1 << index);
    158     fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit;
    159     SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index))));
    160     fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit;
    161 }
    162 
    163 void SkIntersections::swapPts() {
    164     int index;
    165     for (index = 0; index < fUsed; ++index) {
    166         SkTSwap(fT[0][index], fT[1][index]);
    167     }
    168 }
    169 
    170 int SkIntersections::verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom,
    171         SkScalar x, bool flipped) {
    172     SkDLine line;
    173     line.set(a);
    174     return vertical(line, top, bottom, x, flipped);
    175 }
    176 
    177 int SkIntersections::verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom,
    178         SkScalar x, bool flipped) {
    179     SkDQuad quad;
    180     quad.set(a);
    181     return vertical(quad, top, bottom, x, flipped);
    182 }
    183 
    184 int SkIntersections::verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom,
    185         SkScalar x, bool flipped) {
    186     SkDCubic cubic;
    187     cubic.set(a);
    188     return vertical(cubic, top, bottom, x, flipped);
    189 }
    190