add unpremul gm

Change-Id: I3126fb8b055b58e45f1bd0d913413b4d4d38f032
Reviewed-on: https://skia-review.googlesource.com/c/166740
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
diff --git a/gm/gm.cpp b/gm/gm.cpp
index 17b220a..a4b8f02 100644
--- a/gm/gm.cpp
+++ b/gm/gm.cpp
@@ -111,3 +111,54 @@
 SkString skiagm::SimpleGM::onShortName() {
     return fName;
 }
+
+template <typename Fn>
+static void mark(SkCanvas* canvas, SkScalar x, SkScalar y, Fn&& fn) {
+    SkPaint alpha;
+    alpha.setAlpha(0x50);
+    canvas->saveLayer(nullptr, &alpha);
+        canvas->translate(x,y);
+        canvas->scale(2,2);
+        fn();
+    canvas->restore();
+}
+
+void MarkGMGood(SkCanvas* canvas, SkScalar x, SkScalar y) {
+    mark(canvas, x,y, [&]{
+        SkPaint paint;
+
+        // A green circle.
+        paint.setColor(SkColorSetRGB(27, 158, 119));
+        canvas->drawCircle(0,0, 12, paint);
+
+        // Cut out a check mark.
+        paint.setBlendMode(SkBlendMode::kSrc);
+        paint.setColor(0x00000000);
+        paint.setStrokeWidth(2);
+        paint.setStyle(SkPaint::kStroke_Style);
+        canvas->drawLine(-6, 0,
+                         -1, 5, paint);
+        canvas->drawLine(-1, +5,
+                         +7, -5, paint);
+    });
+}
+
+void MarkGMBad(SkCanvas* canvas, SkScalar x, SkScalar y) {
+    mark(canvas, x,y, [&] {
+        SkPaint paint;
+
+        // A red circle.
+        paint.setColor(SkColorSetRGB(231, 41, 138));
+        canvas->drawCircle(0,0, 12, paint);
+
+        // Cut out an 'X'.
+        paint.setBlendMode(SkBlendMode::kSrc);
+        paint.setColor(0x00000000);
+        paint.setStrokeWidth(2);
+        paint.setStyle(SkPaint::kStroke_Style);
+        canvas->drawLine(-5,-5,
+                         +5,+5, paint);
+        canvas->drawLine(+5,-5,
+                         -5,+5, paint);
+    });
+}
diff --git a/gm/gm.h b/gm/gm.h
index 8536709..519c9df 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -144,4 +144,7 @@
     };
 }
 
+void MarkGMGood(SkCanvas*, SkScalar x, SkScalar y);
+void MarkGMBad (SkCanvas*, SkScalar x, SkScalar y);
+
 #endif
diff --git a/gm/p3.cpp b/gm/p3.cpp
index bb0cfb6..f8e139b 100644
--- a/gm/p3.cpp
+++ b/gm/p3.cpp
@@ -11,57 +11,6 @@
 #include "SkGradientShader.h"
 #include "SkString.h"
 
-template <typename Fn>
-static void mark(SkCanvas* canvas, Fn&& fn) {
-    SkPaint alpha;
-    alpha.setAlpha(0x50);
-    canvas->saveLayer(nullptr, &alpha);
-        canvas->translate(140,40);
-        canvas->scale(2,2);
-        fn();
-    canvas->restore();
-}
-
-static void mark_good(SkCanvas* canvas) {
-    mark(canvas, [&]{
-        SkPaint paint;
-
-        // A green circle.
-        paint.setColor(SkColorSetRGB(27, 158, 119));
-        canvas->drawCircle(0,0, 12, paint);
-
-        // Cut out a check mark.
-        paint.setBlendMode(SkBlendMode::kSrc);
-        paint.setColor(0x00000000);
-        paint.setStrokeWidth(2);
-        paint.setStyle(SkPaint::kStroke_Style);
-        canvas->drawLine(-6, 0,
-                         -1, 5, paint);
-        canvas->drawLine(-1, +5,
-                         +7, -5, paint);
-    });
-}
-
-static void mark_bad(SkCanvas* canvas) {
-    mark(canvas, [&] {
-        SkPaint paint;
-
-        // A red circle.
-        paint.setColor(SkColorSetRGB(231, 41, 138));
-        canvas->drawCircle(0,0, 12, paint);
-
-        // Cut out an 'X'.
-        paint.setBlendMode(SkBlendMode::kSrc);
-        paint.setColor(0x00000000);
-        paint.setStrokeWidth(2);
-        paint.setStyle(SkPaint::kStroke_Style);
-        canvas->drawLine(-5,-5,
-                         +5,+5, paint);
-        canvas->drawLine(+5,-5,
-                         -5,+5, paint);
-    });
-}
-
 static bool nearly_equal(SkColor4f x, SkColor4f y) {
     const float K = 0.01f;
     return fabsf(x.fR - y.fR) < K
@@ -99,7 +48,7 @@
     SkBitmap bm;
     bm.allocPixels(SkImageInfo::Make(1,1, kRGBA_F32_SkColorType, kUnpremul_SkAlphaType, canvas_cs));
     if (!canvas->readPixels(bm, x,y)) {
-        mark_good(canvas);
+        MarkGMGood(canvas, 140,40);
         canvas->drawString("can't readPixels() on this canvas :(", 100,20, text);
         return;
     }
@@ -119,9 +68,9 @@
     }
 
     if (nearly_equal(pixel, expected)) {
-        mark_good(canvas);
+        MarkGMGood(canvas, 140,40);
     } else {
-        mark_bad(canvas);
+        MarkGMBad(canvas, 140,40);
     }
 
     struct {
diff --git a/gm/unpremul.cpp b/gm/unpremul.cpp
new file mode 100644
index 0000000..445a6ef
--- /dev/null
+++ b/gm/unpremul.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkColor.h"
+
+DEF_SIMPLE_GM(unpremul, canvas, 200, 200) {
+    const SkColor color = 0xbf400000;
+
+    auto grade = [&](int x, int y){
+        SkBitmap bm;
+        bm.allocPixels(SkImageInfo::Make(1,1,
+                                         kBGRA_8888_SkColorType,
+                                         kUnpremul_SkAlphaType,
+                                         SkColorSpace::MakeSRGB()));
+        if (!canvas->readPixels(bm, x,y)) {
+            // Picture-backed canvases, that sort of thing.  Just assume they're good.
+            MarkGMGood(canvas, 140,40);
+            return;
+        }
+
+        SkColor pixel;
+        memcpy(&pixel, bm.getAddr(0,0), sizeof(pixel));
+
+        auto close = [](int x, int y) {
+            return x-y < 2
+                && y-x < 2;
+        };
+
+        if (close(SkColorGetR(pixel), SkColorGetR(color)) &&
+            close(SkColorGetG(pixel), SkColorGetG(color)) &&
+            close(SkColorGetB(pixel), SkColorGetB(color)) &&
+            close(SkColorGetA(pixel), SkColorGetA(color))) {
+
+            MarkGMGood(canvas, 140,40);
+        } else {
+            MarkGMBad(canvas, 140,40);
+        }
+    };
+
+    {
+        SkPaint paint;
+        paint.setBlendMode(SkBlendMode::kSrc);
+        paint.setColor(color);
+
+        canvas->drawRect({0,0,100,100}, paint);
+        grade(50,50);
+    }
+
+    canvas->translate(0,100);
+
+    {
+        SkPaint paint;
+        paint.setBlendMode(SkBlendMode::kSrc);
+
+        SkBitmap bm;
+        bm.allocPixels(SkImageInfo::Make(100,100, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType));
+        bm.eraseColor(color);
+
+        canvas->drawBitmap(bm, 0,0, &paint);
+        grade(50,150);
+    }
+
+}
diff --git a/gn/gm.gni b/gn/gm.gni
index 618a8f0..ecc0828 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -337,6 +337,7 @@
   "$_gm/transparency.cpp",
   "$_gm/trickycubicstrokes.cpp",
   "$_gm/typeface.cpp",
+  "$_gm/unpremul.cpp",
   "$_gm/variedtext.cpp",
   "$_gm/vertices.cpp",
   "$_gm/verylargebitmap.cpp",