// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/compiler_specific.h" #include "skia/ext/analysis_canvas.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkShader.h" namespace { void SolidColorFill(skia::AnalysisCanvas& canvas) { canvas.clear(SkColorSetARGB(255, 255, 255, 255)); } void TransparentFill(skia::AnalysisCanvas& canvas) { canvas.clear(SkColorSetARGB(0, 0, 0, 0)); } } // namespace namespace skia { TEST(AnalysisCanvasTest, EmptyCanvas) { SkBitmap emptyBitmap; emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); SkColor color; EXPECT_TRUE(canvas.GetColorIfSolid(&color)); EXPECT_EQ(color, SkColorSetARGB(0, 0, 0, 0)); } TEST(AnalysisCanvasTest, ClearCanvas) { SkBitmap emptyBitmap; emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); // Transparent color SkColor color = SkColorSetARGB(0, 12, 34, 56); canvas.clear(color); SkColor outputColor; EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); // Solid color color = SkColorSetARGB(255, 65, 43, 21); canvas.clear(color); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); EXPECT_EQ(outputColor, color); // Translucent color color = SkColorSetARGB(128, 11, 22, 33); canvas.clear(color); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); // Test helper methods SolidColorFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); TransparentFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); } TEST(AnalysisCanvasTest, ComplexActions) { SkBitmap emptyBitmap; emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); // Draw paint test. SkColor color = SkColorSetARGB(255, 11, 22, 33); SkPaint paint; paint.setColor(color); canvas.drawPaint(paint); SkColor outputColor; //TODO(vmpstr): This should return true. (crbug.com/180597) EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); // Draw points test. SkPoint points[4] = { SkPoint::Make(0, 0), SkPoint::Make(255, 0), SkPoint::Make(255, 255), SkPoint::Make(0, 255) }; SolidColorFill(canvas); canvas.drawPoints(SkCanvas::kLines_PointMode, 4, points, paint); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); // Draw oval test. SolidColorFill(canvas); canvas.drawOval(SkRect::MakeWH(255, 255), paint); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); // Draw bitmap test. SolidColorFill(canvas); SkBitmap secondBitmap; secondBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); canvas.drawBitmap(secondBitmap, 0, 0); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); } TEST(AnalysisCanvasTest, SimpleDrawRect) { SkBitmap emptyBitmap; emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); SkColor color = SkColorSetARGB(255, 11, 22, 33); SkPaint paint; paint.setColor(color); canvas.clipRect(SkRect::MakeWH(255, 255)); canvas.drawRect(SkRect::MakeWH(255, 255), paint); SkColor outputColor; EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); EXPECT_EQ(color, outputColor); color = SkColorSetARGB(255, 22, 33, 44); paint.setColor(color); canvas.translate(-128, -128); canvas.drawRect(SkRect::MakeWH(382, 382), paint); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); color = SkColorSetARGB(255, 33, 44, 55); paint.setColor(color); canvas.drawRect(SkRect::MakeWH(383, 383), paint); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); EXPECT_EQ(color, outputColor); color = SkColorSetARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRect(SkRect::MakeWH(383, 383), paint); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); EXPECT_EQ(outputColor, SkColorSetARGB(255, 33, 44, 55)); color = SkColorSetARGB(128, 128, 128, 128); paint.setColor(color); canvas.drawRect(SkRect::MakeWH(383, 383), paint); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); paint.setXfermodeMode(SkXfermode::kClear_Mode); canvas.drawRect(SkRect::MakeWH(382, 382), paint); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); canvas.drawRect(SkRect::MakeWH(383, 383), paint); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); canvas.translate(128, 128); color = SkColorSetARGB(255, 11, 22, 33); paint.setColor(color); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); canvas.drawRect(SkRect::MakeWH(255, 255), paint); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); EXPECT_EQ(color, outputColor); canvas.rotate(50); canvas.drawRect(SkRect::MakeWH(255, 255), paint); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); } TEST(AnalysisCanvasTest, ClipPath) { SkBitmap emptyBitmap; emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); SkPath path; path.moveTo(0, 0); path.lineTo(255, 0); path.lineTo(255, 255); path.lineTo(0, 255); SkColor outputColor; SolidColorFill(canvas); canvas.clipPath(path); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); canvas.save(); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); canvas.clipPath(path); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); canvas.restore(); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); SolidColorFill(canvas); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); } TEST(AnalysisCanvasTest, SaveLayerRestore) { SkBitmap emptyBitmap; emptyBitmap.setConfig(SkBitmap::kNo_Config, 255, 255); skia::AnalysisDevice device(emptyBitmap); skia::AnalysisCanvas canvas(&device); SkColor outputColor; SolidColorFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); SkRect bounds = SkRect::MakeWH(255, 255); SkPaint paint; paint.setColor(SkColorSetARGB(255, 255, 255, 255)); paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); // This should force non-transparency canvas.saveLayer(&bounds, &paint, SkCanvas::kMatrix_SaveFlag); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); TransparentFill(canvas); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); SolidColorFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); paint.setXfermodeMode(SkXfermode::kDst_Mode); // This should force non-solid color canvas.saveLayer(&bounds, &paint, SkCanvas::kMatrix_SaveFlag); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); TransparentFill(canvas); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); SolidColorFill(canvas); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); canvas.restore(); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); TransparentFill(canvas); EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); SolidColorFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); canvas.restore(); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); TransparentFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); SolidColorFill(canvas); EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); } TEST(AnalysisCanvasTest, HasText) { int width = 200; int height = 100; SkBitmap bitmap; bitmap.setConfig(SkBitmap::kNo_Config, width, height); const char* text = "A"; size_t byteLength = 1; SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25)); SkPath path; path.moveTo(point); path.lineTo(SkIntToScalar(75), SkIntToScalar(75)); SkPaint paint; paint.setColor(SK_ColorGRAY); paint.setTextSize(SkIntToScalar(10)); { skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); // Test after initialization. EXPECT_FALSE(canvas.HasText()); // Test drawing anything other than text. canvas.drawRect(SkRect::MakeWH(width/2, height), paint); EXPECT_FALSE(canvas.HasText()); } { // Test SkCanvas::drawText. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawText(text, byteLength, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); } { // Test SkCanvas::drawPosText. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawPosText(text, byteLength, &point, paint); EXPECT_TRUE(canvas.HasText()); } { // Test SkCanvas::drawPosTextH. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawPosTextH(text, byteLength, &point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); } { // Test SkCanvas::drawTextOnPathHV. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawTextOnPathHV(text, byteLength, path, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); } { // Test SkCanvas::drawTextOnPath. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawTextOnPath(text, byteLength, path, NULL, paint); EXPECT_TRUE(canvas.HasText()); } { // Text under opaque rect. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawText(text, byteLength, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); canvas.drawRect(SkRect::MakeWH(width, height), paint); EXPECT_FALSE(canvas.HasText()); } { // Text under translucent rect. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawText(text, byteLength, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); SkPaint translucentPaint; translucentPaint.setColor(0x88FFFFFF); canvas.drawRect(SkRect::MakeWH(width, height), translucentPaint); EXPECT_TRUE(canvas.HasText()); } { // Text under rect in clear mode. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawText(text, byteLength, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); SkPaint clearModePaint; clearModePaint.setXfermodeMode(SkXfermode::kClear_Mode); canvas.drawRect(SkRect::MakeWH(width, height), clearModePaint); EXPECT_FALSE(canvas.HasText()); } { // Clear. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.drawText(text, byteLength, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); canvas.clear(SK_ColorGRAY); EXPECT_FALSE(canvas.HasText()); } { // Text inside clip region. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.clipRect(SkRect::MakeWH(100, 100)); canvas.drawText(text, byteLength, point.fX, point.fY, paint); EXPECT_TRUE(canvas.HasText()); } { // Text outside clip region. skia::AnalysisDevice device(bitmap); skia::AnalysisCanvas canvas(&device); canvas.clipRect(SkRect::MakeXYWH(100, 0, 100, 100)); canvas.drawText(text, byteLength, point.fX, point.fY, paint); // Analysis device does not do any clipping. // So even when text is outside the clip region, // it is marked as having the text. // TODO(alokp): We may be able to do some trivial rejection. EXPECT_TRUE(canvas.HasText()); } } } // namespace skia