Index: src/core/SkScan_Path.cpp |
diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp |
index 5d9e0ca2a658ae58d81e84d5ba51edc5bfde00cc..430cd1d8413b27d9f48bf09734adb8cf79578db4 100644 |
--- a/src/core/SkScan_Path.cpp |
+++ b/src/core/SkScan_Path.cpp |
@@ -45,34 +45,23 @@ static inline void remove_edge(SkEdge* edge) { |
edge->fNext->fPrev = edge->fPrev; |
} |
-static inline void swap_edges(SkEdge* prev, SkEdge* next) { |
- SkASSERT(prev->fNext == next && next->fPrev == prev); |
- |
- // remove prev from the list |
- prev->fPrev->fNext = next; |
- next->fPrev = prev->fPrev; |
- |
- // insert prev after next |
- prev->fNext = next->fNext; |
- next->fNext->fPrev = prev; |
- next->fNext = prev; |
- prev->fPrev = next; |
+static inline void insert_edge_after(SkEdge* edge, SkEdge* afterMe) { |
+ edge->fPrev = afterMe; |
+ edge->fNext = afterMe->fNext; |
+ afterMe->fNext->fPrev = edge; |
+ afterMe->fNext = edge; |
} |
static void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) { |
SkFixed x = edge->fX; |
- for (;;) { |
- SkEdge* prev = edge->fPrev; |
- |
- // add 1 to curr_y since we may have added new edges (built from curves) |
- // that start on the next scanline |
- SkASSERT(prev && prev->fFirstY <= curr_y + 1); |
- |
- if (prev->fX <= x) { |
- break; |
- } |
- swap_edges(prev, edge); |
+ SkEdge* prev = edge->fPrev; |
+ while (prev->fX > x) { |
+ prev = prev->fPrev; |
+ } |
+ if (prev->fNext != edge) { |
+ remove_edge(edge); |
+ insert_edge_after(edge, prev); |
} |
} |
@@ -113,7 +102,7 @@ typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); |
static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, |
SkBlitter* blitter, int start_y, int stop_y, |
- PrePostProc proc) { |
+ PrePostProc proc, int rightClip) { |
validate_sort(prevHead->fNext); |
int curr_y = start_y; |
@@ -183,6 +172,14 @@ static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, |
SkASSERT(currE); |
} |
+ // was our right-edge culled away? |
+ if (in_interval) { |
+ int width = rightClip - left; |
+ if (width > 0) { |
+ blitter->blitH(left, curr_y, width); |
+ } |
+ } |
+ |
if (proc) { |
proc(blitter, curr_y, PREPOST_END); // post-proc |
} |
@@ -430,13 +427,15 @@ static SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) { |
// clipRect (if no null) has already been shifted up |
// |
void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter, |
- int start_y, int stop_y, int shiftEdgesUp, |
- const SkRegion& clipRgn) { |
+ int start_y, int stop_y, int shiftEdgesUp, const SkRegion& clipRgn) { |
SkASSERT(blitter); |
SkEdgeBuilder builder; |
- int count = builder.build(path, clipRect, shiftEdgesUp); |
+ // If we're convex, then we need both edges, even the right edge is past the clip |
+ const bool cullToTheRight = !path.isConvex(); |
+ |
+ int count = builder.build(path, clipRect, shiftEdgesUp, cullToTheRight); |
SkEdge** list = builder.edgeList(); |
if (count < 2) { |
@@ -503,7 +502,14 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte |
if (path.isConvex() && (NULL == proc)) { |
walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL); |
} else { |
- walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc); |
+ int rightEdge; |
+ if (clipRect) { |
+ rightEdge = clipRect->right(); |
+ } else { |
+ rightEdge = SkScalarRoundToInt(path.getBounds().right()) << shiftEdgesUp; |
+ } |
+ |
+ walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc, rightEdge); |
} |
} |