1 // Copyright (c) 2011 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/string_util.h"
15 #include "base/stringprintf.h"
16 #include "base/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 FilePath
& filename
) : ignore_alpha_(true) {
88 std::string compressed
;
89 file_util::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 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 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_
= 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 FilePath
test_file(const 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 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 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 FilePath::StringType
& filename
) const {
301 Image(canvas
).SaveToFile(test_file(filename
));
304 ProcessAction action_
;
306 // Path to directory used to contain the test data.
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 FilePath
& filename
,
337 std::string compressed
;
338 file_util::ReadFileToString(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(VectorPlatformDeviceEmf::CreateDevice(
394 size_
, size_
, true, context_
->context()));
395 pcanvas_
= new PlatformCanvas(size_
, size_
, false);
398 vcanvas_
->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode
);
399 pcanvas_
->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode
);
402 // Compares both canvas and returns the pixel difference in percentage between
403 // both images. 0 on success and ]0, 100] on failure.
404 double ProcessImage(const FilePath::StringType
& filename
) {
405 std::wstring
number(base::StringPrintf(L
"%02d_", number_
++));
406 double diff1
= parent::ProcessCanvas(*vcanvas_
, number
+ L
"vc_" + filename
);
407 double diff2
= parent::ProcessCanvas(*pcanvas_
, number
+ L
"pc_" + filename
);
408 if (!compare_canvas_
)
409 return std::max(diff1
, diff2
);
411 Image
image1(*vcanvas_
);
412 Image
image2(*pcanvas_
);
413 double diff
= image1
.PercentageDifferent(image2
);
414 return std::max(std::max(diff1
, diff2
), diff
);
417 // Returns COMPARE, which is the default. If kGenerateSwitch command
418 // line argument is used to start this process, GENERATE is returned instead.
419 static ProcessAction
CurrentMode() {
420 return CommandLine::ForCurrentProcess()->HasSwitch(kGenerateSwitch
) ?
424 // Length in x and y of the square canvas.
427 // Current image number in the current test. Used to number of test files.
430 // A temporary HDC to draw into.
433 // Bitmap created inside context_.
436 // Vector based canvas.
437 VectorCanvas
* vcanvas_
;
439 // Pixel based canvas.
440 PlatformCanvas
* pcanvas_
;
442 // When true (default), vcanvas_ and pcanvas_ contents are compared and
443 // verified to be identical.
444 bool compare_canvas_
;
448 ////////////////////////////////////////////////////////////////////////////////
451 TEST_F(VectorCanvasTest
, Uninitialized
) {
452 // Do a little mubadumba do get uninitialized stuff.
453 VectorCanvasTest::TearDown();
455 // The goal is not to verify that have the same uninitialized data.
456 compare_canvas_
= false;
458 context_
= new Context();
459 bitmap_
= new Bitmap(*context_
, size_
, size_
);
460 vcanvas_
= new VectorCanvas(VectorPlatformDeviceEmf::CreateDevice(
461 size_
, size_
, true, context_
->context()));
462 pcanvas_
= new PlatformCanvas(size_
, size_
, false);
464 // VectorCanvas default initialization is black.
465 // PlatformCanvas default initialization is almost white 0x01FFFEFD (invalid
466 // Skia color) in both Debug and Release. See magicTransparencyColor in
467 // platform_device.cc
468 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("empty")));
471 TEST_F(VectorCanvasTest
, BasicDrawing
) {
472 EXPECT_EQ(Image(*vcanvas_
).PercentageDifferent(Image(*pcanvas_
)), 0.)
474 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
478 vcanvas_
->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode
);
479 pcanvas_
->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode
);
481 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawARGB")));
483 // Diagonal line top-left to bottom-right.
486 // Default color is black.
487 vcanvas_
->drawLine(10, 10, 90, 90, paint
);
488 pcanvas_
->drawLine(10, 10, 90, 90, paint
);
490 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_black")));
495 paint
.setColor(SK_ColorGREEN
);
496 vcanvas_
->drawRectCoords(25, 25, 75, 75, paint
);
497 pcanvas_
->drawRectCoords(25, 25, 75, 75, paint
);
499 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_green")));
501 // A single-point rect doesn't leave any mark.
504 paint
.setColor(SK_ColorBLUE
);
505 vcanvas_
->drawRectCoords(5, 5, 5, 5, paint
);
506 pcanvas_
->drawRectCoords(5, 5, 5, 5, paint
);
508 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
513 paint
.setColor(SK_ColorBLUE
);
514 vcanvas_
->drawRectCoords(75, 50, 80, 55, paint
);
515 pcanvas_
->drawRectCoords(75, 50, 80, 55, paint
);
517 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
521 vcanvas_
->drawPaint(SkPaint());
522 pcanvas_
->drawPaint(SkPaint());
524 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
526 // Horizontal line left to right.
529 paint
.setColor(SK_ColorRED
);
530 vcanvas_
->drawLine(10, 20, 90, 20, paint
);
531 pcanvas_
->drawLine(10, 20, 90, 20, paint
);
533 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_left_to_right")));
535 // Vertical line downward.
538 paint
.setColor(SK_ColorRED
);
539 vcanvas_
->drawLine(30, 10, 30, 90, paint
);
540 pcanvas_
->drawLine(30, 10, 30, 90, paint
);
542 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_red")));
545 TEST_F(VectorCanvasTest
, Circles
) {
546 // There is NO WAY to make them agree. At least verify that the output doesn't
547 // change across versions. This test is disabled. See bug 1060231.
548 compare_canvas_
= false;
554 path
.addCircle(50, 75, 10);
555 paint
.setStyle(SkPaint::kStroke_Style
);
556 paint
.setColor(SK_ColorMAGENTA
);
557 vcanvas_
->drawPath(path
, paint
);
558 pcanvas_
->drawPath(path
, paint
);
560 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke")));
566 path
.addCircle(50, 25, 10);
567 paint
.setStyle(SkPaint::kFill_Style
);
568 vcanvas_
->drawPath(path
, paint
);
569 pcanvas_
->drawPath(path
, paint
);
571 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_fill")));
573 // Stroked Circle over.
577 path
.addCircle(50, 25, 10);
578 paint
.setStyle(SkPaint::kStroke_Style
);
579 paint
.setColor(SK_ColorBLUE
);
580 vcanvas_
->drawPath(path
, paint
);
581 pcanvas_
->drawPath(path
, paint
);
583 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_over_strike")));
585 // Stroke and Fill Circle.
589 path
.addCircle(12, 50, 10);
590 paint
.setStyle(SkPaint::kStrokeAndFill_Style
);
591 paint
.setColor(SK_ColorRED
);
592 vcanvas_
->drawPath(path
, paint
);
593 pcanvas_
->drawPath(path
, paint
);
595 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke_and_fill")));
597 // Line + Quad + Cubic.
601 paint
.setStyle(SkPaint::kStroke_Style
);
602 paint
.setColor(SK_ColorGREEN
);
606 path
.quadTo(20, 50, 10, 90);
607 path
.quadTo(50, 20, 90, 10);
608 path
.cubicTo(20, 40, 50, 50, 10, 10);
609 path
.cubicTo(30, 20, 50, 50, 90, 10);
610 path
.addRect(90, 90, 95, 96);
611 vcanvas_
->drawPath(path
, paint
);
612 pcanvas_
->drawPath(path
, paint
);
614 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("mixed_stroke")));
617 TEST_F(VectorCanvasTest
, LineOrientation
) {
618 // There is NO WAY to make them agree. At least verify that the output doesn't
619 // change across versions. This test is disabled. See bug 1060231.
620 compare_canvas_
= false;
625 paint
.setColor(SK_ColorRED
);
627 vcanvas_
->drawLine(10, 20, 90, 20, paint
);
628 pcanvas_
->drawLine(10, 20, 90, 20, paint
);
630 vcanvas_
->drawLine(90, 30, 10, 30, paint
);
631 pcanvas_
->drawLine(90, 30, 10, 30, paint
);
633 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal")));
638 paint
.setColor(SK_ColorRED
);
640 vcanvas_
->drawLine(20, 10, 20, 90, paint
);
641 pcanvas_
->drawLine(20, 10, 20, 90, paint
);
643 vcanvas_
->drawLine(30, 90, 30, 10, paint
);
644 pcanvas_
->drawLine(30, 90, 30, 10, paint
);
646 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical")));
648 // Try again with a 180 degres rotation.
649 vcanvas_
->rotate(180);
650 pcanvas_
->rotate(180);
652 // Horizontal lines (rotated).
655 paint
.setColor(SK_ColorRED
);
656 vcanvas_
->drawLine(-10, -25, -90, -25, paint
);
657 pcanvas_
->drawLine(-10, -25, -90, -25, paint
);
658 vcanvas_
->drawLine(-90, -35, -10, -35, paint
);
659 pcanvas_
->drawLine(-90, -35, -10, -35, paint
);
661 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal_180")));
663 // Vertical lines (rotated).
666 paint
.setColor(SK_ColorRED
);
667 vcanvas_
->drawLine(-25, -10, -25, -90, paint
);
668 pcanvas_
->drawLine(-25, -10, -25, -90, paint
);
669 vcanvas_
->drawLine(-35, -90, -35, -10, paint
);
670 pcanvas_
->drawLine(-35, -90, -35, -10, paint
);
672 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical_180")));
675 TEST_F(VectorCanvasTest
, PathOrientation
) {
676 // There is NO WAY to make them agree. At least verify that the output doesn't
677 // change across versions. This test is disabled. See bug 1060231.
678 compare_canvas_
= false;
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_ltr")));
700 paint
.setStyle(SkPaint::kStroke_Style
);
701 paint
.setColor(SK_ColorRED
);
709 vcanvas_
->drawPath(path
, paint
);
710 pcanvas_
->drawPath(path
, paint
);
712 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_rtl")));
715 TEST_F(VectorCanvasTest
, DiagonalLines
) {
717 paint
.setColor(SK_ColorRED
);
719 vcanvas_
->drawLine(10, 10, 90, 90, paint
);
720 pcanvas_
->drawLine(10, 10, 90, 90, paint
);
721 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("nw-se")));
723 // Starting here, there is NO WAY to make them agree. At least verify that the
724 // output doesn't change across versions. This test is disabled. See bug
726 compare_canvas_
= false;
728 vcanvas_
->drawLine(10, 95, 90, 15, paint
);
729 pcanvas_
->drawLine(10, 95, 90, 15, paint
);
730 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("sw-ne")));
732 vcanvas_
->drawLine(90, 10, 10, 90, paint
);
733 pcanvas_
->drawLine(90, 10, 10, 90, paint
);
734 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("ne-sw")));
736 vcanvas_
->drawLine(95, 90, 15, 10, paint
);
737 pcanvas_
->drawLine(95, 90, 15, 10, paint
);
738 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("se-nw")));
741 TEST_F(VectorCanvasTest
, PathEffects
) {
744 SkScalar intervals
[] = { 1, 1 };
745 SkPathEffect
* effect
= new SkDashPathEffect(intervals
, arraysize(intervals
),
747 paint
.setPathEffect(effect
)->unref();
748 paint
.setColor(SK_ColorMAGENTA
);
749 paint
.setStyle(SkPaint::kStroke_Style
);
751 vcanvas_
->drawLine(10, 10, 90, 10, paint
);
752 pcanvas_
->drawLine(10, 10, 90, 10, paint
);
754 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_line")));
757 // Starting here, there is NO WAY to make them agree. At least verify that the
758 // output doesn't change across versions. This test is disabled. See bug
760 compare_canvas_
= false;
764 SkScalar intervals
[] = { 3, 5 };
765 SkPathEffect
* effect
= new SkDashPathEffect(intervals
, arraysize(intervals
),
767 paint
.setPathEffect(effect
)->unref();
768 paint
.setColor(SK_ColorMAGENTA
);
769 paint
.setStyle(SkPaint::kStroke_Style
);
775 vcanvas_
->drawPath(path
, paint
);
776 pcanvas_
->drawPath(path
, paint
);
778 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
782 SkScalar intervals
[] = { 2, 1 };
783 SkPathEffect
* effect
= new SkDashPathEffect(intervals
, arraysize(intervals
),
785 paint
.setPathEffect(effect
)->unref();
786 paint
.setColor(SK_ColorMAGENTA
);
787 paint
.setStyle(SkPaint::kStroke_Style
);
789 vcanvas_
->drawRectCoords(20, 20, 30, 30, paint
);
790 pcanvas_
->drawRectCoords(20, 20, 30, 30, paint
);
792 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_rect")));
794 // This thing looks like it has been drawn by a 3 years old kid. I haven't
795 // filed a bug on this since I guess nobody is expecting this to look nice.
798 SkScalar intervals
[] = { 1, 1 };
799 SkPathEffect
* effect
= new SkDashPathEffect(intervals
, arraysize(intervals
),
801 paint
.setPathEffect(effect
)->unref();
802 paint
.setColor(SK_ColorMAGENTA
);
803 paint
.setStyle(SkPaint::kStroke_Style
);
806 path
.addCircle(50, 75, 10);
807 vcanvas_
->drawPath(path
, paint
);
808 pcanvas_
->drawPath(path
, paint
);
809 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle")));
813 TEST_F(VectorCanvasTest
, Bitmaps
) {
816 LoadPngFileToSkBitmap(test_file(L
"bitmap_opaque.png"), &bitmap
, true);
817 vcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
818 pcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
819 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("opaque")));
824 LoadPngFileToSkBitmap(test_file(L
"bitmap_alpha.png"), &bitmap
, false);
825 vcanvas_
->drawBitmap(bitmap
, 5, 15, NULL
);
826 pcanvas_
->drawBitmap(bitmap
, 5, 15, NULL
);
827 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("alpha")));
831 TEST_F(VectorCanvasTest
, ClippingRect
) {
833 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
839 rect
.fBottom
= 30.5f
;
840 vcanvas_
->clipRect(rect
);
841 pcanvas_
->clipRect(rect
);
843 vcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
844 pcanvas_
->drawBitmap(bitmap
, 13, 3, NULL
);
845 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rect")));
848 TEST_F(VectorCanvasTest
, ClippingPath
) {
850 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
853 path
.addCircle(20, 20, 10);
854 vcanvas_
->clipPath(path
);
855 pcanvas_
->clipPath(path
);
857 vcanvas_
->drawBitmap(bitmap
, 14, 3, NULL
);
858 pcanvas_
->drawBitmap(bitmap
, 14, 3, NULL
);
859 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("path")));
862 TEST_F(VectorCanvasTest
, ClippingCombined
) {
864 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
871 rect
.fBottom
= 30.5f
;
872 vcanvas_
->clipRect(rect
);
873 pcanvas_
->clipRect(rect
);
875 path
.addCircle(20, 20, 10);
876 vcanvas_
->clipPath(path
, SkRegion::kUnion_Op
);
877 pcanvas_
->clipPath(path
, SkRegion::kUnion_Op
);
879 vcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
880 pcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
881 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("combined")));
884 TEST_F(VectorCanvasTest
, ClippingIntersect
) {
886 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
893 rect
.fBottom
= 30.5f
;
894 vcanvas_
->clipRect(rect
);
895 pcanvas_
->clipRect(rect
);
897 path
.addCircle(23, 23, 15);
898 vcanvas_
->clipPath(path
);
899 pcanvas_
->clipPath(path
);
901 vcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
902 pcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
903 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("intersect")));
906 TEST_F(VectorCanvasTest
, ClippingClean
) {
908 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
911 SkRegion
old_region(pcanvas_
->getTotalClip());
916 rect
.fBottom
= 30.5f
;
917 vcanvas_
->clipRect(rect
);
918 pcanvas_
->clipRect(rect
);
920 vcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
921 pcanvas_
->drawBitmap(bitmap
, 15, 3, NULL
);
922 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clipped")));
923 vcanvas_
->clipRegion(old_region
, SkRegion::kReplace_Op
);
924 pcanvas_
->clipRegion(old_region
, SkRegion::kReplace_Op
);
927 // Verify that the clipping region has been fixed back.
928 vcanvas_
->drawBitmap(bitmap
, 55, 3, NULL
);
929 pcanvas_
->drawBitmap(bitmap
, 55, 3, NULL
);
930 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("unclipped")));
934 // See http://crbug.com/26938
935 TEST_F(VectorCanvasTest
, DISABLED_Matrix
) {
937 LoadPngFileToSkBitmap(test_file(L
"..\\bitmaps\\bitmap_opaque.png"), &bitmap
,
940 vcanvas_
->translate(15, 3);
941 pcanvas_
->translate(15, 3);
942 vcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
943 pcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
944 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate1")));
947 vcanvas_
->translate(-30, -23);
948 pcanvas_
->translate(-30, -23);
949 vcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
950 pcanvas_
->drawBitmap(bitmap
, 0, 0, NULL
);
951 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("translate2")));
953 vcanvas_
->resetMatrix();
954 pcanvas_
->resetMatrix();
956 // For scaling and rotation, they use a different algorithm (nearest
957 // neighborhood vs smoothing). At least verify that the output doesn't change
959 compare_canvas_
= false;
962 vcanvas_
->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
963 pcanvas_
->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
964 vcanvas_
->drawBitmap(bitmap
, 1, 1, NULL
);
965 pcanvas_
->drawBitmap(bitmap
, 1, 1, NULL
);
966 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("scale")));
968 vcanvas_
->resetMatrix();
969 pcanvas_
->resetMatrix();
972 vcanvas_
->rotate(67);
973 pcanvas_
->rotate(67);
974 vcanvas_
->drawBitmap(bitmap
, 20, -50, NULL
);
975 pcanvas_
->drawBitmap(bitmap
, 20, -50, NULL
);
976 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rotate")));