ProfileInfoCache: Don't delete ProfileAvatarDownloader while we're being called by it
[chromium-blink-merge.git] / skia / ext / vector_canvas_unittest.cc
blobd3ad9a0c358db02757597feb83a9ec27ddce2865
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/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"
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 = base::UTF16ToASCII(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 base::CommandLine::ForCurrentProcess()->HasSwitch(kGenerateSwitch)
422 ? GENERATE
423 : COMPARE;
426 // Length in x and y of the square canvas.
427 int size_;
429 // Current image number in the current test. Used to number of test files.
430 int number_;
432 // A temporary HDC to draw into.
433 Context* context_;
435 // Bitmap created inside context_.
436 Bitmap* bitmap_;
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 ////////////////////////////////////////////////////////////////////////////////
451 // Actual tests
453 #if !defined(USE_AURA) // http://crbug.com/154358
455 TEST_F(VectorCanvasTest, BasicDrawing) {
456 EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
457 << L"clean";
458 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("clean")));
460 // Clear white.
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.
469 SkPaint paint;
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")));
476 // Rect.
478 SkPaint paint;
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.
487 SkPaint paint;
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")));
494 // Rect.
496 SkPaint paint;
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")));
503 // Empty again
505 vcanvas_->drawPaint(SkPaint());
506 pcanvas_->drawPaint(SkPaint());
508 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPaint_black")));
510 // Horizontal line left to right.
512 SkPaint paint;
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.
521 SkPaint paint;
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;
534 // Stroked Circle.
536 SkPaint paint;
537 SkPath path;
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")));
546 // Filled Circle.
548 SkPaint paint;
549 SkPath path;
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.
559 SkPaint paint;
560 SkPath path;
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.
571 SkPaint paint;
572 SkPath path;
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.
583 SkPaint paint;
584 SkPath path;
585 paint.setStyle(SkPaint::kStroke_Style);
586 paint.setColor(SK_ColorGREEN);
587 path.moveTo(1, 1);
588 path.lineTo(60, 40);
589 path.lineTo(80, 80);
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;
606 // Horizontal lines.
608 SkPaint paint;
609 paint.setColor(SK_ColorRED);
610 // Left to right.
611 vcanvas_->drawLine(10, 20, 90, 20, paint);
612 pcanvas_->drawLine(10, 20, 90, 20, paint);
613 // Right to left.
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")));
619 // Vertical lines.
621 SkPaint paint;
622 paint.setColor(SK_ColorRED);
623 // Top down.
624 vcanvas_->drawLine(20, 10, 20, 90, paint);
625 pcanvas_->drawLine(20, 10, 20, 90, paint);
626 // Bottom up.
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).
638 SkPaint paint;
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).
649 SkPaint paint;
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;
664 // Horizontal lines.
666 SkPaint paint;
667 paint.setStyle(SkPaint::kStroke_Style);
668 paint.setColor(SK_ColorRED);
669 SkPath path;
670 SkPoint start;
671 start.set(10, 20);
672 SkPoint end;
673 end.set(90, 20);
674 path.moveTo(start);
675 path.lineTo(end);
676 vcanvas_->drawPath(path, paint);
677 pcanvas_->drawPath(path, paint);
679 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("drawPath_ltr")));
681 // Horizontal lines.
683 SkPaint paint;
684 paint.setStyle(SkPaint::kStroke_Style);
685 paint.setColor(SK_ColorRED);
686 SkPath path;
687 SkPoint start;
688 start.set(90, 30);
689 SkPoint end;
690 end.set(10, 30);
691 path.moveTo(start);
692 path.lineTo(end);
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) {
700 SkPaint paint;
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
709 // 1060231.
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")));
725 #if defined(OS_WIN)
726 #define MAYBE_PathEffects DISABLED_PathEffects
727 #else
728 #define MAYBE_PathEffects PathEffects
729 #endif
730 TEST_F(VectorCanvasTest, MAYBE_PathEffects) {
732 SkPaint paint;
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
748 // 1060231.
749 compare_canvas_ = false;
752 SkPaint paint;
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);
760 SkPath path;
761 path.moveTo(10, 15);
762 path.lineTo(90, 15);
763 path.lineTo(90, 90);
764 vcanvas_->drawPath(path, paint);
765 pcanvas_->drawPath(path, paint);
767 EXPECT_EQ(0., ProcessImage(FILE_PATH_LITERAL("dash_path")));
770 SkPaint paint;
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.
786 SkPaint paint;
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);
794 SkPath path;
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) {
804 SkBitmap bitmap;
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")));
812 SkBitmap bitmap;
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) {
821 SkBitmap bitmap;
822 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
823 true);
824 SkRect rect;
825 rect.fLeft = 2;
826 rect.fTop = 2;
827 rect.fRight = 30.5f;
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) {
838 SkBitmap bitmap;
839 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
840 true);
841 SkPath path;
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) {
852 SkBitmap bitmap;
853 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
854 true);
856 SkRect rect;
857 rect.fLeft = 2;
858 rect.fTop = 2;
859 rect.fRight = 30.5f;
860 rect.fBottom = 30.5f;
861 vcanvas_->clipRect(rect);
862 pcanvas_->clipRect(rect);
863 SkPath path;
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) {
874 SkBitmap bitmap;
875 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
876 true);
878 SkRect rect;
879 rect.fLeft = 2;
880 rect.fTop = 2;
881 rect.fRight = 30.5f;
882 rect.fBottom = 30.5f;
883 vcanvas_->clipRect(rect);
884 pcanvas_->clipRect(rect);
885 SkPath path;
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) {
896 SkBitmap bitmap;
897 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
898 true);
900 SkAutoCanvasRestore acrv(vcanvas_, true);
901 SkAutoCanvasRestore acrp(pcanvas_, true);
902 SkRect rect;
903 rect.fLeft = 2;
904 rect.fTop = 2;
905 rect.fRight = 30.5f;
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) {
924 SkBitmap bitmap;
925 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap,
926 true);
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
946 // across versions.
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)
970 } // namespace skia