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/files/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/geometry/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 base::CommandLine::ForCurrentProcess()->HasSwitch(kGenerateSwitch
)
426 // Length in x and y of the square canvas.
429 // Current image number in the current test. Used to number of test files.
432 // A temporary HDC to draw into.
435 // Bitmap created inside context_.
438 // Vector based canvas.
439 VectorCanvas
* vcanvas_
;
441 // Pixel based canvas.
442 PlatformCanvas
* pcanvas_
;
444 // When true (default), vcanvas_ and pcanvas_ contents are compared and
445 // verified to be identical.
446 bool compare_canvas_
;
450 ////////////////////////////////////////////////////////////////////////////////
453 #if !defined(USE_AURA) // http://crbug.com/154358
455 TEST_F(VectorCanvasTest
, BasicDrawing
) {
456 EXPECT_EQ(Image(*vcanvas_
).PercentageDifferent(Image(*pcanvas_
)), 0.)
458 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
462 vcanvas_
->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode
);
463 pcanvas_
->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode
);
465 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawARGB")));
467 // Diagonal line top-left to bottom-right.
470 // Default color is black.
471 vcanvas_
->drawLine(10, 10, 90, 90, paint
);
472 pcanvas_
->drawLine(10, 10, 90, 90, paint
);
474 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_black")));
479 paint
.setColor(SK_ColorGREEN
);
480 vcanvas_
->drawRectCoords(25, 25, 75, 75, paint
);
481 pcanvas_
->drawRectCoords(25, 25, 75, 75, paint
);
483 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_green")));
485 // A single-point rect doesn't leave any mark.
488 paint
.setColor(SK_ColorBLUE
);
489 vcanvas_
->drawRectCoords(5, 5, 5, 5, paint
);
490 pcanvas_
->drawRectCoords(5, 5, 5, 5, paint
);
492 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
497 paint
.setColor(SK_ColorBLUE
);
498 vcanvas_
->drawRectCoords(75, 50, 80, 55, paint
);
499 pcanvas_
->drawRectCoords(75, 50, 80, 55, paint
);
501 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
505 vcanvas_
->drawPaint(SkPaint());
506 pcanvas_
->drawPaint(SkPaint());
508 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
510 // Horizontal line left to right.
513 paint
.setColor(SK_ColorRED
);
514 vcanvas_
->drawLine(10, 20, 90, 20, paint
);
515 pcanvas_
->drawLine(10, 20, 90, 20, paint
);
517 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_left_to_right")));
519 // Vertical line downward.
522 paint
.setColor(SK_ColorRED
);
523 vcanvas_
->drawLine(30, 10, 30, 90, paint
);
524 pcanvas_
->drawLine(30, 10, 30, 90, paint
);
526 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_red")));
529 TEST_F(VectorCanvasTest
, Circles
) {
530 // There is NO WAY to make them agree. At least verify that the output doesn't
531 // change across versions. This test is disabled. See bug 1060231.
532 compare_canvas_
= false;
538 path
.addCircle(50, 75, 10);
539 paint
.setStyle(SkPaint::kStroke_Style
);
540 paint
.setColor(SK_ColorMAGENTA
);
541 vcanvas_
->drawPath(path
, paint
);
542 pcanvas_
->drawPath(path
, paint
);
544 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke")));
550 path
.addCircle(50, 25, 10);
551 paint
.setStyle(SkPaint::kFill_Style
);
552 vcanvas_
->drawPath(path
, paint
);
553 pcanvas_
->drawPath(path
, paint
);
555 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_fill")));
557 // Stroked Circle over.
561 path
.addCircle(50, 25, 10);
562 paint
.setStyle(SkPaint::kStroke_Style
);
563 paint
.setColor(SK_ColorBLUE
);
564 vcanvas_
->drawPath(path
, paint
);
565 pcanvas_
->drawPath(path
, paint
);
567 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_over_strike")));
569 // Stroke and Fill Circle.
573 path
.addCircle(12, 50, 10);
574 paint
.setStyle(SkPaint::kStrokeAndFill_Style
);
575 paint
.setColor(SK_ColorRED
);
576 vcanvas_
->drawPath(path
, paint
);
577 pcanvas_
->drawPath(path
, paint
);
579 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke_and_fill")));
581 // Line + Quad + Cubic.
585 paint
.setStyle(SkPaint::kStroke_Style
);
586 paint
.setColor(SK_ColorGREEN
);
590 path
.quadTo(20, 50, 10, 90);
591 path
.quadTo(50, 20, 90, 10);
592 path
.cubicTo(20, 40, 50, 50, 10, 10);
593 path
.cubicTo(30, 20, 50, 50, 90, 10);
594 path
.addRect(90, 90, 95, 96);
595 vcanvas_
->drawPath(path
, paint
);
596 pcanvas_
->drawPath(path
, paint
);
598 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("mixed_stroke")));
601 TEST_F(VectorCanvasTest
, LineOrientation
) {
602 // There is NO WAY to make them agree. At least verify that the output doesn't
603 // change across versions. This test is disabled. See bug 1060231.
604 compare_canvas_
= false;
609 paint
.setColor(SK_ColorRED
);
611 vcanvas_
->drawLine(10, 20, 90, 20, paint
);
612 pcanvas_
->drawLine(10, 20, 90, 20, paint
);
614 vcanvas_
->drawLine(90, 30, 10, 30, paint
);
615 pcanvas_
->drawLine(90, 30, 10, 30, paint
);
617 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal")));
622 paint
.setColor(SK_ColorRED
);
624 vcanvas_
->drawLine(20, 10, 20, 90, paint
);
625 pcanvas_
->drawLine(20, 10, 20, 90, paint
);
627 vcanvas_
->drawLine(30, 90, 30, 10, paint
);
628 pcanvas_
->drawLine(30, 90, 30, 10, paint
);
630 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical")));
632 // Try again with a 180 degres rotation.
633 vcanvas_
->rotate(180);
634 pcanvas_
->rotate(180);
636 // Horizontal lines (rotated).
639 paint
.setColor(SK_ColorRED
);
640 vcanvas_
->drawLine(-10, -25, -90, -25, paint
);
641 pcanvas_
->drawLine(-10, -25, -90, -25, paint
);
642 vcanvas_
->drawLine(-90, -35, -10, -35, paint
);
643 pcanvas_
->drawLine(-90, -35, -10, -35, paint
);
645 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal_180")));
647 // Vertical lines (rotated).
650 paint
.setColor(SK_ColorRED
);
651 vcanvas_
->drawLine(-25, -10, -25, -90, paint
);
652 pcanvas_
->drawLine(-25, -10, -25, -90, paint
);
653 vcanvas_
->drawLine(-35, -90, -35, -10, paint
);
654 pcanvas_
->drawLine(-35, -90, -35, -10, paint
);
656 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical_180")));
659 TEST_F(VectorCanvasTest
, PathOrientation
) {
660 // There is NO WAY to make them agree. At least verify that the output doesn't
661 // change across versions. This test is disabled. See bug 1060231.
662 compare_canvas_
= false;
667 paint
.setStyle(SkPaint::kStroke_Style
);
668 paint
.setColor(SK_ColorRED
);
676 vcanvas_
->drawPath(path
, paint
);
677 pcanvas_
->drawPath(path
, paint
);
679 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
684 paint
.setStyle(SkPaint::kStroke_Style
);
685 paint
.setColor(SK_ColorRED
);
693 vcanvas_
->drawPath(path
, paint
);
694 pcanvas_
->drawPath(path
, paint
);
696 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_rtl")));
699 TEST_F(VectorCanvasTest
, DiagonalLines
) {
701 paint
.setColor(SK_ColorRED
);
703 vcanvas_
->drawLine(10, 10, 90, 90, paint
);
704 pcanvas_
->drawLine(10, 10, 90, 90, paint
);
705 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("nw-se")));
707 // Starting here, there is NO WAY to make them agree. At least verify that the
708 // output doesn't change across versions. This test is disabled. See bug
710 compare_canvas_
= false;
712 vcanvas_
->drawLine(10, 95, 90, 15, paint
);
713 pcanvas_
->drawLine(10, 95, 90, 15, paint
);
714 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("sw-ne")));
716 vcanvas_
->drawLine(90, 10, 10, 90, paint
);
717 pcanvas_
->drawLine(90, 10, 10, 90, paint
);
718 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("ne-sw")));
720 vcanvas_
->drawLine(95, 90, 15, 10, paint
);
721 pcanvas_
->drawLine(95, 90, 15, 10, paint
);
722 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("se-nw")));
726 #define MAYBE_PathEffects DISABLED_PathEffects
728 #define MAYBE_PathEffects PathEffects
730 TEST_F(VectorCanvasTest
, MAYBE_PathEffects
) {
733 SkScalar intervals
[] = { 1, 1 };
734 skia::RefPtr
<SkPathEffect
> effect
= skia::AdoptRef(
735 new SkDashPathEffect(intervals
, arraysize(intervals
), 0));
736 paint
.setPathEffect(effect
.get());
737 paint
.setColor(SK_ColorMAGENTA
);
738 paint
.setStyle(SkPaint::kStroke_Style
);
740 vcanvas_
->drawLine(10, 10, 90, 10, paint
);
741 pcanvas_
->drawLine(10, 10, 90, 10, paint
);
743 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_line")));
746 // Starting here, there is NO WAY to make them agree. At least verify that the
747 // output doesn't change across versions. This test is disabled. See bug
749 compare_canvas_
= false;
753 SkScalar intervals
[] = { 3, 5 };
754 skia::RefPtr
<SkPathEffect
> effect
= skia::AdoptRef(
755 new SkDashPathEffect(intervals
, arraysize(intervals
), 0));
756 paint
.setPathEffect(effect
.get());
757 paint
.setColor(SK_ColorMAGENTA
);
758 paint
.setStyle(SkPaint::kStroke_Style
);
764 vcanvas_
->drawPath(path
, paint
);
765 pcanvas_
->drawPath(path
, paint
);
767 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
771 SkScalar intervals
[] = { 2, 1 };
772 skia::RefPtr
<SkPathEffect
> effect
= skia::AdoptRef(
773 new SkDashPathEffect(intervals
, arraysize(intervals
), 0));
774 paint
.setPathEffect(effect
.get());
775 paint
.setColor(SK_ColorMAGENTA
);
776 paint
.setStyle(SkPaint::kStroke_Style
);
778 vcanvas_
->drawRectCoords(20, 20, 30, 30, paint
);
779 pcanvas_
->drawRectCoords(20, 20, 30, 30, paint
);
781 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_rect")));
783 // This thing looks like it has been drawn by a 3 years old kid. I haven't
784 // filed a bug on this since I guess nobody is expecting this to look nice.
787 SkScalar intervals
[] = { 1, 1 };
788 skia::RefPtr
<SkPathEffect
> effect
= skia::AdoptRef(
789 new SkDashPathEffect(intervals
, arraysize(intervals
), 0));
790 paint
.setPathEffect(effect
.get());
791 paint
.setColor(SK_ColorMAGENTA
);
792 paint
.setStyle(SkPaint::kStroke_Style
);
795 path
.addCircle(50, 75, 10);
796 vcanvas_
->drawPath(path
, paint
);
797 pcanvas_
->drawPath(path
, paint
);
798 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle")));
802 TEST_F(VectorCanvasTest
, Bitmaps
) {
805 LoadPngFileToSkBitmap(test_file(L
"bitmap_opaque.png"), &bitmap
, true);
806 vcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
807 pcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
808 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("opaque")));
813 LoadPngFileToSkBitmap(test_file(L
"bitmap_alpha.png"), &bitmap
, false);
814 vcanvas_
->drawBitmap(bitmap
, 5, 15, NULL
);
815 pcanvas_
->drawBitmap(bitmap
, 5, 15, NULL
);
816 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("alpha")));
820 TEST_F(VectorCanvasTest
, ClippingRect
) {
822 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
828 rect
.fBottom
= 30.5f
;
829 vcanvas_
->clipRect(rect
);
830 pcanvas_
->clipRect(rect
);
832 vcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
833 pcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
834 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rect")));
837 TEST_F(VectorCanvasTest
, ClippingPath
) {
839 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
842 path
.addCircle(20, 20, 10);
843 vcanvas_
->clipPath(path
);
844 pcanvas_
->clipPath(path
);
846 vcanvas_
->drawBitmap(bitmap
, 14, 3, NULL
);
847 pcanvas_
->drawBitmap(bitmap
, 14, 3, NULL
);
848 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("path")));
851 TEST_F(VectorCanvasTest
, ClippingCombined
) {
853 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
860 rect
.fBottom
= 30.5f
;
861 vcanvas_
->clipRect(rect
);
862 pcanvas_
->clipRect(rect
);
864 path
.addCircle(20, 20, 10);
865 vcanvas_
->clipPath(path
, SkRegion::kUnion_Op
);
866 pcanvas_
->clipPath(path
, SkRegion::kUnion_Op
);
868 vcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
869 pcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
870 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("combined")));
873 TEST_F(VectorCanvasTest
, ClippingIntersect
) {
875 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
882 rect
.fBottom
= 30.5f
;
883 vcanvas_
->clipRect(rect
);
884 pcanvas_
->clipRect(rect
);
886 path
.addCircle(23, 23, 15);
887 vcanvas_
->clipPath(path
);
888 pcanvas_
->clipPath(path
);
890 vcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
891 pcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
892 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("intersect")));
895 TEST_F(VectorCanvasTest
, ClippingClean
) {
897 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
900 SkAutoCanvasRestore
acrv(vcanvas_
, true);
901 SkAutoCanvasRestore
acrp(pcanvas_
, true);
906 rect
.fBottom
= 30.5f
;
907 vcanvas_
->clipRect(rect
);
908 pcanvas_
->clipRect(rect
);
910 vcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
911 pcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
912 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clipped")));
915 // Verify that the clipping region has been fixed back.
916 vcanvas_
->drawBitmap(bitmap
, 55, 3, NULL
);
917 pcanvas_
->drawBitmap(bitmap
, 55, 3, NULL
);
918 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("unclipped")));
922 // See http://crbug.com/26938
923 TEST_F(VectorCanvasTest
, DISABLED_Matrix
) {
925 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
928 vcanvas_
->translate(15, 3);
929 pcanvas_
->translate(15, 3);
930 vcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
931 pcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
932 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate1")));
935 vcanvas_
->translate(-30, -23);
936 pcanvas_
->translate(-30, -23);
937 vcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
938 pcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
939 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate2")));
941 vcanvas_
->resetMatrix();
942 pcanvas_
->resetMatrix();
944 // For scaling and rotation, they use a different algorithm (nearest
945 // neighborhood vs smoothing). At least verify that the output doesn't change
947 compare_canvas_
= false;
950 vcanvas_
->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
951 pcanvas_
->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
952 vcanvas_
->drawBitmap(bitmap
, 1, 1, NULL
);
953 pcanvas_
->drawBitmap(bitmap
, 1, 1, NULL
);
954 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("scale")));
956 vcanvas_
->resetMatrix();
957 pcanvas_
->resetMatrix();
960 vcanvas_
->rotate(67);
961 pcanvas_
->rotate(67);
962 vcanvas_
->drawBitmap(bitmap
, 20, -50, NULL
);
963 pcanvas_
->drawBitmap(bitmap
, 20, -50, NULL
);
964 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rotate")));
968 #endif // !defined(USE_AURA)