普通文本  |  407行  |  12.26 KB

// 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