Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright 2015 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #ifndef GrAAConvexTessellator_DEFINED | |
| 9 #define GrAAConvexTessellator_DEFINED | |
| 10 | |
| 11 #include "SkColor.h" | |
| 12 #include "SkPoint.h" | |
| 13 #include "SkScalar.h" | |
| 14 #include "SkTDArray.h" | |
| 15 | |
| 16 class SkCanvas; | |
| 17 class SkMatrix; | |
| 18 class SkPath; | |
| 19 | |
| 20 #define GR_AA_CONVEX_TESSELLATOR_VIZ 1 | |
| 21 | |
| 22 class GrAAConvexTessellator; | |
| 23 | |
| 24 // The GrAAConvexTessellator holds the global pool of vertices. The GrRing | |
| 25 // holds a set of indices into that global pool that together define a | |
| 26 // single polygon inset. | |
| 27 class GrRing { | |
|
bsalomon
2015/04/24 15:44:44
Seems like Ring should be a nested class of GrAACT
robertphillips
2015/05/05 15:21:33
Done. The GrAACT does need to know the size but I
| |
| 28 public: | |
| 29 GrRing() : fSide(SkPoint::kOn_Side) {} | |
| 30 | |
| 31 void setSide(SkPoint::Side side) { fSide = side; } | |
| 32 SkPoint::Side side() const { return fSide; } | |
| 33 | |
| 34 void setReserve(int numPts); | |
| 35 void rewind(); | |
| 36 | |
| 37 int numPts0() const { return fIndices.count(); } | |
| 38 | |
| 39 void addIdx1(int index, int origEdgeId) { | |
| 40 *fIndices.push() = index; | |
| 41 *fOrigEdgeIds.push() = origEdgeId; | |
| 42 } | |
| 43 | |
| 44 // init should be called after all the indices have been added (via addIdx) | |
| 45 void init(const GrAAConvexTessellator& tess); | |
| 46 | |
| 47 const SkPoint& norm1(int index) const { return fNorms[index]; } | |
| 48 const SkPoint& bisector(int index) const { return fBisectors[index]; } | |
| 49 int index(int index) const { return fIndices[index]; } | |
| 50 int origEdgeID(int index) const { return fOrigEdgeIds[index]; } | |
| 51 | |
| 52 // only call after 'init' | |
| 53 SkScalar computeDepthFromEdge(GrAAConvexTessellator& tess, | |
| 54 int edgeIdx, const SkPoint& p) const; | |
| 55 | |
| 56 #if GR_AA_CONVEX_TESSELLATOR_VIZ | |
| 57 void draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const; | |
| 58 #endif | |
| 59 | |
| 60 int numPts2() const { return fPts2.count(); } | |
| 61 | |
| 62 const SkPoint& lastPoint() const { return fPts2[fPts2.count()-1];} | |
| 63 const SkPoint& firstPoint() const { return fPts2[0]; } | |
| 64 const SkPoint& point(int index) const { return fPts2[index]; } | |
| 65 | |
| 66 int originatingIdx(int index) const { | |
| 67 return fOriginatingIdx2[index]; | |
| 68 } | |
| 69 | |
| 70 int origEdge2(int index) const { | |
| 71 return fOrigEdgeIds2[index]; | |
| 72 } | |
| 73 | |
| 74 bool needsToBeNew(int index) const { | |
| 75 return fNeedsToBeNew2[index]; | |
| 76 } | |
| 77 | |
| 78 int addNewPt(const SkPoint& newPt, int originatingIdx, int origEdge, bool ne edsToBeNew) { | |
| 79 *fPts2.push() = newPt; | |
| 80 *fOrigEdgeIds2.push() = origEdge; | |
| 81 *fOriginatingIdx2.push() = originatingIdx; | |
| 82 *fNeedsToBeNew2.push() = needsToBeNew; | |
| 83 return fPts2.count() - 1; | |
| 84 } | |
| 85 | |
| 86 int fuseWithPrior(int origEdgeId) { | |
| 87 this->validate(); | |
| 88 | |
| 89 fOrigEdgeIds2[fOrigEdgeIds2.count()-1] = origEdgeId; | |
| 90 fOriginatingIdx2[fOriginatingIdx2.count()-1] = -1; | |
| 91 fNeedsToBeNew2[fNeedsToBeNew2.count()-1] = true; | |
| 92 return fPts2.count() - 1; | |
| 93 } | |
| 94 | |
| 95 int fuseWithNext() { | |
| 96 this->validate(); | |
| 97 | |
| 98 fOriginatingIdx2[0] = -1; | |
| 99 fNeedsToBeNew2[0] = true; | |
| 100 return 0; | |
| 101 } | |
| 102 | |
| 103 int fuseWithBoth() { | |
| 104 this->validate(); | |
| 105 | |
| 106 if (fPts2.count() > 1) { | |
| 107 fPts2.pop(); | |
| 108 fOriginatingIdx2.pop(); | |
| 109 fOrigEdgeIds2.pop(); | |
| 110 fNeedsToBeNew2.pop(); | |
| 111 } | |
| 112 | |
| 113 this->validate(); | |
| 114 | |
| 115 fOriginatingIdx2[0] = -1; | |
| 116 fNeedsToBeNew2[0] = true; | |
| 117 return 0; | |
| 118 } | |
| 119 | |
| 120 private: | |
| 121 void validate() const; | |
| 122 void computeNormals(const GrAAConvexTessellator& result); | |
| 123 void computeBisectors(); | |
| 124 | |
| 125 bool isConvex(const GrAAConvexTessellator& tess) const; | |
| 126 | |
| 127 // TODO: the ring operates in two modes: a construction phase and | |
| 128 // an information phase. The data used by the two phases is almost completel y | |
| 129 // disjoint but of equal size. We could reuse the memory between the | |
| 130 // two phases. | |
| 131 #if 0 | |
| 132 enum RingMode { | |
| 133 InProgress_RingMode, | |
| 134 Finished_RingMode, | |
| 135 FinishedWithInfo_RingMode | |
| 136 }; | |
| 137 | |
| 138 typedef struct { | |
| 139 SkPoint fPt; // new ring point not yet in the global pool | |
| 140 int fOriginatingIdx; // Index of the vert that was slid along the bisector for this | |
| 141 // point. Set to -1 if this point was fused with another. | |
| 142 int fOrigEdgeId; // The closest edge in fInitialRing | |
| 143 bool fNeedsToBeNew; | |
| 144 } InProgressInfo; | |
| 145 | |
| 146 typedef struct { | |
| 147 SkPoint fNorm; | |
| 148 SkPoint fBisector; | |
| 149 int fIndex; // index of the point in the global pool | |
| 150 int fOrigEdgeId; // The closest edge in fInitialRing | |
| 151 } FinishedInfo; | |
| 152 | |
| 153 RingMode fMode; | |
| 154 | |
| 155 typedef union { | |
| 156 InProgressInfo fIPI; | |
| 157 FinishedInfo fFI; | |
| 158 } SingleEntry; | |
| 159 | |
| 160 SkTDArray<SingleEntry> fVertInfo; | |
| 161 #endif | |
| 162 | |
| 163 SkPoint::Side fSide; | |
| 164 | |
| 165 SkTDArray<SkPoint> fPts2; | |
| 166 SkTDArray<int> fOriginatingIdx2; | |
| 167 SkTDArray<int> fOrigEdgeIds2; | |
| 168 SkTDArray<bool> fNeedsToBeNew2; | |
| 169 | |
| 170 SkTDArray<SkPoint> fNorms; | |
| 171 SkTDArray<SkPoint> fBisectors; | |
| 172 SkTDArray<int> fIndices; | |
| 173 SkTDArray<int> fOrigEdgeIds; | |
| 174 | |
| 175 }; | |
| 176 | |
| 177 | |
| 178 class GrAAConvexTessellator { | |
| 179 public: | |
| 180 GrAAConvexTessellator(SkScalar targetDepth = 0.5f) : fTargetDepth(targetDept h) { } | |
| 181 | |
| 182 void setTargetDepth(SkScalar targetDepth) { fTargetDepth = targetDepth; } | |
| 183 SkScalar targetDepth() const { return fTargetDepth; } | |
| 184 | |
| 185 bool tessellate(const SkMatrix& m, const SkPath& path); | |
| 186 | |
| 187 // The next five should only be called after tessellate | |
| 188 int numPts() const { return fPts.count(); } | |
| 189 int numIndices() const { return fIndices.count(); } | |
| 190 | |
| 191 const SkPoint& point(int index) const { return fPts[index]; } | |
| 192 int index(int index) const { return fIndices[index]; } | |
| 193 | |
| 194 #if GR_AA_CONVEX_TESSELLATOR_VIZ | |
| 195 void draw(SkCanvas* canvas) const; | |
| 196 #endif | |
| 197 | |
| 198 private: | |
| 199 const SkPoint& lastPoint() const { return fPts.top(); } | |
| 200 SkScalar depth(int index) const { return fDepths[index]; } | |
| 201 bool movable(int index) const { return fMovable[index]; } | |
| 202 | |
| 203 int addPt(const SkPoint& pt, SkScalar depth, bool movable); | |
|
bsalomon
2015/04/24 15:44:44
comment about what movable means?
robertphillips
2015/05/05 15:21:33
Done.
| |
| 204 void popLastPt(); | |
| 205 void popFirstPtShuffle(); | |
| 206 | |
| 207 void updatePt(int index, const SkPoint& pt, SkScalar depth); | |
| 208 | |
| 209 void addTri(int i0, int i1, int i2); | |
| 210 | |
| 211 void reservePts(int count) { | |
| 212 fPts.setReserve(count); | |
| 213 fDepths.setReserve(count); | |
| 214 fMovable.setReserve(count); | |
| 215 } | |
| 216 | |
| 217 SkPoint computePtAlongBisector(int startIdx, const SkPoint& bisector, | |
| 218 int edgeIdx, SkScalar desiredDepth) const; | |
| 219 | |
| 220 // return false on failure/degenerate path | |
| 221 bool extractFromPath(const SkMatrix& m, const SkPath& path); | |
| 222 | |
| 223 void fanRing(const GrRing& ring); | |
| 224 void createOuterRing(const GrRing& ring); | |
| 225 | |
| 226 GrRing* getNextRing(GrRing* lastRing); | |
| 227 | |
| 228 bool createInsetRing(const GrRing& lastRing, GrRing* nextRing); | |
| 229 | |
| 230 void validate() const; | |
| 231 | |
| 232 #ifdef SK_DEBUG | |
| 233 SkScalar computeRealDepth(const SkPoint& p) const; | |
| 234 void checkAllDepths() const; | |
| 235 #endif | |
| 236 | |
| 237 // fPts, fWeights & fMovable should always have the same # of elements | |
| 238 SkTDArray<SkPoint> fPts; | |
| 239 SkTDArray<SkScalar> fDepths; | |
| 240 // movable points are those that can be slid further along their bisector | |
| 241 SkTDArray<bool> fMovable; | |
| 242 | |
| 243 SkTDArray<int> fIndices; | |
| 244 | |
| 245 GrRing fInitialRing; | |
| 246 #if GR_AA_CONVEX_TESSELLATOR_VIZ | |
| 247 // When visualizing save all the rings | |
| 248 SkTDArray<GrRing*> fRings; | |
| 249 #else | |
| 250 GrRing fRings[2]; | |
| 251 #endif | |
| 252 | |
| 253 SkScalar fTargetDepth; | |
| 254 }; | |
| 255 | |
| 256 | |
| 257 #endif | |
| 258 | |
| OLD | NEW |