summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp1123
1 files changed, 1123 insertions, 0 deletions
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp
new file mode 100644
index 00000000000..dbf9861c786
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/platform/graphics/GraphicsContextTest.cpp
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "platform/graphics/GraphicsContext.h"
+
+#include "platform/graphics/BitmapImage.h"
+#include "platform/graphics/DisplayList.h"
+#include "platform/graphics/ImageBuffer.h"
+#include "platform/graphics/skia/NativeImageSkia.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+
+namespace {
+
+#define EXPECT_EQ_RECT(a, b) \
+ EXPECT_EQ(a.x(), b.x()); \
+ EXPECT_EQ(a.y(), b.y()); \
+ EXPECT_EQ(a.width(), b.width()); \
+ EXPECT_EQ(a.height(), b.height());
+
+#define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = opaqueRect.y(); y < opaqueRect.maxY(); ++y) \
+ for (int x = opaqueRect.x(); x < opaqueRect.maxX(); ++x) { \
+ int alpha = *bitmap.getAddr32(x, y) >> 24; \
+ EXPECT_EQ(255, alpha); \
+ } \
+}
+
+#define EXPECT_PIXELS_MATCH_EXACT(bitmap, opaqueRect) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = 0; y < bitmap.height(); ++y) \
+ for (int x = 0; x < bitmap.width(); ++x) { \
+ int alpha = *bitmap.getAddr32(x, y) >> 24; \
+ bool opaque = opaqueRect.contains(x, y); \
+ EXPECT_EQ(opaque, alpha == 255); \
+ } \
+}
+
+TEST(GraphicsContextTest, trackOpaqueTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), alpha, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositePlusLighter);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(99, 13, 10, 90), alpha, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 10, 89, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(8, 8, 3, 90), opaque, CompositeSourceOut);
+ EXPECT_EQ_RECT(IntRect(11, 10, 88, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(30, 30, 290, 290), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(40, 20, 290, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), alpha);
+ EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 10, 290, 310), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueClipTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.save();
+ context.clip(FloatRect(0, 0, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.save();
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ // The intersection of the two clips becomes empty.
+ context.clip(FloatRect(30, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ // The transform and the clip need to interact correctly (transform first)
+ context.save();
+ context.translate(10, 10);
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ // The transform and the clip need to interact correctly (clip first)
+ context.save();
+ context.clip(FloatRect(20, 20, 10, 10));
+ context.translate(10, 10);
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ context.clearRect(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ Path path;
+ path.moveTo(FloatPoint(0, 0));
+ path.addLineTo(FloatPoint(100, 0));
+
+ // Non-rectangular clips just cause the paint to be considered non-opaque.
+ context.save();
+ context.clipPath(path, RULE_EVENODD);
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+
+ // Another non-rectangular clip.
+ context.save();
+ context.clip(IntRect(30, 30, 20, 20));
+ context.clipOut(IntRect(30, 30, 10, 10));
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.restore();
+}
+
+TEST(GraphicsContextTest, trackImageMask)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
+ // out a transparency layer below that is filled with the mask color. In the end this should
+ // not be marked opaque.
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(1);
+ context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
+
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.beginTransparencyLayer(1);
+
+ OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
+ alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
+
+ context.endLayer();
+ context.endLayer();
+
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
+ // out a transparency layer below that is filled with the mask color. In the end this should
+ // not be marked opaque.
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(1);
+ context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
+
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.beginTransparencyLayer(1);
+
+ OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
+ alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
+
+ context.setCompositeOperation(CompositeSourceOver);
+ context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
+
+ // We can't have an opaque mask actually, but we can pretend here like it would look if we did.
+ context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver);
+
+ context.endLayer();
+ context.endLayer();
+
+ EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueJoinTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Doesn't join
+ context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ // Does join
+ context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueLineTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.setShouldAntialias(false);
+ context.setMiterLimit(0);
+ context.setStrokeThickness(4);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+ context.setCompositeOperation(CompositeSourceOver);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(opaque);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+ context.setCompositeOperation(CompositeSourceOver);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(false);
+ context.save();
+ context.setStrokeColor(opaque);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+ context.save();
+ context.setStrokeColor(opaque);
+ context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setStrokeColor(alpha);
+ context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaquePathTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+ context.setCompositeOperation(CompositeSourceIn);
+
+ Path path;
+
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(0, 0));
+ path.addLineTo(FloatPoint(100, 0));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(opaque);
+ path.moveTo(FloatPoint(0, 10));
+ path.addLineTo(FloatPoint(100, 13));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(0, 10));
+ path.addLineTo(FloatPoint(100, 13));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(0, 14));
+ path.addLineTo(FloatPoint(100, 10));
+ context.fillPath(path);
+ EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ path.clear();
+}
+
+TEST(GraphicsContextTest, trackOpaqueImageTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+ RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap));
+ EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque());
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+ RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap));
+ EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), IntPoint(0, 0));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), IntPoint(0, 0));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), IntPoint(5, 5));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), IntPoint(5, 5));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(opaqueImage.get(), IntPoint(10, 10));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+ context.drawImage(alphaImage.get(), IntPoint(10, 10));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setAlphaAsFloat(0.5);
+ context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn);
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn);
+ EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.save();
+ context.setAlphaAsFloat(0.5);
+ context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn);
+ context.restore();
+ EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueOvalTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillEllipse(FloatRect(10, 10, 90, 90));
+ context.strokeEllipse(FloatRect(10, 10, 90, 90));
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+
+ context.setShouldAntialias(false);
+
+ context.setFillColor(opaque);
+ context.fillEllipse(FloatRect(10, 10, 50, 30));
+ context.strokeEllipse(FloatRect(10, 10, 50, 30));
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setFillColor(alpha);
+ context.fillEllipse(FloatRect(10, 10, 30, 50));
+ context.strokeEllipse(FloatRect(10, 10, 30, 50));
+ EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setShouldAntialias(true);
+
+ context.setFillColor(opaque);
+ context.fillEllipse(FloatRect(10, 10, 50, 30));
+ context.strokeEllipse(FloatRect(10, 10, 50, 30));
+ EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setFillColor(alpha);
+ context.fillEllipse(FloatRect(20, 10, 30, 50));
+ context.strokeEllipse(FloatRect(20, 10, 30, 50));
+ EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueRoundedRectTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+ IntSize radii(10, 10);
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.setCompositeOperation(CompositeSourceIn);
+ context.setShouldAntialias(false);
+
+ context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha);
+ EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha);
+ EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque);
+ EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueTextTest)
+{
+ int width = 200, height = 200;
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(width, height));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ SkRect textRect = SkRect::MakeWH(width, height);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ SkPaint opaquePaint;
+ opaquePaint.setColor(opaque.rgb());
+ opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ SkPaint alphaPaint;
+ alphaPaint.setColor(alpha.rgb());
+ alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ SkPoint point = SkPoint::Make(0, 0);
+
+ context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawPosText("A", 1, &point, textRect, opaquePaint);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawPosText("A", 1, &point, textRect, alphaPaint);
+ EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueWritePixelsTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ context.writePixels(opaqueBitmap, 50, 50);
+ EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 10, 0);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 10, 1);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 0, 10);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.writePixels(alphaBitmap, 1, 10);
+ EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ context.drawBitmap(opaqueBitmap, 10, 10, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 10, 0, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 10, 1, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 0, 10, &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmap(alphaBitmap, 1, 10, &paint);
+ EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(200, 200));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+
+ SkBitmap opaqueBitmap;
+ ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */));
+ for (int y = 0; y < opaqueBitmap.height(); ++y)
+ for (int x = 0; x < opaqueBitmap.width(); ++x)
+ *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
+
+ SkBitmap alphaBitmap;
+ ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10));
+ for (int y = 0; y < alphaBitmap.height(); ++y)
+ for (int x = 0; x < alphaBitmap.width(); ++x)
+ *alphaBitmap.getAddr32(x, y) = 0x00000000;
+
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint);
+ EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint);
+ EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, contextTransparencyLayerTest)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(20, 20, 10, 10));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.beginTransparencyLayer(0.5);
+ context.save();
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ context.restore();
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.clearRect(FloatRect(20, 20, 10, 10));
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+
+ context.beginTransparencyLayer(0.5);
+ context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, UnboundedDrawsAreClipped)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ Path path;
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+
+ // Make skia unable to compute fast bounds for our paths.
+ DashArray dashArray;
+ dashArray.append(1);
+ dashArray.append(0);
+ context.setLineDash(dashArray, 0);
+
+ // Make the device opaque in 10,10 40x40.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Clip to the left edge of the opaque area.
+ context.clip(IntRect(10, 10, 10, 40));
+
+ // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.setFillColor(alpha);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
+}
+
+TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+
+ GraphicsContext context(&canvas);
+ context.setTrackOpaqueRegion(true);
+
+ Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
+ Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
+
+ Path path;
+ context.setShouldAntialias(false);
+ context.setMiterLimit(1);
+ context.setStrokeThickness(5);
+ context.setLineCap(SquareCap);
+ context.setStrokeStyle(SolidStroke);
+
+ // Make skia unable to compute fast bounds for our paths.
+ DashArray dashArray;
+ dashArray.append(1);
+ dashArray.append(0);
+ context.setLineDash(dashArray, 0);
+
+ // Make the device opaque in 10,10 40x40.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Begin a layer that preserves opaque.
+ context.setCompositeOperation(CompositeSourceOver);
+ context.beginTransparencyLayer(0.5);
+
+ // Begin a layer that does not preserve opaque.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should not destroy the device opaqueness.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+
+ // This should not destroy the device opaqueness either.
+ context.setFillColor(opaque);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ context.endLayer();
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Now begin a layer that does not preserve opaque and draw through it to the device.
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should destroy the device opaqueness.
+ context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
+
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+
+ // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region.
+
+ context.setCompositeOperation(CompositeSourceOut);
+ context.beginTransparencyLayer(0.5);
+
+ // This should nuke the device opaqueness.
+ context.setFillColor(opaque);
+ path.moveTo(FloatPoint(10, 10));
+ path.addLineTo(FloatPoint(40, 40));
+ context.strokePath(path);
+
+ context.endLayer();
+ EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
+ EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
+}
+
+#define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0);
+#define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0);
+
+TEST(GraphicsContextTest, RecordingTotalMatrix)
+{
+ SkBitmap bitmap;
+ ASSERT_TRUE(bitmap.allocN32Pixels(400, 400));
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ GraphicsContext context(&canvas);
+
+ SkCanvas controlCanvas(400, 400);
+ GraphicsContext controlContext(&controlCanvas);
+
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+ DISPATCH2(context, controlContext, scale, 2, 2);
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.save();
+ context.beginRecording(FloatRect(0, 0, 200, 200));
+ DISPATCH2(context, controlContext, translate, 10, 10);
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.save();
+ context.beginRecording(FloatRect(10, 10, 100, 100));
+ DISPATCH1(context, controlContext, rotate, 45);
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.restore();
+ context.endRecording();
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+
+ controlContext.restore();
+ context.endRecording();
+ EXPECT_EQ(context.getCTM(), controlContext.getCTM());
+}
+
+TEST(GraphicsContextTest, DisplayList)
+{
+ FloatRect rect(0, 0, 1, 1);
+ RefPtr<DisplayList> dl = adoptRef(new DisplayList(rect));
+
+ // picture() returns 0 initially
+ SkPicture* pic = dl->picture();
+ EXPECT_FALSE(pic);
+
+ // endRecording without a beginRecording does nothing
+ dl->endRecording();
+ pic = dl->picture();
+ EXPECT_FALSE(pic);
+
+ // Two beginRecordings in a row generate two canvases.
+ // Unfortunately the new one could be allocated in the same
+ // spot as the old one so ref the first one to prolong its life.
+ IntSize size(1, 1);
+ SkCanvas* canvas1 = dl->beginRecording(size);
+ EXPECT_TRUE(canvas1);
+ canvas1->ref();
+ SkCanvas* canvas2 = dl->beginRecording(size);
+ EXPECT_TRUE(canvas2);
+
+ EXPECT_NE(canvas1, canvas2);
+ EXPECT_EQ(1, canvas1->getRefCnt());
+ canvas1->unref();
+
+ EXPECT_TRUE(dl->isRecording());
+
+ // picture() returns 0 during recording
+ pic = dl->picture();
+ EXPECT_FALSE(pic);
+
+ // endRecording finally makes the picture accessible
+ dl->endRecording();
+ pic = dl->picture();
+ EXPECT_TRUE(pic);
+ EXPECT_EQ(1, pic->getRefCnt());
+}
+
+} // namespace