From dca6a56b71b922aab32098d6a55bbb041f3a2b48 Mon Sep 17 00:00:00 2001 From: "reed@android.com" Date: Mon, 22 Feb 2010 16:05:48 +0000 Subject: [PATCH] explicitly pass bounds.top to the edgelist walker, so we don't leave any gaps when the path is in an inverse fillmode, and its top or bottom are on a fractional boundary. (thanks senorblanco) git-svn-id: http://skia.googlecode.com/svn/trunk@504 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkScanPriv.h | 2 +- src/core/SkScan_AntiPath.cpp | 4 ++-- src/core/SkScan_Path.cpp | 21 +++++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/core/SkScanPriv.h b/src/core/SkScanPriv.h index 43dfdef486..74c2ee768e 100644 --- a/src/core/SkScanPriv.h +++ b/src/core/SkScanPriv.h @@ -37,7 +37,7 @@ private: // clipRect == null means path is entirely inside the clip void sk_fill_path(const SkPath& path, const SkIRect* clipRect, - SkBlitter* blitter, int stop_y, int shiftEdgesUp, + SkBlitter* blitter, int start_y, int stop_y, int shiftEdgesUp, const SkRegion& clipRgn); // blit the rects above and below avoid, clipped to clp diff --git a/src/core/SkScan_AntiPath.cpp b/src/core/SkScan_AntiPath.cpp index 7b24f73d56..21fd5c99b7 100644 --- a/src/core/SkScan_AntiPath.cpp +++ b/src/core/SkScan_AntiPath.cpp @@ -412,11 +412,11 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip, { MaskSuperBlitter superBlit(blitter, ir, clip); SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); - sk_fill_path(path, superClipRect, &superBlit, ir.fBottom, SHIFT, clip); + sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip); } else { SuperBlitter superBlit(blitter, ir, clip); - sk_fill_path(path, superClipRect, &superBlit, ir.fBottom, SHIFT, clip); + sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, clip); } } diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp index 9751d2a4c3..38f16e61e5 100644 --- a/src/core/SkScan_Path.cpp +++ b/src/core/SkScan_Path.cpp @@ -127,11 +127,12 @@ typedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); #define PREPOST_END false static void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, - SkBlitter* blitter, int stop_y, PrePostProc proc) + SkBlitter* blitter, int start_y, int stop_y, + PrePostProc proc) { validate_sort(prevHead->fNext); - int curr_y = prevHead->fNext->fFirstY; + int curr_y = start_y; // returns 1 for evenodd, -1 for winding, regardless of inverse-ness int windingMask = (fillType & 1) ? 1 : -1; @@ -476,7 +477,7 @@ 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 stop_y, int shiftEdgesUp, const SkRegion& clipRgn) + int start_y, int stop_y, int shiftEdgesUp, const SkRegion& clipRgn) { SkASSERT(&path && blitter); @@ -527,7 +528,11 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte // now edge is the head of the sorted linklist + start_y <<= shiftEdgesUp; stop_y <<= shiftEdgesUp; + if (clipRect && start_y < clipRect->fTop) { + start_y = clipRect->fTop; + } if (clipRect && stop_y > clipRect->fBottom) { stop_y = clipRect->fBottom; } @@ -541,7 +546,7 @@ void sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitte proc = PrePostInverseBlitterProc; } - walk_edges(&headEdge, path.getFillType(), blitter, stop_y, proc); + walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc); } void sk_blit_above_and_below(SkBlitter* blitter, const SkIRect& ir, @@ -625,7 +630,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& clip, if (path.isInverseFillType()) { sk_blit_above_and_below(blitter, ir, clip); } - sk_fill_path(path, clipper.getClipRect(), blitter, ir.fBottom, 0, clip); + sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 0, clip); } else { // what does it mean to not have a blitter if path.isInverseFillType??? } @@ -685,7 +690,11 @@ static void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect, if (clipRect && stop_y > clipRect->fBottom) { stop_y = clipRect->fBottom; } - walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, stop_y, NULL); + int start_y = ir.fTop; + if (clipRect && start_y < clipRect->fTop) { + start_y = clipRect->fTop; + } + walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL); } void SkScan::FillTriangle(const SkPoint pts[], const SkRegion* clip, -- 2.34.1