OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkEdgeBuilder.h" | 7 #include "SkEdgeBuilder.h" |
8 #include "SkPath.h" | 8 #include "SkPath.h" |
9 #include "SkEdge.h" | 9 #include "SkEdge.h" |
10 #include "SkAnalyticEdge.h" | |
11 #include "SkEdgeClipper.h" | 10 #include "SkEdgeClipper.h" |
12 #include "SkLineClipper.h" | 11 #include "SkLineClipper.h" |
13 #include "SkGeometry.h" | 12 #include "SkGeometry.h" |
14 | 13 |
15 template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) { | 14 template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) { |
16 return static_cast<T*>(alloc.allocThrow(sizeof(T))); | 15 return static_cast<T*>(alloc.allocThrow(sizeof(T))); |
17 } | 16 } |
18 | 17 |
19 /////////////////////////////////////////////////////////////////////////////// | 18 /////////////////////////////////////////////////////////////////////////////// |
20 | 19 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 return kPartial_Combine; | 55 return kPartial_Combine; |
57 } | 56 } |
58 last->fLastY = last->fFirstY - 1; | 57 last->fLastY = last->fFirstY - 1; |
59 last->fFirstY = edge->fFirstY; | 58 last->fFirstY = edge->fFirstY; |
60 last->fWinding = edge->fWinding; | 59 last->fWinding = edge->fWinding; |
61 return kPartial_Combine; | 60 return kPartial_Combine; |
62 } | 61 } |
63 return kNo_Combine; | 62 return kNo_Combine; |
64 } | 63 } |
65 | 64 |
66 SkEdgeBuilder::Combine SkEdgeBuilder::CombineVertical( | 65 static bool vertical_line(const SkEdge* edge) { |
67 const SkAnalyticEdge* edge, SkAnalyticEdge* last) { | |
68 SkASSERT(fAnalyticAA); | |
69 if (last->fCurveCount || last->fDX || edge->fX != last->fX) { | |
70 return kNo_Combine; | |
71 } | |
72 if (edge->fWinding == last->fWinding) { | |
73 if (edge->fLowerY == last->fUpperY) { | |
74 last->fUpperY = edge->fUpperY; | |
75 last->fY = last->fUpperY; | |
76 return kPartial_Combine; | |
77 } | |
78 if (edge->fUpperY == last->fLowerY) { | |
79 last->fLowerY = edge->fLowerY; | |
80 return kPartial_Combine; | |
81 } | |
82 return kNo_Combine; | |
83 } | |
84 if (edge->fUpperY == last->fUpperY) { | |
85 if (edge->fLowerY == last->fLowerY) { | |
86 return kTotal_Combine; | |
87 } | |
88 if (edge->fLowerY < last->fLowerY) { | |
89 last->fUpperY = edge->fLowerY; | |
90 last->fY = last->fUpperY; | |
91 return kPartial_Combine; | |
92 } | |
93 last->fUpperY = last->fLowerY; | |
94 last->fY = last->fUpperY; | |
95 last->fLowerY = edge->fLowerY; | |
96 last->fWinding = edge->fWinding; | |
97 return kPartial_Combine; | |
98 } | |
99 if (edge->fLowerY == last->fLowerY) { | |
100 if (edge->fUpperY > last->fUpperY) { | |
101 last->fLowerY = edge->fUpperY; | |
102 return kPartial_Combine; | |
103 } | |
104 last->fLowerY = last->fUpperY; | |
105 last->fUpperY = edge->fUpperY; | |
106 last->fY = last->fUpperY; | |
107 last->fWinding = edge->fWinding; | |
108 return kPartial_Combine; | |
109 } | |
110 return kNo_Combine; | |
111 } | |
112 | |
113 bool SkEdgeBuilder::vertical_line(const SkEdge* edge) { | |
114 return !edge->fDX && !edge->fCurveCount; | |
115 } | |
116 | |
117 bool SkEdgeBuilder::vertical_line(const SkAnalyticEdge* edge) { | |
118 SkASSERT(fAnalyticAA); | |
119 return !edge->fDX && !edge->fCurveCount; | 66 return !edge->fDX && !edge->fCurveCount; |
120 } | 67 } |
121 | 68 |
122 void SkEdgeBuilder::addLine(const SkPoint pts[]) { | 69 void SkEdgeBuilder::addLine(const SkPoint pts[]) { |
123 if (fAnalyticAA) { | 70 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); |
124 SkAnalyticEdge* edge = typedAllocThrow<SkAnalyticEdge>(fAlloc); | 71 if (edge->setLine(pts[0], pts[1], fShiftUp)) { |
125 if (edge->setLine(pts[0], pts[1])) { | 72 if (vertical_line(edge) && fList.count()) { |
126 if (vertical_line(edge) && fList.count()) { | 73 Combine combine = CombineVertical(edge, *(fList.end() - 1)); |
127 Combine combine = CombineVertical(edge, (SkAnalyticEdge*)*(fList
.end() - 1)); | 74 if (kNo_Combine != combine) { |
128 if (kNo_Combine != combine) { | 75 if (kTotal_Combine == combine) { |
129 if (kTotal_Combine == combine) { | 76 fList.pop(); |
130 fList.pop(); | |
131 } | |
132 goto unallocate_analytic_edge; | |
133 } | 77 } |
| 78 goto unallocate_edge; |
134 } | 79 } |
135 fList.push(edge); | |
136 } else { | |
137 unallocate_analytic_edge: | |
138 ; | |
139 // TODO: unallocate edge from storage... | |
140 } | 80 } |
| 81 fList.push(edge); |
141 } else { | 82 } else { |
142 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); | |
143 if (edge->setLine(pts[0], pts[1], fShiftUp)) { | |
144 if (vertical_line(edge) && fList.count()) { | |
145 Combine combine = CombineVertical(edge, (SkEdge*)*(fList.end() -
1)); | |
146 if (kNo_Combine != combine) { | |
147 if (kTotal_Combine == combine) { | |
148 fList.pop(); | |
149 } | |
150 goto unallocate_edge; | |
151 } | |
152 } | |
153 fList.push(edge); | |
154 } else { | |
155 unallocate_edge: | 83 unallocate_edge: |
156 ; | 84 ; |
157 // TODO: unallocate edge from storage... | 85 // TODO: unallocate edge from storage... |
158 } | |
159 } | 86 } |
160 } | 87 } |
161 | 88 |
162 void SkEdgeBuilder::addQuad(const SkPoint pts[]) { | 89 void SkEdgeBuilder::addQuad(const SkPoint pts[]) { |
163 if (fAnalyticAA) { | 90 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); |
164 SkAnalyticQuadraticEdge* edge = typedAllocThrow<SkAnalyticQuadraticEdge>
(fAlloc); | 91 if (edge->setQuadratic(pts, fShiftUp)) { |
165 if (edge->setQuadratic(pts)) { | 92 fList.push(edge); |
166 fList.push(edge); | |
167 } else { | |
168 // TODO: unallocate edge from storage... | |
169 } | |
170 } else { | 93 } else { |
171 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); | 94 // TODO: unallocate edge from storage... |
172 if (edge->setQuadratic(pts, fShiftUp)) { | |
173 fList.push(edge); | |
174 } else { | |
175 // TODO: unallocate edge from storage... | |
176 } | |
177 } | 95 } |
178 } | 96 } |
179 | 97 |
180 void SkEdgeBuilder::addCubic(const SkPoint pts[]) { | 98 void SkEdgeBuilder::addCubic(const SkPoint pts[]) { |
181 if (fAnalyticAA) { | 99 SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); |
182 SkAnalyticCubicEdge* edge = typedAllocThrow<SkAnalyticCubicEdge>(fAlloc)
; | 100 if (edge->setCubic(pts, fShiftUp)) { |
183 if (edge->setCubic(pts)) { | 101 fList.push(edge); |
184 fList.push(edge); | |
185 } else { | |
186 // TODO: unallocate edge from storage... | |
187 } | |
188 } else { | 102 } else { |
189 SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc); | 103 // TODO: unallocate edge from storage... |
190 if (edge->setCubic(pts, fShiftUp)) { | |
191 fList.push(edge); | |
192 } else { | |
193 // TODO: unallocate edge from storage... | |
194 } | |
195 } | 104 } |
196 } | 105 } |
197 | 106 |
198 void SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) { | 107 void SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) { |
199 SkPoint pts[4]; | 108 SkPoint pts[4]; |
200 SkPath::Verb verb; | 109 SkPath::Verb verb; |
201 | 110 |
202 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) { | 111 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) { |
203 switch (verb) { | 112 switch (verb) { |
204 case SkPath::kLine_Verb: | 113 case SkPath::kLine_Verb: |
(...skipping 14 matching lines...) Expand all Loading... |
219 /////////////////////////////////////////////////////////////////////////////// | 128 /////////////////////////////////////////////////////////////////////////////// |
220 | 129 |
221 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { | 130 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { |
222 dst->set(SkIntToScalar(src.fLeft >> shift), | 131 dst->set(SkIntToScalar(src.fLeft >> shift), |
223 SkIntToScalar(src.fTop >> shift), | 132 SkIntToScalar(src.fTop >> shift), |
224 SkIntToScalar(src.fRight >> shift), | 133 SkIntToScalar(src.fRight >> shift), |
225 SkIntToScalar(src.fBottom >> shift)); | 134 SkIntToScalar(src.fBottom >> shift)); |
226 } | 135 } |
227 | 136 |
228 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge**
edgePtr) { | 137 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge**
edgePtr) { |
229 return !vertical_line(edge) || edgePtr <= (SkEdge**)fEdgeList ? kNo_Combine
: | 138 return !vertical_line(edge) || edgePtr <= fEdgeList ? kNo_Combine : |
230 CombineVertical(edge, edgePtr[-1]); | 139 CombineVertical(edge, edgePtr[-1]); |
231 } | 140 } |
232 | 141 |
233 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkAnalyticEdge* edge, | |
234 SkAnalyticEdge** edgePtr) { | |
235 SkASSERT(fAnalyticAA); | |
236 return !vertical_line(edge) || edgePtr <= (SkAnalyticEdge**)fEdgeList ? kNo_
Combine : | |
237 CombineVertical(edge, edgePtr[-1]); | |
238 } | |
239 | |
240 int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
Up, | 142 int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
Up, |
241 bool canCullToTheRight) { | 143 bool canCullToTheRight) { |
242 SkPath::Iter iter(path, true); | 144 SkPath::Iter iter(path, true); |
243 SkPoint pts[4]; | 145 SkPoint pts[4]; |
244 SkPath::Verb verb; | 146 SkPath::Verb verb; |
245 | 147 |
246 int maxEdgeCount = path.countPoints(); | 148 int maxEdgeCount = path.countPoints(); |
247 if (iclip) { | 149 if (iclip) { |
248 // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since | 150 // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since |
249 // we turn portions that are clipped out on the left/right into vertical | 151 // we turn portions that are clipped out on the left/right into vertical |
250 // segments. | 152 // segments. |
251 maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments; | 153 maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments; |
252 } | 154 } |
253 size_t edgeSize = fAnalyticAA ? sizeof(SkAnalyticEdge) : sizeof(SkEdge); | 155 size_t maxEdgeSize = maxEdgeCount * sizeof(SkEdge); |
254 size_t maxEdgeSize = maxEdgeCount * edgeSize; | 156 size_t maxEdgePtrSize = maxEdgeCount * sizeof(SkEdge*); |
255 size_t maxEdgePtrSize = maxEdgeCount * sizeof(char*); | |
256 | 157 |
257 // lets store the edges and their pointers in the same block | 158 // lets store the edges and their pointers in the same block |
258 char* storage = (char*)fAlloc.allocThrow(maxEdgeSize + maxEdgePtrSize); | 159 char* storage = (char*)fAlloc.allocThrow(maxEdgeSize + maxEdgePtrSize); |
259 char* edge = (char*)storage; | 160 SkEdge* edge = reinterpret_cast<SkEdge*>(storage); |
260 char** edgePtr = (char**)(storage + maxEdgeSize); | 161 SkEdge** edgePtr = reinterpret_cast<SkEdge**>(storage + maxEdgeSize); |
261 // Record the beginning of our pointers, so we can return them to the caller | 162 // Record the beginning of our pointers, so we can return them to the caller |
262 fEdgeList = (void**)edgePtr; | 163 fEdgeList = edgePtr; |
263 | 164 |
264 if (iclip) { | 165 if (iclip) { |
265 SkRect clip; | 166 SkRect clip; |
266 setShiftedClip(&clip, *iclip, shiftUp); | 167 setShiftedClip(&clip, *iclip, shiftUp); |
267 | 168 |
268 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { | 169 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { |
269 switch (verb) { | 170 switch (verb) { |
270 case SkPath::kMove_Verb: | 171 case SkPath::kMove_Verb: |
271 case SkPath::kClose_Verb: | 172 case SkPath::kClose_Verb: |
272 // we ignore these, and just get the whole segment from | 173 // we ignore these, and just get the whole segment from |
273 // the corresponding line/quad/cubic verbs | 174 // the corresponding line/quad/cubic verbs |
274 break; | 175 break; |
275 case SkPath::kLine_Verb: { | 176 case SkPath::kLine_Verb: { |
276 SkPoint lines[SkLineClipper::kMaxPoints]; | 177 SkPoint lines[SkLineClipper::kMaxPoints]; |
277 int lineCount = SkLineClipper::ClipLine(pts, clip, lines, ca
nCullToTheRight); | 178 int lineCount = SkLineClipper::ClipLine(pts, clip, lines, ca
nCullToTheRight); |
278 SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments
); | 179 SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments
); |
279 for (int i = 0; i < lineCount; i++) { | 180 for (int i = 0; i < lineCount; i++) { |
280 bool setLineResult = fAnalyticAA ? | 181 if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { |
281 ((SkAnalyticEdge*)edge)->setLine(lines[i], lines
[i + 1]) : | 182 Combine combine = checkVertical(edge, edgePtr); |
282 ((SkEdge*)edge)->setLine(lines[i], lines[i + 1],
shiftUp); | |
283 if (setLineResult) { | |
284 Combine combine = fAnalyticAA ? | |
285 checkVertical((SkAnalyticEdge*)edge, (SkAnal
yticEdge**)edgePtr) : | |
286 checkVertical((SkEdge*)edge, (SkEdge**)edgeP
tr); | |
287 if (kNo_Combine == combine) { | 183 if (kNo_Combine == combine) { |
288 *edgePtr++ = edge; | 184 *edgePtr++ = edge++; |
289 edge += edgeSize; | |
290 } else if (kTotal_Combine == combine) { | 185 } else if (kTotal_Combine == combine) { |
291 --edgePtr; | 186 --edgePtr; |
292 } | 187 } |
293 } | 188 } |
294 } | 189 } |
295 break; | 190 break; |
296 } | 191 } |
297 default: | 192 default: |
298 SkDEBUGFAIL("unexpected verb"); | 193 SkDEBUGFAIL("unexpected verb"); |
299 break; | 194 break; |
300 } | 195 } |
301 } | 196 } |
302 } else { | 197 } else { |
303 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { | 198 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { |
304 switch (verb) { | 199 switch (verb) { |
305 case SkPath::kMove_Verb: | 200 case SkPath::kMove_Verb: |
306 case SkPath::kClose_Verb: | 201 case SkPath::kClose_Verb: |
307 // we ignore these, and just get the whole segment from | 202 // we ignore these, and just get the whole segment from |
308 // the corresponding line/quad/cubic verbs | 203 // the corresponding line/quad/cubic verbs |
309 break; | 204 break; |
310 case SkPath::kLine_Verb: { | 205 case SkPath::kLine_Verb: |
311 bool setLineResult = fAnalyticAA ? | 206 if (edge->setLine(pts[0], pts[1], shiftUp)) { |
312 ((SkAnalyticEdge*)edge)->setLine(pts[0], pts[1]) : | 207 Combine combine = checkVertical(edge, edgePtr); |
313 ((SkEdge*)edge)->setLine(pts[0], pts[1], shiftUp); | |
314 if (setLineResult) { | |
315 Combine combine = fAnalyticAA ? | |
316 checkVertical((SkAnalyticEdge*)edge, (SkAnalytic
Edge**)edgePtr) : | |
317 checkVertical((SkEdge*)edge, (SkEdge**)edgePtr); | |
318 if (kNo_Combine == combine) { | 208 if (kNo_Combine == combine) { |
319 *edgePtr++ = edge; | 209 *edgePtr++ = edge++; |
320 edge += edgeSize; | |
321 } else if (kTotal_Combine == combine) { | 210 } else if (kTotal_Combine == combine) { |
322 --edgePtr; | 211 --edgePtr; |
323 } | 212 } |
324 } | 213 } |
325 break; | 214 break; |
326 } | |
327 default: | 215 default: |
328 SkDEBUGFAIL("unexpected verb"); | 216 SkDEBUGFAIL("unexpected verb"); |
329 break; | 217 break; |
330 } | 218 } |
331 } | 219 } |
332 } | 220 } |
333 SkASSERT((char*)edge <= (char*)fEdgeList); | 221 SkASSERT((char*)edge <= (char*)fEdgeList); |
334 SkASSERT(edgePtr - (char**)fEdgeList <= maxEdgeCount); | 222 SkASSERT(edgePtr - fEdgeList <= maxEdgeCount); |
335 return SkToInt(edgePtr - (char**)fEdgeList); | 223 return SkToInt(edgePtr - fEdgeList); |
336 } | 224 } |
337 | 225 |
338 static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) { | 226 static void handle_quad(SkEdgeBuilder* builder, const SkPoint pts[3]) { |
339 SkPoint monoX[5]; | 227 SkPoint monoX[5]; |
340 int n = SkChopQuadAtYExtrema(pts, monoX); | 228 int n = SkChopQuadAtYExtrema(pts, monoX); |
341 for (int i = 0; i <= n; i++) { | 229 for (int i = 0; i <= n; i++) { |
342 builder->addQuad(&monoX[i * 2]); | 230 builder->addQuad(&monoX[i * 2]); |
343 } | 231 } |
344 } | 232 } |
345 | 233 |
346 int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp, | 234 int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip, int shiftUp, |
347 bool canCullToTheRight, bool analyticAA) { | 235 bool canCullToTheRight) { |
348 fAlloc.reset(); | 236 fAlloc.reset(); |
349 fList.reset(); | 237 fList.reset(); |
350 fShiftUp = shiftUp; | 238 fShiftUp = shiftUp; |
351 fAnalyticAA = analyticAA; | |
352 | 239 |
353 if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { | 240 if (SkPath::kLine_SegmentMask == path.getSegmentMasks()) { |
354 return this->buildPoly(path, iclip, shiftUp, canCullToTheRight); | 241 return this->buildPoly(path, iclip, shiftUp, canCullToTheRight); |
355 } | 242 } |
356 | 243 |
357 SkAutoConicToQuads quadder; | 244 SkAutoConicToQuads quadder; |
358 const SkScalar conicTol = SK_Scalar1 / 4; | 245 const SkScalar conicTol = SK_Scalar1 / 4; |
359 | 246 |
360 SkPath::Iter iter(path, true); | 247 SkPath::Iter iter(path, true); |
361 SkPoint pts[4]; | 248 SkPoint pts[4]; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 } | 326 } |
440 default: | 327 default: |
441 SkDEBUGFAIL("unexpected verb"); | 328 SkDEBUGFAIL("unexpected verb"); |
442 break; | 329 break; |
443 } | 330 } |
444 } | 331 } |
445 } | 332 } |
446 fEdgeList = fList.begin(); | 333 fEdgeList = fList.begin(); |
447 return fList.count(); | 334 return fList.count(); |
448 } | 335 } |
OLD | NEW |