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