1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/build_config.h"
11 #include "base/command_line.h"
12 #include "base/file_util.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "skia/ext/vector_canvas.h"
18 #include "skia/ext/vector_platform_device_emf_win.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/skia/include/effects/SkDashPathEffect.h"
21 #include "ui/gfx/codec/png_codec.h"
22 #include "ui/gfx/size.h"
28 const char kGenerateSwitch[] = "vector-canvas-generate";
30 // Lightweight HDC management.
33 Context() : context_(CreateCompatibleDC(NULL)) {
34 EXPECT_TRUE(context_);
40 HDC context() const { return context_; }
45 DISALLOW_COPY_AND_ASSIGN(Context);
48 // Lightweight HBITMAP management.
51 Bitmap(const Context& context, int x, int y) {
53 hdr.biSize = sizeof(BITMAPINFOHEADER);
55 hdr.biHeight = -y; // Minus means top-down bitmap.
58 hdr.biCompression = BI_RGB; // No compression.
60 hdr.biXPelsPerMeter = 1;
61 hdr.biYPelsPerMeter = 1;
63 hdr.biClrImportant = 0;
64 bitmap_ = CreateDIBSection(context.context(),
65 reinterpret_cast<BITMAPINFO*>(&hdr), 0,
68 EXPECT_TRUE(SelectObject(context.context(), bitmap_));
71 EXPECT_TRUE(DeleteObject(bitmap_));
79 DISALLOW_COPY_AND_ASSIGN(Bitmap);
82 // Lightweight raw-bitmap management. The image, once initialized, is immuable.
83 // It is mainly used for comparison.
86 // Creates the image from the given filename on disk.
87 explicit Image(const base::FilePath& filename) : ignore_alpha_(true) {
88 std::string compressed;
89 base::ReadFileToString(filename, &compressed);
90 EXPECT_TRUE(compressed.size());
93 EXPECT_TRUE(gfx::PNGCodec::Decode(
94 reinterpret_cast<const unsigned char*>(compressed.data()),
95 compressed.size(), &bitmap));
99 // Loads the image from a canvas.
100 Image(skia::PlatformCanvas& canvas) : ignore_alpha_(true) {
101 // Use a different way to access the bitmap. The normal way would be to
102 // query the SkBitmap.
103 skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
104 HDC context = scoped_platform_paint.GetPlatformSurface();
105 HGDIOBJ bitmap = GetCurrentObject(context, OBJ_BITMAP);
106 EXPECT_TRUE(bitmap != NULL);
107 // Initialize the clip region to the entire bitmap.
109 EXPECT_EQ(GetObject(bitmap, sizeof(BITMAP), &bitmap_data), sizeof(BITMAP));
110 width_ = bitmap_data.bmWidth;
111 height_ = bitmap_data.bmHeight;
112 row_length_ = bitmap_data.bmWidthBytes;
113 size_t size = row_length_ * height_;
115 memcpy(&*data_.begin(), bitmap_data.bmBits, size);
118 // Loads the image from a canvas.
119 Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
123 int width() const { return width_; }
124 int height() const { return height_; }
125 int row_length() const { return row_length_; }
127 // Save the image to a png file. Used to create the initial test files.
128 void SaveToFile(const base::FilePath& filename) {
129 std::vector<unsigned char> compressed;
130 ASSERT_TRUE(gfx::PNGCodec::Encode(&*data_.begin(),
131 gfx::PNGCodec::FORMAT_BGRA,
132 gfx::Size(width_, height_),
135 std::vector<gfx::PNGCodec::Comment>(),
137 ASSERT_TRUE(compressed.size());
138 FILE* f = file_util::OpenFile(filename, "wb");
140 ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
142 file_util::CloseFile(f);
145 // Returns the percentage of the image that is different from the other,
146 // between 0 and 100.
147 double PercentageDifferent(const Image& rhs) const {
148 if (width_ != rhs.width_ ||
149 height_ != rhs.height_ ||
150 row_length_ != rhs.row_length_ ||
153 return 100.; // When of different size or empty, they are 100% different.
155 // Compute pixels different in the overlap
156 int pixels_different = 0;
157 for (int y = 0; y < height_; ++y) {
158 for (int x = 0; x < width_; ++x) {
159 uint32_t lhs_pixel = pixel_at(x, y);
160 uint32_t rhs_pixel = rhs.pixel_at(x, y);
161 if (lhs_pixel != rhs_pixel)
166 // Like the WebKit ImageDiff tool, we define percentage different in terms
167 // of the size of the 'actual' bitmap.
168 double total_pixels = static_cast<double>(width_) *
169 static_cast<double>(height_);
170 return static_cast<double>(pixels_different) / total_pixels * 100.;
173 // Returns the 0x0RGB or 0xARGB value of the pixel at the given location,
174 // depending on ignore_alpha_.
175 uint32 pixel_at(int x, int y) const {
176 EXPECT_TRUE(x >= 0 && x < width_);
177 EXPECT_TRUE(y >= 0 && y < height_);
178 const uint32* data = reinterpret_cast<const uint32*>(&*data_.begin());
179 const uint32* data_row = data + y * row_length_ / sizeof(uint32);
181 return data_row[x] & 0xFFFFFF; // Strip out A.
187 void SetSkBitmap(const SkBitmap& bitmap) {
188 SkAutoLockPixels lock(bitmap);
189 width_ = bitmap.width();
190 height_ = bitmap.height();
191 row_length_ = static_cast<int>(bitmap.rowBytes());
192 size_t size = row_length_ * height_;
194 memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size);
198 // Pixel dimensions of the image.
202 // Length of a line in bytes.
205 // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
207 std::vector<unsigned char> data_;
209 // Flag to signal if the comparison functions should ignore the alpha channel.
210 const bool ignore_alpha_;
212 DISALLOW_COPY_AND_ASSIGN(Image);
215 // Base for tests. Capability to process an image.
216 class ImageTest : public testing::Test {
218 // In what state is the test running.
225 ImageTest(ProcessAction default_action)
226 : action_(default_action) {
230 virtual void SetUp() {
231 const testing::TestInfo& test_info =
232 *testing::UnitTest::GetInstance()->current_test_info();
233 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir_);
234 test_dir_ = test_dir_.AppendASCII("skia").
237 AppendASCII(test_info.test_case_name()).
238 AppendASCII(test_info.name());
240 // Hack for a quick lowercase. We assume all the tests names are ASCII.
241 base::FilePath::StringType tmp(test_dir_.value());
242 for (size_t i = 0; i < tmp.size(); ++i)
243 tmp[i] = base::ToLowerASCII(tmp[i]);
244 test_dir_ = base::FilePath(tmp);
246 if (action_ == GENERATE) {
247 // Make sure the directory exist.
248 file_util::CreateDirectory(test_dir_);
252 // Returns the fully qualified path of a data file.
253 base::FilePath test_file(const base::FilePath::StringType& filename) const {
254 // Hack for a quick lowercase. We assume all the test data file names are
257 std::string tmp = WideToASCII(filename);
259 std::string tmp(filename);
261 for (size_t i = 0; i < tmp.size(); ++i)
262 tmp[i] = base::ToLowerASCII(tmp[i]);
264 return test_dir_.AppendASCII(tmp);
267 // Compares or saves the bitmap currently loaded in the context, depending on
268 // kGenerating value. Returns 0 on success or any positive value between ]0,
269 // 100] on failure. The return value is the percentage of difference between
270 // the image in the file and the image in the canvas.
271 double ProcessCanvas(skia::PlatformCanvas& canvas,
272 base::FilePath::StringType filename) const {
273 filename = filename + FILE_PATH_LITERAL(".png");
276 SaveImage(canvas, filename);
279 return CompareImage(canvas, filename);
283 // Invalid state, returns that the image is 100 different.
288 // Compares the bitmap currently loaded in the context with the file. Returns
289 // the percentage of pixel difference between both images, between 0 and 100.
290 double CompareImage(skia::PlatformCanvas& canvas,
291 const base::FilePath::StringType& filename) const {
292 Image image1(canvas);
293 Image image2(test_file(filename));
294 double diff = image1.PercentageDifferent(image2);
298 // Saves the bitmap currently loaded in the context into the file.
299 void SaveImage(skia::PlatformCanvas& canvas,
300 const base::FilePath::StringType& filename) const {
301 Image(canvas).SaveToFile(test_file(filename));
304 ProcessAction action_;
306 // Path to directory used to contain the test data.
307 base::FilePath test_dir_;
309 DISALLOW_COPY_AND_ASSIGN(ImageTest);
312 // Premultiply the Alpha channel on the R, B and G channels.
313 void Premultiply(SkBitmap bitmap) {
314 SkAutoLockPixels lock(bitmap);
315 for (int x = 0; x < bitmap.width(); ++x) {
316 for (int y = 0; y < bitmap.height(); ++y) {
317 uint32_t* pixel_addr = bitmap.getAddr32(x, y);
318 uint32_t color = *pixel_addr;
319 BYTE alpha = SkColorGetA(color);
323 BYTE alpha_offset = alpha / 2;
324 *pixel_addr = SkColorSetARGB(
326 (SkColorGetR(color) * 255 + alpha_offset) / alpha,
327 (SkColorGetG(color) * 255 + alpha_offset) / alpha,
328 (SkColorGetB(color) * 255 + alpha_offset) / alpha);
334 void LoadPngFileToSkBitmap(const base::FilePath& filename,
337 std::string compressed;
338 base::ReadFileToString(base::MakeAbsoluteFilePath(filename), &compressed);
339 ASSERT_TRUE(compressed.size());
341 ASSERT_TRUE(gfx::PNGCodec::Decode(
342 reinterpret_cast<const unsigned char*>(compressed.data()),
343 compressed.size(), bitmap));
345 EXPECT_EQ(is_opaque, bitmap->isOpaque());
346 Premultiply(*bitmap);
352 inline std::ostream& operator<<(std::ostream& out, const Image& image) {
353 return out << "Image(" << image.width() << ", "
354 << image.height() << ", " << image.row_length() << ")";
357 // Runs simultaneously the same drawing commands on VectorCanvas and
358 // PlatformCanvas and compare the results.
359 class VectorCanvasTest : public ImageTest {
361 typedef ImageTest parent;
363 VectorCanvasTest() : parent(CurrentMode()), compare_canvas_(true) {
367 virtual void SetUp() {
373 virtual void TearDown() {
389 void Init(int size) {
391 context_ = new Context();
392 bitmap_ = new Bitmap(*context_, size_, size_);
393 vcanvas_ = new VectorCanvas(
394 VectorPlatformDeviceEmf::CreateDevice(
395 size_, size_, true, context_->context()));
396 pcanvas_ = CreatePlatformCanvas(size_, size_, false);
399 vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
400 pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
403 // Compares both canvas and returns the pixel difference in percentage between
404 // both images. 0 on success and ]0, 100] on failure.
405 double ProcessImage(const base::FilePath::StringType& filename) {
406 std::wstring number(base::StringPrintf(L"%02d_", number_++));
407 double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename);
408 double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename);
409 if (!compare_canvas_)
410 return std::max(diff1, diff2);
412 Image image1(*vcanvas_);
413 Image image2(*pcanvas_);
414 double diff = image1.PercentageDifferent(image2);
415 return std::max(std::max(diff1, diff2), diff);
418 // Returns COMPARE, which is the default. If kGenerateSwitch command
419 // line argument is used to start this process, GENERATE is returned instead.
420 static ProcessAction CurrentMode() {
421 return CommandLine::ForCurrentProcess()->HasSwitch(kGenerateSwitch) ?
425 // Length in x and y of the square canvas.
428 // Current image number in the current test. Used to number of test files.
431 // A temporary HDC to draw into.
434 // Bitmap created inside context_.
437 // Vector based canvas.
438 VectorCanvas* vcanvas_;
440 // Pixel based canvas.
441 PlatformCanvas* pcanvas_;
443 // When true (default), vcanvas_ and pcanvas_ contents are compared and
444 // verified to be identical.
445 bool compare_canvas_;
449 ////////////////////////////////////////////////////////////////////////////////
452 #if !defined(USE_AURA) // http://crbug.com/154358
454 TEST_F(VectorCanvasTest, BasicDrawing) {
455 EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
457 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
461 vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
462 pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
464 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawARGB")));
466 // Diagonal line top-left to bottom-right.
469 // Default color is black.
470 vcanvas_->drawLine(10, 10, 90, 90, paint);
471 pcanvas_->drawLine(10, 10, 90, 90, paint);
473 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_black")));
478 paint.setColor(SK_ColorGREEN);
479 vcanvas_->drawRectCoords(25, 25, 75, 75, paint);
480 pcanvas_->drawRectCoords(25, 25, 75, 75, paint);
482 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_green")));
484 // A single-point rect doesn't leave any mark.
487 paint.setColor(SK_ColorBLUE);
488 vcanvas_->drawRectCoords(5, 5, 5, 5, paint);
489 pcanvas_->drawRectCoords(5, 5, 5, 5, paint);
491 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
496 paint.setColor(SK_ColorBLUE);
497 vcanvas_->drawRectCoords(75, 50, 80, 55, paint);
498 pcanvas_->drawRectCoords(75, 50, 80, 55, paint);
500 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
504 vcanvas_->drawPaint(SkPaint());
505 pcanvas_->drawPaint(SkPaint());
507 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
509 // Horizontal line left to right.
512 paint.setColor(SK_ColorRED);
513 vcanvas_->drawLine(10, 20, 90, 20, paint);
514 pcanvas_->drawLine(10, 20, 90, 20, paint);
516 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_left_to_right")));
518 // Vertical line downward.
521 paint.setColor(SK_ColorRED);
522 vcanvas_->drawLine(30, 10, 30, 90, paint);
523 pcanvas_->drawLine(30, 10, 30, 90, paint);
525 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_red")));
528 TEST_F(VectorCanvasTest, Circles) {
529 // There is NO WAY to make them agree. At least verify that the output doesn't
530 // change across versions. This test is disabled. See bug 1060231.
531 compare_canvas_ = false;
537 path.addCircle(50, 75, 10);
538 paint.setStyle(SkPaint::kStroke_Style);
539 paint.setColor(SK_ColorMAGENTA);
540 vcanvas_->drawPath(path, paint);
541 pcanvas_->drawPath(path, paint);
543 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke")));
549 path.addCircle(50, 25, 10);
550 paint.setStyle(SkPaint::kFill_Style);
551 vcanvas_->drawPath(path, paint);
552 pcanvas_->drawPath(path, paint);
554 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_fill")));
556 // Stroked Circle over.
560 path.addCircle(50, 25, 10);
561 paint.setStyle(SkPaint::kStroke_Style);
562 paint.setColor(SK_ColorBLUE);
563 vcanvas_->drawPath(path, paint);
564 pcanvas_->drawPath(path, paint);
566 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_over_strike")));
568 // Stroke and Fill Circle.
572 path.addCircle(12, 50, 10);
573 paint.setStyle(SkPaint::kStrokeAndFill_Style);
574 paint.setColor(SK_ColorRED);
575 vcanvas_->drawPath(path, paint);
576 pcanvas_->drawPath(path, paint);
578 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke_and_fill")));
580 // Line + Quad + Cubic.
584 paint.setStyle(SkPaint::kStroke_Style);
585 paint.setColor(SK_ColorGREEN);
589 path.quadTo(20, 50, 10, 90);
590 path.quadTo(50, 20, 90, 10);
591 path.cubicTo(20, 40, 50, 50, 10, 10);
592 path.cubicTo(30, 20, 50, 50, 90, 10);
593 path.addRect(90, 90, 95, 96);
594 vcanvas_->drawPath(path, paint);
595 pcanvas_->drawPath(path, paint);
597 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("mixed_stroke")));
600 TEST_F(VectorCanvasTest, LineOrientation) {
601 // There is NO WAY to make them agree. At least verify that the output doesn't
602 // change across versions. This test is disabled. See bug 1060231.
603 compare_canvas_ = false;
608 paint.setColor(SK_ColorRED);
610 vcanvas_->drawLine(10, 20, 90, 20, paint);
611 pcanvas_->drawLine(10, 20, 90, 20, paint);
613 vcanvas_->drawLine(90, 30, 10, 30, paint);
614 pcanvas_->drawLine(90, 30, 10, 30, paint);
616 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal")));
621 paint.setColor(SK_ColorRED);
623 vcanvas_->drawLine(20, 10, 20, 90, paint);
624 pcanvas_->drawLine(20, 10, 20, 90, paint);
626 vcanvas_->drawLine(30, 90, 30, 10, paint);
627 pcanvas_->drawLine(30, 90, 30, 10, paint);
629 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical")));
631 // Try again with a 180 degres rotation.
632 vcanvas_->rotate(180);
633 pcanvas_->rotate(180);
635 // Horizontal lines (rotated).
638 paint.setColor(SK_ColorRED);
639 vcanvas_->drawLine(-10, -25, -90, -25, paint);
640 pcanvas_->drawLine(-10, -25, -90, -25, paint);
641 vcanvas_->drawLine(-90, -35, -10, -35, paint);
642 pcanvas_->drawLine(-90, -35, -10, -35, paint);
644 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal_180")));
646 // Vertical lines (rotated).
649 paint.setColor(SK_ColorRED);
650 vcanvas_->drawLine(-25, -10, -25, -90, paint);
651 pcanvas_->drawLine(-25, -10, -25, -90, paint);
652 vcanvas_->drawLine(-35, -90, -35, -10, paint);
653 pcanvas_->drawLine(-35, -90, -35, -10, paint);
655 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical_180")));
658 TEST_F(VectorCanvasTest, PathOrientation) {
659 // There is NO WAY to make them agree. At least verify that the output doesn't
660 // change across versions. This test is disabled. See bug 1060231.
661 compare_canvas_ = false;
666 paint.setStyle(SkPaint::kStroke_Style);
667 paint.setColor(SK_ColorRED);
675 vcanvas_->drawPath(path, paint);
676 pcanvas_->drawPath(path, paint);
678 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
683 paint.setStyle(SkPaint::kStroke_Style);
684 paint.setColor(SK_ColorRED);
692 vcanvas_->drawPath(path, paint);
693 pcanvas_->drawPath(path, paint);
695 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_rtl")));
698 TEST_F(VectorCanvasTest, DiagonalLines) {
700 paint.setColor(SK_ColorRED);
702 vcanvas_->drawLine(10, 10, 90, 90, paint);
703 pcanvas_->drawLine(10, 10, 90, 90, paint);
704 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("nw-se")));
706 // Starting here, there is NO WAY to make them agree. At least verify that the
707 // output doesn't change across versions. This test is disabled. See bug
709 compare_canvas_ = false;
711 vcanvas_->drawLine(10, 95, 90, 15, paint);
712 pcanvas_->drawLine(10, 95, 90, 15, paint);
713 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("sw-ne")));
715 vcanvas_->drawLine(90, 10, 10, 90, paint);
716 pcanvas_->drawLine(90, 10, 10, 90, paint);
717 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("ne-sw")));
719 vcanvas_->drawLine(95, 90, 15, 10, paint);
720 pcanvas_->drawLine(95, 90, 15, 10, paint);
721 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("se-nw")));
725 #define MAYBE_PathEffects DISABLED_PathEffects
727 #define MAYBE_PathEffects PathEffects
729 TEST_F(VectorCanvasTest, MAYBE_PathEffects) {
732 SkScalar intervals[] = { 1, 1 };
733 skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
734 new SkDashPathEffect(intervals, arraysize(intervals), 0));
735 paint.setPathEffect(effect.get());
736 paint.setColor(SK_ColorMAGENTA);
737 paint.setStyle(SkPaint::kStroke_Style);
739 vcanvas_->drawLine(10, 10, 90, 10, paint);
740 pcanvas_->drawLine(10, 10, 90, 10, paint);
742 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_line")));
745 // Starting here, there is NO WAY to make them agree. At least verify that the
746 // output doesn't change across versions. This test is disabled. See bug
748 compare_canvas_ = false;
752 SkScalar intervals[] = { 3, 5 };
753 skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
754 new SkDashPathEffect(intervals, arraysize(intervals), 0));
755 paint.setPathEffect(effect.get());
756 paint.setColor(SK_ColorMAGENTA);
757 paint.setStyle(SkPaint::kStroke_Style);
763 vcanvas_->drawPath(path, paint);
764 pcanvas_->drawPath(path, paint);
766 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
770 SkScalar intervals[] = { 2, 1 };
771 skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
772 new SkDashPathEffect(intervals, arraysize(intervals), 0));
773 paint.setPathEffect(effect.get());
774 paint.setColor(SK_ColorMAGENTA);
775 paint.setStyle(SkPaint::kStroke_Style);
777 vcanvas_->drawRectCoords(20, 20, 30, 30, paint);
778 pcanvas_->drawRectCoords(20, 20, 30, 30, paint);
780 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_rect")));
782 // This thing looks like it has been drawn by a 3 years old kid. I haven't
783 // filed a bug on this since I guess nobody is expecting this to look nice.
786 SkScalar intervals[] = { 1, 1 };
787 skia::RefPtr<SkPathEffect> effect = skia::AdoptRef(
788 new SkDashPathEffect(intervals, arraysize(intervals), 0));
789 paint.setPathEffect(effect.get());
790 paint.setColor(SK_ColorMAGENTA);
791 paint.setStyle(SkPaint::kStroke_Style);
794 path.addCircle(50, 75, 10);
795 vcanvas_->drawPath(path, paint);
796 pcanvas_->drawPath(path, paint);
797 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle")));
801 TEST_F(VectorCanvasTest, Bitmaps) {
804 LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap, true);
805 vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
806 pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
807 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("opaque")));
812 LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap, false);
813 vcanvas_->drawBitmap(bitmap, 5, 15, NULL);
814 pcanvas_->drawBitmap(bitmap, 5, 15, NULL);
815 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("alpha")));
819 TEST_F(VectorCanvasTest, ClippingRect) {
821 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
827 rect.fBottom = 30.5f;
828 vcanvas_->clipRect(rect);
829 pcanvas_->clipRect(rect);
831 vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
832 pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
833 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rect")));
836 TEST_F(VectorCanvasTest, ClippingPath) {
838 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
841 path.addCircle(20, 20, 10);
842 vcanvas_->clipPath(path);
843 pcanvas_->clipPath(path);
845 vcanvas_->drawBitmap(bitmap, 14, 3, NULL);
846 pcanvas_->drawBitmap(bitmap, 14, 3, NULL);
847 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("path")));
850 TEST_F(VectorCanvasTest, ClippingCombined) {
852 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
859 rect.fBottom = 30.5f;
860 vcanvas_->clipRect(rect);
861 pcanvas_->clipRect(rect);
863 path.addCircle(20, 20, 10);
864 vcanvas_->clipPath(path, SkRegion::kUnion_Op);
865 pcanvas_->clipPath(path, SkRegion::kUnion_Op);
867 vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
868 pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
869 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("combined")));
872 TEST_F(VectorCanvasTest, ClippingIntersect) {
874 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
881 rect.fBottom = 30.5f;
882 vcanvas_->clipRect(rect);
883 pcanvas_->clipRect(rect);
885 path.addCircle(23, 23, 15);
886 vcanvas_->clipPath(path);
887 pcanvas_->clipPath(path);
889 vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
890 pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
891 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("intersect")));
894 TEST_F(VectorCanvasTest, ClippingClean) {
896 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
899 SkAutoCanvasRestore acrv(vcanvas_, true);
900 SkAutoCanvasRestore acrp(pcanvas_, true);
905 rect.fBottom = 30.5f;
906 vcanvas_->clipRect(rect);
907 pcanvas_->clipRect(rect);
909 vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
910 pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
911 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clipped")));
914 // Verify that the clipping region has been fixed back.
915 vcanvas_->drawBitmap(bitmap, 55, 3, NULL);
916 pcanvas_->drawBitmap(bitmap, 55, 3, NULL);
917 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("unclipped")));
921 // See http://crbug.com/26938
922 TEST_F(VectorCanvasTest, DISABLED_Matrix) {
924 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
927 vcanvas_->translate(15, 3);
928 pcanvas_->translate(15, 3);
929 vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
930 pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
931 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate1")));
934 vcanvas_->translate(-30, -23);
935 pcanvas_->translate(-30, -23);
936 vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
937 pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
938 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate2")));
940 vcanvas_->resetMatrix();
941 pcanvas_->resetMatrix();
943 // For scaling and rotation, they use a different algorithm (nearest
944 // neighborhood vs smoothing). At least verify that the output doesn't change
946 compare_canvas_ = false;
949 vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
950 pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
951 vcanvas_->drawBitmap(bitmap, 1, 1, NULL);
952 pcanvas_->drawBitmap(bitmap, 1, 1, NULL);
953 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("scale")));
955 vcanvas_->resetMatrix();
956 pcanvas_->resetMatrix();
959 vcanvas_->rotate(67);
960 pcanvas_->rotate(67);
961 vcanvas_->drawBitmap(bitmap, 20, -50, NULL);
962 pcanvas_->drawBitmap(bitmap, 20, -50, NULL);
963 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rotate")));
967 #endif // !defined(USE_AURA)