Index: src/core/SkScan_Path.cpp |
diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp |
index 30a7c576598d56df96757bda6257dbba0f1e3301..ade0a1bbd8b79b37c6e35b7b5fe59b8a258c31b5 100644 |
--- a/src/core/SkScan_Path.cpp |
+++ b/src/core/SkScan_Path.cpp |
@@ -559,6 +559,37 @@ static bool clip_to_limit(const SkRegion& orig, SkRegion* reduced) { |
return true; |
} |
+/** |
+ * Variant of SkScalarRoundToInt, identical to SkDScalarRoundToInt except when the input fraction |
+ * is 0.5. In this case only, round the value down. This is used to round the top and left |
+ * of a rectangle, and corresponds to the way the scan converter treats the top and left edges. |
+ */ |
+static inline int round_down_to_int(SkScalar x) { |
+ double xx = x; |
+ xx += 0.5; |
+ double floorXX = floor(xx); |
+ return (int)floorXX - (xx == floorXX); |
+} |
+ |
+/** |
+ * Variant of SkRect::round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) |
+ * using double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(), |
+ * which may be slower than calling SkScalarRountToInt(), but gives slightly more accurate |
+ * results. |
+ * |
+ * e.g. |
+ * SkScalar x = 0.49999997f; |
reed1
2016/01/04 19:43:39
I think the comment block needs to be expanded, no
caryclark
2016/01/04 20:58:42
Done.
|
+ * int ix = SkScalarRoundToInt(x); |
+ * SkASSERT(0 == ix); // <--- fails |
+ * ix = SkDScalarRoundToInt(x); |
+ * SkASSERT(0 == ix); // <--- succeeds |
+ */ |
+static void round_out(const SkRect& src, SkIRect* dst) { |
reed1
2016/01/04 19:43:39
SkRect uses "out" to mean we floor/ceiling the val
caryclark
2016/01/04 20:58:42
Done.
|
+ SkASSERT(dst); |
+ dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop), |
+ SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom)); |
+} |
+ |
void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, |
SkBlitter* blitter) { |
if (origClip.isEmpty()) { |
@@ -582,7 +613,7 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, |
// bounds that is tighter than the corresponding SkEdges. The edge code basically converts |
// the floats to fixed, and then "rounds". If we called round() instead of dround() here, |
// we could generate the wrong ir for values like 0.4999997. |
- path.getBounds().dround(&ir); |
+ round_out(path.getBounds(), &ir); |
if (ir.isEmpty()) { |
if (path.isInverseFillType()) { |
blitter->blitRegion(*clipPtr); |