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

Unified Diff: Source/platform/graphics/GraphicsContextTest.cpp

Issue 651243002: Clarify GraphicsContext::beginLayer()/endLayer() have unexpected behaviors. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: beginLayer()/endLayer() don't behave like save()/restore() Created 6 years, 2 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
Index: Source/platform/graphics/GraphicsContextTest.cpp
diff --git a/Source/platform/graphics/GraphicsContextTest.cpp b/Source/platform/graphics/GraphicsContextTest.cpp
index fe8b95e939a8b6b9ff9302c82b5914cec334658a..a911387f56d01d41d30778e7d6e521ed747147d2 100644
--- a/Source/platform/graphics/GraphicsContextTest.cpp
+++ b/Source/platform/graphics/GraphicsContextTest.cpp
@@ -66,6 +66,17 @@ namespace {
} \
}
+#define EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, color) \
+{ \
+ SkAutoLockPixels locker(bitmap); \
+ for (int y = rect.y(); y < rect.maxY(); ++y) { \
+ for (int x = rect.x(); x < rect.maxX(); ++x) { \
+ RGBA32 pixel = *bitmap.getAddr32(x, y); \
+ EXPECT_EQ(color, pixel); \
+ } \
+ } \
+}
+
TEST(GraphicsContextTest, trackOpaqueTest)
{
SkBitmap bitmap;
@@ -1214,4 +1225,156 @@ TEST(GraphicsContextTest, RecordingCanvas)
context.endRecording();
}
+TEST(GraphicsContextTest, BeginLayerDontAffectCanvasState)
+{
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(1, 1);
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ GraphicsContext context(&canvas);
+
+ IntRect rect(0, 0, 1, 1);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::transparent);
+ context.fillRect(rect, Color::gray);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::gray);
+
+ // Translate out of bound not to draw.
+ context.translate(1, 0);
+ context.fillRect(rect, Color::darkGray);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::gray);
+ EXPECT_EQ(SK_Scalar1, context.getTotalMatrix().getTranslateX());
+
+ context.beginLayer(1, CompositeSourceOver);
+ context.translate(-1, 0);
+ EXPECT_EQ(0, context.getTotalMatrix().getTranslateX());
+ context.fillRect(rect, Color::darkGray);
+ context.endLayer();
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::darkGray);
+
+ // GraphicsContext::endLayer() must preserve current states.
+ EXPECT_EQ(0, context.getTotalMatrix().getTranslateX());
+
+ context.fillRect(rect, Color::lightGray);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::lightGray);
+}
+
+// Although this test looks like duplicated to BeginLayerPreserveCanvasState,
+// this is needed because GraphicsContext keeps a composite operator in SkPaint
+// while setting a transform to SkCanvas directly.
+TEST(GraphicsContextTest, BeginLayerDontAffectPaintState)
+{
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(1, 1);
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ GraphicsContext context(&canvas);
+
+ IntRect rect(0, 0, 1, 1);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::transparent);
+ EXPECT_EQ(CompositeSourceOver, context.compositeOperation());
+ context.fillRect(rect, Color::gray);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::gray);
+
+ // Set CompositeDestinationIn not to draw.
+ context.setCompositeOperation(CompositeDestinationIn);
+ context.fillRect(rect, Color::darkGray);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::gray);
+ EXPECT_EQ(CompositeDestinationIn, context.compositeOperation());
+
+ context.beginLayer(1, CompositeSourceIn);
+ EXPECT_EQ(CompositeDestinationIn, context.compositeOperation());
+ context.setCompositeOperation(CompositeSourceOver);
+ EXPECT_EQ(CompositeSourceOver, context.compositeOperation());
+ context.fillRect(rect, Color::darkGray);
+ context.endLayer();
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::darkGray);
+
+ // GraphicsContext::endLayer() must preserve current states.
+ EXPECT_EQ(CompositeSourceOver, context.compositeOperation());
+
+ context.fillRect(rect, Color::lightGray);
+ EXPECT_PIXELS_MATCH_COLOR(bitmap, rect, Color::lightGray);
+}
+
+// Cannot reuse SkClipStack::Element::operator==() because it checks save count.
+bool equal(const SkClipStack::Element* a, const SkClipStack::Element* b)
+{
+ if (a->getOp() != b->getOp() || a->getType() != b->getType() || a->isAA() != b->isAA()) {
+ return false;
+ }
+ switch (a->getType()) {
+ case SkClipStack::Element::kPath_Type:
+ return a->getPath() == b->getPath();
+ case SkClipStack::Element::kRRect_Type:
+ return a->getRRect() == b->getRRect();
+ case SkClipStack::Element::kRect_Type:
+ return a->getRect() == b->getRect();
+ case SkClipStack::Element::kEmpty_Type:
+ return true;
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+}
+
+// Cannot reuse SkClipStack::operator==() because it checks save count.
+bool equal(const SkClipStack* a, const SkClipStack* b)
+{
+ SkClipStack::B2TIter aIter(*a);
+ SkClipStack::B2TIter bIter(*b);
+ const SkClipStack::Element* aElement = aIter.next();
+ const SkClipStack::Element* bElement = bIter.next();
+
+ while (aElement && bElement) {
+ if (!equal(aElement, bElement)) {
+ return false;
+ }
+ aElement = aIter.next();
+ bElement = bIter.next();
+ }
+ return !aElement && !bElement;
+}
+
+TEST(GraphicsContextTest, BeginLayerDontAffectClipState)
+{
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(10, 10);
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ GraphicsContext context(&canvas);
+ // Reference to compare clip stack. It's needed because SkCanvas::saveLayer() can perform an additional clip op.
+ SkBitmap bitmapRef;
+ bitmapRef.allocN32Pixels(10, 10);
+ bitmapRef.eraseColor(0);
+ SkCanvas canvasRef(bitmapRef);
+ GraphicsContext contextRef(&canvasRef);
+
+ context.clip(IntRect(1, 1, 9, 9));
+ contextRef.clip(IntRect(1, 1, 9, 9));
+ context.save();
+ context.clip(IntRect(0, 0, 7, 7));
+ context.translate(1, 1);
+ context.clip(IntRect(0, 0, 7, 7));
+ contextRef.save();
+ contextRef.clip(IntRect(0, 0, 7, 7));
+ contextRef.translate(1, 1);
+ contextRef.clip(IntRect(0, 0, 7, 7));
+ EXPECT_TRUE(equal(canvasRef.getClipStack(), canvas.getClipStack()));
+
+ RoundedRect roundedClipRect(IntRect(20, 20, 70, 70), RoundedRect::Radii(IntSize(2, 3), IntSize(2, 3), IntSize(2, 3), IntSize(2, 3)));
+ context.beginLayer(1, CompositeSourceOver);
+ context.scale(0.1, 0.1);
+ context.clipRoundedRect(roundedClipRect);
+ context.clipOut(IntRect(40, 40, 10, 10));
+ context.endLayer();
+ contextRef.scale(0.1, 0.1);
+ contextRef.clipRoundedRect(roundedClipRect);
+ contextRef.clipOut(IntRect(40, 40, 10, 10));
+
+ // GraphicsContext::endLayer() must preserve clip state.
+ EXPECT_TRUE(equal(canvasRef.getClipStack(), canvas.getClipStack()));
+ context.restore();
+ contextRef.restore();
+}
+
} // namespace
« Source/platform/graphics/GraphicsContext.cpp ('K') | « Source/platform/graphics/GraphicsContext.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698