Index: src/core/SkScan_Hairline.cpp |
diff --git a/src/core/SkScan_Hairline.cpp b/src/core/SkScan_Hairline.cpp |
index 9b21c421edf6c8d8dc57f3df7afa63c953085c69..2d964bd1e7aefb0f68d531f57ca78e309b55d405 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,72 @@ 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, 8)); |
+ |
+ 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; |
+} |
+ |
+//#define SK_SHOW_HAIRCLIP_STATS |
+#ifdef SK_SHOW_HAIRCLIP_STATS |
+static int gKillClip, gRejectClip, gClipCount; |
+#endif |
+ |
+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); |
+#ifdef SK_SHOW_HAIRCLIP_STATS |
reed1
2016/05/11 19:47:50
I'm fine with these, or fine if we remove all this
|
+ gClipCount += 1; |
+#endif |
+ SkRect bounds = compute_nocheck_quad_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 |
+ } |
+ |
+ hair_quad(pts, clip, blitter, level, lineproc); |
+} |
+ |
static inline Sk2s abs(const Sk2s& value) { |
return Sk2s::Max(value, Sk2s(0)-value); |
} |
@@ -329,31 +395,6 @@ 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) { |
@@ -512,7 +553,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()) { |
reed1
2016/05/11 19:47:50
funny indenting (tabs?)
|
+ insetClip = &insetStorage; |
+ } |
outsetClip = &outsetStorage; |
} |
} |
@@ -541,7 +584,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 +597,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]; |