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