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
= base::OpenFile(filename
, "wb");
140 ASSERT_EQ(fwrite(&*compressed
.begin(), 1, compressed
.size(), 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 base::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
= base::UTF16ToASCII(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)