Index: src/core/SkScan_Hairline.cpp |
diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp |
index 9b21c421edf6c8d8dc57f3df7afa63c953085c69..a023ca1f24f92037a9deacc6475fa4c1d5d23fd7 100644 |
--- a/src/core/SkScan_Hairline.cpp |
+++ b/src/core/SkScan_Hairline.cpp |
@@ -214,7 +214,7 @@ static int compute_int_quad_dist(const SkPoint pts[3]) { |
} |
} |
-static void hairquad(const SkPoint pts[3], const SkRegion* clip, |
+static void hair_quad(const SkPoint pts[3], const SkRegion* clip, |
SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc) { |
SkASSERT(level <= kMaxQuadSubdivideLevel); |
@@ -239,6 +239,54 @@ static void hairquad(const SkPoint pts[3], const SkRegion* clip, |
lineproc(tmp, lines + 1, clip, blitter); |
} |
+static SkRect compute_nocheck_quad_bounds(const SkPoint pts[3]) { |
+ SkASSERT(SkScalarsAreFinite(&pts[0].fX, 6)); |
+ |
+ Sk2s min = Sk2s::Load(pts); |
+ Sk2s max = min; |
+ for (int i = 1; i < 3; ++i) { |
+ Sk2s pair = Sk2s::Load(pts+i); |
+ min = Sk2s::Min(min, pair); |
+ max = Sk2s::Max(max, pair); |
+ } |
+ return { min[0], min[1], max[0], max[1] }; |
+} |
+ |
+static bool is_inverted(const SkRect& r) { |
+ return r.fLeft > r.fRight || r.fTop > r.fBottom; |
+} |
+ |
+// Can't call SkRect::intersects, since it cares about empty, and we don't (since we tracking |
+// something to be stroked, so empty can still draw something (e.g. horizontal line) |
+static bool geometric_overlap(const SkRect& a, const SkRect& b) { |
+ SkASSERT(!is_inverted(a) && !is_inverted(b)); |
+ return a.fLeft < b.fRight && b.fLeft < a.fRight && |
+ a.fTop < b.fBottom && b.fTop < a.fBottom; |
+} |
+ |
+// Can't call SkRect::contains, since it cares about empty, and we don't (since we tracking |
+// something to be stroked, so empty can still draw something (e.g. horizontal line) |
+static bool geometric_contains(const SkRect& outer, const SkRect& inner) { |
+ SkASSERT(!is_inverted(outer) && !is_inverted(inner)); |
+ return inner.fRight <= outer.fRight && inner.fLeft >= outer.fLeft && |
+ inner.fBottom <= outer.fBottom && inner.fTop >= outer.fTop; |
+} |
+ |
+static inline void hairquad(const SkPoint pts[3], const SkRegion* clip, const SkRect* insetClip, const SkRect* outsetClip, |
+ SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc) { |
+ if (insetClip) { |
+ SkASSERT(outsetClip); |
+ SkRect bounds = compute_nocheck_quad_bounds(pts); |
+ if (!geometric_overlap(*outsetClip, bounds)) { |
+ return; |
+ } else if (geometric_contains(*insetClip, bounds)) { |
+ clip = nullptr; |
+ } |
+ } |
+ |
+ hair_quad(pts, clip, blitter, level, lineproc); |
+} |
+ |
static inline Sk2s abs(const Sk2s& value) { |
return Sk2s::Max(value, Sk2s(0)-value); |
} |
@@ -329,54 +377,16 @@ static SkRect compute_nocheck_cubic_bounds(const SkPoint pts[4]) { |
return { min[0], min[1], max[0], max[1] }; |
} |
-static bool is_inverted(const SkRect& r) { |
- return r.fLeft > r.fRight || r.fTop > r.fBottom; |
-} |
- |
-// Can't call SkRect::intersects, since it cares about empty, and we don't (since we tracking |
-// something to be stroked, so empty can still draw something (e.g. horizontal line) |
-static bool geometric_overlap(const SkRect& a, const SkRect& b) { |
- SkASSERT(!is_inverted(a) && !is_inverted(b)); |
- return a.fLeft < b.fRight && b.fLeft < a.fRight && |
- a.fTop < b.fBottom && b.fTop < a.fBottom; |
-} |
- |
-// Can't call SkRect::contains, since it cares about empty, and we don't (since we tracking |
-// something to be stroked, so empty can still draw something (e.g. horizontal line) |
-static bool geometric_contains(const SkRect& outer, const SkRect& inner) { |
- SkASSERT(!is_inverted(outer) && !is_inverted(inner)); |
- return inner.fRight <= outer.fRight && inner.fLeft >= outer.fLeft && |
- inner.fBottom <= outer.fBottom && inner.fTop >= outer.fTop; |
-} |
- |
-//#define SK_SHOW_HAIRCLIP_STATS |
-#ifdef SK_SHOW_HAIRCLIP_STATS |
-static int gKillClip, gRejectClip, gClipCount; |
-#endif |
- |
static inline void haircubic(const SkPoint pts[4], const SkRegion* clip, const SkRect* insetClip, const SkRect* outsetClip, |
SkBlitter* blitter, int level, SkScan::HairRgnProc lineproc) { |
if (insetClip) { |
SkASSERT(outsetClip); |
-#ifdef SK_SHOW_HAIRCLIP_STATS |
- gClipCount += 1; |
-#endif |
SkRect bounds = compute_nocheck_cubic_bounds(pts); |
if (!geometric_overlap(*outsetClip, bounds)) { |
-#ifdef SK_SHOW_HAIRCLIP_STATS |
- gRejectClip += 1; |
-#endif |
return; |
} else if (geometric_contains(*insetClip, bounds)) { |
clip = nullptr; |
-#ifdef SK_SHOW_HAIRCLIP_STATS |
- gKillClip += 1; |
-#endif |
} |
-#ifdef SK_SHOW_HAIRCLIP_STATS |
- if (0 == gClipCount % 256) |
- SkDebugf("kill %g reject %g total %d\n", 1.0*gKillClip / gClipCount, 1.0*gRejectClip/gClipCount, gClipCount); |
-#endif |
} |
if (quick_cubic_niceness_check(pts)) { |
@@ -512,7 +522,9 @@ void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter |
*/ |
insetStorage.setEmpty(); // just so we don't pass an inverted rect |
} |
- insetClip = &insetStorage; |
+ if (rclip.isRect()) { |
+ insetClip = &insetStorage; |
+ } |
outsetClip = &outsetStorage; |
} |
} |
@@ -541,7 +553,7 @@ void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter |
if (SkPaint::kButt_Cap != capStyle) { |
extend_pts<capStyle>(prevVerb, iter.peek(), pts, 3); |
} |
- hairquad(pts, clip, blitter, compute_quad_level(pts), lineproc); |
+ hairquad(pts, clip, insetClip, outsetClip, blitter, compute_quad_level(pts), lineproc); |
lastPt = pts[2]; |
break; |
case SkPath::kConic_Verb: { |
@@ -554,7 +566,7 @@ void hair_path(const SkPath& path, const SkRasterClip& rclip, SkBlitter* blitter |
iter.conicWeight(), tol); |
for (int i = 0; i < converter.countQuads(); ++i) { |
int level = compute_quad_level(quadPts); |
- hairquad(quadPts, clip, blitter, level, lineproc); |
+ hairquad(quadPts, clip, insetClip, outsetClip, blitter, level, lineproc); |
quadPts += 2; |
} |
lastPt = pts[2]; |