Add creis, davidben, and mmenke to content/browser/loader/OWNERs.
[chromium-blink-merge.git] / skia / ext / vector_canvas_unittest.cc
blobb7e9105cce00027e62eddec3d4c71def9678dd92
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"
7 #if !defined(OS_WIN)
8 #include <unistd.h>
9 #endif
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"
24 namespace skia {
26 namespace {
28 const char kGenerateSwitch[] = "vector-canvas-generate";
30 // Lightweight HDC management.
31 class Context {
32 public:
33 Context() : context_(CreateCompatibleDC(NULL)) {
34 EXPECT_TRUE(context_);
36 ~Context() {
37 DeleteDC(context_);
40 HDC context() const { return context_; }
42 private:
43 HDC context_;
45 DISALLOW_COPY_AND_ASSIGN(Context);
48 // Lightweight HBITMAP management.
49 class Bitmap {
50 public:
51 Bitmap(const Context& context, int x, int y) {
52 BITMAPINFOHEADER hdr;
53 hdr.biSize = sizeof(BITMAPINFOHEADER);
54 hdr.biWidth = x;
55 hdr.biHeight = -y; // Minus means top-down bitmap.
56 hdr.biPlanes = 1;
57 hdr.biBitCount = 32;
58 hdr.biCompression = BI_RGB; // No compression.
59 hdr.biSizeImage = 0;
60 hdr.biXPelsPerMeter = 1;
61 hdr.biYPelsPerMeter = 1;
62 hdr.biClrUsed = 0;
63 hdr.biClrImportant = 0;
64 bitmap_ = CreateDIBSection(context.context(),
65 reinterpret_cast<BITMAPINFO*>(&hdr), 0,
66 &data_, NULL, 0);
67 EXPECT_TRUE(bitmap_);
68 EXPECT_TRUE(SelectObject(context.context(), bitmap_));
70 ~Bitmap() {
71 EXPECT_TRUE(DeleteObject(bitmap_));
74 private:
75 HBITMAP bitmap_;
77 void* data_;
79 DISALLOW_COPY_AND_ASSIGN(Bitmap);
82 // Lightweight raw-bitmap management. The image, once initialized, is immuable.
83 // It is mainly used for comparison.
84 class Image {
85 public:
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());
92 SkBitmap bitmap;
93 EXPECT_TRUE(gfx::PNGCodec::Decode(
94 reinterpret_cast<const unsigned char*>(compressed.data()),
95 compressed.size(), &bitmap));
96 SetSkBitmap(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.
108 BITMAP bitmap_data;
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_;
114 data_.resize(size);
115 memcpy(&*data_.begin(), bitmap_data.bmBits, size);
118 // Loads the image from a canvas.
119 Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
120 SetSkBitmap(bitmap);
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_),
133 row_length_,
134 true,
135 std::vector<gfx::PNGCodec::Comment>(),
136 &compressed));
137 ASSERT_TRUE(compressed.size());
138 FILE* f = base::OpenFile(filename, "wb");
139 ASSERT_TRUE(f);
140 ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
141 compressed.size());
142 base::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_ ||
151 width_ == 0 ||
152 height_ == 0) {
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)
162 ++pixels_different;
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);
180 if (ignore_alpha_)
181 return data_row[x] & 0xFFFFFF; // Strip out A.
182 else
183 return data_row[x];
186 protected:
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_;
193 data_.resize(size);
194 memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size);
197 private:
198 // Pixel dimensions of the image.
199 int width_;
200 int height_;
202 // Length of a line in bytes.
203 int row_length_;
205 // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
206 // 0xABGR).
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 {
217 public:
218 // In what state is the test running.
219 enum ProcessAction {
220 GENERATE,
221 COMPARE,
222 NOOP,
225 ImageTest(ProcessAction default_action)
226 : action_(default_action) {
229 protected:
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").
235 AppendASCII("ext").
236 AppendASCII("data").
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
255 // ASCII.
256 #if defined(OS_WIN)
257 std::string tmp = WideToASCII(filename);
258 #else
259 std::string tmp(filename);
260 #endif
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");
274 switch (action_) {
275 case GENERATE:
276 SaveImage(canvas, filename);
277 return 0.;
278 case COMPARE:
279 return CompareImage(canvas, filename);
280 case NOOP:
281 return 0;
282 default:
283 // Invalid state, returns that the image is 100 different.
284 return 100.;
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);
295 return diff;
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);
320 if (!alpha) {
321 *pixel_addr = 0;
322 } else {
323 BYTE alpha_offset = alpha / 2;
324 *pixel_addr = SkColorSetARGB(
325 SkColorGetA(color),
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,
335 SkBitmap* bitmap,
336 bool is_opaque) {
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);
349 } // namespace
351 // Streams an image.
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 {
360 public:
361 typedef ImageTest parent;
363 VectorCanvasTest() : parent(CurrentMode()), compare_canvas_(true) {
366 protected:
367 virtual void SetUp() {
368 parent::SetUp();
369 Init(100);
370 number_ = 0;
373 virtual void TearDown() {
374 delete pcanvas_;
375 pcanvas_ = NULL;
377 delete vcanvas_;
378 vcanvas_ = NULL;
380 delete bitmap_;
381 bitmap_ = NULL;
383 delete context_;
384 context_ = NULL;
386 parent::TearDown();
389 void Init(int size) {
390 size_ = 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);
398 // Clear white.
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) ?
422 GENERATE : COMPARE;
425 // Length in x and y of the square canvas.
426 int size_;
428 // Current image number in the current test. Used to number of test files.
429 int number_;
431 // A temporary HDC to draw into.
432 Context* context_;
434 // Bitmap created inside context_.
435 Bitmap* bitmap_;
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 ////////////////////////////////////////////////////////////////////////////////
450 // Actual tests
452 #if !defined(USE_AURA) // http://crbug.com/154358
454 TEST_F(VectorCanvasTest, BasicDrawing) {
455 EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
456 << L"clean";
457 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
459 // Clear white.
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.
468 SkPaint paint;
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")));
475 // Rect.
477 SkPaint paint;
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.
486 SkPaint paint;
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")));
493 // Rect.
495 SkPaint paint;
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")));
502 // Empty again
504 vcanvas_->drawPaint(SkPaint());
505 pcanvas_->drawPaint(SkPaint());
507 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
509 // Horizontal line left to right.
511 SkPaint paint;
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.
520 SkPaint paint;
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;
533 // Stroked Circle.
535 SkPaint paint;
536 SkPath path;
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")));
545 // Filled Circle.
547 SkPaint paint;
548 SkPath path;
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.
558 SkPaint paint;
559 SkPath path;
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.
570 SkPaint paint;
571 SkPath path;
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.
582 SkPaint paint;
583 SkPath path;
584 paint.setStyle(SkPaint::kStroke_Style);
585 paint.setColor(SK_ColorGREEN);
586 path.moveTo(1, 1);
587 path.lineTo(60, 40);
588 path.lineTo(80, 80);
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;
605 // Horizontal lines.
607 SkPaint paint;
608 paint.setColor(SK_ColorRED);
609 // Left to right.
610 vcanvas_->drawLine(10, 20, 90, 20, paint);
611 pcanvas_->drawLine(10, 20, 90, 20, paint);
612 // Right to left.
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")));
618 // Vertical lines.
620 SkPaint paint;
621 paint.setColor(SK_ColorRED);
622 // Top down.
623 vcanvas_->drawLine(20, 10, 20, 90, paint);
624 pcanvas_->drawLine(20, 10, 20, 90, paint);
625 // Bottom up.
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).
637 SkPaint paint;
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).
648 SkPaint paint;
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;
663 // Horizontal lines.
665 SkPaint paint;
666 paint.setStyle(SkPaint::kStroke_Style);
667 paint.setColor(SK_ColorRED);
668 SkPath path;
669 SkPoint start;
670 start.set(10, 20);
671 SkPoint end;
672 end.set(90, 20);
673 path.moveTo(start);
674 path.lineTo(end);
675 vcanvas_->drawPath(path, paint);
676 pcanvas_->drawPath(path, paint);
678 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
680 // Horizontal lines.
682 SkPaint paint;
683 paint.setStyle(SkPaint::kStroke_Style);
684 paint.setColor(SK_ColorRED);
685 SkPath path;
686 SkPoint start;
687 start.set(90, 30);
688 SkPoint end;
689 end.set(10, 30);
690 path.moveTo(start);
691 path.lineTo(end);
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) {
699 SkPaint paint;
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
708 // 1060231.
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")));
724 #if defined(OS_WIN)
725 #define MAYBE_PathEffects DISABLED_PathEffects
726 #else
727 #define MAYBE_PathEffects PathEffects
728 #endif
729 TEST_F(VectorCanvasTest, MAYBE_PathEffects) {
731 SkPaint paint;
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
747 // 1060231.
748 compare_canvas_ = false;
751 SkPaint paint;
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);
759 SkPath path;
760 path.moveTo(10, 15);
761 path.lineTo(90, 15);
762 path.lineTo(90, 90);
763 vcanvas_->drawPath(path, paint);
764 pcanvas_->drawPath(path, paint);
766 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
769 SkPaint paint;
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.
785 SkPaint paint;
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);
793 SkPath path;
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) {
803 SkBitmap bitmap;
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")));
811 SkBitmap bitmap;
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) {
820 SkBitmap bitmap;
821 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
822 true);
823 SkRect rect;
824 rect.fLeft = 2;
825 rect.fTop = 2;
826 rect.fRight = 30.5f;
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) {
837 SkBitmap bitmap;
838 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
839 true);
840 SkPath path;
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) {
851 SkBitmap bitmap;
852 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
853 true);
855 SkRect rect;
856 rect.fLeft = 2;
857 rect.fTop = 2;
858 rect.fRight = 30.5f;
859 rect.fBottom = 30.5f;
860 vcanvas_->clipRect(rect);
861 pcanvas_->clipRect(rect);
862 SkPath path;
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) {
873 SkBitmap bitmap;
874 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
875 true);
877 SkRect rect;
878 rect.fLeft = 2;
879 rect.fTop = 2;
880 rect.fRight = 30.5f;
881 rect.fBottom = 30.5f;
882 vcanvas_->clipRect(rect);
883 pcanvas_->clipRect(rect);
884 SkPath path;
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) {
895 SkBitmap bitmap;
896 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
897 true);
899 SkAutoCanvasRestore acrv(vcanvas_, true);
900 SkAutoCanvasRestore acrp(pcanvas_, true);
901 SkRect rect;
902 rect.fLeft = 2;
903 rect.fTop = 2;
904 rect.fRight = 30.5f;
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) {
923 SkBitmap bitmap;
924 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
925 true);
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
945 // across versions.
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)
969 } // namespace skia