| Index: src/core/SkScan_Path.cpp
|
| diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp
|
| index 30a7c576598d56df96757bda6257dbba0f1e3301..804148db360c4d93e2dfb7aae4c45e967940c120 100644
|
| --- a/src/core/SkScan_Path.cpp
|
| +++ b/src/core/SkScan_Path.cpp
|
| @@ -559,6 +559,42 @@ 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. Also rounds top and left using double, flooring when the fraction is exactly 0.5f.
|
| + *
|
| + * e.g.
|
| + * SkScalar left = 0.5f;
|
| + * int ileft = SkScalarRoundToInt(left);
|
| + * SkASSERT(0 == ileft); // <--- fails
|
| + * int ileft = round_down_to_int(left);
|
| + * SkASSERT(0 == ileft); // <--- succeeds
|
| + * SkScalar right = 0.49999997f;
|
| + * int iright = SkScalarRoundToInt(right);
|
| + * SkASSERT(0 == iright); // <--- fails
|
| + * iright = SkDScalarRoundToInt(right);
|
| + * SkASSERT(0 == iright); // <--- succeeds
|
| + */
|
| +static void round_asymmetric_to_int(const SkRect& src, SkIRect* dst) {
|
| + 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()) {
|
| @@ -578,11 +614,11 @@ void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
|
| // don't reference "origClip" any more, just use clipPtr
|
|
|
| SkIRect ir;
|
| - // We deliberately call dround() instead of round(), since we can't afford to generate a
|
| - // 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);
|
| + // We deliberately call round_asymmetric_to_int() instead of round(), since we can't afford
|
| + // to generate a 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
|
| + // round_asymmetric_to_int() here, we could generate the wrong ir for values like 0.4999997.
|
| + round_asymmetric_to_int(path.getBounds(), &ir);
|
| if (ir.isEmpty()) {
|
| if (path.isInverseFillType()) {
|
| blitter->blitRegion(*clipPtr);
|
|
|