Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: src/gpu/GrAAFlatteningConvexTessellator.cpp

Issue 1158803002: Added GrAAFlatteningConvexPathRenderer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: hopefully fixed windows build issues Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "GrAAConvexTessellator.h" 8 #include "GrAAFlatteningConvexTessellator.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkPath.h" 10 #include "SkPath.h"
11 #include "SkPoint.h" 11 #include "SkPoint.h"
12 #include "SkString.h" 12 #include "SkString.h"
13 #include "GrPathUtils.h"
13 14
14 // Next steps: 15 // Next steps:
15 // use in AAConvexPathRenderer 16 // use in AAConvexPathRenderer
16 // add an interactive sample app slide 17 // add an interactive sample app slide
17 // add debug check that all points are suitably far apart 18 // add debug check that all points are suitably far apart
18 // test more degenerate cases 19 // test more degenerate cases
19 20
20 // The tolerance for fusing vertices and eliminating colinear lines (It is in de vice space). 21 // The tolerance for fusing vertices and eliminating colinear lines (It is in de vice space).
21 static const SkScalar kClose = (SK_Scalar1 / 16); 22 static const SkScalar kClose = (SK_Scalar1 / 16);
22 static const SkScalar kCloseSqd = SkScalarMul(kClose, kClose); 23 static const SkScalar kCloseSqd = SkScalarMul(kClose, kClose);
(...skipping 19 matching lines...) Expand all
42 SkScalar distSq = p0.distanceToSqd(p1); 43 SkScalar distSq = p0.distanceToSqd(p1);
43 return distSq < kCloseSqd; 44 return distSq < kCloseSqd;
44 } 45 }
45 46
46 static SkScalar abs_dist_from_line(const SkPoint& p0, const SkVector& v, const S kPoint& test) { 47 static SkScalar abs_dist_from_line(const SkPoint& p0, const SkVector& v, const S kPoint& test) {
47 SkPoint testV = test - p0; 48 SkPoint testV = test - p0;
48 SkScalar dist = testV.fX * v.fY - testV.fY * v.fX; 49 SkScalar dist = testV.fX * v.fY - testV.fY * v.fX;
49 return SkScalarAbs(dist); 50 return SkScalarAbs(dist);
50 } 51 }
51 52
52 int GrAAConvexTessellator::addPt(const SkPoint& pt, 53 int GrAAFlatteningConvexTessellator::addPt(const SkPoint& pt,
robertphillips 2015/05/27 18:10:54 line these guys up ?
53 SkScalar depth, 54 SkScalar depth,
54 bool movable) { 55 bool movable,
56 bool isCurve) {
55 this->validate(); 57 this->validate();
56 58
57 int index = fPts.count(); 59 int index = fPts.count();
58 *fPts.push() = pt; 60 *fPts.push() = pt;
59 *fDepths.push() = depth; 61 *fDepths.push() = depth;
60 *fMovable.push() = movable; 62 *fMovable.push() = movable;
63 *fIsCurve.push() = isCurve;
61 64
62 this->validate(); 65 this->validate();
63 return index; 66 return index;
64 } 67 }
65 68
66 void GrAAConvexTessellator::popLastPt() { 69 void GrAAFlatteningConvexTessellator::popLastPt() {
67 this->validate(); 70 this->validate();
68 71
69 fPts.pop(); 72 fPts.pop();
70 fDepths.pop(); 73 fDepths.pop();
71 fMovable.pop(); 74 fMovable.pop();
72 75
73 this->validate(); 76 this->validate();
74 } 77 }
75 78
76 void GrAAConvexTessellator::popFirstPtShuffle() { 79 void GrAAFlatteningConvexTessellator::popFirstPtShuffle() {
77 this->validate(); 80 this->validate();
78 81
79 fPts.removeShuffle(0); 82 fPts.removeShuffle(0);
80 fDepths.removeShuffle(0); 83 fDepths.removeShuffle(0);
81 fMovable.removeShuffle(0); 84 fMovable.removeShuffle(0);
82 85
83 this->validate(); 86 this->validate();
84 } 87 }
85 88
86 void GrAAConvexTessellator::updatePt(int index, 89 void GrAAFlatteningConvexTessellator::updatePt(int index,
robertphillips 2015/05/27 18:10:54 line up ?
87 const SkPoint& pt, 90 const SkPoint& pt,
88 SkScalar depth) { 91 SkScalar depth) {
89 this->validate(); 92 this->validate();
90 SkASSERT(fMovable[index]); 93 SkASSERT(fMovable[index]);
91 94
92 fPts[index] = pt; 95 fPts[index] = pt;
93 fDepths[index] = depth; 96 fDepths[index] = depth;
94 } 97 }
95 98
96 void GrAAConvexTessellator::addTri(int i0, int i1, int i2) { 99 void GrAAFlatteningConvexTessellator::addTri(int i0, int i1, int i2) {
97 if (i0 == i1 || i1 == i2 || i2 == i0) { 100 if (i0 == i1 || i1 == i2 || i2 == i0) {
98 return; 101 return;
99 } 102 }
100 103
101 *fIndices.push() = i0; 104 *fIndices.push() = i0;
102 *fIndices.push() = i1; 105 *fIndices.push() = i1;
103 *fIndices.push() = i2; 106 *fIndices.push() = i2;
104 } 107 }
105 108
106 void GrAAConvexTessellator::rewind() { 109 void GrAAFlatteningConvexTessellator::rewind() {
107 fPts.rewind(); 110 fPts.rewind();
108 fDepths.rewind(); 111 fDepths.rewind();
109 fMovable.rewind(); 112 fMovable.rewind();
110 fIndices.rewind(); 113 fIndices.rewind();
111 fNorms.rewind(); 114 fNorms.rewind();
112 fInitialRing.rewind(); 115 fInitialRing.rewind();
113 fCandidateVerts.rewind(); 116 fCandidateVerts.rewind();
114 #if GR_AA_CONVEX_TESSELLATOR_VIZ 117 #if GR_AA_FLATTENING_CONVEX_TESSELLATOR_VIZ
115 fRings.rewind(); // TODO: leak in this case! 118 fRings.rewind(); // TODO: leak in this case!
116 #else 119 #else
117 fRings[0].rewind(); 120 fRings[0].rewind();
118 fRings[1].rewind(); 121 fRings[1].rewind();
119 #endif 122 #endif
120 } 123 }
121 124
122 void GrAAConvexTessellator::computeBisectors() { 125 void GrAAFlatteningConvexTessellator::computeBisectors() {
123 fBisectors.setCount(fNorms.count()); 126 fBisectors.setCount(fNorms.count());
124 127
125 int prev = fBisectors.count() - 1; 128 int prev = fBisectors.count() - 1;
126 for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) { 129 for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) {
127 fBisectors[cur] = fNorms[cur] + fNorms[prev]; 130 fBisectors[cur] = fNorms[cur] + fNorms[prev];
128 if (!fBisectors[cur].normalize()) { 131 if (!fBisectors[cur].normalize()) {
129 SkASSERT(SkPoint::kLeft_Side == fSide || SkPoint::kRight_Side == fSi de); 132 SkASSERT(SkPoint::kLeft_Side == fSide || SkPoint::kRight_Side == fSi de);
130 fBisectors[cur].setOrthog(fNorms[cur], (SkPoint::Side)-fSide); 133 fBisectors[cur].setOrthog(fNorms[cur], (SkPoint::Side)-fSide);
131 SkVector other; 134 SkVector other;
132 other.setOrthog(fNorms[prev], fSide); 135 other.setOrthog(fNorms[prev], fSide);
133 fBisectors[cur] += other; 136 fBisectors[cur] += other;
134 SkAssertResult(fBisectors[cur].normalize()); 137 SkAssertResult(fBisectors[cur].normalize());
135 } else { 138 } else {
136 fBisectors[cur].negate(); // make the bisector face in 139 fBisectors[cur].negate(); // make the bisector face in
137 } 140 }
138 141
139 SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length())); 142 SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length()));
140 } 143 }
141 } 144 }
142 145
143 // The general idea here is to, conceptually, start with the original polygon an d slide 146 // The general idea here is to, conceptually, start with the original polygon an d slide
144 // the vertices along the bisectors until the first intersection. At that 147 // the vertices along the bisectors until the first intersection. At that
145 // point two of the edges collapse and the process repeats on the new polygon. 148 // point two of the edges collapse and the process repeats on the new polygon.
146 // The polygon state is captured in the Ring class while the GrAAConvexTessellat or 149 // The polygon state is captured in the Ring class while the GrAAFlatteningConve xTessellator
147 // controls the iteration. The CandidateVerts holds the formative points for the 150 // controls the iteration. The CandidateVerts holds the formative points for the
148 // next ring. 151 // next ring.
149 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) { 152 bool GrAAFlatteningConvexTessellator::tessellate(const SkMatrix& m, const SkPath & path) {
150 static const int kMaxNumRings = 8; 153 static const int kMaxNumRings = 1;
151 154
152 SkDEBUGCODE(fShouldCheckDepths = true;) 155 SkDEBUGCODE(fShouldCheckDepths = true;)
153 156
154 if (!this->extractFromPath(m, path)) { 157 if (!this->extractFromPath(m, path)) {
155 return false; 158 return false;
156 } 159 }
157 160
158 this->createOuterRing(); 161 this->createOuterRing();
159 162
160 // the bisectors are only needed for the computation of the outer ring 163 // the bisectors are only needed for the computation of the outer ring
(...skipping 22 matching lines...) Expand all
183 186
184 #ifdef SK_DEBUG 187 #ifdef SK_DEBUG
185 this->validate(); 188 this->validate();
186 if (fShouldCheckDepths) { 189 if (fShouldCheckDepths) {
187 SkDEBUGCODE(this->checkAllDepths();) 190 SkDEBUGCODE(this->checkAllDepths();)
188 } 191 }
189 #endif 192 #endif
190 return true; 193 return true;
191 } 194 }
192 195
193 SkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const { 196 SkScalar GrAAFlatteningConvexTessellator::computeDepthFromEdge(int edgeIdx, cons t SkPoint& p) const {
194 SkASSERT(edgeIdx < fNorms.count()); 197 SkASSERT(edgeIdx < fNorms.count());
195 198
196 SkPoint v = p - fPts[edgeIdx]; 199 SkPoint v = p - fPts[edgeIdx];
197 SkScalar depth = -fNorms[edgeIdx].dot(v); 200 SkScalar depth = -fNorms[edgeIdx].dot(v);
198 SkASSERT(depth >= 0.0f); 201 SkASSERT(depth >= 0.0f);
199 return depth; 202 return depth;
200 } 203 }
201 204
202 // Find a point that is 'desiredDepth' away from the 'edgeIdx'-th edge and lies 205 // Find a point that is 'desiredDepth' away from the 'edgeIdx'-th edge and lies
203 // along the 'bisector' from the 'startIdx'-th point. 206 // along the 'bisector' from the 'startIdx'-th point.
204 bool GrAAConvexTessellator::computePtAlongBisector(int startIdx, 207 bool GrAAFlatteningConvexTessellator::computePtAlongBisector(int startIdx,
robertphillips 2015/05/27 18:10:54 line up ?
205 const SkVector& bisector, 208 const SkVector& bisector,
206 int edgeIdx, 209 int edgeIdx,
207 SkScalar desiredDepth, 210 SkScalar desiredDepth,
208 SkPoint* result) const { 211 SkPoint* result) const {
209 const SkPoint& norm = fNorms[edgeIdx]; 212 const SkPoint& norm = fNorms[edgeIdx];
210 213
211 // First find the point where the edge and the bisector intersect 214 // First find the point where the edge and the bisector intersect
212 SkPoint newP; 215 SkPoint newP;
213 SkScalar t = perp_intersect(fPts[startIdx], bisector, fPts[edgeIdx], norm); 216 SkScalar t = perp_intersect(fPts[startIdx], bisector, fPts[edgeIdx], norm);
214 if (SkScalarNearlyEqual(t, 0.0f)) { 217 if (SkScalarNearlyEqual(t, 0.0f)) {
(...skipping 13 matching lines...) Expand all
228 t = -desiredDepth / bisector.dot(norm); 231 t = -desiredDepth / bisector.dot(norm);
229 SkASSERT(t > 0.0f); 232 SkASSERT(t > 0.0f);
230 *result = bisector; 233 *result = bisector;
231 result->scale(t); 234 result->scale(t);
232 *result += newP; 235 *result += newP;
233 236
234 237
235 return true; 238 return true;
236 } 239 }
237 240
238 bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat h) { 241 bool GrAAFlatteningConvexTessellator::extractFromPath(const SkMatrix& m, const S kPath& path) {
239 SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks());
240 SkASSERT(SkPath::kConvex_Convexity == path.getConvexity()); 242 SkASSERT(SkPath::kConvex_Convexity == path.getConvexity());
241 243
242 // Outer ring: 3*numPts 244 // Outer ring: 3*numPts
243 // Middle ring: numPts 245 // Middle ring: numPts
244 // Presumptive inner ring: numPts 246 // Presumptive inner ring: numPts
245 this->reservePts(5*path.countPoints()); 247 this->reservePts(5*path.countPoints());
246 // Outer ring: 12*numPts 248 // Outer ring: 12*numPts
247 // Middle ring: 0 249 // Middle ring: 0
248 // Presumptive inner ring: 6*numPts + 6 250 // Presumptive inner ring: 6*numPts + 6
249 fIndices.setReserve(18*path.countPoints() + 6); 251 fIndices.setReserve(18*path.countPoints() + 6);
250 252
251 fNorms.setReserve(path.countPoints()); 253 fNorms.setReserve(path.countPoints());
252 254
253 SkScalar minCross = SK_ScalarMax, maxCross = -SK_ScalarMax;
254
255 // TODO: is there a faster way to extract the points from the path? Perhaps 255 // TODO: is there a faster way to extract the points from the path? Perhaps
256 // get all the points via a new entry point, transform them all in bulk 256 // get all the points via a new entry point, transform them all in bulk
257 // and then walk them to find duplicates? 257 // and then walk them to find duplicates?
258 SkPath::Iter iter(path, true); 258 SkPath::Iter iter(path, true);
259 SkPoint pts[4]; 259 SkPoint pts[4];
260 SkPath::Verb verb; 260 SkPath::Verb verb;
261 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 261 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
262 switch (verb) { 262 switch (verb) {
263 case SkPath::kLine_Verb: 263 case SkPath::kLine_Verb:
264 m.mapPoints(&pts[1], 1); 264 lineTo(m, pts[1], false);
bsalomon 2015/05/27 17:11:07 style nit, for (non-static) method calls we prefix
ethannicholas 2015/05/27 19:22:30 Done.
265 if (this->numPts() > 0 && duplicate_pt(pts[1], this->lastPoint() )) {
266 continue;
267 }
268
269 SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1);
270 if (this->numPts() >= 2 &&
271 abs_dist_from_line(fPts.top(), fNorms.top(), pts[1]) < kClos e) {
272 // The old last point is on the line from the second to last to the new point
273 this->popLastPt();
274 fNorms.pop();
275 }
276
277 this->addPt(pts[1], 0.0f, false);
278 if (this->numPts() > 1) {
279 *fNorms.push() = fPts.top() - fPts[fPts.count()-2];
280 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top() );
281 SkASSERT(len > 0.0f);
282 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length()));
283 }
284
285 if (this->numPts() >= 3) {
286 int cur = this->numPts()-1;
287 SkScalar cross = SkPoint::CrossProduct(fNorms[cur-1], fNorms [cur-2]);
288 maxCross = SkTMax(maxCross, cross);
289 minCross = SkTMin(minCross, cross);
290 }
291 break; 265 break;
292 case SkPath::kQuad_Verb: 266 case SkPath::kQuad_Verb:
267 quadTo(m, pts);
268 break;
269 case SkPath::kCubic_Verb:
270 cubicTo(m, pts);
271 break;
293 case SkPath::kConic_Verb: 272 case SkPath::kConic_Verb:
294 case SkPath::kCubic_Verb: 273 conicTo(m, pts, iter.conicWeight());
295 SkASSERT(false);
296 break; 274 break;
297 case SkPath::kMove_Verb: 275 case SkPath::kMove_Verb:
298 case SkPath::kClose_Verb: 276 case SkPath::kClose_Verb:
299 case SkPath::kDone_Verb: 277 case SkPath::kDone_Verb:
300 break; 278 break;
301 } 279 }
302 } 280 }
303 281
304 if (this->numPts() < 3) { 282 if (this->numPts() < 3) {
305 return false; 283 return false;
(...skipping 30 matching lines...) Expand all
336 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms[0]); 314 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms[0]);
337 SkASSERT(len > 0.0f); 315 SkASSERT(len > 0.0f);
338 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[0].length())); 316 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[0].length()));
339 } 317 }
340 318
341 if (this->numPts() < 3) { 319 if (this->numPts() < 3) {
342 return false; 320 return false;
343 } 321 }
344 322
345 // Check the cross produce of the final trio 323 // Check the cross produce of the final trio
346 SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top()); 324 SkScalar cross = SkPoint::CrossProduct(fNorms[0], fNorms.top());
robertphillips 2015/05/27 18:10:54 Hmmm ...
ethannicholas 2015/05/27 19:22:30 The work to compute the min & max cross products s
347 maxCross = SkTMax(maxCross, cross); 325 if (cross > 0.0f) {
348 minCross = SkTMin(minCross, cross);
349
350 if (maxCross > 0.0f) {
351 SkASSERT(minCross >= 0.0f);
352 fSide = SkPoint::kRight_Side; 326 fSide = SkPoint::kRight_Side;
353 } else { 327 } else {
354 SkASSERT(minCross <= 0.0f);
355 fSide = SkPoint::kLeft_Side; 328 fSide = SkPoint::kLeft_Side;
356 } 329 }
357 330
358 // Make all the normals face outwards rather than along the edge 331 // Make all the normals face outwards rather than along the edge
359 for (int cur = 0; cur < fNorms.count(); ++cur) { 332 for (int cur = 0; cur < fNorms.count(); ++cur) {
360 fNorms[cur].setOrthog(fNorms[cur], fSide); 333 fNorms[cur].setOrthog(fNorms[cur], fSide);
361 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length())); 334 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
362 } 335 }
363 336
364 this->computeBisectors(); 337 this->computeBisectors();
365 338
366 fCandidateVerts.setReserve(this->numPts()); 339 fCandidateVerts.setReserve(this->numPts());
367 fInitialRing.setReserve(this->numPts()); 340 fInitialRing.setReserve(this->numPts());
368 for (int i = 0; i < this->numPts(); ++i) { 341 for (int i = 0; i < this->numPts(); ++i) {
369 fInitialRing.addIdx(i, i); 342 fInitialRing.addIdx(i, i);
370 } 343 }
371 fInitialRing.init(fNorms, fBisectors); 344 fInitialRing.init(fNorms, fBisectors);
372 345
373 this->validate(); 346 this->validate();
374 return true; 347 return true;
375 } 348 }
376 349
377 GrAAConvexTessellator::Ring* GrAAConvexTessellator::getNextRing(Ring* lastRing) { 350 GrAAFlatteningConvexTessellator::Ring* GrAAFlatteningConvexTessellator::getNextR ing(Ring* lastRing) {
378 #if GR_AA_CONVEX_TESSELLATOR_VIZ 351 #if GR_AA_FLATTENING_CONVEX_TESSELLATOR_VIZ
379 Ring* ring = *fRings.push() = SkNEW(Ring); 352 Ring* ring = *fRings.push() = SkNEW(Ring);
380 ring->setReserve(fInitialRing.numPts()); 353 ring->setReserve(fInitialRing.numPts());
381 ring->rewind(); 354 ring->rewind();
382 return ring; 355 return ring;
383 #else 356 #else
384 // Flip flop back and forth between fRings[0] & fRings[1] 357 // Flip flop back and forth between fRings[0] & fRings[1]
385 int nextRing = (lastRing == &fRings[0]) ? 1 : 0; 358 int nextRing = (lastRing == &fRings[0]) ? 1 : 0;
386 fRings[nextRing].setReserve(fInitialRing.numPts()); 359 fRings[nextRing].setReserve(fInitialRing.numPts());
387 fRings[nextRing].rewind(); 360 fRings[nextRing].rewind();
388 return &fRings[nextRing]; 361 return &fRings[nextRing];
389 #endif 362 #endif
390 } 363 }
391 364
392 void GrAAConvexTessellator::fanRing(const Ring& ring) { 365 void GrAAFlatteningConvexTessellator::fanRing(const Ring& ring) {
393 // fan out from point 0 366 // fan out from point 0
394 for (int cur = 1; cur < ring.numPts()-1; ++cur) { 367 for (int cur = 1; cur < ring.numPts()-1; ++cur) {
395 this->addTri(ring.index(0), ring.index(cur), ring.index(cur+1)); 368 this->addTri(ring.index(0), ring.index(cur), ring.index(cur+1));
396 } 369 }
397 } 370 }
398 371
399 void GrAAConvexTessellator::createOuterRing() { 372 void GrAAFlatteningConvexTessellator::createOuterRing() {
400 // For now, we're only generating one outer ring (at the start). This 373 // For now, we're only generating one outer ring (at the start). This
401 // could be relaxed for stroking use cases. 374 // could be relaxed for stroking use cases.
402 SkASSERT(0 == fIndices.count()); 375 SkASSERT(0 == fIndices.count());
403 SkASSERT(fPts.count() == fNorms.count()); 376 SkASSERT(fPts.count() == fNorms.count());
404 377
405 const int numPts = fPts.count(); 378 const int numPts = fPts.count();
406 379
407 // For each vertex of the original polygon we add three points to the
408 // outset polygon - one extending perpendicular to each impinging edge
409 // and one along the bisector. Two triangles are added for each corner
410 // and two are added along each edge.
411 int prev = numPts - 1; 380 int prev = numPts - 1;
412 int lastPerpIdx = -1, firstPerpIdx = -1, newIdx0, newIdx1, newIdx2; 381 int lastPerpIdx = -1, firstPerpIdx = -1, newIdx0, newIdx1, newIdx2;
413 for (int cur = 0; cur < numPts; ++cur) { 382 for (int cur = 0; cur < numPts; ++cur) {
414 // The perpendicular point for the last edge 383 if (fIsCurve[cur]) {
415 SkPoint temp = fNorms[prev]; 384 // Inside a curve, we assume that the curvature is shallow enough (d ue to tesselation)
416 temp.scale(fTargetDepth); 385 // that we only need one corner point. Mathematically, the distance the corner point
417 temp += fPts[cur]; 386 // gets shifted out should depend on the angle between the two line segments (as in
387 // mitering), but again due to tesselation we assume that this angle is small and
388 // therefore the correction factor is negligible and we do not bothe r with it.
bsalomon 2015/05/27 17:11:07 Is it reasonable to have an assert that verifies t
ethannicholas 2015/05/27 19:22:30 Done.
418 389
419 // We know it isn't a duplicate of the prior point (since it and this 390 // The bisector outset point
420 // one are just perpendicular offsets from the non-merged polygon points ) 391 SkPoint temp = fBisectors[cur];
421 newIdx0 = this->addPt(temp, -fTargetDepth, false); 392 temp.scale(-fTargetDepth); // the bisectors point in
393 temp += fPts[cur];
422 394
423 // The bisector outset point 395 newIdx1 = this->addPt(temp, -fTargetDepth, false, true);
424 temp = fBisectors[cur];
425 temp.scale(-fTargetDepth); // the bisectors point in
426 temp += fPts[cur];
427 396
428 // For very shallow angles all the corner points could fuse 397 if (0 == cur) {
429 if (duplicate_pt(temp, this->point(newIdx0))) { 398 // Store the index of the first perpendicular point to finish up
430 newIdx1 = newIdx0; 399 firstPerpIdx = newIdx1;
431 } else { 400 SkASSERT(-1 == lastPerpIdx);
432 newIdx1 = this->addPt(temp, -fTargetDepth, false); 401 } else {
402 // The triangles for the previous edge
403 this->addTri(prev, newIdx1, cur);
404 this->addTri(prev, lastPerpIdx, newIdx1);
405 }
406
407 prev = cur;
408 // Track the last perpendicular outset point so we can construct the
409 // trailing edge triangles.
410 lastPerpIdx = newIdx1;
433 } 411 }
412 else {
413 // For each vertex of the original polygon we add three points to th e
414 // outset polygon - one extending perpendicular to each impinging ed ge
415 // and one along the bisector. Two triangles are added for each corn er
416 // and two are added along each edge.
434 417
435 // The perpendicular point for the next edge. 418 // The perpendicular point for the last edge
436 temp = fNorms[cur]; 419 SkPoint temp = fNorms[prev];
437 temp.scale(fTargetDepth); 420 temp.scale(fTargetDepth);
438 temp += fPts[cur]; 421 temp += fPts[cur];
439 422
440 // For very shallow angles all the corner points could fuse. 423 // We know it isn't a duplicate of the prior point (since it and thi s
441 if (duplicate_pt(temp, this->point(newIdx1))) { 424 // one are just perpendicular offsets from the non-merged polygon po ints)
442 newIdx2 = newIdx1; 425 newIdx0 = this->addPt(temp, -fTargetDepth, false, false);
443 } else { 426
444 newIdx2 = this->addPt(temp, -fTargetDepth, false); 427 // The bisector outset point
428 temp = fBisectors[cur];
429 temp.scale(-fTargetDepth); // the bisectors point in
430 temp += fPts[cur];
431
432 // For very shallow angles all the corner points could fuse
433 if (duplicate_pt(temp, this->point(newIdx0))) {
434 newIdx1 = newIdx0;
435 } else {
436 newIdx1 = this->addPt(temp, -fTargetDepth, false, false);
437 }
438
439 // The perpendicular point for the next edge.
440 temp = fNorms[cur];
441 temp.scale(fTargetDepth);
442 temp += fPts[cur];
443
444 // For very shallow angles all the corner points could fuse.
445 if (duplicate_pt(temp, this->point(newIdx1))) {
446 newIdx2 = newIdx1;
447 } else {
448 newIdx2 = this->addPt(temp, -fTargetDepth, false, false);
449 }
450
451 if (0 == cur) {
452 // Store the index of the first perpendicular point to finish up
453 firstPerpIdx = newIdx0;
454 SkASSERT(-1 == lastPerpIdx);
455 } else {
456 // The triangles for the previous edge
457 this->addTri(prev, newIdx0, cur);
458 this->addTri(prev, lastPerpIdx, newIdx0);
459 }
460
461 // The two triangles for the corner
462 this->addTri(cur, newIdx0, newIdx1);
463 this->addTri(cur, newIdx1, newIdx2);
464
465 prev = cur;
466 // Track the last perpendicular outset point so we can construct the
467 // trailing edge triangles.
468 lastPerpIdx = newIdx2;
445 } 469 }
446
447 if (0 == cur) {
448 // Store the index of the first perpendicular point to finish up
449 firstPerpIdx = newIdx0;
450 SkASSERT(-1 == lastPerpIdx);
451 } else {
452 // The triangles for the previous edge
453 this->addTri(prev, newIdx0, cur);
454 this->addTri(prev, lastPerpIdx, newIdx0);
455 }
456
457 // The two triangles for the corner
458 this->addTri(cur, newIdx0, newIdx1);
459 this->addTri(cur, newIdx1, newIdx2);
460
461 prev = cur;
462 // Track the last perpendicular outset point so we can construct the
463 // trailing edge triangles.
464 lastPerpIdx = newIdx2;
465 } 470 }
466 471
467 // pick up the final edge rect 472 // pick up the final edge rect
468 this->addTri(numPts-1, firstPerpIdx, 0); 473 this->addTri(numPts - 1, firstPerpIdx, 0);
469 this->addTri(numPts-1, lastPerpIdx, firstPerpIdx); 474 this->addTri(numPts - 1, lastPerpIdx, firstPerpIdx);
470 475
471 this->validate(); 476 this->validate();
472 } 477 }
473 478
474 // Something went wrong in the creation of the next ring. Mark the last good 479 // Something went wrong in the creation of the next ring. Mark the last good
475 // ring as being at the desired depth and fan it. 480 // ring as being at the desired depth and fan it.
476 void GrAAConvexTessellator::terminate(const Ring& ring) { 481 void GrAAFlatteningConvexTessellator::terminate(const Ring& ring) {
477 for (int i = 0; i < ring.numPts(); ++i) { 482 for (int i = 0; i < ring.numPts(); ++i) {
478 fDepths[ring.index(i)] = fTargetDepth; 483 fDepths[ring.index(i)] = fTargetDepth;
479 } 484 }
480 485
481 this->fanRing(ring); 486 this->fanRing(ring);
482 } 487 }
483 488
484 // return true when processing is complete 489 // return true when processing is complete
485 bool GrAAConvexTessellator::createInsetRing(const Ring& lastRing, Ring* nextRing ) { 490 bool GrAAFlatteningConvexTessellator::createInsetRing(const Ring& lastRing, Ring * nextRing) {
486 bool done = false; 491 bool done = false;
487 492
488 fCandidateVerts.rewind(); 493 fCandidateVerts.rewind();
489 494
490 // Loop through all the points in the ring and find the intersection with th e smallest depth 495 // Loop through all the points in the ring and find the intersection with th e smallest depth
491 SkScalar minDist = SK_ScalarMax, minT = 0.0f; 496 SkScalar minDist = SK_ScalarMax, minT = 0.0f;
492 int minEdgeIdx = -1; 497 int minEdgeIdx = -1;
493 498
494 for (int cur = 0; cur < lastRing.numPts(); ++cur) { 499 for (int cur = 0; cur < lastRing.numPts(); ++cur) {
495 int next = (cur + 1) % lastRing.numPts(); 500 int next = (cur + 1) % lastRing.numPts();
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 } 590 }
586 } 591 }
587 592
588 // Fold the new ring's points into the global pool 593 // Fold the new ring's points into the global pool
589 for (int i = 0; i < fCandidateVerts.numPts(); ++i) { 594 for (int i = 0; i < fCandidateVerts.numPts(); ++i) {
590 int newIdx; 595 int newIdx;
591 if (fCandidateVerts.needsToBeNew(i)) { 596 if (fCandidateVerts.needsToBeNew(i)) {
592 // if the originating index is still valid then this point wasn't 597 // if the originating index is still valid then this point wasn't
593 // fused (and is thus movable) 598 // fused (and is thus movable)
594 newIdx = this->addPt(fCandidateVerts.point(i), depth, 599 newIdx = this->addPt(fCandidateVerts.point(i), depth,
595 fCandidateVerts.originatingIdx(i) != -1); 600 fCandidateVerts.originatingIdx(i) != -1, false) ;
596 } else { 601 } else {
597 SkASSERT(fCandidateVerts.originatingIdx(i) != -1); 602 SkASSERT(fCandidateVerts.originatingIdx(i) != -1);
598 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.po int(i), depth); 603 this->updatePt(fCandidateVerts.originatingIdx(i), fCandidateVerts.po int(i), depth);
599 newIdx = fCandidateVerts.originatingIdx(i); 604 newIdx = fCandidateVerts.originatingIdx(i);
600 } 605 }
601 606
602 nextRing->addIdx(newIdx, fCandidateVerts.origEdge(i)); 607 nextRing->addIdx(newIdx, fCandidateVerts.origEdge(i));
603 } 608 }
604 609
605 // 'dst' currently has indices into the ring. Remap these to be indices 610 // 'dst' currently has indices into the ring. Remap these to be indices
(...skipping 13 matching lines...) Expand all
619 this->fanRing(*nextRing); 624 this->fanRing(*nextRing);
620 } 625 }
621 626
622 if (nextRing->numPts() < 3) { 627 if (nextRing->numPts() < 3) {
623 done = true; 628 done = true;
624 } 629 }
625 630
626 return done; 631 return done;
627 } 632 }
628 633
629 void GrAAConvexTessellator::validate() const { 634 void GrAAFlatteningConvexTessellator::validate() const {
630 SkASSERT(fPts.count() == fDepths.count()); 635 SkASSERT(fPts.count() == fDepths.count());
631 SkASSERT(fPts.count() == fMovable.count()); 636 SkASSERT(fPts.count() == fMovable.count());
632 SkASSERT(0 == (fIndices.count() % 3)); 637 SkASSERT(0 == (fIndices.count() % 3));
633 } 638 }
634 639
635 ////////////////////////////////////////////////////////////////////////////// 640 //////////////////////////////////////////////////////////////////////////////
636 void GrAAConvexTessellator::Ring::init(const GrAAConvexTessellator& tess) { 641 void GrAAFlatteningConvexTessellator::Ring::init(const GrAAFlatteningConvexTesse llator& tess) {
637 this->computeNormals(tess); 642 this->computeNormals(tess);
638 this->computeBisectors(tess); 643 this->computeBisectors(tess);
639 SkASSERT(this->isConvex(tess)); 644 SkASSERT(this->isConvex(tess));
640 } 645 }
641 646
642 void GrAAConvexTessellator::Ring::init(const SkTDArray<SkVector>& norms, 647 void GrAAFlatteningConvexTessellator::Ring::init(const SkTDArray<SkVector>& norm s,
643 const SkTDArray<SkVector>& bisectors) { 648 const SkTDArray<SkVector>& bisectors) {
644 for (int i = 0; i < fPts.count(); ++i) { 649 for (int i = 0; i < fPts.count(); ++i) {
645 fPts[i].fNorm = norms[i]; 650 fPts[i].fNorm = norms[i];
646 fPts[i].fBisector = bisectors[i]; 651 fPts[i].fBisector = bisectors[i];
647 } 652 }
648 } 653 }
649 654
650 // Compute the outward facing normal at each vertex. 655 // Compute the outward facing normal at each vertex.
651 void GrAAConvexTessellator::Ring::computeNormals(const GrAAConvexTessellator& te ss) { 656 void GrAAFlatteningConvexTessellator::Ring::computeNormals(const GrAAFlatteningC onvexTessellator& tess) {
652 for (int cur = 0; cur < fPts.count(); ++cur) { 657 for (int cur = 0; cur < fPts.count(); ++cur) {
653 int next = (cur + 1) % fPts.count(); 658 int next = (cur + 1) % fPts.count();
654 659
655 fPts[cur].fNorm = tess.point(fPts[next].fIndex) - tess.point(fPts[cur].f Index); 660 fPts[cur].fNorm = tess.point(fPts[next].fIndex) - tess.point(fPts[cur].f Index);
656 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fPts[cur].fNorm); 661 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fPts[cur].fNorm);
657 SkASSERT(len > 0.0f); 662 SkASSERT(len > 0.0f);
658 fPts[cur].fNorm.setOrthog(fPts[cur].fNorm, tess.side()); 663 fPts[cur].fNorm.setOrthog(fPts[cur].fNorm, tess.side());
659 664
660 SkASSERT(SkScalarNearlyEqual(1.0f, fPts[cur].fNorm.length())); 665 SkASSERT(SkScalarNearlyEqual(1.0f, fPts[cur].fNorm.length()));
661 } 666 }
662 } 667 }
663 668
664 void GrAAConvexTessellator::Ring::computeBisectors(const GrAAConvexTessellator& tess) { 669 void GrAAFlatteningConvexTessellator::Ring::computeBisectors(const GrAAFlattenin gConvexTessellator& tess) {
665 int prev = fPts.count() - 1; 670 int prev = fPts.count() - 1;
666 for (int cur = 0; cur < fPts.count(); prev = cur, ++cur) { 671 for (int cur = 0; cur < fPts.count(); prev = cur, ++cur) {
667 fPts[cur].fBisector = fPts[cur].fNorm + fPts[prev].fNorm; 672 fPts[cur].fBisector = fPts[cur].fNorm + fPts[prev].fNorm;
668 if (!fPts[cur].fBisector.normalize()) { 673 if (!fPts[cur].fBisector.normalize()) {
669 SkASSERT(SkPoint::kLeft_Side == tess.side() || SkPoint::kRight_Side == tess.side()); 674 SkASSERT(SkPoint::kLeft_Side == tess.side() || SkPoint::kRight_Side == tess.side());
670 fPts[cur].fBisector.setOrthog(fPts[cur].fNorm, (SkPoint::Side)-tess. side()); 675 fPts[cur].fBisector.setOrthog(fPts[cur].fNorm, (SkPoint::Side)-tess. side());
671 SkVector other; 676 SkVector other;
672 other.setOrthog(fPts[prev].fNorm, tess.side()); 677 other.setOrthog(fPts[prev].fNorm, tess.side());
673 fPts[cur].fBisector += other; 678 fPts[cur].fBisector += other;
674 SkAssertResult(fPts[cur].fBisector.normalize()); 679 SkAssertResult(fPts[cur].fBisector.normalize());
675 } else { 680 } else {
676 fPts[cur].fBisector.negate(); // make the bisector face in 681 fPts[cur].fBisector.negate(); // make the bisector face in
677 } 682 }
678 683
679 SkASSERT(SkScalarNearlyEqual(1.0f, fPts[cur].fBisector.length())); 684 SkASSERT(SkScalarNearlyEqual(1.0f, fPts[cur].fBisector.length()));
680 } 685 }
681 } 686 }
682 687
683 ////////////////////////////////////////////////////////////////////////////// 688 //////////////////////////////////////////////////////////////////////////////
684 #ifdef SK_DEBUG 689 #ifdef SK_DEBUG
685 // Is this ring convex? 690 // Is this ring convex?
686 bool GrAAConvexTessellator::Ring::isConvex(const GrAAConvexTessellator& tess) co nst { 691 bool GrAAFlatteningConvexTessellator::Ring::isConvex(const GrAAFlatteningConvexT essellator& tess) const {
687 if (fPts.count() < 3) { 692 if (fPts.count() < 3) {
688 return false; 693 return false;
689 } 694 }
690 695
691 SkPoint prev = tess.point(fPts[0].fIndex) - tess.point(fPts.top().fIndex); 696 SkPoint prev = tess.point(fPts[0].fIndex) - tess.point(fPts.top().fIndex);
692 SkPoint cur = tess.point(fPts[1].fIndex) - tess.point(fPts[0].fIndex); 697 SkPoint cur = tess.point(fPts[1].fIndex) - tess.point(fPts[0].fIndex);
693 SkScalar minDot = prev.fX * cur.fY - prev.fY * cur.fX; 698 SkScalar minDot = prev.fX * cur.fY - prev.fY * cur.fX;
694 SkScalar maxDot = minDot; 699 SkScalar maxDot = minDot;
695 700
696 prev = cur; 701 prev = cur;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 } 737 }
733 738
734 if (perpDist < 0.0f) { 739 if (perpDist < 0.0f) {
735 perpDist = -perpDist; 740 perpDist = -perpDist;
736 } else { 741 } else {
737 *sign = 1; 742 *sign = 1;
738 } 743 }
739 return perpDist; 744 return perpDist;
740 } 745 }
741 746
742 SkScalar GrAAConvexTessellator::computeRealDepth(const SkPoint& p) const { 747 SkScalar GrAAFlatteningConvexTessellator::computeRealDepth(const SkPoint& p) con st {
743 SkScalar minDist = SK_ScalarMax; 748 SkScalar minDist = SK_ScalarMax;
744 int closestSign, sign; 749 int closestSign, sign;
745 750
746 for (int edge = 0; edge < fNorms.count(); ++edge) { 751 for (int edge = 0; edge < fNorms.count(); ++edge) {
747 SkScalar dist = capsule_depth(this->point(edge), 752 SkScalar dist = capsule_depth(this->point(edge),
748 this->point((edge+1) % fNorms.count()), 753 this->point((edge+1) % fNorms.count()),
749 p, fSide, &sign); 754 p, fSide, &sign);
750 SkASSERT(dist >= 0.0f); 755 SkASSERT(dist >= 0.0f);
751 756
752 if (minDist > dist) { 757 if (minDist > dist) {
753 minDist = dist; 758 minDist = dist;
754 closestSign = sign; 759 closestSign = sign;
755 } 760 }
756 } 761 }
757 762
758 return closestSign * minDist; 763 return closestSign * minDist;
759 } 764 }
760 765
761 // Verify that the incrementally computed depths are close to the actual depths. 766 // Verify that the incrementally computed depths are close to the actual depths.
762 void GrAAConvexTessellator::checkAllDepths() const { 767 void GrAAFlatteningConvexTessellator::checkAllDepths() const {
763 for (int cur = 0; cur < this->numPts(); ++cur) { 768 for (int cur = 0; cur < this->numPts(); ++cur) {
764 SkScalar realDepth = this->computeRealDepth(this->point(cur)); 769 SkScalar realDepth = this->computeRealDepth(this->point(cur));
765 SkScalar computedDepth = this->depth(cur); 770 SkScalar computedDepth = this->depth(cur);
766 SkASSERT(SkScalarNearlyEqual(realDepth, computedDepth, 0.01f)); 771 SkASSERT(SkScalarNearlyEqual(realDepth, computedDepth, 0.01f));
767 } 772 }
768 } 773 }
769 #endif 774 #endif
770 775
776 #define kQuadTolerance 0.2f
777 #define kCubicTolerance 0.2f
778 #define kConicTolerance 0.5f
779
780 void GrAAFlatteningConvexTessellator::lineTo(const SkMatrix& m, SkPoint p, bool isCurve) {
781 m.mapPoints(&p, 1);
782 if (this->numPts() > 0 && duplicate_pt(p, this->lastPoint())) {
783 return;
784 }
785
786 SkASSERT(fPts.count() <= 1 || fPts.count() == fNorms.count()+1);
787 if (this->numPts() >= 2 &&
788 abs_dist_from_line(fPts.top(), fNorms.top(), p) < kClose) {
789 // The old last point is on the line from the second to last to the new point
790 this->popLastPt();
791 fNorms.pop();
792 fIsCurve.pop();
793 }
794 this->addPt(p, 0.0f, false, isCurve);
795 if (this->numPts() > 1) {
796 *fNorms.push() = fPts.top() - fPts[fPts.count()-2];
797 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms.top());
798 SkASSERT(len > 0.0f);
799 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms.top().length()));
800 }
801 }
802
803 void GrAAFlatteningConvexTessellator::quadTo(const SkMatrix& m, SkPoint* pts) {
804 int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance);
805 fPointBuffer.setReserve(maxCount);
806 SkPoint* target = fPointBuffer.begin();
807 int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2],
808 kQuadTolerance, &target, maxCount);
809 fPointBuffer.setCount(count);
810 for (int i = 0; i < count; i++) {
811 lineTo(m, fPointBuffer[i], true);
812 }
813 }
814
815 void GrAAFlatteningConvexTessellator::cubicTo(const SkMatrix& m, SkPoint* pts) {
816 int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance);
817 fPointBuffer.setReserve(maxCount);
818 SkPoint* target = fPointBuffer.begin();
819 int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3],
820 kCubicTolerance, &target, maxCount);
821 fPointBuffer.setCount(count);
822 for (int i = 0; i < count; i++) {
823 lineTo(m, fPointBuffer[i], true);
824 }
825 }
826
827 // include down here to avoid compilation errors caused by "-" overload in SkGeo metry.h
bsalomon 2015/05/27 17:11:07 What's the error?
ethannicholas 2015/05/27 19:22:30 In file included from ../../src/gpu/GrAAFlattening
828 #include "SkGeometry.h"
829
830 void GrAAFlatteningConvexTessellator::conicTo(const SkMatrix& m, SkPoint* pts, S kScalar w) {
831 SkAutoConicToQuads quadder;
832 const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance);
833 SkPoint lastPoint = *(quads++);
834 int count = quadder.countQuads();
835 for (int i = 0; i < count; ++i) {
836 SkPoint quadPts[3];
837 quadPts[0] = lastPoint;
838 quadPts[1] = quads[0];
839 quadPts[2] = i == count - 1 ? pts[2] : quads[1];
840 quadTo(m, quadPts);
841 lastPoint = quadPts[2];
842 quads += 2;
843 }
844 }
845
771 ////////////////////////////////////////////////////////////////////////////// 846 //////////////////////////////////////////////////////////////////////////////
772 #if GR_AA_CONVEX_TESSELLATOR_VIZ 847 #if GR_AA_FLATTENING_CONVEX_TESSELLATOR_VIZ
773 static const SkScalar kPointRadius = 0.02f; 848 static const SkScalar kPointRadius = 0.02f;
774 static const SkScalar kArrowStrokeWidth = 0.0f; 849 static const SkScalar kArrowStrokeWidth = 0.0f;
775 static const SkScalar kArrowLength = 0.2f; 850 static const SkScalar kArrowLength = 0.2f;
776 static const SkScalar kEdgeTextSize = 0.1f; 851 static const SkScalar kEdgeTextSize = 0.1f;
777 static const SkScalar kPointTextSize = 0.02f; 852 static const SkScalar kPointTextSize = 0.02f;
778 853
779 static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) { 854 static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue, bool stroke) {
780 SkPaint paint; 855 SkPaint paint;
781 SkASSERT(paramValue <= 1.0f); 856 SkASSERT(paramValue <= 1.0f);
782 int gs = int(255*paramValue); 857 int gs = int(255*paramValue);
(...skipping 22 matching lines...) Expand all
805 SkPaint paint; 880 SkPaint paint;
806 paint.setColor(color); 881 paint.setColor(color);
807 paint.setStrokeWidth(kArrowStrokeWidth); 882 paint.setStrokeWidth(kArrowStrokeWidth);
808 paint.setStyle(SkPaint::kStroke_Style); 883 paint.setStyle(SkPaint::kStroke_Style);
809 884
810 canvas->drawLine(p.fX, p.fY, 885 canvas->drawLine(p.fX, p.fY,
811 p.fX + len * n.fX, p.fY + len * n.fY, 886 p.fX + len * n.fX, p.fY + len * n.fY,
812 paint); 887 paint);
813 } 888 }
814 889
815 void GrAAConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAConvexTessell ator& tess) const { 890 void GrAAFlatteningConvexTessellator::Ring::draw(SkCanvas* canvas, const GrAAFla tteningConvexTessellator& tess) const {
bsalomon 2015/05/27 17:11:07 nit, 100 col wrap
ethannicholas 2015/05/27 19:22:30 Done.
816 SkPaint paint; 891 SkPaint paint;
817 paint.setTextSize(kEdgeTextSize); 892 paint.setTextSize(kEdgeTextSize);
818 893
819 for (int cur = 0; cur < fPts.count(); ++cur) { 894 for (int cur = 0; cur < fPts.count(); ++cur) {
820 int next = (cur + 1) % fPts.count(); 895 int next = (cur + 1) % fPts.count();
821 896
822 draw_line(canvas, 897 draw_line(canvas,
823 tess.point(fPts[cur].fIndex), 898 tess.point(fPts[cur].fIndex),
824 tess.point(fPts[next].fIndex), 899 tess.point(fPts[next].fIndex),
825 SK_ColorGREEN); 900 SK_ColorGREEN);
(...skipping 11 matching lines...) Expand all
837 num.printf("%d", this->origEdgeID(cur)); 912 num.printf("%d", this->origEdgeID(cur));
838 canvas->drawText(num.c_str(), num.size(), mid.fX, mid.fY, paint); 913 canvas->drawText(num.c_str(), num.size(), mid.fX, mid.fY, paint);
839 914
840 if (fPts.count()) { 915 if (fPts.count()) {
841 draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector , 916 draw_arrow(canvas, tess.point(fPts[cur].fIndex), fPts[cur].fBisector ,
842 kArrowLength, SK_ColorBLUE); 917 kArrowLength, SK_ColorBLUE);
843 } 918 }
844 } 919 }
845 } 920 }
846 921
847 void GrAAConvexTessellator::draw(SkCanvas* canvas) const { 922 void GrAAFlatteningConvexTessellator::draw(SkCanvas* canvas) const {
848 for (int i = 0; i < fIndices.count(); i += 3) { 923 for (int i = 0; i < fIndices.count(); i += 3) {
849 SkASSERT(fIndices[i] < this->numPts()) ; 924 SkASSERT(fIndices[i] < this->numPts()) ;
850 SkASSERT(fIndices[i+1] < this->numPts()) ; 925 SkASSERT(fIndices[i+1] < this->numPts()) ;
851 SkASSERT(fIndices[i+2] < this->numPts()) ; 926 SkASSERT(fIndices[i+2] < this->numPts()) ;
852 927
853 draw_line(canvas, 928 draw_line(canvas,
854 this->point(this->fIndices[i]), this->point(this->fIndices[i+1 ]), 929 this->point(this->fIndices[i]), this->point(this->fIndices[i+1 ]),
855 SK_ColorBLACK); 930 SK_ColorBLACK);
856 draw_line(canvas, 931 draw_line(canvas,
857 this->point(this->fIndices[i+1]), this->point(this->fIndices[i +2]), 932 this->point(this->fIndices[i+1]), this->point(this->fIndices[i +2]),
(...skipping 23 matching lines...) Expand all
881 SkString num; 956 SkString num;
882 num.printf("%d", i); 957 num.printf("%d", i);
883 canvas->drawText(num.c_str(), num.size(), 958 canvas->drawText(num.c_str(), num.size(),
884 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ), 959 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ),
885 paint); 960 paint);
886 } 961 }
887 } 962 }
888 963
889 #endif 964 #endif
890 965
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698