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

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

Issue 1120023003: Refugee from Dead Machine 13: New version of the convex AA tessellator Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: update Created 4 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
« no previous file with comments | « src/gpu/GrAAConvexTessellator.h ('k') | src/gpu/GrAARectRenderer.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #include "GrAAConvexTessellator.h"
9 #include "SkCanvas.h"
10 #include "SkPath.h"
11 #include "SkPoint.h"
12 #include "SkString.h"
13
14 // Next steps:
15 // use in AAConvexPathRenderer
16 // add an interactive sample app slide
17 // add debug check that all points are suitably far apart
18 // test more degenerate cases
19
20 // 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 kCloseSqd = SkScalarMul(kClose, kClose);
23
24 static void intersect2(const SkPoint& p0, const SkPoint& n0,
25 const SkPoint& p1, const SkPoint& n1,
26 SkScalar* t0) {
27 SkASSERT(SkScalarNearlyEqual(n0.lengthSqd(), 1.0f));
28 SkASSERT(SkScalarNearlyEqual(n1.lengthSqd(), 1.0f));
29
30 const SkPoint v = p1 - p0;
31
32 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX;
33 *t0 = (v.fX * n1.fY - v.fY * n1.fX) / perpDot;
34
35 if (*t0 < 0.0f) {
36 *t0 = 100000;
37 }
38 // SkASSERT(*t0 >= 0.0f);
39 }
40
41 static void intersect(const SkPoint& p0, const SkPoint& n0,
42 const SkPoint& p1, const SkPoint& n1,
43 SkScalar* t0, SkScalar* t1) {
44 SkASSERT(SkScalarNearlyEqual(n0.lengthSqd(), 1.0f));
45 SkASSERT(SkScalarNearlyEqual(n1.lengthSqd(), 1.0f));
46
47 const SkPoint v = p1 - p0;
48
49 SkScalar perpDot = n0.fX * n1.fY - n0.fY * n1.fX;
50 *t0 = (v.fX * n1.fY - v.fY * n1.fX) / perpDot;
51 *t1 = (v.fX * n0.fY - v.fY * n0.fX) / perpDot;
52
53 SkASSERT(*t0 >= 0.0f && *t1 >= 0.0f);
54 }
55
56 // This is a special case version of intersect where we have the vector
57 // perpendicular to the second line rather than the vector parallel to it.
58 static SkScalar perp_intersect(const SkPoint& p0, const SkPoint& n0,
59 const SkPoint& p1, const SkPoint& perp) {
60 SkASSERT(SkScalarNearlyEqual(n0.lengthSqd(), 1.0f));
61 SkASSERT(SkScalarNearlyEqual(perp.lengthSqd(), 1.0f));
62
63 const SkPoint v = p1 - p0;
64 SkScalar perpDot = n0.dot(perp);
65 return v.dot(perp) / perpDot;
66 }
67
68 static bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) {
69 SkScalar distSq = p0.distanceToSqd(p1);
70 return distSq < kCloseSqd;
71 }
72
73 static SkScalar abs_dist_from_line(const SkPoint& p0, const SkPoint& p1, const S kPoint& test) {
74 // TODO: update this to use the normals computed for a ring rather than reco mputing
75 SkPoint v = p1 - p0;
76 v.normalize();
77
78 SkPoint testV = test - p0;
79 SkScalar dist = testV.fX * v.fY - testV.fY * v.fX;
80 return SkScalarAbs(dist);
81 }
82
83 int GrAAConvexTessellator::addPt(const SkPoint& pt, SkScalar depth) {
84 this->validate();
85
86 int index = fPts.count();
87 *fPts.push() = pt;
88 *fDepths.push() = depth;
89
90 this->validate();
91 return index;
92 }
93
94 void GrAAConvexTessellator::popLastPt() {
95 this->validate();
96
97 fPts.pop();
98 fDepths.pop();
99
100 this->validate();
101 }
102
103 void GrAAConvexTessellator::popFirstPtShuffle() {
104 this->validate();
105
106 fPts.removeShuffle(0);
107 fDepths.removeShuffle(0);
108
109 this->validate();
110 }
111
112 void GrAAConvexTessellator::addTri(int i0, int i1, int i2) {
113 if (i0 == i1 || i1 == i2 || i2 == i0) {
114 return;
115 }
116
117 *fIndices.push() = i0;
118 *fIndices.push() = i1;
119 *fIndices.push() = i2;
120 }
121
122 void GrAAConvexTessellator::rewind() {
123 fPts.rewind();
124 fDepths.rewind();
125 fIndices.rewind();
126 fNorms.rewind();
127 fBisectors.rewind();
128
129 fPQueue.rewind();
130 fVerts1.rewind();
131 }
132
133 void GrAAConvexTessellator::computeNormals() {
134 int numPts = this->numPts();
135
136 fNorms.setCount(numPts);
137
138 for (int cur = 0; cur < numPts; ++cur) {
139 int next = (cur + 1) % numPts;
140
141 fNorms[cur] = fPts[next] - fPts[cur];
142 SkDEBUGCODE(SkScalar len =) SkPoint::Normalize(&fNorms[cur]);
143 SkASSERT(len > 0.0f);
144 fNorms[cur].setOrthog(fNorms[cur], fSide);
145
146 SkASSERT(SkScalarNearlyEqual(1.0f, fNorms[cur].length()));
147 }
148 }
149
150 void GrAAConvexTessellator::computeBisectors() {
151 fBisectors.setCount(fNorms.count());
152
153 int prev = fBisectors.count() - 1;
154 for (int cur = 0; cur < fBisectors.count(); prev = cur, ++cur) {
155 fBisectors[cur] = fNorms[cur] + fNorms[prev];
156 fBisectors[cur].normalize();
157 fBisectors[cur].negate(); // make the bisector face in
158
159 SkASSERT(SkScalarNearlyEqual(1.0f, fBisectors[cur].length()));
160 }
161 }
162
163 // The general idea here is to, conceptually, start with the original polygon an d slide
164 // the vertices along the bisectors until the first intersection. At that
165 // point two of the edges collapse and the process repeats on the new polygon.
166 bool GrAAConvexTessellator::tessellate(const SkMatrix& m, const SkPath& path) {
167 if (!this->extractFromPath(m, path)) {
168 return false;
169 }
170
171 this->computeNormals();
172 this->computeBisectors();
173 this->initPQueue();
174
175 this->createOuterRing();
176 this->createInsetRing();
177
178 this->validate();
179 SkDEBUGCODE(this->checkAllDepths();)
180 return true;
181 }
182
183 SkScalar GrAAConvexTessellator::computeDepthFromEdge(int edgeIdx, const SkPoint& p) const {
184 SkASSERT(edgeIdx < fNorms.count());
185
186 SkPoint v = p - fPts[edgeIdx];
187 SkScalar depth = -fNorms[edgeIdx].dot(v);
188 SkASSERT(depth >= 0.0f);
189 return depth;
190 }
191
192 // Find a point that is 'desiredDepth' away from the 'edgeIdx'-th edge and lies
193 // along the 'bisector' from the 'startIdx'-th point.
194 SkPoint GrAAConvexTessellator::computePtAlongBisector(int startIdx,
195 const SkVector& bisector,
196 int edgeIdx,
197 SkScalar desiredDepth) con st {
198 const SkPoint& norm = fNorms[edgeIdx];
199
200 // First find the point where the edge and the bisector intersect
201 SkPoint newP;
202 SkScalar t = perp_intersect(fPts[startIdx], bisector, fPts[edgeIdx], norm);
203 if (SkScalarNearlyEqual(t, 0.0f)) {
204 // the start point was one of the original ring points
205 SkASSERT(startIdx < fNorms.count());
206 newP = fPts[startIdx];
207 } else {
208 SkASSERT(t < 0.0f);
209 newP = bisector;
210 newP.scale(t);
211 newP += fPts[startIdx];
212 }
213
214 // Then offset along the bisector from that point the correct distance
215 t = -desiredDepth / bisector.dot(norm);
216 SkASSERT(t > 0.0f);
217 SkPoint result = bisector;
218 result.scale(t);
219 result += newP;
220
221 return result;
222 }
223
224 bool GrAAConvexTessellator::extractFromPath(const SkMatrix& m, const SkPath& pat h) {
225 SkASSERT(SkPath::kLine_SegmentMask == path.getSegmentMasks());
226 SkASSERT(SkPath::kConvex_Convexity == path.getConvexity());
227
228 // Outer ring: 3*numPts
229 // Middle ring: numPts
230 // Presumptive inner ring: numPts
231 this->reservePts(5*path.countPoints());
232 // Outer ring: 12*numPts
233 // Middle ring: 0
234 // Presumptive inner ring: 6*numPts + 6
235 fIndices.setReserve(18*path.countPoints() + 6);
236
237 SkScalar minCross = SK_ScalarMax, maxCross = -SK_ScalarMax;
238
239 SkPath::Iter iter(path, true);
240 SkPoint pts[4];
241 SkPath::Verb verb;
242 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
243 switch (verb) {
244 case SkPath::kLine_Verb:
245 m.mapPoints(&pts[1], 1);
246 if (this->numPts() > 0 && duplicate_pt(pts[1], fPts.top())) {
247 continue;
248 }
249
250 if (this->numPts() >= 2 &&
251 abs_dist_from_line(fPts[this->numPts()-1], fPts[this->numPts ()-2], pts[1]) <
252 kClose) {
253 // The old last point is on the line from the second to last to the new point
254 this->popLastPt();
255 }
256
257 this->addPt(pts[1], 0.0f);
258
259 if (this->numPts() >= 3) {
260 int cur = this->numPts()-1;
261
262 SkScalar cross = SkPoint::CrossProduct(fPts[cur] - fPts[cur- 1],
263 fPts[cur-1] - fPts[cu r-2]);
264 if (maxCross < cross) {
265 maxCross = cross;
266 }
267 if (minCross > cross) {
268 minCross = cross;
269 }
270 }
271 break;
272 case SkPath::kQuad_Verb:
273 case SkPath::kConic_Verb:
274 case SkPath::kCubic_Verb:
275 SkASSERT(false);
276 break;
277 case SkPath::kMove_Verb:
278 case SkPath::kClose_Verb:
279 case SkPath::kDone_Verb:
280 break;
281 }
282 }
283
284 if (!this->numPts()) {
285 return false;
286 }
287
288 // check if last point is a duplicate of the first point. If so, remove it.
289 if (duplicate_pt(fPts[this->numPts()-1], fPts[0])) {
290 this->popLastPt();
291 }
292
293 if (this->numPts() >= 3 &&
294 abs_dist_from_line(fPts[this->numPts()-1], fPts[this->numPts()-2], fPts[ 0]) < kClose) {
295 // The last point is on the line from the second to last to the first po int.
296 this->popLastPt();
297 }
298
299 if (this->numPts() >= 3 &&
300 abs_dist_from_line(fPts[0], fPts[this->numPts()-1], fPts[1]) < kClose) {
301 // The first point is on the line from the last to the second.
302 this->popFirstPtShuffle();
303 }
304
305 if (this->numPts() < 3) {
306 return false;
307 }
308
309 // Check the cross produce of the final trio
310 SkScalar cross = SkPoint::CrossProduct(fPts[1] - fPts[0], fPts[0] - fPts[fPt s.count()-1]);
311 if (maxCross < cross) {
312 maxCross = cross;
313 }
314 if (minCross > cross) {
315 minCross = cross;
316 }
317
318 if (maxCross > 0.0f) {
319 SkASSERT(minCross >= 0.0f);
320 fSide = SkPoint::kRight_Side;
321 } else {
322 SkASSERT(minCross <= 0.0f);
323 fSide = SkPoint::kLeft_Side;
324 }
325
326 this->validate();
327 return true;
328 }
329
330 void GrAAConvexTessellator::createOuterRing() {
331 // For now, we're only generating one outer ring (at the start). This
332 // could be relaxed for stroking use cases.
333 SkASSERT(0 == fIndices.count());
334 SkASSERT(fPts.count() == fNorms.count());
335
336 const int numPts = fPts.count();
337
338 // For each vertex of the original polygon we add three points to the
339 // outset polygon - one extending perpendicular to each impinging edge
340 // and one along the bisector. Two triangles are added for each corner
341 // and two are added along each edge.
342 int prev = numPts - 1;
343 int lastPerpIdx = -1, firstPerpIdx, newIdx0, newIdx1, newIdx2;
344 for (int cur = 0; cur < numPts; ++cur) {
345 // The perpendicular point for the last edge
346 SkPoint temp = fNorms[prev];
347 temp.scale(fTargetDepth);
348 temp += fPts[cur];
349
350 // We know it isn't a duplicate of the prior point (since it and this
351 // one are just perpendicular offsets from the non-merged polygon points )
352 newIdx0 = this->addPt(temp, -fTargetDepth);
353
354 // The bisector outset point
355 temp = fBisectors[cur];
356 temp.scale(-fTargetDepth); // the bisectors point in
357 temp += fPts[cur];
358
359 // For very shallow angles all the corner points could fuse
360 if (duplicate_pt(temp, fPts[newIdx0])) {
361 newIdx1 = newIdx0;
362 } else {
363 newIdx1 = this->addPt(temp, -fTargetDepth);
364 }
365
366 // The perpendicular point for the next edge.
367 temp = fNorms[cur];
368 temp.scale(fTargetDepth);
369 temp += fPts[cur];
370
371 // For very shallow angles all the corner points could fuse.
372 if (duplicate_pt(temp, fPts[newIdx1])) {
373 newIdx2 = newIdx1;
374 } else {
375 newIdx2 = this->addPt(temp, -fTargetDepth);
376 }
377
378 if (0 == cur) {
379 // Store the index of the first perpendicular point to finish up
380 firstPerpIdx = newIdx0;
381 SkASSERT(-1 == lastPerpIdx);
382 } else {
383 // The triangles for the previous edge
384 this->addTri(prev, newIdx0, cur);
385 this->addTri(prev, lastPerpIdx, newIdx0);
386 }
387
388 // The two triangles for the corner
389 this->addTri(cur, newIdx0, newIdx1);
390 this->addTri(cur, newIdx1, newIdx2);
391
392 prev = cur;
393 // Track the last perpendicular outset point so we can construct the
394 // trailing edge triangles.
395 lastPerpIdx = newIdx2;
396 }
397
398 // pick up the final edge rect
399 this->addTri(numPts-1, firstPerpIdx, 0);
400 this->addTri(numPts-1, lastPerpIdx, firstPerpIdx);
401
402 this->validate();
403 }
404
405
406 void GrAAConvexTessellator::stepAllIn() {
407 #if 1
408 //SkASSERT(fPQueue.count() >= 3);
409
410 // 'dst' is the index into the vertex array each point in the last ring
411 // maps to/transforms into in the next ring.
412 SkTDArray<int> dst;
413 dst.setCount(fVerts1.count());
414 SkTDArray<SkPoint> pts;
415 pts.setReserve(fVerts1.count());
416
417 GrVertInfo* first = &fVerts1[0];
418
419 // Check on the first point (who compares with no one)
420 SkPoint newPt = this->computePtAlongBisector(first->originatingPt(),
421 first->bisector(),
422 first->edgeId(),
423 fTargetDepth);
424 dst[0] = 0;
425 *pts.push() = newPt;
426
427 GrVertInfo* cur;
428 int i;
429 // Handle the middle points (who only compare with the prior point)
430 for (i = 1, cur = first->next(); cur != first->prev(); ++i, cur=cur->next()) {
431 newPt = this->computePtAlongBisector(cur->originatingPt(),
432 cur->bisector(),
433 cur->edgeId(),
434 fTargetDepth);
435 if (!duplicate_pt(newPt, pts.top())) {
436 dst[i] = pts.count();
437 *pts.push() = newPt;
438 } else {
439 dst[i] = pts.count()-1;
440 }
441 }
442 SkASSERT(i == fVerts1.count()-1);
443
444 // Check on the last point (handling the wrap around)
445 newPt = this->computePtAlongBisector(first->prev()->originatingPt(),
446 first->prev()->bisector(),
447 first->prev()->edgeId(),
448 fTargetDepth);
449 bool dupPrev = duplicate_pt(newPt, pts.top());
450 bool dupNext = duplicate_pt(newPt, pts[0]);
451
452 if (!dupPrev && !dupNext) {
453 dst.top() = pts.count();
454 *pts.push() = newPt;
455 } else if (dupPrev && !dupNext) {
456 dst.top() = pts.count()-1;
457 } else if (!dupPrev && dupNext) {
458 dst.top() = 0;
459 } else {
460 bool dupPrevVsNext = duplicate_pt(pts[0], pts.top());
461
462 if (!dupPrevVsNext) {
463 dst.top() = pts.count()-1;
464 } else {
465 if (pts.count() > 1) {
466 pts.pop();
467 }
468
469 dst.top() = 0;
470 dst[dst.count()-2] = 0;
471 }
472 }
473
474 SkTDArray<int> remap; // yuck
475 remap.setCount(pts.count());
476
477 // Fold the new ring's points into the global pool
478 for (int i = 0; i < pts.count(); ++i) {
479 remap[i] = this->addPt(pts[i], fTargetDepth);
480 }
481
482 // 'dst' currently has indices into the ring. Remap these to be indices
483 // into the global pool since the triangulation operates in that space.
484 for (int i = 0; i < dst.count(); ++i) {
485 dst[i] = remap[dst[i]];
486 }
487
488 this->addTri(first->originatingPt(), first->next()->originatingPt(), dst[0]) ;
489 this->addTri(dst[0], first->next()->originatingPt(), dst[1]);
490
491 for (i = 1, cur = first->next(); cur != first; ++i, cur=cur->next()) {
492 this->addTri(cur->originatingPt(), cur->next()->originatingPt(), dst[i]) ;
493 this->addTri(dst[i], cur->next()->originatingPt(), dst[(i+1)%dst.count() ]);
494 }
495
496 // fan out from point 0
497 for (int cur = 1; cur < remap.count()-1; ++cur) {
498 this->addTri(remap[0], remap[cur], remap[cur+1]);
499 }
500 #endif
501 }
502
503 static void add_to_dll(GrCandidateVert* prev, GrCandidateVert* newV, GrCandidate Vert* next) {
504 SkASSERT(newV);
505
506 newV->setPrev(prev);
507 newV->setNext(next);
508
509 if (prev) {
510 prev->setNext(newV);
511 }
512 if (next) {
513 next->setPrev(newV);
514 }
515 }
516
517 static void rm_from_dll(GrCandidateVert* v) {
518 if (v->prev()) {
519 v->prev()->setNext(v->next());
520 }
521 if (v->next()) {
522 v->next()->setPrev(v->prev());
523 }
524 }
525
526 void GrAAConvexTessellator::createCandidate(GrVertInfo* v, GrCandidateVert** pre v,
527 GrCandidateVert* next, bool checkNex t){
528 SkScalar tPrev, tNext;
529 intersect2(this->point(v->originatingPt()), v->bisector(),
530 this->point(v->prev()->originatingPt()), v->prev()->bisector(),
531 &tPrev);
532 intersect2(this->point(v->originatingPt()), v->bisector(),
533 this->point(v->next()->originatingPt()), v->next()->bisector(),
534 &tNext);
535
536 SkScalar t;
537 GrVertInfo* prevSubsumed, *nextSubsumed;
538 if (tPrev < tNext) {
539 t = tPrev;
540 prevSubsumed = v->prev();
541 nextSubsumed = v;
542 } else {
543 t = tNext;
544 prevSubsumed = v;
545 nextSubsumed = v->next();
546 }
547
548 SkPoint newPt = v->bisector();
549 newPt.scale(t);
550 newPt += this->point(v->originatingPt());
551
552 SkScalar depth = this->computeDepthFromEdge(v->edgeId(), newPt);
553
554 if (SkScalarNearlyEqual(depth, (*prev)->depth(), kClose) &&
555 duplicate_pt((*prev)->pt(), newPt)) {
556 (*prev)->setNextSubsumed(v);
557 (*prev)->recomputeBi();
558 return;
559 }
560
561 if (checkNext && SkScalarNearlyEqual(depth, next->depth(), kClose) &&
562 duplicate_pt(next->pt(), newPt)) {
563 next->setPrevSubsumed(v);
564 next->recomputeBi();
565 return;
566 }
567
568 GrCandidateVert* newI = this->get();
569
570 newI->setPt(newPt);
571 newI->setBisector(v->bisector());
572 newI->setDepth(depth);
573 newI->setOriginatingPt(v->originatingPt());
574 newI->setPrevSubsumed(prevSubsumed);
575 newI->setNextSubsumed(nextSubsumed);
576 add_to_dll(*prev, newI, next);
577
578 fPQueue.insert(newI);
579 *prev = newI;
580 }
581
582 void GrAAConvexTessellator::recompute(GrCandidateVert* v) {
583
584 GrVertInfo* from = v->prevSubsumed();
585 GrVertInfo* to = v->nextSubsumed();
586
587 GrCandidateVert* trailing = v->prev();
588 GrCandidateVert* leading = v->next();
589
590 // First retract 'v'
591 rm_from_dll(v);
592 fPQueue.remove(v);
593 this->release(v);
594
595 for (GrVertInfo* cur = from; cur != to; cur = cur->next()) {
596 this->createCandidate(cur, &trailing, leading, false);
597 }
598
599 this->createCandidate(to, &trailing, leading, true);
600 }
601
602 void GrAAConvexTessellator::initPQueue() {
603
604 fVerts1.setCount(fPts.count());
605 fCandidates1.setCount(fPts.count());
606 for (int i = fPts.count()-1; i >= 0; --i) {
607 fCandidates1[i].setOriginatingPt(i);
608 this->release(&fCandidates1[i]);
609 }
610 fPQueue.setReserve(fPts.count());
611
612 int prev = fPts.count()-1;
613 for (int cur = 0; cur < fPts.count(); prev = cur, ++cur) {
614 int next = (cur + 1) % fPts.count();
615
616 fVerts1[cur].setOriginatingPt(cur);
617 fVerts1[cur].setPrev(&fVerts1[prev]);
618 fVerts1[cur].setNext(&fVerts1[next]);
619
620 fVerts1[cur].setBisector(fBisectors[cur]);
621 fVerts1[cur].setEdgeId(cur);
622 }
623
624 SkScalar tTemp, tPrev, tNext;
625 intersect(fPts.top(), fBisectors.top(),
626 fPts[0], fBisectors[0],
627 &tTemp, &tPrev);
628
629 GrCandidateVert* prevI = NULL;
630
631 // Add all the candidate points to a priority queue sorted by the depth of t he first
632 // intersection between the bisector of its originating point and its two ne ighbor's bisectors
633 for (int cur = 0; cur < fPts.count(); ++cur) {
634 int next = (cur + 1) % fPts.count();
635
636 intersect(fPts[cur], fBisectors[cur],
637 fPts[next], fBisectors[next],
638 &tNext, &tTemp);
639
640 SkScalar t;
641 GrVertInfo* prevSubsumed, *nextSubsumed;
642 if (tPrev < tNext) {
643 t = tPrev;
644 prevSubsumed = fVerts1[cur].prev();
645 nextSubsumed = &fVerts1[cur];
646 } else {
647 t = tNext;
648 prevSubsumed = &fVerts1[cur];
649 nextSubsumed = fVerts1[cur].next();
650 }
651
652 SkPoint newPt = fBisectors[cur];
653 newPt.scale(t);
654 newPt += fPts[cur];
655
656 SkScalar depth = this->computeDepthFromEdge(cur, newPt);
657
658 if (prevI && duplicate_pt(prevI->pt(), newPt)) {
659 SkASSERT(SkScalarNearlyEqual(prevI->depth(), depth));
660 // fuse with prior
661 prevI->setNextSubsumed(nextSubsumed);
662 SkVector newBi = prevI->prevSubsumed()->bisector();
663 newBi += prevI->nextSubsumed()->bisector();
664 newBi.normalize();
665 prevI->setBisector(newBi);
666 tPrev = tTemp;
667 continue;
668 }
669
670 GrCandidateVert* newI = this->get();
671
672 newI->setPt(newPt);
673 newI->setBisector(fBisectors[cur]);
674 newI->setDepth(depth);
675 newI->setOriginatingPt(cur);
676 newI->setPrevSubsumed(prevSubsumed);
677 newI->setNextSubsumed(nextSubsumed);
678 add_to_dll(prevI, newI, NULL);
679
680 fPQueue.insert(newI);
681
682 prevI = newI;
683 tPrev = tTemp;
684 }
685
686 prevI->setNext(&fCandidates1[0]);
687 fCandidates1[0].setPrev(prevI);
688
689 if (fCandidates1.count() > 1) {
690 if (duplicate_pt(prevI->pt(), fCandidates1[0].pt())) {
691 SkASSERT(SkScalarNearlyEqual(prevI->depth(), fCandidates1[0].depth() ));
692
693 fCandidates1[0].setPrevSubsumed(prevI->prevSubsumed());
694 SkVector newBi = fCandidates1[0].prevSubsumed()->bisector();
695 newBi += fCandidates1[0].nextSubsumed()->bisector();
696 newBi.normalize();
697 fCandidates1[0].setBisector(newBi);
698 rm_from_dll(prevI);
699 fPQueue.remove(prevI);
700 this->release(prevI);
701 }
702 }
703 }
704
705 static void rm_from_dllV(GrVertInfo* v) {
706 v->prev()->setNext(v->next());
707 v->next()->setPrev(v->prev());
708 v->setNext(NULL);
709 v->setPrev(NULL);
710 }
711
712 static void add_to_dllV(GrVertInfo* v, GrVertInfo* prev, GrVertInfo* next) {
713 v->setPrev(prev);
714 v->setNext(next);
715
716 prev->setNext(v);
717 next->setPrev(v);
718 }
719
720 void GrAAConvexTessellator::removeDups(GrVertInfo* start, int* trailingIdx) {
721 #if 0
722 GrVertInfo* next;
723 for (GrVertInfo* cur = start->next(); cur != start; cur = next) {
724 next = cur->next();
725
726 if (!duplicate_pt(start->newPt(), cur->newPt())) {
727 return; // found a non-duplicate
728 }
729
730 SkASSERT(SkScalarNearlyEqual(start->depth(), cur->depth(), kClose));
731 this->addTri(*trailingIdx, cur->index1(), start->index1());
732 fPQueue.remove(cur);
733 *trailingIdx = cur->index1();
734 rm_from_dll(cur);
735 }
736 #endif
737 }
738
739 void GrAAConvexTessellator::removeDups2(GrVertInfo* start, int* trailingIdx) {
740 #if 0
741 GrVertInfo* prev;
742 for (GrVertInfo* cur = start->next(); cur != start; cur = prev) {
743 prev = cur->prev();
744
745 if (!duplicate_pt(start->newPt(), cur->newPt())) {
746 return; // found a non-duplicate
747 }
748
749 SkASSERT(SkScalarNearlyEqual(start->depth(), cur->depth()));
750 this->addTri(*trailingIdx, cur->index1(), start->index1());
751 fPQueue.remove(cur);
752 *trailingIdx = cur->index1();
753 rm_from_dll(cur);
754 }
755 #endif
756 }
757
758 void GrAAConvexTessellator::createInsetRing() {
759
760 #if 0
761 while (fPQueue.count()) {
762 GrCandidateVert* curI = fPQueue.peek();
763
764 int newIdx = this->addPt(curI->pt(), curI->depth());
765 SkDebugf("newIdx %d\n", newIdx);
766
767 fPQueue.pop();
768 }
769
770 return;
771 #endif
772
773 int floob = 0;
774 while (fPQueue.count() && floob < 4) {
775 floob++;
776
777 GrCandidateVert* curI = fPQueue.peek();
778 fPQueue.pop();
779 rm_from_dll(curI);
780
781 if (curI->depth() >= fTargetDepth) {
782 // None of the bisectors intersect before reaching the desired depth .
783 // Just step them all to the desired depth
784 this->stepAllIn();
785 return;
786 }
787
788
789 int newIdx = this->addPt(curI->pt(), curI->depth());
790
791 GrVertInfo* prev = curI->prevSubsumed();
792 GrVertInfo* next = curI->nextSubsumed();
793 int newEdgeId = next->edgeId();
794 GrVertInfo* pp = prev->prev();
795 GrVertInfo* nn = next->next();
796
797 #if 0
798 SkVector newBisector = prev->bisector();
799 newBisector += next->bisector();
800 newBisector.normalize();
801 #endif
802
803 if (!fPQueue.count()) {
804 GrVertInfo* foo = prev;
805 do {
806 this->addTri(foo->originatingPt(), foo->next()->originatingPt(), newIdx);
807 foo = foo->next();
808 } while (foo != next);
809 return;
810 }
811
812 bool nextNeedsRecompute = false, prevNeedsRecompute = false;
813 if (curI->next()->prevSubsumed() == next) {
814 curI->next()->setPrevSubsumed(nn);
815 nextNeedsRecompute = true;
816 }
817 if (curI->prev()->nextSubsumed() == prev) {
818 curI->prev()->setNextSubsumed(pp);
819 prevNeedsRecompute = true;
820 }
821
822 this->addTri(pp->originatingPt(), pp->next()->originatingPt(), newIdx);
823 this->addTri(nn->prev()->originatingPt(), nn->originatingPt(), newIdx);
824
825 GrVertInfo *cur = prev, *next2;
826 do {
827 next2 = cur->next();
828 this->addTri(cur->originatingPt(), next2->originatingPt(), newIdx);
829 rm_from_dllV(cur);
830 cur = next2;
831 } while (cur != nn);
832
833 GrVertInfo* newV = prev; // recycle prev - let next and all the ones in between lie fallow
834 newV->setOriginatingPt(newIdx);
835 newV->setBisector(curI->bisector());
836 newV->setEdgeId(newEdgeId);
837 add_to_dllV(newV, pp, nn);
838
839 {
840 SkScalar tPrev, tNext;
841 intersect2(curI->pt(), curI->bisector(),
842 this->point(pp->originatingPt()), pp->bisector(),
843 &tPrev);
844 intersect2(curI->pt(), curI->bisector(),
845 this->point(nn->originatingPt()), nn->bisector(),
846 &tNext);
847
848 SkScalar t;
849 GrVertInfo* prevSubsumed, *nextSubsumed;
850 if (tPrev < tNext) {
851 t = tPrev;
852 prevSubsumed = pp;
853 nextSubsumed = newV;
854 } else {
855 t = tNext;
856 prevSubsumed = newV;
857 nextSubsumed = nn;
858 }
859
860 SkPoint newPt = newV->bisector();
861 newPt.scale(t);
862 newPt += this->point(newV->originatingPt());
863
864 SkScalar depth = this->computeDepthFromEdge(newV->edgeId(), newPt);
865
866 if (!prevNeedsRecompute &&
867 SkScalarNearlyEqual(depth, curI->prev()->depth(), kClose) &&
868 duplicate_pt(curI->prev()->pt(), newPt)) {
869 curI->prev()->setNextSubsumed(newV);
870 curI->prev()->recomputeBi();
871 continue;
872 }
873
874 if (!nextNeedsRecompute &&
875 SkScalarNearlyEqual(depth, curI->next()->depth(), kClose) &&
876 duplicate_pt(curI->next()->pt(), newPt)) {
877 curI->next()->setPrevSubsumed(newV);
878 curI->next()->recomputeBi();
879 continue;
880 }
881
882 GrCandidateVert* newI = curI; // recycle curI
883
884 newI->setPt(newPt);
885 newI->setBisector(newV->bisector());
886 newI->setDepth(depth);
887 newI->setOriginatingPt(newIdx);
888 newI->setPrevSubsumed(prevSubsumed);
889 newI->setNextSubsumed(nextSubsumed);
890 add_to_dll(newI->prev(), newI, newI->next());
891
892 fPQueue.insert(newI);
893
894 if (nextNeedsRecompute) {
895 this->recompute(newI->next());
896 }
897 if (prevNeedsRecompute) {
898 this->recompute(newI->prev());
899 }
900 }
901
902 #if 0
903 fPQueue.remove(curVert);
904 fPQueue.remove(otherVert);
905 rm_from_dll(otherVert);
906 #endif
907
908 #if 0
909 int dyingCurIdx = curVert->index1();
910 int newIdx = this->addPt(curVert->newPt(), curVert->depth());
911
912 if (curVert->wasNext()) {
913 this->addTri(dyingCurIdx, otherVert->index1(), newIdx); // tri for t he dying edge
914 } else {
915 this->addTri(otherVert->index1(), dyingCurIdx, newIdx); // tri for t he dying edge
916 }
917
918 curVert->setIndex(newIdx);
919
920 int trailingIdx = curVert->prev()->index1();
921 int leadingIdx = curVert->next()->index1();
922
923 this->removeDups(curVert, &leadingIdx);
924 this->removeDups2(curVert, &trailingIdx);
925
926 if (curVert->wasNext()) {
927 this->addTri(trailingIdx, dyingCurIdx, newIdx);
928 this->addTri(newIdx, otherVert->index1(), leadingIdx);
929 } else {
930 this->addTri(trailingIdx, otherVert->index1(), newIdx);
931 this->addTri(newIdx, dyingCurIdx, leadingIdx);
932 }
933
934 if (fPQueue.count() < 2) {
935 break;
936 }
937
938 curVert->setBisector(newBisector);
939 curVert->setEdgeId(newEdgeId);
940 curVert->computeIntersection(*this);
941
942 fPQueue.insert(curVert);
943 #endif
944 }
945
946 while (fPQueue.count()) {
947 GrCandidateVert* curI = fPQueue.peek();
948
949 int newIdx = this->addPt(curI->pt(), curI->depth());
950 SkDebugf("newIdx %d\n", newIdx);
951
952 fPQueue.pop();
953 }
954
955 }
956
957 void GrAAConvexTessellator::validate() const {
958 SkASSERT(fPts.count() == fDepths.count());
959 SkASSERT(0 == (fIndices.count() % 3));
960 }
961
962 //////////////////////////////////////////////////////////////////////////////
963 void GrVertInfo::updateGeometry(const GrAAConvexTessellator& tess) {
964 SkVector prevV = tess.point(fPrev->originatingPt()) - tess.point(fIndex1);
965 SkVector nextV = tess.point(fNext->originatingPt()) - tess.point(fIndex1);
966
967 nextV.normalize();
968 prevV.normalize();
969 prevV += nextV;
970 fBisector = prevV;
971 fBisector.normalize();
972 }
973
974
975 void GrCandidateVert::recomputeBi() {
976 SkVector newBi = this->prevSubsumed()->bisector();
977 newBi += this->nextSubsumed()->bisector();
978 newBi.normalize();
979 this->setBisector(newBi);
980 }
981
982 void GrCandidateVert::computeIntersection() {
983 #if 0
984 SkScalar tPrev, tNext;
985 intersect2(fPt, fBisector,
986 fPrev->fPt, fPrev->fBisector,
987 &tPrev);
988 intersect2(fPt, fBisector,
989 fNext->fPt, fNext->fBisector,
990 &tNext);
991 SkScalar t = SkMinScalar(tPrev, tNext);
992 if (tPrev < tNext) {
993 fWasNext = false;
994 } else {
995 fWasNext = true;
996 }
997
998 fNewPt = fBisector;
999 fNewPt.scale(t);
1000 fNewPt += tess.point(fIndex1);
1001
1002 fDepth = tess.computeDepthFromEdge(fEdgeId, fNewPt);
1003 #endif
1004 }
1005
1006 #if 0
1007 void GrVertInfo::computeIntersection(const GrAAConvexTessellator& tess) {
1008 SkScalar tPrev, tNext;
1009 intersect2(tess.point(fIndex1), fBisector,
1010 tess.point(fPrev->index1()), fPrev->bisector(),
1011 &tPrev);
1012 intersect2(tess.point(fIndex1), fBisector,
1013 tess.point(fNext->index1()), fNext->bisector(),
1014 &tNext);
1015 SkScalar t = SkMinScalar(tPrev, tNext);
1016 if (tPrev < tNext) {
1017 fWasNext = false;
1018 } else {
1019 fWasNext = true;
1020 }
1021
1022 fNewPt = fBisector;
1023 fNewPt.scale(t);
1024 fNewPt += tess.point(fIndex1);
1025
1026 fDepth = tess.computeDepthFromEdge(fEdgeId, fNewPt);
1027 }
1028 #endif
1029
1030 //////////////////////////////////////////////////////////////////////////////
1031 #ifdef SK_DEBUG
1032 #if 0
1033 // Is this ring convex?
1034 bool GrRing::isConvex(const GrAAConvexTessellator& tess) const {
1035 if (fIndices.count() < 3) {
1036 return false;
1037 }
1038
1039 SkPoint prev = tess.point(fIndices[0]) - tess.point(fIndices[fIndices.count( )-1]);
1040 SkPoint cur = tess.point(fIndices[1]) - tess.point(fIndices[0]);
1041 SkScalar minDot = prev.fX * cur.fY - prev.fY * cur.fX;
1042 SkScalar maxDot = minDot;
1043
1044 prev = cur;
1045 for (int i = 1; i < fIndices.count(); ++i) {
1046 int next = (i + 1) % fIndices.count();
1047
1048 cur = tess.point(fIndices[next]) - tess.point(fIndices[i]);
1049 SkScalar dot = prev.fX * cur.fY - prev.fY * cur.fX;
1050
1051 minDot = SkMinScalar(minDot, dot);
1052 maxDot = SkMaxScalar(maxDot, dot);
1053
1054 prev = cur;
1055 }
1056
1057 return (maxDot > 0.0f) == (minDot >= 0.0f);
1058 }
1059 #endif
1060
1061 static SkScalar capsule_depth(const SkPoint& p0, const SkPoint& p1,
1062 const SkPoint& test, SkPoint::Side side,
1063 int* sign) {
1064 *sign = -1;
1065 SkPoint edge = p1 - p0;
1066 SkScalar len = SkPoint::Normalize(&edge);
1067
1068 SkPoint testVec = test - p0;
1069
1070 SkScalar d0 = edge.dot(testVec);
1071 if (d0 < 0.0f) {
1072 return SkPoint::Distance(p0, test);
1073 }
1074 if (d0 > len) {
1075 return SkPoint::Distance(p1, test);
1076 }
1077
1078 SkScalar perpDist = testVec.fY * edge.fX - testVec.fX * edge.fY;
1079 if (SkPoint::kRight_Side == side) {
1080 perpDist = -perpDist;
1081 }
1082
1083 if (perpDist < 0.0f) {
1084 perpDist = -perpDist;
1085 } else {
1086 *sign = 1;
1087 }
1088 return perpDist;
1089 }
1090
1091 SkScalar GrAAConvexTessellator::computeRealDepth(const SkPoint& p) const {
1092 SkScalar minDist = SK_ScalarMax;
1093 int closestEdge, closestSign, sign;
1094
1095 for (int edge = 0; edge < fNorms.count(); ++edge) {
1096 SkScalar dist = capsule_depth(fPts[edge],
1097 fPts[(edge+1) % fNorms.count()],
1098 p, fSide, &sign);
1099 SkASSERT(dist >= 0.0f);
1100
1101 if (minDist > dist) {
1102 minDist = dist;
1103 closestEdge = edge;
1104 closestSign = sign;
1105 }
1106 }
1107
1108 return closestSign * minDist;
1109 }
1110
1111 // Verify that the incrementally computed depths are close to the actual depths.
1112 void GrAAConvexTessellator::checkAllDepths() const {
1113 for (int cur = 0; cur < this->numPts(); ++cur) {
1114 SkScalar realDepth = this->computeRealDepth(this->point(cur));
1115 realDepth++;
1116 // SkASSERT(SkScalarNearlyEqual(realDepth, this->depth(cur)));
1117 }
1118 }
1119 #endif
1120
1121 //////////////////////////////////////////////////////////////////////////////
1122 #if GR_AA_CONVEX_TESSELLATOR_VIZ
1123 static const SkScalar kPointRadius = 0.02f;
1124 static const SkScalar kArrowStrokeWidth = 0.0f;
1125 static const SkScalar kArrowLength = 0.1f;
1126 static const SkScalar kEdgeTextSize = 0.2f;
1127 static const SkScalar kPointTextSize = 0.02f;
1128
1129 static void draw_point(SkCanvas* canvas, const SkPoint& p, SkScalar paramValue) {
1130 SkPaint paint;
1131 if (paramValue > 1.0f) {
1132 //SkASSERT(0);
1133 paramValue = 1.0f;
1134 }
1135 int gs = int(255*paramValue);
1136 paint.setARGB(255, gs, gs, gs);
1137
1138 canvas->drawCircle(p.fX, p.fY, kPointRadius, paint);
1139 }
1140
1141 static void draw_line(SkCanvas* canvas, const SkPoint& p0, const SkPoint& p1, Sk Color color) {
1142 SkPaint p;
1143 p.setColor(color);
1144
1145 canvas->drawLine(p0.fX, p0.fY, p1.fX, p1.fY, p);
1146 }
1147
1148 static void draw_arrow(SkCanvas*canvas, const SkPoint& p, const SkPoint &n,
1149 SkScalar len, SkColor color) {
1150 SkPaint paint;
1151 paint.setColor(color);
1152 paint.setStrokeWidth(kArrowStrokeWidth);
1153 paint.setStyle(SkPaint::kStroke_Style);
1154
1155 canvas->drawLine(p.fX, p.fY,
1156 p.fX + len * n.fX, p.fY + len * n.fY,
1157 paint);
1158 }
1159
1160 void GrAAConvexTessellator::drawInitialPoly(SkCanvas* canvas) const {
1161 SkPaint paint;
1162 paint.setTextSize(kEdgeTextSize);
1163
1164 for (int cur = 0; cur < fNorms.count(); ++cur) {
1165 int next = (cur + 1) % fNorms.count();
1166
1167 draw_line(canvas, this->point(cur), this->point(next), SK_ColorGREEN);
1168
1169 SkPoint mid = this->point(cur) + this->point(next);
1170 mid.scale(0.5f);
1171
1172 draw_arrow(canvas, mid, fNorms[cur], kArrowLength, SK_ColorRED);
1173 mid.fX += (kArrowLength/2) * fNorms[cur].fX;
1174 mid.fY += (kArrowLength/2) * fNorms[cur].fY;
1175
1176 SkString num;
1177 num.printf("%d", cur);
1178 canvas->drawText(num.c_str(), num.size(), mid.fX, mid.fY, paint);
1179
1180 draw_arrow(canvas, this->point(cur), fBisectors[cur], kArrowLength, SK_C olorBLUE);
1181 }
1182 }
1183
1184 void GrAAConvexTessellator::draw(SkCanvas* canvas) const {
1185 for (int i = 0; i < fIndices.count(); i += 3) {
1186 SkASSERT(fIndices[i] < this->numPts()) ;
1187 SkASSERT(fIndices[i+1] < this->numPts()) ;
1188 SkASSERT(fIndices[i+2] < this->numPts()) ;
1189
1190 draw_line(canvas,
1191 this->point(this->fIndices[i]), this->point(this->fIndices[i+1 ]),
1192 SK_ColorBLACK);
1193 draw_line(canvas,
1194 this->point(this->fIndices[i+1]), this->point(this->fIndices[i +2]),
1195 SK_ColorBLACK);
1196 draw_line(canvas,
1197 this->point(this->fIndices[i+2]), this->point(this->fIndices[i ]),
1198 SK_ColorBLACK);
1199 }
1200
1201 this->drawInitialPoly(canvas);
1202
1203 for (int i = 0; i < this->numPts(); ++i) {
1204 draw_point(canvas,
1205 this->point(i), 0.5f + (this->depth(i)/(2*fTargetDepth)));
1206
1207 SkPaint paint;
1208 paint.setTextSize(kPointTextSize);
1209 paint.setTextAlign(SkPaint::kCenter_Align);
1210 if (this->depth(i) <= -fTargetDepth) {
1211 paint.setColor(SK_ColorWHITE);
1212 }
1213
1214 SkString num;
1215 num.printf("%d", i);
1216 canvas->drawText(num.c_str(), num.size(),
1217 this->point(i).fX, this->point(i).fY+(kPointRadius/2.0f ),
1218 paint);
1219 }
1220 }
1221
1222 #endif
1223
OLDNEW
« no previous file with comments | « src/gpu/GrAAConvexTessellator.h ('k') | src/gpu/GrAARectRenderer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698