OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
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 "SkScanPriv.h" | 8 #include "SkScanPriv.h" |
9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
10 #include "SkEdge.h" | 10 #include "SkEdge.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 } | 38 } |
39 #else | 39 #else |
40 #define validate_sort(edge) | 40 #define validate_sort(edge) |
41 #endif | 41 #endif |
42 | 42 |
43 static inline void remove_edge(SkEdge* edge) { | 43 static inline void remove_edge(SkEdge* edge) { |
44 edge->fPrev->fNext = edge->fNext; | 44 edge->fPrev->fNext = edge->fNext; |
45 edge->fNext->fPrev = edge->fPrev; | 45 edge->fNext->fPrev = edge->fPrev; |
46 } | 46 } |
47 | 47 |
48 static inline void insert_edge_after(SkEdge* edge, SkEdge* afterMe) { | 48 static inline void swap_edges(SkEdge* prev, SkEdge* next) { |
49 edge->fPrev = afterMe; | 49 SkASSERT(prev->fNext == next && next->fPrev == prev); |
50 edge->fNext = afterMe->fNext; | 50 |
51 afterMe->fNext->fPrev = edge; | 51 // remove prev from the list |
52 afterMe->fNext = edge; | 52 prev->fPrev->fNext = next; |
| 53 next->fPrev = prev->fPrev; |
| 54 |
| 55 // insert prev after next |
| 56 prev->fNext = next->fNext; |
| 57 next->fNext->fPrev = prev; |
| 58 next->fNext = prev; |
| 59 prev->fPrev = next; |
53 } | 60 } |
54 | 61 |
55 static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, cur
r_y)) { | 62 static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, cur
r_y)) { |
56 SkFixed x = edge->fX; | 63 SkFixed x = edge->fX; |
57 | 64 |
58 SkEdge* prev = edge->fPrev; | 65 for (;;) { |
59 while (prev->fX > x) { | 66 SkEdge* prev = edge->fPrev; |
60 prev = prev->fPrev; | 67 |
61 } | 68 // add 1 to curr_y since we may have added new edges (built from curves) |
62 if (prev->fNext != edge) { | 69 // that start on the next scanline |
63 remove_edge(edge); | 70 SkASSERT(prev && prev->fFirstY <= curr_y + 1); |
64 insert_edge_after(edge, prev); | 71 |
| 72 if (prev->fX <= x) { |
| 73 break; |
| 74 } |
| 75 swap_edges(prev, edge); |
65 } | 76 } |
66 } | 77 } |
67 | 78 |
68 static void insert_new_edges(SkEdge* newEdge, int curr_y) { | 79 static void insert_new_edges(SkEdge* newEdge, int curr_y) { |
69 SkASSERT(newEdge->fFirstY >= curr_y); | 80 SkASSERT(newEdge->fFirstY >= curr_y); |
70 | 81 |
71 while (newEdge->fFirstY == curr_y) { | 82 while (newEdge->fFirstY == curr_y) { |
72 SkEdge* next = newEdge->fNext; | 83 SkEdge* next = newEdge->fNext; |
73 backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); | 84 backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); |
74 newEdge = next; | 85 newEdge = next; |
(...skipping 20 matching lines...) Expand all Loading... |
95 #pragma warning ( push ) | 106 #pragma warning ( push ) |
96 #pragma warning ( disable : 4701 ) | 107 #pragma warning ( disable : 4701 ) |
97 #endif | 108 #endif |
98 | 109 |
99 typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); | 110 typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); |
100 #define PREPOST_START true | 111 #define PREPOST_START true |
101 #define PREPOST_END false | 112 #define PREPOST_END false |
102 | 113 |
103 static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, | 114 static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, |
104 SkBlitter* blitter, int start_y, int stop_y, | 115 SkBlitter* blitter, int start_y, int stop_y, |
105 PrePostProc proc, int rightClip) { | 116 PrePostProc proc) { |
106 validate_sort(prevHead->fNext); | 117 validate_sort(prevHead->fNext); |
107 | 118 |
108 int curr_y = start_y; | 119 int curr_y = start_y; |
109 // returns 1 for evenodd, -1 for winding, regardless of inverse-ness | 120 // returns 1 for evenodd, -1 for winding, regardless of inverse-ness |
110 int windingMask = (fillType & 1) ? 1 : -1; | 121 int windingMask = (fillType & 1) ? 1 : -1; |
111 | 122 |
112 for (;;) { | 123 for (;;) { |
113 int w = 0; | 124 int w = 0; |
114 int left SK_INIT_TO_AVOID_WARNING; | 125 int left SK_INIT_TO_AVOID_WARNING; |
115 bool in_interval = false; | 126 bool in_interval = false; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 if (newX < prevX) { // ripple currE backwards until it is x-sort
ed | 176 if (newX < prevX) { // ripple currE backwards until it is x-sort
ed |
166 backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); | 177 backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); |
167 } else { | 178 } else { |
168 prevX = newX; | 179 prevX = newX; |
169 } | 180 } |
170 } | 181 } |
171 currE = next; | 182 currE = next; |
172 SkASSERT(currE); | 183 SkASSERT(currE); |
173 } | 184 } |
174 | 185 |
175 // was our right-edge culled away? | |
176 if (in_interval) { | |
177 int width = rightClip - left; | |
178 if (width > 0) { | |
179 blitter->blitH(left, curr_y, width); | |
180 } | |
181 } | |
182 | |
183 if (proc) { | 186 if (proc) { |
184 proc(blitter, curr_y, PREPOST_END); // post-proc | 187 proc(blitter, curr_y, PREPOST_END); // post-proc |
185 } | 188 } |
186 | 189 |
187 curr_y += 1; | 190 curr_y += 1; |
188 if (curr_y >= stop_y) { | 191 if (curr_y >= stop_y) { |
189 break; | 192 break; |
190 } | 193 } |
191 // now currE points to the first edge with a Yint larger than curr_y | 194 // now currE points to the first edge with a Yint larger than curr_y |
192 insert_new_edges(currE, curr_y); | 195 insert_new_edges(currE, curr_y); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 // | 429 // |
427 // clipRect (if no null) has already been shifted up | 430 // clipRect (if no null) has already been shifted up |
428 // | 431 // |
429 void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
r, | 432 void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte
r, |
430 int start_y, int stop_y, int shiftEdgesUp, | 433 int start_y, int stop_y, int shiftEdgesUp, |
431 const SkRegion& clipRgn) { | 434 const SkRegion& clipRgn) { |
432 SkASSERT(blitter); | 435 SkASSERT(blitter); |
433 | 436 |
434 SkEdgeBuilder builder; | 437 SkEdgeBuilder builder; |
435 | 438 |
436 // If we're convex, then we need both edges, even the right edge is past the
clip | 439 int count = builder.build(path, clipRect, shiftEdgesUp); |
437 const bool cullToTheRight = !path.isConvex(); | |
438 | |
439 int count = builder.build(path, clipRect, shiftEdgesUp, cullToTheRight); | |
440 SkEdge** list = builder.edgeList(); | 440 SkEdge** list = builder.edgeList(); |
441 | 441 |
442 if (count < 2) { | 442 if (count < 2) { |
443 if (path.isInverseFillType()) { | 443 if (path.isInverseFillType()) { |
444 /* | 444 /* |
445 * Since we are in inverse-fill, our caller has already drawn above | 445 * Since we are in inverse-fill, our caller has already drawn above |
446 * our top (start_y) and will draw below our bottom (stop_y). Thus | 446 * our top (start_y) and will draw below our bottom (stop_y). Thus |
447 * we need to restrict our drawing to the intersection of the clip | 447 * we need to restrict our drawing to the intersection of the clip |
448 * and those two limits. | 448 * and those two limits. |
449 */ | 449 */ |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 | 493 |
494 InverseBlitter ib; | 494 InverseBlitter ib; |
495 PrePostProc proc = NULL; | 495 PrePostProc proc = NULL; |
496 | 496 |
497 if (path.isInverseFillType()) { | 497 if (path.isInverseFillType()) { |
498 ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); | 498 ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); |
499 blitter = &ib; | 499 blitter = &ib; |
500 proc = PrePostInverseBlitterProc; | 500 proc = PrePostInverseBlitterProc; |
501 } | 501 } |
502 | 502 |
503 int rightEdge; | |
504 if (clipRect) { | |
505 rightEdge = clipRect->right(); | |
506 } else { | |
507 rightEdge = SkScalarRoundToInt(path.getBounds().right()); | |
508 } | |
509 | |
510 if (path.isConvex() && (NULL == proc)) { | 503 if (path.isConvex() && (NULL == proc)) { |
511 walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_
y, NULL); | 504 walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_
y, NULL); |
512 } else { | 505 } else { |
513 walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc
, rightEdge); | 506 walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc
); |
514 } | 507 } |
515 } | 508 } |
516 | 509 |
517 void sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip)
{ | 510 void sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip)
{ |
518 const SkIRect& cr = clip.getBounds(); | 511 const SkIRect& cr = clip.getBounds(); |
519 SkIRect tmp; | 512 SkIRect tmp; |
520 | 513 |
521 tmp.fLeft = cr.fLeft; | 514 tmp.fLeft = cr.fLeft; |
522 tmp.fRight = cr.fRight; | 515 tmp.fRight = cr.fRight; |
523 tmp.fTop = cr.fTop; | 516 tmp.fTop = cr.fTop; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 clipRgn = &wrap.getRgn(); | 724 clipRgn = &wrap.getRgn(); |
732 blitter = wrap.getBlitter(); | 725 blitter = wrap.getBlitter(); |
733 } | 726 } |
734 | 727 |
735 SkScanClipper clipper(blitter, clipRgn, ir); | 728 SkScanClipper clipper(blitter, clipRgn, ir); |
736 blitter = clipper.getBlitter(); | 729 blitter = clipper.getBlitter(); |
737 if (blitter) { | 730 if (blitter) { |
738 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); | 731 sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); |
739 } | 732 } |
740 } | 733 } |
OLD | NEW |