OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkEdgeBuilder.h" | 8 #include "SkEdgeBuilder.h" |
9 #include "SkPath.h" | 9 #include "SkPath.h" |
10 #include "SkEdge.h" | 10 #include "SkEdge.h" |
11 #include "SkEdgeClipper.h" | 11 #include "SkEdgeClipper.h" |
12 #include "SkLineClipper.h" | 12 #include "SkLineClipper.h" |
13 #include "SkGeometry.h" | 13 #include "SkGeometry.h" |
14 | 14 |
15 template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) { | 15 template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) { |
16 return static_cast<T*>(alloc.allocThrow(sizeof(T))); | 16 return static_cast<T*>(alloc.allocThrow(sizeof(T))); |
17 } | 17 } |
18 | 18 |
19 /////////////////////////////////////////////////////////////////////////////// | 19 /////////////////////////////////////////////////////////////////////////////// |
20 | 20 |
21 SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) { | 21 SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) { |
22 fEdgeList = nullptr; | 22 fEdgeList = nullptr; |
23 } | 23 } |
24 | 24 |
| 25 SkEdgeBuilder::Combine SkEdgeBuilder::CombineVertical(const SkEdge* edge, SkEdge
* last) { |
| 26 if (last->fCurveCount || last->fDX || edge->fX != last->fX) { |
| 27 return kNo_Combine; |
| 28 } |
| 29 if (edge->fWinding == last->fWinding) { |
| 30 if (edge->fLastY + 1 == last->fFirstY) { |
| 31 last->fFirstY = edge->fFirstY; |
| 32 return kPartial_Combine; |
| 33 } |
| 34 if (edge->fFirstY == last->fLastY + 1) { |
| 35 last->fLastY = edge->fLastY; |
| 36 return kPartial_Combine; |
| 37 } |
| 38 return kNo_Combine; |
| 39 } |
| 40 if (edge->fFirstY == last->fFirstY) { |
| 41 if (edge->fLastY == last->fLastY) { |
| 42 return kTotal_Combine; |
| 43 } |
| 44 if (edge->fLastY < last->fLastY) { |
| 45 last->fFirstY = edge->fLastY + 1; |
| 46 return kPartial_Combine; |
| 47 } |
| 48 last->fFirstY = last->fLastY + 1; |
| 49 last->fLastY = edge->fLastY; |
| 50 last->fWinding = edge->fWinding; |
| 51 return kPartial_Combine; |
| 52 } |
| 53 if (edge->fLastY == last->fLastY) { |
| 54 if (edge->fFirstY > last->fFirstY) { |
| 55 last->fLastY = edge->fFirstY - 1; |
| 56 return kPartial_Combine; |
| 57 } |
| 58 last->fLastY = last->fFirstY - 1; |
| 59 last->fFirstY = edge->fFirstY; |
| 60 last->fWinding = edge->fWinding; |
| 61 return kPartial_Combine; |
| 62 } |
| 63 return kNo_Combine; |
| 64 } |
| 65 |
| 66 static bool vertical_line(const SkEdge* edge) { |
| 67 #ifdef SK_SUPPORT_LEGACY_VERTICAL_EDGE // this disables combining vertical over
lapping edges |
| 68 return false; |
| 69 #endif |
| 70 return !edge->fDX && !edge->fCurveCount; |
| 71 } |
| 72 |
25 void SkEdgeBuilder::addLine(const SkPoint pts[]) { | 73 void SkEdgeBuilder::addLine(const SkPoint pts[]) { |
26 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); | 74 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc); |
27 if (edge->setLine(pts[0], pts[1], fShiftUp)) { | 75 if (edge->setLine(pts[0], pts[1], fShiftUp)) { |
| 76 if (vertical_line(edge) && fList.count()) { |
| 77 Combine combine = CombineVertical(edge, *(fList.end() - 1)); |
| 78 if (kNo_Combine != combine) { |
| 79 if (kTotal_Combine == combine) { |
| 80 fList.pop(); |
| 81 } |
| 82 goto unallocate_edge; |
| 83 } |
| 84 } |
28 fList.push(edge); | 85 fList.push(edge); |
29 } else { | 86 } else { |
| 87 unallocate_edge: |
| 88 ; |
30 // TODO: unallocate edge from storage... | 89 // TODO: unallocate edge from storage... |
31 } | 90 } |
32 } | 91 } |
33 | 92 |
34 void SkEdgeBuilder::addQuad(const SkPoint pts[]) { | 93 void SkEdgeBuilder::addQuad(const SkPoint pts[]) { |
35 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); | 94 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc); |
36 if (edge->setQuadratic(pts, fShiftUp)) { | 95 if (edge->setQuadratic(pts, fShiftUp)) { |
37 fList.push(edge); | 96 fList.push(edge); |
38 } else { | 97 } else { |
39 // TODO: unallocate edge from storage... | 98 // TODO: unallocate edge from storage... |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 | 131 |
73 /////////////////////////////////////////////////////////////////////////////// | 132 /////////////////////////////////////////////////////////////////////////////// |
74 | 133 |
75 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { | 134 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) { |
76 dst->set(SkIntToScalar(src.fLeft >> shift), | 135 dst->set(SkIntToScalar(src.fLeft >> shift), |
77 SkIntToScalar(src.fTop >> shift), | 136 SkIntToScalar(src.fTop >> shift), |
78 SkIntToScalar(src.fRight >> shift), | 137 SkIntToScalar(src.fRight >> shift), |
79 SkIntToScalar(src.fBottom >> shift)); | 138 SkIntToScalar(src.fBottom >> shift)); |
80 } | 139 } |
81 | 140 |
| 141 SkEdgeBuilder::Combine SkEdgeBuilder::checkVertical(const SkEdge* edge, SkEdge**
edgePtr) { |
| 142 return !vertical_line(edge) || edgePtr <= fEdgeList ? kNo_Combine : |
| 143 CombineVertical(edge, edgePtr[-1]); |
| 144 } |
| 145 |
82 int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
Up, | 146 int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
Up, |
83 bool canCullToTheRight) { | 147 bool canCullToTheRight) { |
84 SkPath::Iter iter(path, true); | 148 SkPath::Iter iter(path, true); |
85 SkPoint pts[4]; | 149 SkPoint pts[4]; |
86 SkPath::Verb verb; | 150 SkPath::Verb verb; |
87 | 151 |
88 int maxEdgeCount = path.countPoints(); | 152 int maxEdgeCount = path.countPoints(); |
89 if (iclip) { | 153 if (iclip) { |
90 // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since | 154 // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since |
91 // we turn portions that are clipped out on the left/right into vertical | 155 // we turn portions that are clipped out on the left/right into vertical |
(...skipping 20 matching lines...) Expand all Loading... |
112 case SkPath::kClose_Verb: | 176 case SkPath::kClose_Verb: |
113 // we ignore these, and just get the whole segment from | 177 // we ignore these, and just get the whole segment from |
114 // the corresponding line/quad/cubic verbs | 178 // the corresponding line/quad/cubic verbs |
115 break; | 179 break; |
116 case SkPath::kLine_Verb: { | 180 case SkPath::kLine_Verb: { |
117 SkPoint lines[SkLineClipper::kMaxPoints]; | 181 SkPoint lines[SkLineClipper::kMaxPoints]; |
118 int lineCount = SkLineClipper::ClipLine(pts, clip, lines, ca
nCullToTheRight); | 182 int lineCount = SkLineClipper::ClipLine(pts, clip, lines, ca
nCullToTheRight); |
119 SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments
); | 183 SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments
); |
120 for (int i = 0; i < lineCount; i++) { | 184 for (int i = 0; i < lineCount; i++) { |
121 if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { | 185 if (edge->setLine(lines[i], lines[i + 1], shiftUp)) { |
122 *edgePtr++ = edge++; | 186 Combine combine = checkVertical(edge, edgePtr); |
| 187 if (kNo_Combine == combine) { |
| 188 *edgePtr++ = edge++; |
| 189 } else if (kTotal_Combine == combine) { |
| 190 --edgePtr; |
| 191 } |
123 } | 192 } |
124 } | 193 } |
125 break; | 194 break; |
126 } | 195 } |
127 default: | 196 default: |
128 SkDEBUGFAIL("unexpected verb"); | 197 SkDEBUGFAIL("unexpected verb"); |
129 break; | 198 break; |
130 } | 199 } |
131 } | 200 } |
132 } else { | 201 } else { |
133 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { | 202 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { |
134 switch (verb) { | 203 switch (verb) { |
135 case SkPath::kMove_Verb: | 204 case SkPath::kMove_Verb: |
136 case SkPath::kClose_Verb: | 205 case SkPath::kClose_Verb: |
137 // we ignore these, and just get the whole segment from | 206 // we ignore these, and just get the whole segment from |
138 // the corresponding line/quad/cubic verbs | 207 // the corresponding line/quad/cubic verbs |
139 break; | 208 break; |
140 case SkPath::kLine_Verb: | 209 case SkPath::kLine_Verb: |
141 if (edge->setLine(pts[0], pts[1], shiftUp)) { | 210 if (edge->setLine(pts[0], pts[1], shiftUp)) { |
142 *edgePtr++ = edge++; | 211 Combine combine = checkVertical(edge, edgePtr); |
| 212 if (kNo_Combine == combine) { |
| 213 *edgePtr++ = edge++; |
| 214 } else if (kTotal_Combine == combine) { |
| 215 --edgePtr; |
| 216 } |
143 } | 217 } |
144 break; | 218 break; |
145 default: | 219 default: |
146 SkDEBUGFAIL("unexpected verb"); | 220 SkDEBUGFAIL("unexpected verb"); |
147 break; | 221 break; |
148 } | 222 } |
149 } | 223 } |
150 } | 224 } |
151 SkASSERT((char*)edge <= (char*)fEdgeList); | 225 SkASSERT((char*)edge <= (char*)fEdgeList); |
152 SkASSERT(edgePtr - fEdgeList <= maxEdgeCount); | 226 SkASSERT(edgePtr - fEdgeList <= maxEdgeCount); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 } | 330 } |
257 default: | 331 default: |
258 SkDEBUGFAIL("unexpected verb"); | 332 SkDEBUGFAIL("unexpected verb"); |
259 break; | 333 break; |
260 } | 334 } |
261 } | 335 } |
262 } | 336 } |
263 fEdgeList = fList.begin(); | 337 fEdgeList = fList.begin(); |
264 return fList.count(); | 338 return fList.count(); |
265 } | 339 } |
OLD | NEW |