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::closestTo(double rangeStart, double rangeEnd, const SkDPoint& testPt, 11 double* closestDist) const { 12 int closest = -1; 13 *closestDist = SK_ScalarMax; 14 for (int index = 0; index < fUsed; ++index) { 15 if (!between(rangeStart, fT[0][index], rangeEnd)) { 16 continue; 17 } 18 const SkDPoint& iPt = fPt[index]; 19 double dist = testPt.distanceSquared(iPt); 20 if (*closestDist > dist) { 21 *closestDist = dist; 22 closest = index; 23 } 24 } 25 return closest; 26 } 27 28 void SkIntersections::flip() { 29 for (int index = 0; index < fUsed; ++index) { 30 fT[1][index] = 1 - fT[1][index]; 31 } 32 } 33 34 int SkIntersections::insert(double one, double two, const SkDPoint& pt) { 35 if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) { 36 // For now, don't allow a mix of coincident and non-coincident intersections 37 return -1; 38 } 39 SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]); 40 int index; 41 for (index = 0; index < fUsed; ++index) { 42 double oldOne = fT[0][index]; 43 double oldTwo = fT[1][index]; 44 if (one == oldOne && two == oldTwo) { 45 return -1; 46 } 47 if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) { 48 if ((!precisely_zero(one) || precisely_zero(oldOne)) 49 && (!precisely_equal(one, 1) || precisely_equal(oldOne, 1)) 50 && (!precisely_zero(two) || precisely_zero(oldTwo)) 51 && (!precisely_equal(two, 1) || precisely_equal(oldTwo, 1))) { 52 return -1; 53 } 54 SkASSERT(one >= 0 && one <= 1); 55 SkASSERT(two >= 0 && two <= 1); 56 // remove this and reinsert below in case replacing would make list unsorted 57 int remaining = fUsed - index - 1; 58 memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining); 59 memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining); 60 memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining); 61 int clearMask = ~((1 << index) - 1); 62 fIsCoincident[0] -= (fIsCoincident[0] >> 1) & clearMask; 63 fIsCoincident[1] -= (fIsCoincident[1] >> 1) & clearMask; 64 --fUsed; 65 break; 66 } 67 #if ONE_OFF_DEBUG 68 if (pt.roughlyEqual(fPt[index])) { 69 SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one); 70 } 71 #endif 72 } 73 for (index = 0; index < fUsed; ++index) { 74 if (fT[0][index] > one) { 75 break; 76 } 77 } 78 if (fUsed >= fMax) { 79 SkOPASSERT(0); // FIXME : this error, if it is to be handled at runtime in release, must 80 // be propagated all the way back down to the caller, and return failure. 81 fUsed = 0; 82 return 0; 83 } 84 int remaining = fUsed - index; 85 if (remaining > 0) { 86 memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining); 87 memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining); 88 memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining); 89 int clearMask = ~((1 << index) - 1); 90 fIsCoincident[0] += fIsCoincident[0] & clearMask; 91 fIsCoincident[1] += fIsCoincident[1] & clearMask; 92 } 93 fPt[index] = pt; 94 if (one < 0 || one > 1) { 95 return -1; 96 } 97 if (two < 0 || two > 1) { 98 return -1; 99 } 100 fT[0][index] = one; 101 fT[1][index] = two; 102 ++fUsed; 103 SkASSERT(fUsed <= SK_ARRAY_COUNT(fPt)); 104 return index; 105 } 106 107 void SkIntersections::insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2) { 108 SkASSERT(one == 0 || one == 1); 109 SkASSERT(two == 0 || two == 1); 110 SkASSERT(pt1 != pt2); 111 fNearlySame[one ? 1 : 0] = true; 112 (void) insert(one, two, pt1); 113 fPt2[one ? 1 : 0] = pt2; 114 } 115 116 int SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt) { 117 int index = insertSwap(one, two, pt); 118 if (index >= 0) { 119 setCoincident(index); 120 } 121 return index; 122 } 123 124 void SkIntersections::setCoincident(int index) { 125 SkASSERT(index >= 0); 126 int bit = 1 << index; 127 fIsCoincident[0] |= bit; 128 fIsCoincident[1] |= bit; 129 } 130 131 void SkIntersections::merge(const SkIntersections& a, int aIndex, const SkIntersections& b, 132 int bIndex) { 133 this->reset(); 134 fT[0][0] = a.fT[0][aIndex]; 135 fT[1][0] = b.fT[0][bIndex]; 136 fPt[0] = a.fPt[aIndex]; 137 fPt2[0] = b.fPt[bIndex]; 138 fUsed = 1; 139 } 140 141 int SkIntersections::mostOutside(double rangeStart, double rangeEnd, const SkDPoint& origin) const { 142 int result = -1; 143 for (int index = 0; index < fUsed; ++index) { 144 if (!between(rangeStart, fT[0][index], rangeEnd)) { 145 continue; 146 } 147 if (result < 0) { 148 result = index; 149 continue; 150 } 151 SkDVector best = fPt[result] - origin; 152 SkDVector test = fPt[index] - origin; 153 if (test.crossCheck(best) < 0) { 154 result = index; 155 } 156 } 157 return result; 158 } 159 160 void SkIntersections::removeOne(int index) { 161 int remaining = --fUsed - index; 162 if (remaining <= 0) { 163 return; 164 } 165 memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining); 166 memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining); 167 memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining); 168 // SkASSERT(fIsCoincident[0] == 0); 169 int coBit = fIsCoincident[0] & (1 << index); 170 fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit; 171 SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index)))); 172 fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit; 173 } 174