OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 | 7 |
8 #ifndef GrAAConvexTessellator_DEFINED | 8 #ifndef GrAAConvexTessellator_DEFINED |
9 #define GrAAConvexTessellator_DEFINED | 9 #define GrAAConvexTessellator_DEFINED |
10 | 10 |
11 #include "SkColor.h" | 11 #include "SkColor.h" |
12 #include "SkPaint.h" | |
13 #include "SkPoint.h" | 12 #include "SkPoint.h" |
14 #include "SkScalar.h" | 13 #include "SkScalar.h" |
15 #include "SkTDArray.h" | 14 #include "SkTDArray.h" |
16 | 15 |
17 class SkCanvas; | 16 class SkCanvas; |
18 class SkMatrix; | 17 class SkMatrix; |
19 class SkPath; | 18 class SkPath; |
20 | 19 |
21 //#define GR_AA_CONVEX_TESSELLATOR_VIZ 1 | 20 //#define GR_AA_CONVEX_TESSELLATOR_VIZ 1 |
22 | 21 |
23 // device space distance which we inset / outset points in order to create the s
oft antialiased edge | |
24 static const SkScalar kAntialiasingRadius = 0.5f; | |
25 | |
26 class GrAAConvexTessellator; | 22 class GrAAConvexTessellator; |
27 | 23 |
28 // The AAConvexTessellator holds the global pool of points and the triangulation | 24 // The AAConvexTessellator holds the global pool of points and the triangulation |
29 // that connects them. It also drives the tessellation process. | 25 // that connects them. It also drives the tessellation process. |
30 // The outward facing normals of the original polygon are stored (in 'fNorms') t
o service | 26 // The outward facing normals of the original polygon are stored (in 'fNorms') t
o service |
31 // computeDepthFromEdge requests. | 27 // computeDepthFromEdge requests. |
32 class GrAAConvexTessellator { | 28 class GrAAConvexTessellator { |
33 public: | 29 public: |
34 GrAAConvexTessellator(SkScalar strokeWidth = -1.0f, | 30 GrAAConvexTessellator(SkScalar targetDepth = 0.5f) |
35 SkPaint::Join join = SkPaint::Join::kBevel_Join, | |
36 SkScalar miterLimit = 0.0f) | |
37 : fSide(SkPoint::kOn_Side) | 31 : fSide(SkPoint::kOn_Side) |
38 , fStrokeWidth(strokeWidth) | 32 , fTargetDepth(targetDepth) { |
39 , fJoin(join) | |
40 , fMiterLimit(miterLimit) { | |
41 } | 33 } |
42 | 34 |
| 35 void setTargetDepth(SkScalar targetDepth) { fTargetDepth = targetDepth; } |
| 36 SkScalar targetDepth() const { return fTargetDepth; } |
| 37 |
43 SkPoint::Side side() const { return fSide; } | 38 SkPoint::Side side() const { return fSide; } |
44 | 39 |
45 bool tessellate(const SkMatrix& m, const SkPath& path); | 40 bool tessellate(const SkMatrix& m, const SkPath& path); |
46 | 41 |
47 // The next five should only be called after tessellate to extract the resul
t | 42 // The next five should only be called after tessellate to extract the resul
t |
48 int numPts() const { return fPts.count(); } | 43 int numPts() const { return fPts.count(); } |
49 int numIndices() const { return fIndices.count(); } | 44 int numIndices() const { return fIndices.count(); } |
50 | 45 |
51 const SkPoint& lastPoint() const { return fPts.top(); } | 46 const SkPoint& lastPoint() const { return fPts.top(); } |
52 const SkPoint& point(int index) const { return fPts[index]; } | 47 const SkPoint& point(int index) const { return fPts[index]; } |
53 int index(int index) const { return fIndices[index]; } | 48 int index(int index) const { return fIndices[index]; } |
54 SkScalar coverage(int index) const { return fCoverages[index]; } | 49 SkScalar depth(int index) const {return fDepths[index]; } |
55 | 50 |
56 #if GR_AA_CONVEX_TESSELLATOR_VIZ | 51 #if GR_AA_CONVEX_TESSELLATOR_VIZ |
57 void draw(SkCanvas* canvas) const; | 52 void draw(SkCanvas* canvas) const; |
58 #endif | 53 #endif |
59 | 54 |
60 // The tessellator can be reused for multiple paths by rewinding in between | 55 // The tessellator can be reused for multiple paths by rewinding in between |
61 void rewind(); | 56 void rewind(); |
62 | 57 |
63 private: | 58 private: |
64 // CandidateVerts holds the vertices for the next ring while they are | 59 // CandidateVerts holds the vertices for the next ring while they are |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 } | 132 } |
138 | 133 |
139 // init should be called after all the indices have been added (via addI
dx) | 134 // init should be called after all the indices have been added (via addI
dx) |
140 void init(const GrAAConvexTessellator& tess); | 135 void init(const GrAAConvexTessellator& tess); |
141 void init(const SkTDArray<SkVector>& norms, const SkTDArray<SkVector>& b
isectors); | 136 void init(const SkTDArray<SkVector>& norms, const SkTDArray<SkVector>& b
isectors); |
142 | 137 |
143 const SkPoint& norm(int index) const { return fPts[index].fNorm; } | 138 const SkPoint& norm(int index) const { return fPts[index].fNorm; } |
144 const SkPoint& bisector(int index) const { return fPts[index].fBisector;
} | 139 const SkPoint& bisector(int index) const { return fPts[index].fBisector;
} |
145 int index(int index) const { return fPts[index].fIndex; } | 140 int index(int index) const { return fPts[index].fIndex; } |
146 int origEdgeID(int index) const { return fPts[index].fOrigEdgeId; } | 141 int origEdgeID(int index) const { return fPts[index].fOrigEdgeId; } |
147 void setOrigEdgeId(int index, int id) { fPts[index].fOrigEdgeId = id; } | |
148 | 142 |
149 #if GR_AA_CONVEX_TESSELLATOR_VIZ | 143 #if GR_AA_CONVEX_TESSELLATOR_VIZ |
150 void draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const; | 144 void draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const; |
151 #endif | 145 #endif |
152 | 146 |
153 private: | 147 private: |
154 void computeNormals(const GrAAConvexTessellator& result); | 148 void computeNormals(const GrAAConvexTessellator& result); |
155 void computeBisectors(const GrAAConvexTessellator& tess); | 149 void computeBisectors(const GrAAConvexTessellator& tess); |
156 | 150 |
157 SkDEBUGCODE(bool isConvex(const GrAAConvexTessellator& tess) const;) | 151 SkDEBUGCODE(bool isConvex(const GrAAConvexTessellator& tess) const;) |
158 | 152 |
159 struct PointData { | 153 struct PointData { |
160 SkPoint fNorm; | 154 SkPoint fNorm; |
161 SkPoint fBisector; | 155 SkPoint fBisector; |
162 int fIndex; | 156 int fIndex; |
163 int fOrigEdgeId; | 157 int fOrigEdgeId; |
164 }; | 158 }; |
165 | 159 |
166 SkTDArray<PointData> fPts; | 160 SkTDArray<PointData> fPts; |
167 }; | 161 }; |
168 | 162 |
169 bool movable(int index) const { return fMovable[index]; } | 163 bool movable(int index) const { return fMovable[index]; } |
170 | 164 |
171 // Movable points are those that can be slid along their bisector. | 165 // Movable points are those that can be slid along their bisector. |
172 // Basically, a point is immovable if it is part of the original | 166 // Basically, a point is immovable if it is part of the original |
173 // polygon or it results from the fusing of two bisectors. | 167 // polygon or it results from the fusing of two bisectors. |
174 int addPt(const SkPoint& pt, SkScalar depth, SkScalar coverage, bool movable
, bool isCurve); | 168 int addPt(const SkPoint& pt, SkScalar depth, bool movable, bool isCurve); |
175 void popLastPt(); | 169 void popLastPt(); |
176 void popFirstPtShuffle(); | 170 void popFirstPtShuffle(); |
177 | 171 |
178 void updatePt(int index, const SkPoint& pt, SkScalar depth, SkScalar coverag
e); | 172 void updatePt(int index, const SkPoint& pt, SkScalar depth); |
179 | 173 |
180 void addTri(int i0, int i1, int i2); | 174 void addTri(int i0, int i1, int i2); |
181 | 175 |
182 void reservePts(int count) { | 176 void reservePts(int count) { |
183 fPts.setReserve(count); | 177 fPts.setReserve(count); |
184 fCoverages.setReserve(count); | 178 fDepths.setReserve(count); |
185 fMovable.setReserve(count); | 179 fMovable.setReserve(count); |
186 } | 180 } |
187 | 181 |
188 SkScalar computeDepthFromEdge(int edgeIdx, const SkPoint& p) const; | 182 SkScalar computeDepthFromEdge(int edgeIdx, const SkPoint& p) const; |
189 | 183 |
190 bool computePtAlongBisector(int startIdx, const SkPoint& bisector, | 184 bool computePtAlongBisector(int startIdx, const SkPoint& bisector, |
191 int edgeIdx, SkScalar desiredDepth, | 185 int edgeIdx, SkScalar desiredDepth, |
192 SkPoint* result) const; | 186 SkPoint* result) const; |
193 | 187 |
194 void lineTo(SkPoint p, bool isCurve); | |
195 | |
196 void lineTo(const SkMatrix& m, SkPoint p, bool isCurve); | 188 void lineTo(const SkMatrix& m, SkPoint p, bool isCurve); |
197 | 189 |
198 void quadTo(SkPoint pts[3]); | |
199 | |
200 void quadTo(const SkMatrix& m, SkPoint pts[3]); | 190 void quadTo(const SkMatrix& m, SkPoint pts[3]); |
201 | 191 |
202 void cubicTo(const SkMatrix& m, SkPoint pts[4]); | 192 void cubicTo(const SkMatrix& m, SkPoint pts[4]); |
203 | 193 |
204 void conicTo(const SkMatrix& m, SkPoint pts[3], SkScalar w); | 194 void conicTo(const SkMatrix& m, SkPoint pts[3], SkScalar w); |
205 | 195 |
206 void terminate(const Ring& lastRing); | 196 void terminate(const Ring& lastRing); |
207 | 197 |
208 // return false on failure/degenerate path | 198 // return false on failure/degenerate path |
209 bool extractFromPath(const SkMatrix& m, const SkPath& path); | 199 bool extractFromPath(const SkMatrix& m, const SkPath& path); |
210 void computeBisectors(); | 200 void computeBisectors(); |
211 | 201 |
212 void fanRing(const Ring& ring); | 202 void fanRing(const Ring& ring); |
| 203 void createOuterRing(); |
213 | 204 |
214 Ring* getNextRing(Ring* lastRing); | 205 Ring* getNextRing(Ring* lastRing); |
215 | 206 |
216 void createOuterRing(const Ring& previousRing, SkScalar outset, SkScalar cov
erage, | 207 bool createInsetRing(const Ring& lastRing, Ring* nextRing); |
217 Ring* nextRing); | |
218 | |
219 bool createInsetRings(Ring& previousRing, SkScalar initialDepth, SkScalar in
itialCoverage, | |
220 SkScalar targetDepth, SkScalar targetCoverage, Ring**
finalRing); | |
221 | |
222 bool createInsetRing(const Ring& lastRing, Ring* nextRing, | |
223 SkScalar initialDepth, SkScalar initialCoverage, SkScal
ar targetDepth, | |
224 SkScalar targetCoverage, bool forceNew); | |
225 | 208 |
226 void validate() const; | 209 void validate() const; |
227 | 210 |
228 // fPts, fCoverages & fMovable should always have the same # of elements | 211 |
| 212 #ifdef SK_DEBUG |
| 213 SkScalar computeRealDepth(const SkPoint& p) const; |
| 214 void checkAllDepths() const; |
| 215 #endif |
| 216 |
| 217 // fPts, fWeights & fMovable should always have the same # of elements |
229 SkTDArray<SkPoint> fPts; | 218 SkTDArray<SkPoint> fPts; |
230 SkTDArray<SkScalar> fCoverages; | 219 SkTDArray<SkScalar> fDepths; |
231 // movable points are those that can be slid further along their bisector | 220 // movable points are those that can be slid further along their bisector |
232 SkTDArray<bool> fMovable; | 221 SkTDArray<bool> fMovable; |
233 | 222 |
234 // The outward facing normals for the original polygon | 223 // The outward facing normals for the original polygon |
235 SkTDArray<SkVector> fNorms; | 224 SkTDArray<SkVector> fNorms; |
236 // The inward facing bisector at each point in the original polygon. Only | 225 // The inward facing bisector at each point in the original polygon. Only |
237 // needed for exterior ring creation and then handed off to the initial ring
. | 226 // needed for exterior ring creation and then handed off to the initial ring
. |
238 SkTDArray<SkVector> fBisectors; | 227 SkTDArray<SkVector> fBisectors; |
239 | 228 |
240 // Tracks whether a given point is interior to a curve. Such points are | 229 // Tracks whether a given point is interior to a curve. Such points are |
241 // assumed to have shallow curvature. | 230 // assumed to have shallow curvature. |
242 SkTDArray<bool> fIsCurve; | 231 SkTDArray<bool> fIsCurve; |
243 | 232 |
244 SkPoint::Side fSide; // winding of the original polygon | 233 SkPoint::Side fSide; // winding of the original polygon |
245 | 234 |
246 // The triangulation of the points | 235 // The triangulation of the points |
247 SkTDArray<int> fIndices; | 236 SkTDArray<int> fIndices; |
248 | 237 |
249 Ring fInitialRing; | 238 Ring fInitialRing; |
250 #if GR_AA_CONVEX_TESSELLATOR_VIZ | 239 #if GR_AA_CONVEX_TESSELLATOR_VIZ |
251 // When visualizing save all the rings | 240 // When visualizing save all the rings |
252 SkTDArray<Ring*> fRings; | 241 SkTDArray<Ring*> fRings; |
253 #else | 242 #else |
254 Ring fRings[2]; | 243 Ring fRings[2]; |
255 #endif | 244 #endif |
256 CandidateVerts fCandidateVerts; | 245 CandidateVerts fCandidateVerts; |
257 | 246 |
258 // < 0 means filling rather than stroking | 247 SkScalar fTargetDepth; |
259 SkScalar fStrokeWidth; | |
260 | |
261 SkPaint::Join fJoin; | |
262 | |
263 SkScalar fMiterLimit; | |
264 | 248 |
265 SkTDArray<SkPoint> fPointBuffer; | 249 SkTDArray<SkPoint> fPointBuffer; |
| 250 |
| 251 // If some goes wrong with the inset computation the tessellator will |
| 252 // truncate the creation of the inset polygon. In this case the depth |
| 253 // check will complain. |
| 254 SkDEBUGCODE(bool fShouldCheckDepths;) |
| 255 |
| 256 SkDEBUGCODE(SkScalar fMinCross;) |
| 257 |
| 258 SkDEBUGCODE(SkScalar fMaxCross;) |
266 }; | 259 }; |
267 | 260 |
268 | 261 |
269 #endif | 262 #endif |
270 | 263 |
OLD | NEW |