| Index: base/gfx/vector_canvas_unittest.cc
|
| ===================================================================
|
| --- base/gfx/vector_canvas_unittest.cc (revision 5678)
|
| +++ base/gfx/vector_canvas_unittest.cc (working copy)
|
| @@ -1,1008 +0,0 @@
|
| -// Copyright (c) 2006-2008 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/gfx/vector_canvas.h"
|
| -
|
| -#include <vector>
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/file_util.h"
|
| -#include "base/gfx/gdi_util.h"
|
| -#include "base/gfx/png_decoder.h"
|
| -#include "base/gfx/png_encoder.h"
|
| -#include "base/gfx/size.h"
|
| -#include "base/path_service.h"
|
| -#include "base/string_util.h"
|
| -#include "base/win_util.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -#include "SkDashPathEffect.h"
|
| -
|
| -namespace {
|
| -
|
| -const wchar_t* const kGenerateSwitch = L"vector-canvas-generate";
|
| -
|
| -// Base class for unit test that uses data. It initializes a directory path
|
| -// based on the test's name.
|
| -class DataUnitTest : public testing::Test {
|
| - public:
|
| - DataUnitTest(const std::wstring& base_path) : base_path_(base_path) { }
|
| -
|
| - protected:
|
| - // Load the test's data path.
|
| - virtual void SetUp() {
|
| - const testing::TestInfo& test_info =
|
| - *testing::UnitTest::GetInstance()->current_test_info();
|
| - PathService::Get(base::DIR_SOURCE_ROOT, &test_dir_);
|
| - file_util::AppendToPath(&test_dir_, base_path_);
|
| - file_util::AppendToPath(&test_dir_, L"data");
|
| - file_util::AppendToPath(&test_dir_,
|
| - ASCIIToWide(test_info.test_case_name()));
|
| - file_util::AppendToPath(&test_dir_, ASCIIToWide(test_info.name()));
|
| -
|
| - // Hack for a quick lowercase. We assume all the tests names are ASCII.
|
| - std::string tmp(WideToASCII(test_dir_));
|
| - for (size_t i = 0; i < tmp.size(); ++i)
|
| - tmp[i] = ToLowerASCII(tmp[i]);
|
| - test_dir_ = ASCIIToWide(tmp);
|
| - }
|
| -
|
| - // Returns the fully qualified path of directory containing test data files.
|
| - const std::wstring& test_dir() const {
|
| - return test_dir_;
|
| - }
|
| -
|
| - // Returns the fully qualified path of a data file.
|
| - std::wstring test_file(const std::wstring& filename) const {
|
| - // Hack for a quick lowercase. We assume all the test data file names are
|
| - // ASCII.
|
| - std::string tmp(WideToASCII(filename));
|
| - for (size_t i = 0; i < tmp.size(); ++i)
|
| - tmp[i] = ToLowerASCII(tmp[i]);
|
| -
|
| - std::wstring path(test_dir());
|
| - file_util::AppendToPath(&path, ASCIIToWide(tmp));
|
| - return path;
|
| - }
|
| -
|
| - private:
|
| - // Path where the unit test is coming from: base, net, chrome, etc.
|
| - std::wstring base_path_;
|
| -
|
| - // Path to directory used to contain the test data.
|
| - std::wstring test_dir_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(DataUnitTest);
|
| -};
|
| -
|
| -// Lightweight HDC management.
|
| -class Context {
|
| - public:
|
| - Context() : context_(CreateCompatibleDC(NULL)) {
|
| - EXPECT_TRUE(context_);
|
| - }
|
| - ~Context() {
|
| - DeleteDC(context_);
|
| - }
|
| -
|
| - HDC context() const { return context_; }
|
| -
|
| - private:
|
| - HDC context_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(Context);
|
| -};
|
| -
|
| -// Lightweight HBITMAP management.
|
| -class Bitmap {
|
| - public:
|
| - Bitmap(const Context& context, int x, int y) {
|
| - BITMAPINFOHEADER hdr;
|
| - gfx::CreateBitmapHeader(x, y, &hdr);
|
| - bitmap_ = CreateDIBSection(context.context(),
|
| - reinterpret_cast<BITMAPINFO*>(&hdr), 0,
|
| - &data_, NULL, 0);
|
| - EXPECT_TRUE(bitmap_);
|
| - EXPECT_TRUE(SelectObject(context.context(), bitmap_));
|
| - }
|
| - ~Bitmap() {
|
| - EXPECT_TRUE(DeleteObject(bitmap_));
|
| - }
|
| -
|
| - private:
|
| - HBITMAP bitmap_;
|
| -
|
| - void* data_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(Bitmap);
|
| -};
|
| -
|
| -// Lightweight raw-bitmap management. The image, once initialized, is immuable.
|
| -// It is mainly used for comparison.
|
| -class Image {
|
| - public:
|
| - // Creates the image from the given filename on disk.
|
| - Image(const std::wstring& filename) : ignore_alpha_(true) {
|
| - std::string compressed;
|
| - file_util::ReadFileToString(filename, &compressed);
|
| - EXPECT_TRUE(compressed.size());
|
| -
|
| - int w;
|
| - int h;
|
| - EXPECT_TRUE(PNGDecoder::Decode(
|
| - reinterpret_cast<const unsigned char*>(compressed.c_str()),
|
| - compressed.size(), PNGDecoder::FORMAT_BGRA, &data_, &w, &h));
|
| - size_.SetSize(w, h);
|
| - row_length_ = w * sizeof(uint32);
|
| - }
|
| -
|
| - // Loads the image from a canvas.
|
| - Image(const gfx::PlatformCanvasWin& canvas) : ignore_alpha_(true) {
|
| - // Use a different way to access the bitmap. The normal way would be to
|
| - // query the SkBitmap.
|
| - HDC context = canvas.getTopPlatformDevice().getBitmapDC();
|
| - HGDIOBJ bitmap = GetCurrentObject(context, OBJ_BITMAP);
|
| - EXPECT_TRUE(bitmap != NULL);
|
| - // Initialize the clip region to the entire bitmap.
|
| - BITMAP bitmap_data;
|
| - EXPECT_EQ(GetObject(bitmap, sizeof(BITMAP), &bitmap_data),
|
| - sizeof(BITMAP));
|
| - size_.SetSize(bitmap_data.bmWidth, bitmap_data.bmHeight);
|
| - row_length_ = bitmap_data.bmWidthBytes;
|
| - size_t size = row_length_ * size_.height();
|
| - data_.resize(size);
|
| - memcpy(&*data_.begin(), bitmap_data.bmBits, size);
|
| - }
|
| -
|
| - // Loads the image from a canvas.
|
| - Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
|
| - SkAutoLockPixels lock(bitmap);
|
| - size_.SetSize(bitmap.width(), bitmap.height());
|
| - row_length_ = static_cast<int>(bitmap.rowBytes());
|
| - size_t size = row_length_ * size_.height();
|
| - data_.resize(size);
|
| - memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size);
|
| - }
|
| -
|
| - const gfx::Size& size() const {
|
| - return size_;
|
| - }
|
| -
|
| - int row_length() const {
|
| - return row_length_;
|
| - }
|
| -
|
| - // Save the image to a png file. Used to create the initial test files.
|
| - void SaveToFile(const std::wstring& filename) {
|
| - std::vector<unsigned char> compressed;
|
| - ASSERT_TRUE(PNGEncoder::Encode(&*data_.begin(),
|
| - PNGEncoder::FORMAT_BGRA,
|
| - size_.width(),
|
| - size_.height(),
|
| - row_length_,
|
| - true,
|
| - &compressed));
|
| - ASSERT_TRUE(compressed.size());
|
| - FILE* f = file_util::OpenFile(filename, "wb");
|
| - ASSERT_TRUE(f);
|
| - ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
|
| - compressed.size());
|
| - file_util::CloseFile(f);
|
| - }
|
| -
|
| - // Returns the percentage of the image that is different from the other,
|
| - // between 0 and 100.
|
| - double PercentageDifferent(const Image& rhs) const {
|
| - if (size_ != rhs.size_ || row_length_ != rhs.row_length_ ||
|
| - size_.width() == 0 || size_.height() == 0)
|
| - return 100.; // When of different size or empty, they are 100% different.
|
| -
|
| - // Compute pixels different in the overlap
|
| - int pixels_different = 0;
|
| - for (int y = 0; y < size_.height(); ++y) {
|
| - for (int x = 0; x < size_.width(); ++x) {
|
| - uint32_t lhs_pixel = pixel_at(x, y);
|
| - uint32_t rhs_pixel = rhs.pixel_at(x, y);
|
| - if (lhs_pixel != rhs_pixel)
|
| - ++pixels_different;
|
| - }
|
| - }
|
| -
|
| - // Like the WebKit ImageDiff tool, we define percentage different in terms
|
| - // of the size of the 'actual' bitmap.
|
| - double total_pixels = static_cast<double>(size_.width()) *
|
| - static_cast<double>(size_.height());
|
| - return static_cast<double>(pixels_different) / total_pixels * 100.;
|
| - }
|
| -
|
| - // Returns the 0x0RGB or 0xARGB value of the pixel at the given location,
|
| - // depending on ignore_alpha_.
|
| - uint32 pixel_at(int x, int y) const {
|
| - EXPECT_TRUE(x >= 0 && x < size_.width());
|
| - EXPECT_TRUE(y >= 0 && y < size_.height());
|
| - const uint32* data = reinterpret_cast<const uint32*>(&*data_.begin());
|
| - const uint32* data_row = data + y * row_length_ / sizeof(uint32);
|
| - if (ignore_alpha_)
|
| - return data_row[x] & 0xFFFFFF; // Strip out A.
|
| - else
|
| - return data_row[x];
|
| - }
|
| -
|
| - private:
|
| - // Pixel dimensions of the image.
|
| - gfx::Size size_;
|
| -
|
| - // Length of a line in bytes.
|
| - int row_length_;
|
| -
|
| - // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
|
| - // 0xABGR).
|
| - std::vector<unsigned char> data_;
|
| -
|
| - // Flag to signal if the comparison functions should ignore the alpha channel.
|
| - const bool ignore_alpha_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(Image);
|
| -};
|
| -
|
| -// Base for tests. Capability to process an image.
|
| -class ImageTest : public DataUnitTest {
|
| - public:
|
| - typedef DataUnitTest parent;
|
| -
|
| - // In what state is the test running.
|
| - enum ProcessAction {
|
| - GENERATE,
|
| - COMPARE,
|
| - NOOP,
|
| - };
|
| -
|
| - ImageTest(const std::wstring& base_path, ProcessAction default_action)
|
| - : parent(base_path),
|
| - action_(default_action) {
|
| - }
|
| -
|
| - protected:
|
| - virtual void SetUp() {
|
| - parent::SetUp();
|
| -
|
| - if (action_ == GENERATE) {
|
| - // Make sure the directory exist.
|
| - file_util::CreateDirectory(test_dir());
|
| - }
|
| - }
|
| -
|
| - // Compares or saves the bitmap currently loaded in the context, depending on
|
| - // kGenerating value. Returns 0 on success or any positive value between ]0,
|
| - // 100] on failure. The return value is the percentage of difference between
|
| - // the image in the file and the image in the canvas.
|
| - double ProcessCanvas(const gfx::PlatformCanvasWin& canvas,
|
| - std::wstring filename) const {
|
| - filename += L".png";
|
| - switch (action_) {
|
| - case GENERATE:
|
| - SaveImage(canvas, filename);
|
| - return 0.;
|
| - case COMPARE:
|
| - return CompareImage(canvas, filename);
|
| - case NOOP:
|
| - return 0;
|
| - default:
|
| - // Invalid state, returns that the image is 100 different.
|
| - return 100.;
|
| - }
|
| - }
|
| -
|
| - // Compares the bitmap currently loaded in the context with the file. Returns
|
| - // the percentage of pixel difference between both images, between 0 and 100.
|
| - double CompareImage(const gfx::PlatformCanvasWin& canvas,
|
| - const std::wstring& filename) const {
|
| - Image image1(canvas);
|
| - Image image2(test_file(filename));
|
| - double diff = image1.PercentageDifferent(image2);
|
| - return diff;
|
| - }
|
| -
|
| - // Saves the bitmap currently loaded in the context into the file.
|
| - void SaveImage(const gfx::PlatformCanvasWin& canvas,
|
| - const std::wstring& filename) const {
|
| - Image(canvas).SaveToFile(test_file(filename));
|
| - }
|
| -
|
| - ProcessAction action_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(ImageTest);
|
| -};
|
| -
|
| -// Premultiply the Alpha channel on the R, B and G channels.
|
| -void Premultiply(SkBitmap bitmap) {
|
| - SkAutoLockPixels lock(bitmap);
|
| - for (int x = 0; x < bitmap.width(); ++x) {
|
| - for (int y = 0; y < bitmap.height(); ++y) {
|
| - uint32_t* pixel_addr = bitmap.getAddr32(x, y);
|
| - uint32_t color = *pixel_addr;
|
| - BYTE alpha = SkColorGetA(color);
|
| - if (!alpha) {
|
| - *pixel_addr = 0;
|
| - } else {
|
| - BYTE alpha_offset = alpha / 2;
|
| - *pixel_addr = SkColorSetARGB(
|
| - SkColorGetA(color),
|
| - (SkColorGetR(color) * 255 + alpha_offset) / alpha,
|
| - (SkColorGetG(color) * 255 + alpha_offset) / alpha,
|
| - (SkColorGetB(color) * 255 + alpha_offset) / alpha);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LoadPngFileToSkBitmap(const std::wstring& file, SkBitmap* bitmap) {
|
| - std::string compressed;
|
| - file_util::ReadFileToString(file, &compressed);
|
| - EXPECT_TRUE(compressed.size());
|
| - // Extra-lame. If you care, fix it.
|
| - std::vector<unsigned char> data;
|
| - data.assign(reinterpret_cast<const unsigned char*>(compressed.c_str()),
|
| - reinterpret_cast<const unsigned char*>(compressed.c_str() +
|
| - compressed.size()));
|
| - EXPECT_TRUE(PNGDecoder::Decode(&data, bitmap));
|
| - EXPECT_FALSE(bitmap->isOpaque());
|
| - Premultiply(*bitmap);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// Streams an image.
|
| -inline std::ostream& operator<<(std::ostream& out, const Image& image) {
|
| - return out << "Image(" << image.size() << ", " << image.row_length() << ")";
|
| -}
|
| -
|
| -// Runs simultaneously the same drawing commands on VectorCanvas and
|
| -// PlatformCanvas and compare the results.
|
| -class VectorCanvasTest : public ImageTest {
|
| - public:
|
| - typedef ImageTest parent;
|
| -
|
| - VectorCanvasTest() : parent(L"base", CurrentMode()), compare_canvas_(true) {
|
| - }
|
| -
|
| - protected:
|
| - virtual void SetUp() {
|
| - parent::SetUp();
|
| - Init(100);
|
| - number_ = 0;
|
| - }
|
| -
|
| - virtual void TearDown() {
|
| - delete pcanvas_;
|
| - pcanvas_ = NULL;
|
| -
|
| - delete vcanvas_;
|
| - vcanvas_ = NULL;
|
| -
|
| - delete bitmap_;
|
| - bitmap_ = NULL;
|
| -
|
| - delete context_;
|
| - context_ = NULL;
|
| -
|
| - parent::TearDown();
|
| - }
|
| -
|
| - void Init(int size) {
|
| - size_ = size;
|
| - context_ = new Context();
|
| - bitmap_ = new Bitmap(*context_, size_, size_);
|
| - vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_);
|
| - pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false);
|
| -
|
| - // Clear white.
|
| - vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
|
| - pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
|
| - }
|
| -
|
| - // Compares both canvas and returns the pixel difference in percentage between
|
| - // both images. 0 on success and ]0, 100] on failure.
|
| - double ProcessImage(const std::wstring& filename) {
|
| - std::wstring number(StringPrintf(L"%02d_", number_++));
|
| - double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename);
|
| - double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename);
|
| - if (!compare_canvas_)
|
| - return std::max(diff1, diff2);
|
| -
|
| - Image image1(*vcanvas_);
|
| - Image image2(*pcanvas_);
|
| - double diff = image1.PercentageDifferent(image2);
|
| - return std::max(std::max(diff1, diff2), diff);
|
| - }
|
| -
|
| - // Returns COMPARE, which is the default. If kGenerateSwitch command
|
| - // line argument is used to start this process, GENERATE is returned instead.
|
| - static ProcessAction CurrentMode() {
|
| - return CommandLine().HasSwitch(kGenerateSwitch) ? GENERATE : COMPARE;
|
| - }
|
| -
|
| - // Length in x and y of the square canvas.
|
| - int size_;
|
| -
|
| - // Current image number in the current test. Used to number of test files.
|
| - int number_;
|
| -
|
| - // A temporary HDC to draw into.
|
| - Context* context_;
|
| -
|
| - // Bitmap created inside context_.
|
| - Bitmap* bitmap_;
|
| -
|
| - // Vector based canvas.
|
| - gfx::VectorCanvas* vcanvas_;
|
| -
|
| - // Pixel based canvas.
|
| - gfx::PlatformCanvasWin* pcanvas_;
|
| -
|
| - // When true (default), vcanvas_ and pcanvas_ contents are compared and
|
| - // verified to be identical.
|
| - bool compare_canvas_;
|
| -};
|
| -
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Actual tests
|
| -
|
| -TEST_F(VectorCanvasTest, Uninitialized) {
|
| - // Do a little mubadumba do get uninitialized stuff.
|
| - VectorCanvasTest::TearDown();
|
| -
|
| - // The goal is not to verify that have the same uninitialized data.
|
| - compare_canvas_ = false;
|
| -
|
| - context_ = new Context();
|
| - bitmap_ = new Bitmap(*context_, size_, size_);
|
| - vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_);
|
| - pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false);
|
| -
|
| - // VectorCanvas default initialization is black.
|
| - // PlatformCanvas default initialization is almost white 0x01FFFEFD (invalid
|
| - // Skia color) in both Debug and Release. See magicTransparencyColor in
|
| - // platform_device.cc
|
| - EXPECT_EQ(0., ProcessImage(L"empty"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, BasicDrawing) {
|
| - EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
|
| - << L"clean";
|
| - EXPECT_EQ(0., ProcessImage(L"clean"));
|
| -
|
| - // Clear white.
|
| - {
|
| - vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
|
| - pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawARGB"));
|
| -
|
| - // Diagonal line top-left to bottom-right.
|
| - {
|
| - SkPaint paint;
|
| - // Default color is black.
|
| - vcanvas_->drawLine(10, 10, 90, 90, paint);
|
| - pcanvas_->drawLine(10, 10, 90, 90, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawLine_black"));
|
| -
|
| - // Rect.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorGREEN);
|
| - vcanvas_->drawRectCoords(25, 25, 75, 75, paint);
|
| - pcanvas_->drawRectCoords(25, 25, 75, 75, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawRect_green"));
|
| -
|
| - // A single-point rect doesn't leave any mark.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorBLUE);
|
| - vcanvas_->drawRectCoords(5, 5, 5, 5, paint);
|
| - pcanvas_->drawRectCoords(5, 5, 5, 5, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawRect_noop"));
|
| -
|
| - // Rect.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorBLUE);
|
| - vcanvas_->drawRectCoords(75, 50, 80, 55, paint);
|
| - pcanvas_->drawRectCoords(75, 50, 80, 55, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawRect_noop"));
|
| -
|
| - // Empty again
|
| - {
|
| - vcanvas_->drawPaint(SkPaint());
|
| - pcanvas_->drawPaint(SkPaint());
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawPaint_black"));
|
| -
|
| - // Horizontal line left to right.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| - vcanvas_->drawLine(10, 20, 90, 20, paint);
|
| - pcanvas_->drawLine(10, 20, 90, 20, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawLine_left_to_right"));
|
| -
|
| - // Vertical line downward.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| - vcanvas_->drawLine(30, 10, 30, 90, paint);
|
| - pcanvas_->drawLine(30, 10, 30, 90, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawLine_red"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, Circles) {
|
| - // There is NO WAY to make them agree. At least verify that the output doesn't
|
| - // change across versions. This test is disabled. See bug 1060231.
|
| - compare_canvas_ = false;
|
| -
|
| - // Stroked Circle.
|
| - {
|
| - SkPaint paint;
|
| - SkPath path;
|
| - path.addCircle(50, 75, 10);
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| - paint.setColor(SK_ColorMAGENTA);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"circle_stroke"));
|
| -
|
| - // Filled Circle.
|
| - {
|
| - SkPaint paint;
|
| - SkPath path;
|
| - path.addCircle(50, 25, 10);
|
| - paint.setStyle(SkPaint::kFill_Style);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"circle_fill"));
|
| -
|
| - // Stroked Circle over.
|
| - {
|
| - SkPaint paint;
|
| - SkPath path;
|
| - path.addCircle(50, 25, 10);
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| - paint.setColor(SK_ColorBLUE);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"circle_over_strike"));
|
| -
|
| - // Stroke and Fill Circle.
|
| - {
|
| - SkPaint paint;
|
| - SkPath path;
|
| - path.addCircle(12, 50, 10);
|
| - paint.setStyle(SkPaint::kStrokeAndFill_Style);
|
| - paint.setColor(SK_ColorRED);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"circle_stroke_and_fill"));
|
| -
|
| - // Line + Quad + Cubic.
|
| - {
|
| - SkPaint paint;
|
| - SkPath path;
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| - paint.setColor(SK_ColorGREEN);
|
| - path.moveTo(1, 1);
|
| - path.lineTo(60, 40);
|
| - path.lineTo(80, 80);
|
| - path.quadTo(20, 50, 10, 90);
|
| - path.quadTo(50, 20, 90, 10);
|
| - path.cubicTo(20, 40, 50, 50, 10, 10);
|
| - path.cubicTo(30, 20, 50, 50, 90, 10);
|
| - path.addRect(90, 90, 95, 96);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"mixed_stroke"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, LineOrientation) {
|
| - // There is NO WAY to make them agree. At least verify that the output doesn't
|
| - // change across versions. This test is disabled. See bug 1060231.
|
| - compare_canvas_ = false;
|
| -
|
| - // Horizontal lines.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| - // Left to right.
|
| - vcanvas_->drawLine(10, 20, 90, 20, paint);
|
| - pcanvas_->drawLine(10, 20, 90, 20, paint);
|
| - // Right to left.
|
| - vcanvas_->drawLine(90, 30, 10, 30, paint);
|
| - pcanvas_->drawLine(90, 30, 10, 30, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"horizontal"));
|
| -
|
| - // Vertical lines.
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| - // Top down.
|
| - vcanvas_->drawLine(20, 10, 20, 90, paint);
|
| - pcanvas_->drawLine(20, 10, 20, 90, paint);
|
| - // Bottom up.
|
| - vcanvas_->drawLine(30, 90, 30, 10, paint);
|
| - pcanvas_->drawLine(30, 90, 30, 10, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"vertical"));
|
| -
|
| - // Try again with a 180 degres rotation.
|
| - vcanvas_->rotate(180);
|
| - pcanvas_->rotate(180);
|
| -
|
| - // Horizontal lines (rotated).
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| - vcanvas_->drawLine(-10, -25, -90, -25, paint);
|
| - pcanvas_->drawLine(-10, -25, -90, -25, paint);
|
| - vcanvas_->drawLine(-90, -35, -10, -35, paint);
|
| - pcanvas_->drawLine(-90, -35, -10, -35, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"horizontal_180"));
|
| -
|
| - // Vertical lines (rotated).
|
| - {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| - vcanvas_->drawLine(-25, -10, -25, -90, paint);
|
| - pcanvas_->drawLine(-25, -10, -25, -90, paint);
|
| - vcanvas_->drawLine(-35, -90, -35, -10, paint);
|
| - pcanvas_->drawLine(-35, -90, -35, -10, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"vertical_180"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, PathOrientation) {
|
| - // There is NO WAY to make them agree. At least verify that the output doesn't
|
| - // change across versions. This test is disabled. See bug 1060231.
|
| - compare_canvas_ = false;
|
| -
|
| - // Horizontal lines.
|
| - {
|
| - SkPaint paint;
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| - paint.setColor(SK_ColorRED);
|
| - SkPath path;
|
| - SkPoint start;
|
| - start.set(10, 20);
|
| - SkPoint end;
|
| - end.set(90, 20);
|
| - path.moveTo(start);
|
| - path.lineTo(end);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawPath_ltr"));
|
| -
|
| - // Horizontal lines.
|
| - {
|
| - SkPaint paint;
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| - paint.setColor(SK_ColorRED);
|
| - SkPath path;
|
| - SkPoint start;
|
| - start.set(90, 30);
|
| - SkPoint end;
|
| - end.set(10, 30);
|
| - path.moveTo(start);
|
| - path.lineTo(end);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"drawPath_rtl"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, DiagonalLines) {
|
| - SkPaint paint;
|
| - paint.setColor(SK_ColorRED);
|
| -
|
| - vcanvas_->drawLine(10, 10, 90, 90, paint);
|
| - pcanvas_->drawLine(10, 10, 90, 90, paint);
|
| - EXPECT_EQ(0., ProcessImage(L"nw-se"));
|
| -
|
| - // Starting here, there is NO WAY to make them agree. At least verify that the
|
| - // output doesn't change across versions. This test is disabled. See bug
|
| - // 1060231.
|
| - compare_canvas_ = false;
|
| -
|
| - vcanvas_->drawLine(10, 95, 90, 15, paint);
|
| - pcanvas_->drawLine(10, 95, 90, 15, paint);
|
| - EXPECT_EQ(0., ProcessImage(L"sw-ne"));
|
| -
|
| - vcanvas_->drawLine(90, 10, 10, 90, paint);
|
| - pcanvas_->drawLine(90, 10, 10, 90, paint);
|
| - EXPECT_EQ(0., ProcessImage(L"ne-sw"));
|
| -
|
| - vcanvas_->drawLine(95, 90, 15, 10, paint);
|
| - pcanvas_->drawLine(95, 90, 15, 10, paint);
|
| - EXPECT_EQ(0., ProcessImage(L"se-nw"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, PathEffects) {
|
| - {
|
| - SkPaint paint;
|
| - SkScalar intervals[] = { 1, 1 };
|
| - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
|
| - 0);
|
| - paint.setPathEffect(effect)->unref();
|
| - paint.setColor(SK_ColorMAGENTA);
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| -
|
| - vcanvas_->drawLine(10, 10, 90, 10, paint);
|
| - pcanvas_->drawLine(10, 10, 90, 10, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"dash_line"));
|
| -
|
| -
|
| - // Starting here, there is NO WAY to make them agree. At least verify that the
|
| - // output doesn't change across versions. This test is disabled. See bug
|
| - // 1060231.
|
| - compare_canvas_ = false;
|
| -
|
| - {
|
| - SkPaint paint;
|
| - SkScalar intervals[] = { 3, 5 };
|
| - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
|
| - 0);
|
| - paint.setPathEffect(effect)->unref();
|
| - paint.setColor(SK_ColorMAGENTA);
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| -
|
| - SkPath path;
|
| - path.moveTo(10, 15);
|
| - path.lineTo(90, 15);
|
| - path.lineTo(90, 90);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"dash_path"));
|
| -
|
| - {
|
| - SkPaint paint;
|
| - SkScalar intervals[] = { 2, 1 };
|
| - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
|
| - 0);
|
| - paint.setPathEffect(effect)->unref();
|
| - paint.setColor(SK_ColorMAGENTA);
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| -
|
| - vcanvas_->drawRectCoords(20, 20, 30, 30, paint);
|
| - pcanvas_->drawRectCoords(20, 20, 30, 30, paint);
|
| - }
|
| - EXPECT_EQ(0., ProcessImage(L"dash_rect"));
|
| -
|
| - // This thing looks like it has been drawn by a 3 years old kid. I haven't
|
| - // filed a bug on this since I guess nobody is expecting this to look nice.
|
| - {
|
| - SkPaint paint;
|
| - SkScalar intervals[] = { 1, 1 };
|
| - SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
|
| - 0);
|
| - paint.setPathEffect(effect)->unref();
|
| - paint.setColor(SK_ColorMAGENTA);
|
| - paint.setStyle(SkPaint::kStroke_Style);
|
| -
|
| - SkPath path;
|
| - path.addCircle(50, 75, 10);
|
| - vcanvas_->drawPath(path, paint);
|
| - pcanvas_->drawPath(path, paint);
|
| - EXPECT_EQ(0., ProcessImage(L"circle"));
|
| - }
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, Bitmaps) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - {
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap);
|
| - vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"opaque"));
|
| - }
|
| -
|
| - {
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap);
|
| - vcanvas_->drawBitmap(bitmap, 5, 15, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 5, 15, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"alpha"));
|
| - }
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, ClippingRect) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
|
| - SkRect rect;
|
| - rect.fLeft = 2;
|
| - rect.fTop = 2;
|
| - rect.fRight = 30.5f;
|
| - rect.fBottom = 30.5f;
|
| - vcanvas_->clipRect(rect);
|
| - pcanvas_->clipRect(rect);
|
| -
|
| - vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"rect"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, ClippingPath) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
|
| - SkPath path;
|
| - path.addCircle(20, 20, 10);
|
| - vcanvas_->clipPath(path);
|
| - pcanvas_->clipPath(path);
|
| -
|
| - vcanvas_->drawBitmap(bitmap, 14, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 14, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"path"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, ClippingCombined) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
|
| -
|
| - SkRect rect;
|
| - rect.fLeft = 2;
|
| - rect.fTop = 2;
|
| - rect.fRight = 30.5f;
|
| - rect.fBottom = 30.5f;
|
| - vcanvas_->clipRect(rect);
|
| - pcanvas_->clipRect(rect);
|
| - SkPath path;
|
| - path.addCircle(20, 20, 10);
|
| - vcanvas_->clipPath(path, SkRegion::kUnion_Op);
|
| - pcanvas_->clipPath(path, SkRegion::kUnion_Op);
|
| -
|
| - vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"combined"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, ClippingIntersect) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
|
| -
|
| - SkRect rect;
|
| - rect.fLeft = 2;
|
| - rect.fTop = 2;
|
| - rect.fRight = 30.5f;
|
| - rect.fBottom = 30.5f;
|
| - vcanvas_->clipRect(rect);
|
| - pcanvas_->clipRect(rect);
|
| - SkPath path;
|
| - path.addCircle(23, 23, 15);
|
| - vcanvas_->clipPath(path);
|
| - pcanvas_->clipPath(path);
|
| -
|
| - vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"intersect"));
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, ClippingClean) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
|
| - {
|
| - SkRegion old_region(pcanvas_->getTotalClip());
|
| - SkRect rect;
|
| - rect.fLeft = 2;
|
| - rect.fTop = 2;
|
| - rect.fRight = 30.5f;
|
| - rect.fBottom = 30.5f;
|
| - vcanvas_->clipRect(rect);
|
| - pcanvas_->clipRect(rect);
|
| -
|
| - vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"clipped"));
|
| - vcanvas_->clipRegion(old_region, SkRegion::kReplace_Op);
|
| - pcanvas_->clipRegion(old_region, SkRegion::kReplace_Op);
|
| - }
|
| - {
|
| - // Verify that the clipping region has been fixed back.
|
| - vcanvas_->drawBitmap(bitmap, 55, 3, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 55, 3, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"unclipped"));
|
| - }
|
| -}
|
| -
|
| -TEST_F(VectorCanvasTest, Matrix) {
|
| - // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
|
| - // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
|
| - // really care about Windows 2000 pixel colors.
|
| - if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
|
| - return;
|
| - SkBitmap bitmap;
|
| - LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
|
| - {
|
| - vcanvas_->translate(15, 3);
|
| - pcanvas_->translate(15, 3);
|
| - vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"translate1"));
|
| - }
|
| - {
|
| - vcanvas_->translate(-30, -23);
|
| - pcanvas_->translate(-30, -23);
|
| - vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"translate2"));
|
| - }
|
| - vcanvas_->resetMatrix();
|
| - pcanvas_->resetMatrix();
|
| -
|
| - // For scaling and rotation, they use a different algorithm (nearest
|
| - // neighborhood vs smoothing). At least verify that the output doesn't change
|
| - // across versions.
|
| - compare_canvas_ = false;
|
| -
|
| - {
|
| - vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
|
| - pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
|
| - vcanvas_->drawBitmap(bitmap, 1, 1, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 1, 1, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"scale"));
|
| - }
|
| - vcanvas_->resetMatrix();
|
| - pcanvas_->resetMatrix();
|
| -
|
| - {
|
| - vcanvas_->rotate(67);
|
| - pcanvas_->rotate(67);
|
| - vcanvas_->drawBitmap(bitmap, 20, -50, NULL);
|
| - pcanvas_->drawBitmap(bitmap, 20, -50, NULL);
|
| - EXPECT_EQ(0., ProcessImage(L"rotate"));
|
| - }
|
| -}
|
| -
|
|
|