aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Lee Salzman <lsalzman@mozilla.com>2017-01-13 13:35:49 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-18 20:43:59 +0000
commit95acbad4fee03a2fa2c0419da70a1b85e21739ef (patch)
treeb36e34b474b932f4624fb1955f2c9c9788a07d37 /src/core
parentce7e18f548cf8af0bc7c3950824221c5c08e1e25 (diff)
ensure path bounds after rounding contain path edges when using SK_RASTERIZE_EVEN_ROUNDING
BUG=skia: Change-Id: I34e93de8fd4faa44336c2698d06595e9c4de86c3 Reviewed-on: https://skia-review.googlesource.com/7040 Reviewed-by: Cary Clark <caryclark@google.com> Commit-Queue: Cary Clark <caryclark@google.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkScan_Path.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/core/SkScan_Path.cpp b/src/core/SkScan_Path.cpp
index 6d28f4b1ae..9f81eac1d5 100644
--- a/src/core/SkScan_Path.cpp
+++ b/src/core/SkScan_Path.cpp
@@ -608,6 +608,19 @@ static inline int round_down_to_int(SkScalar x) {
return (int)ceil(xx);
}
+#ifdef SK_RASTERIZE_EVEN_ROUNDING
+/**
+ * Variant of SkDScalarRoundToInt that biases the input up by a half an FDot6 unit to account
+ * for potential FDot6 rounding in downstream FDot6 calculations.
+ */
+static inline int round_biased_to_int(SkScalar x) {
+ const double bias = 0.5 / SK_FDot6One;
+ double xx = x;
+ xx += 0.5 + bias;
+ return (int)floor(xx);
+}
+#endif
+
/**
* 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(),
@@ -625,11 +638,28 @@ static inline int round_down_to_int(SkScalar x) {
* SkASSERT(0 == iright); // <--- fails
* iright = SkDScalarRoundToInt(right);
* SkASSERT(0 == iright); // <--- succeeds
+ *
+ *
+ * If using SK_RASTERIZE_EVEN_ROUNDING, we need to ensure that bottom and right account for
+ * edges bounded by this rect being rounded to FDot6 format before being later rounded to an
+ * integer. For example, a value like 0.499 can be below 0.5, but round to 0.5 as FDot6, which
+ * would finally round to the integer 1, instead of just rounding to 0.
+ *
+ * To handle this, a small bias of half an FDot6 increment is added before actually rounding to
+ * an integer value. This simulates the rounding of SkScalarRoundToFDot6 without incurring the
+ * range loss of converting to FDot6 format first, preserving the integer range for the SkIRect.
+ * Thus, bottom and right are rounded in this manner (biased up), ensuring the rect is large
+ * enough. Top and left can round as normal since they will round (biased down) to values less
+ * or equal to the desired rect origin.
*/
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),
+#ifdef SK_RASTERIZE_EVEN_ROUNDING
+ round_biased_to_int(src.fRight), round_biased_to_int(src.fBottom));
+#else
SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom));
+#endif
}
void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,