- add sources.
[platform/framework/web/crosswalk.git] / src / skia / ext / vector_canvas_unittest.cc
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.
4
5 #include "build/build_config.h"
6
7 #if !defined(OS_WIN)
8 #include <unistd.h>
9 #endif
10
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"
23
24 namespace skia {
25
26 namespace {
27
28 const char kGenerateSwitch[] = "vector-canvas-generate";
29
30 // Lightweight HDC management.
31 class Context {
32  public:
33   Context() : context_(CreateCompatibleDC(NULL)) {
34     EXPECT_TRUE(context_);
35   }
36   ~Context() {
37     DeleteDC(context_);
38   }
39
40   HDC context() const { return context_; }
41
42  private:
43   HDC context_;
44
45   DISALLOW_COPY_AND_ASSIGN(Context);
46 };
47
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_));
69   }
70   ~Bitmap() {
71     EXPECT_TRUE(DeleteObject(bitmap_));
72   }
73
74  private:
75   HBITMAP bitmap_;
76
77   void* data_;
78
79   DISALLOW_COPY_AND_ASSIGN(Bitmap);
80 };
81
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());
91
92     SkBitmap bitmap;
93     EXPECT_TRUE(gfx::PNGCodec::Decode(
94         reinterpret_cast<const unsigned char*>(compressed.data()),
95         compressed.size(), &bitmap));
96     SetSkBitmap(bitmap);
97   }
98
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);
116   }
117
118   // Loads the image from a canvas.
119   Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
120     SetSkBitmap(bitmap);
121   }
122
123   int width() const { return width_; }
124   int height() const { return height_; }
125   int row_length() const { return row_length_; }
126
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 = file_util::OpenFile(filename, "wb");
139     ASSERT_TRUE(f);
140     ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
141               compressed.size());
142     file_util::CloseFile(f);
143   }
144
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.
154     }
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;
163       }
164     }
165
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.;
171   }
172
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];
184   }
185
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);
195   }
196
197  private:
198   // Pixel dimensions of the image.
199   int width_;
200   int height_;
201
202   // Length of a line in bytes.
203   int row_length_;
204
205   // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
206   // 0xABGR).
207   std::vector<unsigned char> data_;
208
209   // Flag to signal if the comparison functions should ignore the alpha channel.
210   const bool ignore_alpha_;
211
212   DISALLOW_COPY_AND_ASSIGN(Image);
213 };
214
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,
223   };
224
225   ImageTest(ProcessAction default_action)
226       : action_(default_action) {
227   }
228
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());
239
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);
245
246     if (action_ == GENERATE) {
247       // Make sure the directory exist.
248       file_util::CreateDirectory(test_dir_);
249     }
250   }
251
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]);
263
264     return test_dir_.AppendASCII(tmp);
265   }
266
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.;
285     }
286   }
287
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;
296   }
297
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));
302   }
303
304   ProcessAction action_;
305
306   // Path to directory used to contain the test data.
307   base::FilePath test_dir_;
308
309   DISALLOW_COPY_AND_ASSIGN(ImageTest);
310 };
311
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);
329       }
330     }
331   }
332 }
333
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());
340
341   ASSERT_TRUE(gfx::PNGCodec::Decode(
342       reinterpret_cast<const unsigned char*>(compressed.data()),
343       compressed.size(), bitmap));
344
345   EXPECT_EQ(is_opaque, bitmap->isOpaque());
346   Premultiply(*bitmap);
347 }
348
349 }  // namespace
350
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() << ")";
355 }
356
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;
362
363   VectorCanvasTest() : parent(CurrentMode()), compare_canvas_(true) {
364   }
365
366  protected:
367   virtual void SetUp() {
368     parent::SetUp();
369     Init(100);
370     number_ = 0;
371   }
372
373   virtual void TearDown() {
374     delete pcanvas_;
375     pcanvas_ = NULL;
376
377     delete vcanvas_;
378     vcanvas_ = NULL;
379
380     delete bitmap_;
381     bitmap_ = NULL;
382
383     delete context_;
384     context_ = NULL;
385
386     parent::TearDown();
387   }
388
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);
397
398     // Clear white.
399     vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
400     pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
401   }
402
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);
411
412     Image image1(*vcanvas_);
413     Image image2(*pcanvas_);
414     double diff = image1.PercentageDifferent(image2);
415     return std::max(std::max(diff1, diff2), diff);
416   }
417
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;
423   }
424
425   // Length in x and y of the square canvas.
426   int size_;
427
428   // Current image number in the current test. Used to number of test files.
429   int number_;
430
431   // A temporary HDC to draw into.
432   Context* context_;
433
434   // Bitmap created inside context_.
435   Bitmap* bitmap_;
436
437   // Vector based canvas.
438   VectorCanvas* vcanvas_;
439
440   // Pixel based canvas.
441   PlatformCanvas* pcanvas_;
442
443   // When true (default), vcanvas_ and pcanvas_ contents are compared and
444   // verified to be identical.
445   bool compare_canvas_;
446 };
447
448
449 ////////////////////////////////////////////////////////////////////////////////
450 // Actual tests
451
452 #if !defined(USE_AURA)  // http://crbug.com/154358
453
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")));
458
459   // Clear white.
460   {
461     vcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
462     pcanvas_->drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
463   }
464   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawARGB")));
465
466   // Diagonal line top-left to bottom-right.
467   {
468     SkPaint paint;
469     // Default color is black.
470     vcanvas_->drawLine(10, 10, 90, 90, paint);
471     pcanvas_->drawLine(10, 10, 90, 90, paint);
472   }
473   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_black")));
474
475   // Rect.
476   {
477     SkPaint paint;
478     paint.setColor(SK_ColorGREEN);
479     vcanvas_->drawRectCoords(25, 25, 75, 75, paint);
480     pcanvas_->drawRectCoords(25, 25, 75, 75, paint);
481   }
482   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_green")));
483
484   // A single-point rect doesn't leave any mark.
485   {
486     SkPaint paint;
487     paint.setColor(SK_ColorBLUE);
488     vcanvas_->drawRectCoords(5, 5, 5, 5, paint);
489     pcanvas_->drawRectCoords(5, 5, 5, 5, paint);
490   }
491   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
492
493   // Rect.
494   {
495     SkPaint paint;
496     paint.setColor(SK_ColorBLUE);
497     vcanvas_->drawRectCoords(75, 50, 80, 55, paint);
498     pcanvas_->drawRectCoords(75, 50, 80, 55, paint);
499   }
500   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawRect_noop")));
501
502   // Empty again
503   {
504     vcanvas_->drawPaint(SkPaint());
505     pcanvas_->drawPaint(SkPaint());
506   }
507   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
508
509   // Horizontal line left to right.
510   {
511     SkPaint paint;
512     paint.setColor(SK_ColorRED);
513     vcanvas_->drawLine(10, 20, 90, 20, paint);
514     pcanvas_->drawLine(10, 20, 90, 20, paint);
515   }
516   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_left_to_right")));
517
518   // Vertical line downward.
519   {
520     SkPaint paint;
521     paint.setColor(SK_ColorRED);
522     vcanvas_->drawLine(30, 10, 30, 90, paint);
523     pcanvas_->drawLine(30, 10, 30, 90, paint);
524   }
525   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawLine_red")));
526 }
527
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;
532
533   // Stroked Circle.
534   {
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);
542   }
543   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke")));
544
545   // Filled Circle.
546   {
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);
553   }
554   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_fill")));
555
556   // Stroked Circle over.
557   {
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);
565   }
566   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_over_strike")));
567
568   // Stroke and Fill Circle.
569   {
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);
577   }
578   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("circle_stroke_and_fill")));
579
580   // Line + Quad + Cubic.
581   {
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);
596   }
597   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("mixed_stroke")));
598 }
599
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;
604
605   // Horizontal lines.
606   {
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);
615   }
616   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal")));
617
618   // Vertical lines.
619   {
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);
628   }
629   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical")));
630
631   // Try again with a 180 degres rotation.
632   vcanvas_->rotate(180);
633   pcanvas_->rotate(180);
634
635   // Horizontal lines (rotated).
636   {
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);
643   }
644   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("horizontal_180")));
645
646   // Vertical lines (rotated).
647   {
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);
654   }
655   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("vertical_180")));
656 }
657
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;
662
663   // Horizontal lines.
664   {
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);
677   }
678   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
679
680   // Horizontal lines.
681   {
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);
694   }
695   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_rtl")));
696 }
697
698 TEST_F(VectorCanvasTest, DiagonalLines) {
699   SkPaint paint;
700   paint.setColor(SK_ColorRED);
701
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")));
705
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;
710
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")));
714
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")));
718
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")));
722 }
723
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) {
730   {
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);
738
739     vcanvas_->drawLine(10, 10, 90, 10, paint);
740     pcanvas_->drawLine(10, 10, 90, 10, paint);
741   }
742   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_line")));
743
744
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;
749
750   {
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);
758
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);
765   }
766   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
767
768   {
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);
776
777     vcanvas_->drawRectCoords(20, 20, 30, 30, paint);
778     pcanvas_->drawRectCoords(20, 20, 30, 30, paint);
779   }
780   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_rect")));
781
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.
784   {
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);
792
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")));
798   }
799 }
800
801 TEST_F(VectorCanvasTest, Bitmaps) {
802   {
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")));
808   }
809
810   {
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")));
816   }
817 }
818
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);
830
831   vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
832   pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
833   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("rect")));
834 }
835
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);
844
845   vcanvas_->drawBitmap(bitmap, 14, 3, NULL);
846   pcanvas_->drawBitmap(bitmap, 14, 3, NULL);
847   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("path")));
848 }
849
850 TEST_F(VectorCanvasTest, ClippingCombined) {
851   SkBitmap bitmap;
852   LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
853                         true);
854
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);
866
867   vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
868   pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
869   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("combined")));
870 }
871
872 TEST_F(VectorCanvasTest, ClippingIntersect) {
873   SkBitmap bitmap;
874   LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
875                         true);
876
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);
888
889   vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
890   pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
891   EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("intersect")));
892 }
893
894 TEST_F(VectorCanvasTest, ClippingClean) {
895   SkBitmap bitmap;
896   LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
897                         true);
898   {
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);
908
909     vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
910     pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
911     EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clipped")));
912   }
913   {
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")));
918   }
919 }
920
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);
926   {
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")));
932   }
933   {
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")));
939   }
940   vcanvas_->resetMatrix();
941   pcanvas_->resetMatrix();
942
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;
947
948   {
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")));
954   }
955   vcanvas_->resetMatrix();
956   pcanvas_->resetMatrix();
957
958   {
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")));
964   }
965 }
966
967 #endif  // !defined(USE_AURA)
968
969 }  // namespace skia