Chromium Code Reviews| 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); |