Cherry-pick 875e13ca0 to M52.
authormtklein <mtklein@chromium.org>
Tue, 21 Jun 2016 19:03:37 +0000 (12:03 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 21 Jun 2016 19:03:37 +0000 (12:03 -0700)
TBR=

Original description:
    Simplify mask/clip intersection, making sure to explicitly check for an empty mask.

    Previously we were only asserting the mask wasn't empty, which isn't necessarily true when we're given pathological float coordinates like +Inf or NaN.

    A local run of nanobench --match text_ was not able to show this is faster or slower.

    This patch fixed this first Chrome bug on my desktop, and the second is probably a dupe.
    BUG=chromium:619378,chromium:613912

    GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2073873002

    Review-Url: https://codereview.chromium.org/2073873002
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=2085023002
NOTREECHECKS=true
NOTRY=true
NOPRESUBMIT=true

Review-Url: https://codereview.chromium.org/2085023002

src/core/SkDraw.cpp
tests/DrawTextTest.cpp

index 884794261dcad45130cb345e5325075109aa30f2..213c42cb5416af77abd1eaa852f5c20fb20f44fc 100644 (file)
@@ -1460,10 +1460,13 @@ public:
     void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
         position += rounding;
         // Prevent glyphs from being drawn outside of or straddling the edge of device space.
-        if (position.fX > INT_MAX - (INT16_MAX + UINT16_MAX) ||
-            position.fX < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
-            position.fY > INT_MAX - (INT16_MAX + UINT16_MAX) ||
-            position.fY < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) {
+        // Comparisons written a little weirdly so that NaN coordinates are treated safely.
+        auto gt = [](float a, int b) { return !(a <= (float)b); };
+        auto lt = [](float a, int b) { return !(a >= (float)b); };
+        if (gt(position.fX, INT_MAX - (INT16_MAX + UINT16_MAX)) ||
+            lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) ||
+            gt(position.fY, INT_MAX - (INT16_MAX + UINT16_MAX)) ||
+            lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))) {
             return;
         }
 
@@ -1479,6 +1482,7 @@ public:
 
         SkMask mask;
         mask.fBounds.set(left, top, right, bottom);
+        SkASSERT(!mask.fBounds.isEmpty());
 
         if (fUseRegionToDraw) {
             SkRegion::Cliperator clipper(*fClip, mask.fBounds);
index f2da450fe86b14a47a2fa0d3ac777e0d0819611b..bf9bd39f8d1e7a4d4c5f78ba086ed42964d9e962 100644 (file)
 #include "SkPaint.h"
 #include "SkPoint.h"
 #include "SkRect.h"
+#include "SkSurface.h"
 #include "SkTypes.h"
 #include "Test.h"
+#include <math.h>
 
 static const SkColor bgColor = SK_ColorWHITE;
 
@@ -111,3 +113,21 @@ DEF_TEST(DrawText, reporter) {
         }
     }
 }
+
+// Test drawing text at some unusual coordinates.
+// We measure success by not crashing or asserting.
+DEF_TEST(DrawText_weirdCoordinates, r) {
+    auto surface = SkSurface::MakeRasterN32Premul(10,10);
+    auto canvas = surface->getCanvas();
+
+    SkScalar oddballs[] = { 0.0f, (float)INFINITY, (float)NAN, 34359738368.0f };
+
+    for (auto x : oddballs) {
+        canvas->drawText("a", 1, +x, 0.0f, SkPaint());
+        canvas->drawText("a", 1, -x, 0.0f, SkPaint());
+    }
+    for (auto y : oddballs) {
+        canvas->drawText("a", 1, 0.0f, +y, SkPaint());
+        canvas->drawText("a", 1, 0.0f, -y, SkPaint());
+    }
+}