blob: 70e790134b54fd34d69f8b7fc34d1db1f3e9d61e [file] [log] [blame]
caryclark@google.com235f56a2012-09-14 14:19:30 +00001/*
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 */
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +00007
caryclark@google.com235f56a2012-09-14 14:19:30 +00008#include "DataTypes.h"
9#include "Intersections.h"
10
caryclark@google.com73ca6242013-01-17 21:02:47 +000011void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
caryclark@google.comaa358312013-01-29 20:28:49 +000012 SkASSERT((fCoincidentUsed & 1) != 1);
caryclark@google.com73ca6242013-01-17 21:02:47 +000013 for (int index = 0; index < fCoincidentUsed; index += 2) {
14 double cs1 = fCoincidentT[fSwap][index];
15 double ce1 = fCoincidentT[fSwap][index + 1];
16 bool s1in = approximately_between(cs1, s1, ce1);
17 bool e1in = approximately_between(cs1, e1, ce1);
18 double cs2 = fCoincidentT[fSwap ^ 1][index];
19 double ce2 = fCoincidentT[fSwap ^ 1][index + 1];
20 bool s2in = approximately_between(cs2, s2, ce2);
21 bool e2in = approximately_between(cs2, e2, ce2);
22 if ((s1in | e1in) & (s2in | e2in)) {
caryclark@google.comaa358312013-01-29 20:28:49 +000023 double lesser1 = SkTMin(cs1, ce1);
caryclark@google.com73ca6242013-01-17 21:02:47 +000024 index += cs1 > ce1;
caryclark@google.combeda3892013-02-07 13:13:41 +000025 if (s1 < lesser1) {
26 fCoincidentT[fSwap][index] = s1;
27 } else if (e1 < lesser1) {
28 fCoincidentT[fSwap][index] = e1;
caryclark@google.com73ca6242013-01-17 21:02:47 +000029 }
30 index ^= 1;
31 double greater1 = fCoincidentT[fSwap][index];
caryclark@google.combeda3892013-02-07 13:13:41 +000032 if (s1 > greater1) {
33 fCoincidentT[fSwap][index] = s1;
34 } else if (e1 > greater1) {
35 fCoincidentT[fSwap][index] = e1;
caryclark@google.com73ca6242013-01-17 21:02:47 +000036 }
37 index &= ~1;
caryclark@google.comaa358312013-01-29 20:28:49 +000038 double lesser2 = SkTMin(cs2, ce2);
caryclark@google.com73ca6242013-01-17 21:02:47 +000039 index += cs2 > ce2;
caryclark@google.combeda3892013-02-07 13:13:41 +000040 if (s2 < lesser2) {
41 fCoincidentT[fSwap ^ 1][index] = s2;
42 } else if (e2 < lesser2) {
43 fCoincidentT[fSwap ^ 1][index] = e2;
caryclark@google.com73ca6242013-01-17 21:02:47 +000044 }
45 index ^= 1;
46 double greater2 = fCoincidentT[fSwap ^ 1][index];
caryclark@google.combeda3892013-02-07 13:13:41 +000047 if (s2 > greater2) {
48 fCoincidentT[fSwap ^ 1][index] = s2;
49 } else if (e2 > greater2) {
50 fCoincidentT[fSwap ^ 1][index] = e2;
caryclark@google.com73ca6242013-01-17 21:02:47 +000051 }
52 return;
53 }
54 }
caryclark@google.comaa358312013-01-29 20:28:49 +000055 SkASSERT(fCoincidentUsed < 9);
caryclark@google.com73ca6242013-01-17 21:02:47 +000056 fCoincidentT[fSwap][fCoincidentUsed] = s1;
57 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2;
58 ++fCoincidentUsed;
59 fCoincidentT[fSwap][fCoincidentUsed] = e1;
60 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = e2;
61 ++fCoincidentUsed;
caryclark@google.combeda3892013-02-07 13:13:41 +000062 // FIXME: assert that no entries in normal range lie between s and e
63 remove(s1, e1);
64 remove(s2, e2);
caryclark@google.com73ca6242013-01-17 21:02:47 +000065}
66
caryclark@google.com235f56a2012-09-14 14:19:30 +000067void Intersections::cleanUp() {
caryclark@google.comaa358312013-01-29 20:28:49 +000068 SkASSERT(fCoincidentUsed);
69 SkASSERT(fUsed);
caryclark@google.com235f56a2012-09-14 14:19:30 +000070 // find any entries in fT that could be part of the coincident range
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +000071
caryclark@google.com235f56a2012-09-14 14:19:30 +000072}
caryclark@google.com73ca6242013-01-17 21:02:47 +000073
caryclark@google.com05c4bad2013-01-19 13:22:39 +000074// FIXME: this doesn't respect swap, but add coincident does -- seems inconsistent
caryclark@google.com73ca6242013-01-17 21:02:47 +000075void Intersections::insert(double one, double two) {
caryclark@google.comaa358312013-01-29 20:28:49 +000076 SkASSERT(fUsed <= 1 || fT[0][0] < fT[0][1]);
caryclark@google.com73ca6242013-01-17 21:02:47 +000077 int index;
caryclark@google.combeda3892013-02-07 13:13:41 +000078 for (index = 0; index < fCoincidentUsed; ++index ) {
79 if (approximately_equal(fCoincidentT[0][index], one)
80 && approximately_equal(fCoincidentT[1][index], two)) {
81 return;
82 }
83 }
caryclark@google.com73ca6242013-01-17 21:02:47 +000084 for (index = 0; index < fUsed; ++index) {
85 if (approximately_equal(fT[0][index], one)
86 && approximately_equal(fT[1][index], two)) {
87 return;
88 }
89 if (fT[0][index] > one) {
90 break;
91 }
92 }
caryclark@google.comaa358312013-01-29 20:28:49 +000093 SkASSERT(fUsed < 9);
caryclark@google.com73ca6242013-01-17 21:02:47 +000094 int remaining = fUsed - index;
95 if (remaining > 0) {
96 memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
97 memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
98 }
99 fT[0][index] = one;
100 fT[1][index] = two;
101 ++fUsed;
102}
103
104// FIXME: all callers should be moved to regular insert. Failures are likely
105// if two separate callers differ on whether ts are equal or not
106void Intersections::insertOne(double t, int side) {
107 int used = side ? fUsed2 : fUsed;
caryclark@google.comaa358312013-01-29 20:28:49 +0000108 SkASSERT(used <= 1 || fT[side][0] < fT[side][1]);
caryclark@google.com73ca6242013-01-17 21:02:47 +0000109 int index;
110 for (index = 0; index < used; ++index) {
111 if (approximately_equal(fT[side][index], t)) {
112 return;
113 }
114 if (fT[side][index] > t) {
115 break;
116 }
117 }
caryclark@google.comaa358312013-01-29 20:28:49 +0000118 SkASSERT(used < 9);
caryclark@google.com73ca6242013-01-17 21:02:47 +0000119 int remaining = used - index;
120 if (remaining > 0) {
121 memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining);
122 }
123 fT[side][index] = t;
124 side ? ++fUsed2 : ++fUsed;
125}
caryclark@google.combeda3892013-02-07 13:13:41 +0000126
127void Intersections::remove(double one, double two) {
128 int index;
129 for (index = 0; index < fUsed; ++index) {
130 if (approximately_equal(fT[0][index], one)
131 && approximately_equal(fT[1][index], two)) {
132 goto foundIt;
133 }
134 if (fT[0][index] > one) {
135 return;
136 }
137 }
138 return;
139foundIt:
140 SkASSERT(fUsed > 0);
141 int remaining = fUsed - index;
142 if (remaining > 0) {
143 memmove(&fT[0][index], &fT[0][index - 1], sizeof(fT[0][0]) * remaining);
144 memmove(&fT[1][index], &fT[1][index - 1], sizeof(fT[1][0]) * remaining);
145 }
146 --fUsed;
147}