OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "SkOpSegment.h" | 7 #include "SkOpSegment.h" |
| 8 #include "SkTArray.h" |
8 #include "Test.h" | 9 #include "Test.h" |
9 | 10 |
10 static const SkPoint cubics[][4] = { | 11 static const SkPoint cubics[][4] = { |
11 /* 0 */ {{0, 1}, {2, 6}, {4, 2}, {5, 3}}, | 12 /* 0 */ {{0, 1}, {2, 6}, {4, 2}, {5, 3}}, |
12 /* 1 */ {{10, 234}, {10, 229.581726f}, {13.5817204f, 226}, {18, 226}}, | 13 /* 1 */ {{10, 234}, {10, 229.581726f}, {13.5817204f, 226}, {18, 226}}, |
13 /* 2 */ {{132, 11419}, {130.89543151855469f, 11419}, {130, 11418.1044921875f}
, {130, 11417}}, | 14 /* 2 */ {{132, 11419}, {130.89543151855469f, 11419}, {130, 11418.1044921875f}
, {130, 11417}}, |
14 /* 3 */ {{130.04275512695312f, 11417.4130859375f}, {130.23307800292969f, 1141
8.3193359375f}, | 15 /* 3 */ {{130.04275512695312f, 11417.4130859375f}, {130.23307800292969f, 1141
8.3193359375f}, |
15 {131.03709411621094f, 11419}, {132, 11419}}, | 16 {131.03709411621094f, 11419}, {132, 11419}}, |
16 /* 4 */ {{0,1}, {0,5}, {4,1}, {6,4}}, | 17 /* 4 */ {{0,1}, {0,5}, {4,1}, {6,4}}, |
17 /* 5 */ {{1,5}, {4,6}, {1,0}, {4,0}}, | 18 /* 5 */ {{1,5}, {4,6}, {1,0}, {4,0}}, |
18 /* 6 */ {{0,1}, {0,4}, {5,1}, {6,4}}, | 19 /* 6 */ {{0,1}, {0,4}, {5,1}, {6,4}}, |
19 /* 7 */ {{0,1}, {1,2}, {1,0}, {6,1}}, | 20 /* 7 */ {{0,1}, {1,2}, {1,0}, {6,1}}, |
20 /* 8 */ {{0,3}, {0,1}, {2,0}, {1,0}}, | 21 /* 8 */ {{0,3}, {0,1}, {2,0}, {1,0}}, |
21 /* 9 */ {{189,7}, {189,5.3431458473205566f}, {190.3431396484375f,4}, {192,4}}
, | 22 /* 9 */ {{189,7}, {189,5.3431458473205566f}, {190.3431396484375f,4}, {192,4}}
, |
22 /* 10 */ {{0,1}, {1,3}, {1,0}, {6,4}}, | 23 /* 10 */ {{0,1}, {1,3}, {1,0}, {6,4}}, |
23 /* 11 */ {{0,1}, {2,3}, {2,1}, {4,3}}, | 24 /* 11 */ {{0,1}, {2,3}, {2,1}, {4,3}}, |
24 /* 12 */ {{1,2}, {3,4}, {1,0}, {3,2}}, | 25 /* 12 */ {{1,2}, {3,4}, {1,0}, {3,2}}, |
| 26 /* 13 */ {{0,1}, {4,6}, {4,3}, {5,4}}, |
| 27 /* 14 */ {{806,11419}, {806.962890625,11419}, {807.76690673828125,11418.319335
9375}, {807.957275390625,11417.4130859375}}, |
| 28 /* 15 */ {{808,11417}, {808,11418.1044921875}, {807.10455322265625,11419}, {80
6,11419}}, |
| 29 /* 16 */ {{132,11419}, {130.89543151855469,11419}, {130,11418.1044921875}, {13
0,11417}}, |
| 30 /* 17 */ {{130.04275512695312,11417.4130859375}, {130.23312377929687,11418.319
3359375}, {131.03707885742187,11419}, {132,11419}}, |
25 }; | 31 }; |
26 | 32 |
27 static const SkPoint quads[][3] = { | 33 static const SkPoint quads[][3] = { |
28 /* 0 */ {{12.3423996f, 228.342407f}, {10, 230.686295f}, {10, 234}}, | 34 /* 0 */ {{12.3423996f, 228.342407f}, {10, 230.686295f}, {10, 234}}, |
29 /* 1 */ {{304.24319458007812f,591.75677490234375f}, {306,593.51470947265625f}
, {306,596}}, | 35 /* 1 */ {{304.24319458007812f,591.75677490234375f}, {306,593.51470947265625f}
, {306,596}}, |
| 36 /* 2 */ {{0,0}, {3,1}, {0,3}}, |
| 37 /* 3 */ {{0,1}, {3,1}, {0,2}}, |
30 }; | 38 }; |
31 | 39 |
32 static const SkPoint lines[][2] = { | 40 static const SkPoint lines[][2] = { |
33 /* 0 */ {{6, 2}, {2, 4}}, | 41 /* 0 */ {{6, 2}, {2, 4}}, |
34 /* 1 */ {{306,617}, {306,590}}, | 42 /* 1 */ {{306,617}, {306,590}}, |
35 /* 2 */ {{306,596}, {306,617}}, | 43 /* 2 */ {{306,596}, {306,617}}, |
36 /* 3 */ {{6,4}, {0,1}}, | 44 /* 3 */ {{6,4}, {0,1}}, |
37 /* 4 */ {{6,1}, {0,1}}, | 45 /* 4 */ {{6,1}, {0,1}}, |
38 /* 5 */ {{1,0}, {0,3}}, | 46 /* 5 */ {{1,0}, {0,3}}, |
39 /* 6 */ {{246,4}, {189,4}}, | 47 /* 6 */ {{246,4}, {189,4}}, |
40 /* 7 */ {{192,4}, {243,4}}, | 48 /* 7 */ {{192,4}, {243,4}}, |
41 /* 8 */ {{4,3}, {0,1}}, | 49 /* 8 */ {{4,3}, {0,1}}, |
42 /* 9 */ {{3,2}, {1,2}}, | 50 /* 9 */ {{3,2}, {1,2}}, |
| 51 /* 10 */ {{6,4}, {3,4}}, |
43 }; | 52 }; |
44 | 53 |
45 struct SortSet { | 54 struct SortSet { |
46 const SkPoint* ptData; | 55 const SkPoint* ptData; |
47 int ptCount; | 56 int ptCount; |
48 double tStart; | 57 double tStart; |
49 double tEnd; | 58 double tEnd; |
| 59 SkPoint endPt; |
50 }; | 60 }; |
51 | 61 |
52 static const SortSet set1[] = { | 62 static const SortSet set1[] = { |
53 {cubics[0], 4, 0.66666987081928919, 0.875}, | 63 {cubics[0], 4, 0.66666987081928919, 0.875, {0, 0}}, |
54 {lines[0], 2, 0.574070336, 0.388888889}, | 64 {lines[0], 2, 0.574070336, 0.388888889, {0, 0}}, |
55 {cubics[0], 4, 0.66666987081928919, 0.4050371120499307 }, | 65 {cubics[0], 4, 0.66666987081928919, 0.4050371120499307, {0, 0}}, |
56 {lines[0], 2, 0.574070336, 0.9140625}, | 66 {lines[0], 2, 0.574070336, 0.9140625, {0, 0}}, |
| 67 }; |
| 68 |
| 69 static const SortSet set1a[] = { |
| 70 {cubics[0], 4, 0.666666667, 0.405037112, {4.58007812f,2.83203125f}}, |
| 71 {lines[0], 2, 0.574074074, 0.9140625, {4.44444466f,2.77777767f}}, |
57 }; | 72 }; |
58 | 73 |
59 static const SortSet set2[] = { | 74 static const SortSet set2[] = { |
60 {cubics[0], 4, 0.666666667, 0.875}, | 75 {cubics[0], 4, 0.666666667, 0.875, {0, 0}}, |
61 {lines[0], 2, 0.574074074, 0.388888889}, | 76 {lines[0], 2, 0.574074074, 0.388888889, {0, 0}}, |
62 {cubics[0], 4, 0.666666667, 0.405037112}, | 77 {cubics[0], 4, 0.666666667, 0.405037112, {0, 0}}, |
63 {lines[0], 2, 0.574074074, 0.9140625}, | 78 {lines[0], 2, 0.574074074, 0.9140625, {0, 0}}, |
64 }; | 79 }; |
65 | 80 |
66 static const SortSet set3[] = { | 81 static const SortSet set3[] = { |
67 {cubics[1], 4, 0, 1}, | 82 {cubics[1], 4, 0, 1, {0, 0}}, |
68 {quads[0], 3, 1, 0}, | 83 {quads[0], 3, 1, 0, {0, 0}}, |
69 }; | 84 }; |
70 | 85 |
71 static const SortSet set4[] = { | 86 static const SortSet set4[] = { |
72 {cubics[2], 4, 0.812114222, 1}, | 87 {cubics[2], 4, 0.812114222, 1, {0, 0}}, |
73 {cubics[3], 4, 0.0684734759, 0}, | 88 {cubics[3], 4, 0.0684734759, 0, {0, 0}}, |
74 }; | 89 }; |
75 | 90 |
76 static const SortSet set5[] = { | 91 static const SortSet set5[] = { |
77 {lines[1], 2, 0.777777778, 1}, | 92 {lines[1], 2, 0.777777778, 1, {0, 0}}, |
78 {quads[1], 3, 1, 4.34137342e-06}, | 93 {quads[1], 3, 1, 4.34137342e-06, {0, 0}}, |
79 {lines[2], 2, 0, 1}, | 94 {lines[2], 2, 0, 1, {0, 0}}, |
| 95 }; |
| 96 |
| 97 static const SortSet set5a[] = { |
| 98 {lines[1], 2, 0.777777778, 1, {306,590}}, |
| 99 {quads[1], 3, 1, 4.34137342e-06, {304.243195f,591.756775f}}, |
| 100 {lines[2], 2, 0, 1, {306,617}}, |
80 }; | 101 }; |
81 | 102 |
82 static const SortSet set6[] = { | 103 static const SortSet set6[] = { |
83 {lines[3], 2, 0.407407407, 0.554627832}, | 104 {lines[3], 2, 0.407407407, 0.554627832, {0, 0}}, |
84 {cubics[4], 4, 0.666666667, 0.548022446}, | 105 {cubics[4], 4, 0.666666667, 0.548022446, {0, 0}}, |
85 {lines[3], 2, 0.407407407, 0}, | 106 {lines[3], 2, 0.407407407, 0, {0, 0}}, |
86 {cubics[4], 4, 0.666666667, 1}, | 107 {cubics[4], 4, 0.666666667, 1, {0, 0}}, |
| 108 }; |
| 109 |
| 110 static const SortSet set6a[] = { |
| 111 {lines[3], 2, 0.407407407, 0.554627832, {2.6722331f,2.33611655f}}, |
| 112 {cubics[4], 4, 0.666666667, 0.548022446, {2.61642241f,2.83718514f}}, |
| 113 {lines[3], 2, 0.407407407, 0, {6,4}}, |
| 114 {cubics[4], 4, 0.666666667, 1, {6,4}}, |
87 }; | 115 }; |
88 | 116 |
89 static const SortSet set7[] = { | 117 static const SortSet set7[] = { |
90 {cubics[5], 4, 0.545233342, 0.545454545}, | 118 {cubics[5], 4, 0.545233342, 0.545454545, {0, 0}}, |
91 {cubics[6], 4, 0.484938134, 0.484805744}, | 119 {cubics[6], 4, 0.484938134, 0.484805744, {0, 0}}, |
92 {cubics[5], 4, 0.545233342, 0}, | 120 {cubics[5], 4, 0.545233342, 0, {0, 0}}, |
93 {cubics[6], 4, 0.484938134, 0.545454545}, | 121 {cubics[6], 4, 0.484938134, 0.545454545, {0, 0}}, |
94 }; | 122 }; |
95 | 123 |
96 static const SortSet set8[] = { | 124 static const SortSet set8[] = { |
97 {cubics[7], 4, 0.5, 0.522986744 }, | 125 {cubics[7], 4, 0.5, 0.522986744, {0, 0}}, |
98 {lines[4], 2, 0.75, 1}, | 126 {lines[4], 2, 0.75, 1, {0, 0}}, |
99 {cubics[7], 4, 0.5, 0}, | 127 {cubics[7], 4, 0.5, 0, {0, 0}}, |
100 {lines[4], 2, 0.75, 0.737654321}, | 128 {lines[4], 2, 0.75, 0.737654321, {0, 0}}, |
| 129 }; |
| 130 |
| 131 static const SortSet set8a[] = { |
| 132 {cubics[7], 4, 0.5, 0.522986744, {1.60668361f,0.965592742f}}, |
| 133 {lines[4], 2, 0.75, 1, {0,1}}, |
| 134 {cubics[7], 4, 0.5, 0, {0,1}}, |
| 135 {lines[4], 2, 0.75, 0.737654321, {1.57407403f,1}}, |
101 }; | 136 }; |
102 | 137 |
103 static const SortSet set9[] = { | 138 static const SortSet set9[] = { |
104 {cubics[8], 4, 0.4, 1}, | 139 {cubics[8], 4, 0.4, 1, {0, 0}}, |
105 {lines[5], 2, 0.36, 0}, | 140 {lines[5], 2, 0.36, 0, {0, 0}}, |
106 {cubics[8], 4, 0.4, 0.394675838}, | 141 {cubics[8], 4, 0.4, 0.394675838, {0, 0}}, |
107 {lines[5], 2, 0.36, 0.363999782}, | 142 {lines[5], 2, 0.36, 0.363999782, {0, 0}}, |
108 }; | 143 }; |
109 | 144 |
110 static const SortSet set10[] = { | 145 static const SortSet set10[] = { |
111 {lines[6], 2, 0.947368421, 1}, | 146 {lines[6], 2, 0.947368421, 1, {0, 0}}, |
112 {cubics[9], 4, 1, 0.500000357}, | 147 {cubics[9], 4, 1, 0.500000357, {0, 0}}, |
113 {lines[7], 2, 0, 1}, | 148 {lines[7], 2, 0, 1, {0, 0}}, |
114 }; | 149 }; |
115 | 150 |
116 static const SortSet set11[] = { | 151 static const SortSet set11[] = { |
117 {lines[3], 2, 0.75, 1}, | 152 {lines[3], 2, 0.75, 1, {0, 0}}, |
118 {cubics[10], 4, 0.5, 0.228744269}, | 153 {cubics[10], 4, 0.5, 0.228744269, {0, 0}}, |
119 {lines[3], 2, 0.75, 0.627112191}, | 154 {lines[3], 2, 0.75, 0.627112191, {0, 0}}, |
120 {cubics[10], 4, 0.5, 0.6339746}, | 155 {cubics[10], 4, 0.5, 0.6339746, {0, 0}}, |
121 }; | 156 }; |
122 | 157 |
123 static const SortSet set12[] = { | 158 static const SortSet set12[] = { |
124 {cubics[12], 4, 0.5, 1}, | 159 {cubics[12], 4, 0.5, 1, {0, 0}}, |
125 {lines[8], 2, 0.5, 1}, | 160 {lines[8], 2, 0.5, 1, {0, 0}}, |
126 {cubics[11], 4, 0.5, 0}, | 161 {cubics[11], 4, 0.5, 0, {0, 0}}, |
127 {lines[9], 2, 0.5, 1}, | 162 {lines[9], 2, 0.5, 1, {0, 0}}, |
128 {cubics[12], 4, 0.5, 0}, | 163 {cubics[12], 4, 0.5, 0, {0, 0}}, |
129 {lines[8], 2, 0.5, 0}, | 164 {lines[8], 2, 0.5, 0, {0, 0}}, |
130 {cubics[11], 4, 0.5, 1}, | 165 {cubics[11], 4, 0.5, 1, {0, 0}}, |
131 {lines[9], 2, 0.5, 0}, | 166 {lines[9], 2, 0.5, 0, {0, 0}}, |
| 167 }; |
| 168 |
| 169 static const SortSet set13[] = { |
| 170 {cubics[13], 4, 0.5, 0.400631046, {0, 0}}, |
| 171 {lines[10], 2, 0.791666667, 0.928, {0, 0}}, |
| 172 {lines[10], 2, 0.791666667, 0.333333333, {0, 0}}, |
| 173 {cubics[13], 4, 0.5, 0.866666667, {0, 0}}, |
| 174 }; |
| 175 |
| 176 static const SortSet set14[] = { |
| 177 {quads[2], 3, 0.5, 0.310102051, {0, 0}}, |
| 178 {quads[3], 3, 0.5, 0.2, {0, 0}}, |
| 179 {quads[3], 3, 0.5, 0.770156212, {0, 0}}, |
| 180 {quads[2], 3, 0.5, 0.7, {0, 0}}, |
| 181 }; |
| 182 |
| 183 static const SortSet set15[] = { |
| 184 {cubics[14], 4, 0.93081374, 1, {0, 0}}, |
| 185 {cubics[15], 4, 0.188518131, 0, {0, 0}}, |
| 186 {cubics[14], 4, 0.93081374, 0, {0, 0}}, |
| 187 }; |
| 188 |
| 189 static const SortSet set16[] = { |
| 190 {cubics[17], 4, 0.0682619216, 0, {130.042755f,11417.4131f}}, |
| 191 {cubics[16], 4, 0.812302088, 1, {130,11417}}, |
| 192 {cubics[17], 4, 0.0682619216, 1, {132,11419}}, |
132 }; | 193 }; |
133 | 194 |
134 struct SortSetTests { | 195 struct SortSetTests { |
| 196 const char* name; |
135 const SortSet* set; | 197 const SortSet* set; |
136 size_t count; | 198 size_t count; |
137 }; | 199 SkPoint startPt; |
| 200 }; |
| 201 |
| 202 #define TEST_ENTRY(name) #name, name, SK_ARRAY_COUNT(name) |
138 | 203 |
139 static const SortSetTests tests[] = { | 204 static const SortSetTests tests[] = { |
140 { set12, SK_ARRAY_COUNT(set12) }, | 205 { TEST_ENTRY(set16), {130.090179f,11417.5957f} }, |
141 { set11, SK_ARRAY_COUNT(set11) }, | 206 // { TEST_ENTRY(set15), {0, 0}}, |
142 { set10, SK_ARRAY_COUNT(set10) }, | 207 { TEST_ENTRY(set14), {0, 0}}, |
143 { set9, SK_ARRAY_COUNT(set9) }, | 208 { TEST_ENTRY(set13), {0, 0}}, |
144 { set8, SK_ARRAY_COUNT(set8) }, | 209 { TEST_ENTRY(set12), {0, 0}}, |
145 { set7, SK_ARRAY_COUNT(set7) }, | 210 { TEST_ENTRY(set11), {0, 0}}, |
146 { set6, SK_ARRAY_COUNT(set6) }, | 211 { TEST_ENTRY(set10), {0, 0}}, |
147 { set2, SK_ARRAY_COUNT(set2) }, | 212 { TEST_ENTRY(set9), {0, 0}}, |
148 { set5, SK_ARRAY_COUNT(set5) }, | 213 { TEST_ENTRY(set6a), {3.55555558f,2.77777767f} }, |
149 { set4, SK_ARRAY_COUNT(set4) }, | 214 { TEST_ENTRY(set8a), {1.5f,1} }, |
150 { set3, SK_ARRAY_COUNT(set3) }, | 215 { TEST_ENTRY(set8), {0, 0}}, |
151 { set1, SK_ARRAY_COUNT(set1) }, | 216 { TEST_ENTRY(set7), {0, 0}}, |
152 }; | 217 { TEST_ENTRY(set6a), {3.55555558f,2.77777767f} }, |
153 | 218 { TEST_ENTRY(set6), {0, 0}}, |
154 static void setup(const SortSet* set, const size_t idx, SkPoint const ** data, | 219 { TEST_ENTRY(set5a), {306,596} }, |
155 SkOpSegment* seg, int* ts) { | 220 { TEST_ENTRY(set5), {0, 0}}, |
| 221 // { TEST_ENTRY(set4), {0, 0}}, |
| 222 { TEST_ENTRY(set3), {0, 0}}, |
| 223 { TEST_ENTRY(set2), {0, 0}}, |
| 224 // { TEST_ENTRY(set1a), {3.70370364f,3.14814806f} }, |
| 225 { TEST_ENTRY(set1), {0, 0}}, |
| 226 }; |
| 227 |
| 228 #undef TEST_ENTRY |
| 229 |
| 230 static void setup(const SortSet* set, const size_t idx, |
| 231 SkOpSegment* seg, int* ts, const SkPoint& startPt) { |
156 SkPoint start, end; | 232 SkPoint start, end; |
157 *data = set[idx].ptData; | 233 const SkPoint* data = set[idx].ptData; |
| 234 bool useIntersectPt = startPt.fX != 0 || startPt.fY != 0; |
| 235 if (useIntersectPt) { |
| 236 start = startPt; |
| 237 end = set[idx].endPt; |
| 238 } |
158 switch(set[idx].ptCount) { | 239 switch(set[idx].ptCount) { |
159 case 2: { | 240 case 2: { |
160 seg->addLine(*data, false, false); | 241 seg->addLine(data, false, false); |
161 SkDLine dLine; | 242 SkDLine dLine; |
162 dLine.set(set[idx].ptData); | 243 dLine.set(set[idx].ptData); |
| 244 if (useIntersectPt) { |
| 245 break; |
| 246 } |
163 start = dLine.xyAtT(set[idx].tStart).asSkPoint(); | 247 start = dLine.xyAtT(set[idx].tStart).asSkPoint(); |
164 end = dLine.xyAtT(set[idx].tEnd).asSkPoint(); | 248 end = dLine.xyAtT(set[idx].tEnd).asSkPoint(); |
165 } break; | 249 } break; |
166 case 3: { | 250 case 3: { |
167 seg->addQuad(*data, false, false); | 251 seg->addQuad(data, false, false); |
168 SkDQuad dQuad; | 252 SkDQuad dQuad; |
169 dQuad.set(set[idx].ptData); | 253 dQuad.set(set[idx].ptData); |
| 254 if (useIntersectPt) { |
| 255 break; |
| 256 } |
170 start = dQuad.xyAtT(set[idx].tStart).asSkPoint(); | 257 start = dQuad.xyAtT(set[idx].tStart).asSkPoint(); |
171 end = dQuad.xyAtT(set[idx].tEnd).asSkPoint(); | 258 end = dQuad.xyAtT(set[idx].tEnd).asSkPoint(); |
172 } break; | 259 } break; |
173 case 4: { | 260 case 4: { |
174 seg->addCubic(*data, false, false); | 261 seg->addCubic(data, false, false); |
175 SkDCubic dCubic; | 262 SkDCubic dCubic; |
176 dCubic.set(set[idx].ptData); | 263 dCubic.set(set[idx].ptData); |
| 264 if (useIntersectPt) { |
| 265 break; |
| 266 } |
177 start = dCubic.xyAtT(set[idx].tStart).asSkPoint(); | 267 start = dCubic.xyAtT(set[idx].tStart).asSkPoint(); |
178 end = dCubic.xyAtT(set[idx].tEnd).asSkPoint(); | 268 end = dCubic.xyAtT(set[idx].tEnd).asSkPoint(); |
179 } break; | 269 } break; |
180 } | 270 } |
181 double tStart = set[idx].tStart; | 271 double tStart = set[idx].tStart; |
182 double tEnd = set[idx].tEnd; | 272 double tEnd = set[idx].tEnd; |
183 seg->addT(NULL, start, tStart); | 273 seg->addT(NULL, start, tStart); |
184 seg->addT(NULL, end, tEnd); | 274 seg->addT(NULL, end, tEnd); |
185 double tLeft = tStart < tEnd ? 0 : 1; | 275 if (tStart != 0 && tEnd != 0) { |
186 if (tStart != tLeft && tEnd != tLeft) { | 276 seg->addT(NULL, set[idx].ptData[0], 0); |
187 seg->addT(NULL, set[idx].ptData[0], tLeft); | |
188 } | 277 } |
189 double tRight = tStart < tEnd ? 1 : 0; | 278 if (tStart != 1 && tEnd != 1) { |
190 if (tStart != tRight && tEnd != tRight) { | 279 seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1); |
191 seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], tRight); | |
192 } | 280 } |
193 int tIndex = 0; | 281 int tIndex = 0; |
194 do { | 282 do { |
195 if (seg->t(tIndex) == set[idx].tStart) { | 283 if (seg->t(tIndex) == set[idx].tStart) { |
196 ts[0] = tIndex; | 284 ts[0] = tIndex; |
197 } | 285 } |
198 if (seg->t(tIndex) == set[idx].tEnd) { | 286 if (seg->t(tIndex) == set[idx].tEnd) { |
199 ts[1] = tIndex; | 287 ts[1] = tIndex; |
200 } | 288 } |
201 if (seg->t(tIndex) >= 1) { | 289 if (seg->t(tIndex) >= 1) { |
202 break; | 290 break; |
203 } | 291 } |
204 } while (++tIndex); | 292 } while (++tIndex); |
205 } | 293 } |
206 | 294 |
207 static void PathOpsAngleTest(skiatest::Reporter* reporter) { | 295 static void PathOpsAngleTest(skiatest::Reporter* reporter) { |
208 for (size_t index = 0; index < SK_ARRAY_COUNT(tests); ++index) { | 296 for (size_t index = 0; index < SK_ARRAY_COUNT(tests); ++index) { |
209 const SortSetTests& test = tests[index]; | 297 const SortSetTests& test = tests[index]; |
210 for (size_t idxL = 0; idxL < test.count - 1; ++idxL) { | 298 SkTDArray<SkOpAngle> angles; |
211 SkOpSegment lesser, greater; | 299 bool unsortable = false; |
212 int lesserTs[2], greaterTs[2]; | 300 bool unorderable = false; |
213 const SkPoint* lesserData, * greaterData; | 301 SkTArray<SkOpSegment> segs; |
| 302 for (size_t idx = 0; idx < test.count; ++idx) { |
| 303 int ts[2]; |
214 const SortSet* set = test.set; | 304 const SortSet* set = test.set; |
215 setup(set, idxL, &lesserData, &lesser, lesserTs); | 305 SkOpSegment& seg = segs.push_back(); |
216 size_t idxG = idxL + 1; | 306 setup(set, idx, &seg, ts, test.startPt); |
217 setup(set, idxG, &greaterData, &greater, greaterTs); | 307 SkOpAngle* angle = angles.append(); |
218 SkOpAngle first, second; | 308 angle->set(&seg, ts[0], ts[1]); |
219 first.set(lesserData, SkPathOpsPointsToVerb(set[idxL].ptCount - 1),
&lesser, | 309 #if DEBUG_ANGLE |
220 lesserTs[0], lesserTs[1], lesser.spans()); | 310 angle->setID(idx); |
221 second.set(greaterData, SkPathOpsPointsToVerb(set[idxG].ptCount - 1)
, &greater, | 311 #endif |
222 greaterTs[0], greaterTs[1], greater.spans()); | 312 if (angle->unsortable()) { |
223 bool compare = first < second; | 313 #if DEBUG_ANGLE |
224 if (!compare) { | 314 SkDebugf("%s test[%s]: angle[%d] unsortable\n", __FUNCTION__, t
est.name, idx); |
225 SkDebugf("%s test[%d]: lesser[%d] > greater[%d]\n", __FUNCTION_
_, | 315 #endif |
226 index, idxL, idxG); | 316 unsortable = true; |
227 compare = first < second; | |
228 } | 317 } |
229 REPORTER_ASSERT(reporter, compare); | 318 if (angle->unorderable()) { |
| 319 #if DEBUG_ANGLE |
| 320 SkDebugf("%s test[%s]: angle[%d] unorderable\n", __FUNCTION__,
test.name, idx); |
| 321 #endif |
| 322 unorderable = true; |
| 323 } |
230 reporter->bumpTestCount(); | 324 reporter->bumpTestCount(); |
231 } | 325 } |
| 326 if (unsortable || unorderable) { |
| 327 continue; |
| 328 } |
| 329 #if DEBUG_ANGLE |
| 330 SkDebugf("%s test[%s]\n", __FUNCTION__, test.name); |
| 331 #endif |
| 332 for (size_t idxL = 0; idxL < test.count; ++idxL) { |
| 333 const SkOpAngle& first = angles[idxL]; |
| 334 for (size_t idxG = 0; idxG < test.count; ++idxG) { |
| 335 if (idxL == idxG) { |
| 336 continue; |
| 337 } |
| 338 const SkOpAngle& second = angles[idxG]; |
| 339 bool compare = first < second; |
| 340 if (idxL < idxG) { |
| 341 if (!compare) { |
| 342 SkDebugf("%s test[%s]: first[%d] > second[%d]\n", __FUN
CTION__, |
| 343 test.name, idxL, idxG); |
| 344 compare = first < second; |
| 345 } |
| 346 REPORTER_ASSERT(reporter, compare); |
| 347 } else { |
| 348 SkASSERT(idxL > idxG); |
| 349 if (compare) { |
| 350 SkDebugf("%s test[%s]: first[%d] < second[%d]\n", __FUN
CTION__, |
| 351 test.name, idxL, idxG); |
| 352 compare = first < second; |
| 353 } |
| 354 REPORTER_ASSERT(reporter, !compare); |
| 355 } |
| 356 compare = second < first; |
| 357 if (idxL < idxG) { |
| 358 if (compare) { |
| 359 SkDebugf("%s test[%s]: second[%d] < first[%d]\n", __FUN
CTION__, |
| 360 test.name, idxL, idxG); |
| 361 compare = second < first; |
| 362 } |
| 363 REPORTER_ASSERT(reporter, !compare); |
| 364 } else { |
| 365 SkASSERT(idxL > idxG); |
| 366 if (!compare) { |
| 367 SkDebugf("%s test[%s]: second[%d] > first[%d]\n", __FUN
CTION__, |
| 368 test.name, idxL, idxG); |
| 369 compare = second < first; |
| 370 } |
| 371 REPORTER_ASSERT(reporter, compare); |
| 372 } |
| 373 } |
| 374 } |
| 375 reporter->bumpTestCount(); |
232 } | 376 } |
233 } | 377 } |
234 | 378 |
| 379 #if 0 |
| 380 static int find_slop(double x, double y, double rx, double ry) { |
| 381 int slopBits = 0; |
| 382 bool less1, less2; |
| 383 double absX = fabs(x); |
| 384 double absY = fabs(y); |
| 385 double length = absX < absY ? absX / 2 + absY : absX + absY / 2; |
| 386 int exponent; |
| 387 (void) frexp(length, &exponent); |
| 388 double epsilon = ldexp(FLT_EPSILON, exponent); |
| 389 do { |
| 390 // get the length as the larger plus half the smaller (both same signs) |
| 391 // find the ulps of the length |
| 392 // compute the offsets from there |
| 393 double xSlop = epsilon * slopBits; |
| 394 double ySlop = x * y < 0 ? -xSlop : xSlop; // OPTIMIZATION: use copysign
/ _copysign ? |
| 395 double x1 = x - xSlop; |
| 396 double y1 = y + ySlop; |
| 397 double x_ry1 = x1 * ry; |
| 398 double rx_y1 = rx * y1; |
| 399 less1 = x_ry1 < rx_y1; |
| 400 double x2 = x + xSlop; |
| 401 double y2 = y - ySlop; |
| 402 double x_ry2 = x2 * ry; |
| 403 double rx_y2 = rx * y2; |
| 404 less2 = x_ry2 < rx_y2; |
| 405 } while (less1 == less2 && ++slopBits); |
| 406 return slopBits; |
| 407 } |
| 408 |
| 409 // from http://stackoverflow.com/questions/1427422/cheap-algorithm-to-find-measu
re-of-angle-between-vectors |
| 410 static double diamond_angle(double y, double x) |
| 411 { |
| 412 if (y >= 0) |
| 413 return (x >= 0 ? y/(x+y) : 1-x/(-x+y)); |
| 414 else |
| 415 return (x < 0 ? 2-y/(-x-y) : 3+x/(x-y)); |
| 416 } |
| 417 |
| 418 static const double slopTests[][4] = { |
| 419 // x y rx ry |
| 420 {-0.058554756452593892, -0.18804585843827226, -0.018568569646021160, -0.0596
15294434479438}, |
| 421 {-0.0013717412948608398, 0.0041152238845825195, -0.00045837944195925573, 0.0
013753175735478074}, |
| 422 {-2.1033774145221198, -1.4046019261273715e-008, -0.70062688352066704, -1.270
6324683777995e-008}, |
| 423 }; |
| 424 |
| 425 static void PathOpsAngleFindSlop(skiatest::Reporter* reporter) { |
| 426 for (size_t index = 0; index < SK_ARRAY_COUNT(slopTests); ++index) { |
| 427 const double* slopTest = slopTests[index]; |
| 428 double x = slopTest[0]; |
| 429 double y = slopTest[1]; |
| 430 double rx = slopTest[2]; |
| 431 double ry = slopTest[3]; |
| 432 SkDebugf("%s xy %d=%d\n", __FUNCTION__, (int) index, find_slop(x, y, rx
, ry)); |
| 433 SkDebugf("%s rxy %d=%d\n", __FUNCTION__, (int) index, find_slop(rx, ry,
x, y)); |
| 434 double angle = diamond_angle(y, x); |
| 435 double rAngle = diamond_angle(ry, rx); |
| 436 double diff = fabs(angle - rAngle); |
| 437 SkDebugf("%s diamond xy=%1.9g rxy=%1.9g diff=%1.9g factor=%d\n", __FUNCT
ION__, |
| 438 angle, rAngle, diff, (int) (diff / FLT_EPSILON)); |
| 439 |
| 440 } |
| 441 } |
| 442 #endif |
| 443 |
235 #include "TestClassDef.h" | 444 #include "TestClassDef.h" |
236 DEFINE_TESTCLASS_SHORT(PathOpsAngleTest) | 445 DEFINE_TESTCLASS_SHORT(PathOpsAngleTest) |
| 446 |
| 447 // DEFINE_TESTCLASS_SHORT(PathOpsAngleFindSlop) |
OLD | NEW |