Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: src/core/SkScan_Path.cpp

Issue 1544873002: handle halfway case in scan converter (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: delete from public headers Created 4 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/core/SkRect.h ('k') | tests/DrawPathTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « include/core/SkRect.h ('k') | tests/DrawPathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698