Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: base/gfx/vector_canvas_unittest.cc

Issue 11244: Move PlatformCanvas and PlatformDevice from base/gfx to webkit/port. I left h... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/gfx/vector_canvas.cc ('k') | base/gfx/vector_device.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 "base/gfx/vector_canvas.h"
6
7 #include <vector>
8
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/gfx/gdi_util.h"
12 #include "base/gfx/png_decoder.h"
13 #include "base/gfx/png_encoder.h"
14 #include "base/gfx/size.h"
15 #include "base/path_service.h"
16 #include "base/string_util.h"
17 #include "base/win_util.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 #include "SkDashPathEffect.h"
21
22 namespace {
23
24 const wchar_t* const kGenerateSwitch = L"vector-canvas-generate";
25
26 // Base class for unit test that uses data. It initializes a directory path
27 // based on the test's name.
28 class DataUnitTest : public testing::Test {
29 public:
30 DataUnitTest(const std::wstring& base_path) : base_path_(base_path) { }
31
32 protected:
33 // Load the test's data path.
34 virtual void SetUp() {
35 const testing::TestInfo& test_info =
36 *testing::UnitTest::GetInstance()->current_test_info();
37 PathService::Get(base::DIR_SOURCE_ROOT, &test_dir_);
38 file_util::AppendToPath(&test_dir_, base_path_);
39 file_util::AppendToPath(&test_dir_, L"data");
40 file_util::AppendToPath(&test_dir_,
41 ASCIIToWide(test_info.test_case_name()));
42 file_util::AppendToPath(&test_dir_, ASCIIToWide(test_info.name()));
43
44 // Hack for a quick lowercase. We assume all the tests names are ASCII.
45 std::string tmp(WideToASCII(test_dir_));
46 for (size_t i = 0; i < tmp.size(); ++i)
47 tmp[i] = ToLowerASCII(tmp[i]);
48 test_dir_ = ASCIIToWide(tmp);
49 }
50
51 // Returns the fully qualified path of directory containing test data files.
52 const std::wstring& test_dir() const {
53 return test_dir_;
54 }
55
56 // Returns the fully qualified path of a data file.
57 std::wstring test_file(const std::wstring& filename) const {
58 // Hack for a quick lowercase. We assume all the test data file names are
59 // ASCII.
60 std::string tmp(WideToASCII(filename));
61 for (size_t i = 0; i < tmp.size(); ++i)
62 tmp[i] = ToLowerASCII(tmp[i]);
63
64 std::wstring path(test_dir());
65 file_util::AppendToPath(&path, ASCIIToWide(tmp));
66 return path;
67 }
68
69 private:
70 // Path where the unit test is coming from: base, net, chrome, etc.
71 std::wstring base_path_;
72
73 // Path to directory used to contain the test data.
74 std::wstring test_dir_;
75
76 DISALLOW_EVIL_CONSTRUCTORS(DataUnitTest);
77 };
78
79 // Lightweight HDC management.
80 class Context {
81 public:
82 Context() : context_(CreateCompatibleDC(NULL)) {
83 EXPECT_TRUE(context_);
84 }
85 ~Context() {
86 DeleteDC(context_);
87 }
88
89 HDC context() const { return context_; }
90
91 private:
92 HDC context_;
93
94 DISALLOW_EVIL_CONSTRUCTORS(Context);
95 };
96
97 // Lightweight HBITMAP management.
98 class Bitmap {
99 public:
100 Bitmap(const Context& context, int x, int y) {
101 BITMAPINFOHEADER hdr;
102 gfx::CreateBitmapHeader(x, y, &hdr);
103 bitmap_ = CreateDIBSection(context.context(),
104 reinterpret_cast<BITMAPINFO*>(&hdr), 0,
105 &data_, NULL, 0);
106 EXPECT_TRUE(bitmap_);
107 EXPECT_TRUE(SelectObject(context.context(), bitmap_));
108 }
109 ~Bitmap() {
110 EXPECT_TRUE(DeleteObject(bitmap_));
111 }
112
113 private:
114 HBITMAP bitmap_;
115
116 void* data_;
117
118 DISALLOW_EVIL_CONSTRUCTORS(Bitmap);
119 };
120
121 // Lightweight raw-bitmap management. The image, once initialized, is immuable.
122 // It is mainly used for comparison.
123 class Image {
124 public:
125 // Creates the image from the given filename on disk.
126 Image(const std::wstring& filename) : ignore_alpha_(true) {
127 std::string compressed;
128 file_util::ReadFileToString(filename, &compressed);
129 EXPECT_TRUE(compressed.size());
130
131 int w;
132 int h;
133 EXPECT_TRUE(PNGDecoder::Decode(
134 reinterpret_cast<const unsigned char*>(compressed.c_str()),
135 compressed.size(), PNGDecoder::FORMAT_BGRA, &data_, &w, &h));
136 size_.SetSize(w, h);
137 row_length_ = w * sizeof(uint32);
138 }
139
140 // Loads the image from a canvas.
141 Image(const gfx::PlatformCanvasWin& canvas) : ignore_alpha_(true) {
142 // Use a different way to access the bitmap. The normal way would be to
143 // query the SkBitmap.
144 HDC context = canvas.getTopPlatformDevice().getBitmapDC();
145 HGDIOBJ bitmap = GetCurrentObject(context, OBJ_BITMAP);
146 EXPECT_TRUE(bitmap != NULL);
147 // Initialize the clip region to the entire bitmap.
148 BITMAP bitmap_data;
149 EXPECT_EQ(GetObject(bitmap, sizeof(BITMAP), &bitmap_data),
150 sizeof(BITMAP));
151 size_.SetSize(bitmap_data.bmWidth, bitmap_data.bmHeight);
152 row_length_ = bitmap_data.bmWidthBytes;
153 size_t size = row_length_ * size_.height();
154 data_.resize(size);
155 memcpy(&*data_.begin(), bitmap_data.bmBits, size);
156 }
157
158 // Loads the image from a canvas.
159 Image(const SkBitmap& bitmap) : ignore_alpha_(true) {
160 SkAutoLockPixels lock(bitmap);
161 size_.SetSize(bitmap.width(), bitmap.height());
162 row_length_ = static_cast<int>(bitmap.rowBytes());
163 size_t size = row_length_ * size_.height();
164 data_.resize(size);
165 memcpy(&*data_.begin(), bitmap.getAddr(0, 0), size);
166 }
167
168 const gfx::Size& size() const {
169 return size_;
170 }
171
172 int row_length() const {
173 return row_length_;
174 }
175
176 // Save the image to a png file. Used to create the initial test files.
177 void SaveToFile(const std::wstring& filename) {
178 std::vector<unsigned char> compressed;
179 ASSERT_TRUE(PNGEncoder::Encode(&*data_.begin(),
180 PNGEncoder::FORMAT_BGRA,
181 size_.width(),
182 size_.height(),
183 row_length_,
184 true,
185 &compressed));
186 ASSERT_TRUE(compressed.size());
187 FILE* f = file_util::OpenFile(filename, "wb");
188 ASSERT_TRUE(f);
189 ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
190 compressed.size());
191 file_util::CloseFile(f);
192 }
193
194 // Returns the percentage of the image that is different from the other,
195 // between 0 and 100.
196 double PercentageDifferent(const Image& rhs) const {
197 if (size_ != rhs.size_ || row_length_ != rhs.row_length_ ||
198 size_.width() == 0 || size_.height() == 0)
199 return 100.; // When of different size or empty, they are 100% different.
200
201 // Compute pixels different in the overlap
202 int pixels_different = 0;
203 for (int y = 0; y < size_.height(); ++y) {
204 for (int x = 0; x < size_.width(); ++x) {
205 uint32_t lhs_pixel = pixel_at(x, y);
206 uint32_t rhs_pixel = rhs.pixel_at(x, y);
207 if (lhs_pixel != rhs_pixel)
208 ++pixels_different;
209 }
210 }
211
212 // Like the WebKit ImageDiff tool, we define percentage different in terms
213 // of the size of the 'actual' bitmap.
214 double total_pixels = static_cast<double>(size_.width()) *
215 static_cast<double>(size_.height());
216 return static_cast<double>(pixels_different) / total_pixels * 100.;
217 }
218
219 // Returns the 0x0RGB or 0xARGB value of the pixel at the given location,
220 // depending on ignore_alpha_.
221 uint32 pixel_at(int x, int y) const {
222 EXPECT_TRUE(x >= 0 && x < size_.width());
223 EXPECT_TRUE(y >= 0 && y < size_.height());
224 const uint32* data = reinterpret_cast<const uint32*>(&*data_.begin());
225 const uint32* data_row = data + y * row_length_ / sizeof(uint32);
226 if (ignore_alpha_)
227 return data_row[x] & 0xFFFFFF; // Strip out A.
228 else
229 return data_row[x];
230 }
231
232 private:
233 // Pixel dimensions of the image.
234 gfx::Size size_;
235
236 // Length of a line in bytes.
237 int row_length_;
238
239 // Actual bitmap data in arrays of RGBAs (so when loaded as uint32, it's
240 // 0xABGR).
241 std::vector<unsigned char> data_;
242
243 // Flag to signal if the comparison functions should ignore the alpha channel.
244 const bool ignore_alpha_;
245
246 DISALLOW_EVIL_CONSTRUCTORS(Image);
247 };
248
249 // Base for tests. Capability to process an image.
250 class ImageTest : public DataUnitTest {
251 public:
252 typedef DataUnitTest parent;
253
254 // In what state is the test running.
255 enum ProcessAction {
256 GENERATE,
257 COMPARE,
258 NOOP,
259 };
260
261 ImageTest(const std::wstring& base_path, ProcessAction default_action)
262 : parent(base_path),
263 action_(default_action) {
264 }
265
266 protected:
267 virtual void SetUp() {
268 parent::SetUp();
269
270 if (action_ == GENERATE) {
271 // Make sure the directory exist.
272 file_util::CreateDirectory(test_dir());
273 }
274 }
275
276 // Compares or saves the bitmap currently loaded in the context, depending on
277 // kGenerating value. Returns 0 on success or any positive value between ]0,
278 // 100] on failure. The return value is the percentage of difference between
279 // the image in the file and the image in the canvas.
280 double ProcessCanvas(const gfx::PlatformCanvasWin& canvas,
281 std::wstring filename) const {
282 filename += L".png";
283 switch (action_) {
284 case GENERATE:
285 SaveImage(canvas, filename);
286 return 0.;
287 case COMPARE:
288 return CompareImage(canvas, filename);
289 case NOOP:
290 return 0;
291 default:
292 // Invalid state, returns that the image is 100 different.
293 return 100.;
294 }
295 }
296
297 // Compares the bitmap currently loaded in the context with the file. Returns
298 // the percentage of pixel difference between both images, between 0 and 100.
299 double CompareImage(const gfx::PlatformCanvasWin& canvas,
300 const std::wstring& filename) const {
301 Image image1(canvas);
302 Image image2(test_file(filename));
303 double diff = image1.PercentageDifferent(image2);
304 return diff;
305 }
306
307 // Saves the bitmap currently loaded in the context into the file.
308 void SaveImage(const gfx::PlatformCanvasWin& canvas,
309 const std::wstring& filename) const {
310 Image(canvas).SaveToFile(test_file(filename));
311 }
312
313 ProcessAction action_;
314
315 DISALLOW_EVIL_CONSTRUCTORS(ImageTest);
316 };
317
318 // Premultiply the Alpha channel on the R, B and G channels.
319 void Premultiply(SkBitmap bitmap) {
320 SkAutoLockPixels lock(bitmap);
321 for (int x = 0; x < bitmap.width(); ++x) {
322 for (int y = 0; y < bitmap.height(); ++y) {
323 uint32_t* pixel_addr = bitmap.getAddr32(x, y);
324 uint32_t color = *pixel_addr;
325 BYTE alpha = SkColorGetA(color);
326 if (!alpha) {
327 *pixel_addr = 0;
328 } else {
329 BYTE alpha_offset = alpha / 2;
330 *pixel_addr = SkColorSetARGB(
331 SkColorGetA(color),
332 (SkColorGetR(color) * 255 + alpha_offset) / alpha,
333 (SkColorGetG(color) * 255 + alpha_offset) / alpha,
334 (SkColorGetB(color) * 255 + alpha_offset) / alpha);
335 }
336 }
337 }
338 }
339
340 void LoadPngFileToSkBitmap(const std::wstring& file, SkBitmap* bitmap) {
341 std::string compressed;
342 file_util::ReadFileToString(file, &compressed);
343 EXPECT_TRUE(compressed.size());
344 // Extra-lame. If you care, fix it.
345 std::vector<unsigned char> data;
346 data.assign(reinterpret_cast<const unsigned char*>(compressed.c_str()),
347 reinterpret_cast<const unsigned char*>(compressed.c_str() +
348 compressed.size()));
349 EXPECT_TRUE(PNGDecoder::Decode(&data, bitmap));
350 EXPECT_FALSE(bitmap->isOpaque());
351 Premultiply(*bitmap);
352 }
353
354 } // namespace
355
356 // Streams an image.
357 inline std::ostream& operator<<(std::ostream& out, const Image& image) {
358 return out << "Image(" << image.size() << ", " << image.row_length() << ")";
359 }
360
361 // Runs simultaneously the same drawing commands on VectorCanvas and
362 // PlatformCanvas and compare the results.
363 class VectorCanvasTest : public ImageTest {
364 public:
365 typedef ImageTest parent;
366
367 VectorCanvasTest() : parent(L"base", CurrentMode()), compare_canvas_(true) {
368 }
369
370 protected:
371 virtual void SetUp() {
372 parent::SetUp();
373 Init(100);
374 number_ = 0;
375 }
376
377 virtual void TearDown() {
378 delete pcanvas_;
379 pcanvas_ = NULL;
380
381 delete vcanvas_;
382 vcanvas_ = NULL;
383
384 delete bitmap_;
385 bitmap_ = NULL;
386
387 delete context_;
388 context_ = NULL;
389
390 parent::TearDown();
391 }
392
393 void Init(int size) {
394 size_ = size;
395 context_ = new Context();
396 bitmap_ = new Bitmap(*context_, size_, size_);
397 vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_);
398 pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false);
399
400 // Clear white.
401 vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
402 pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
403 }
404
405 // Compares both canvas and returns the pixel difference in percentage between
406 // both images. 0 on success and ]0, 100] on failure.
407 double ProcessImage(const std::wstring& filename) {
408 std::wstring number(StringPrintf(L"%02d_", number_++));
409 double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename);
410 double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename);
411 if (!compare_canvas_)
412 return std::max(diff1, diff2);
413
414 Image image1(*vcanvas_);
415 Image image2(*pcanvas_);
416 double diff = image1.PercentageDifferent(image2);
417 return std::max(std::max(diff1, diff2), diff);
418 }
419
420 // Returns COMPARE, which is the default. If kGenerateSwitch command
421 // line argument is used to start this process, GENERATE is returned instead.
422 static ProcessAction CurrentMode() {
423 return CommandLine().HasSwitch(kGenerateSwitch) ? GENERATE : COMPARE;
424 }
425
426 // Length in x and y of the square canvas.
427 int size_;
428
429 // Current image number in the current test. Used to number of test files.
430 int number_;
431
432 // A temporary HDC to draw into.
433 Context* context_;
434
435 // Bitmap created inside context_.
436 Bitmap* bitmap_;
437
438 // Vector based canvas.
439 gfx::VectorCanvas* vcanvas_;
440
441 // Pixel based canvas.
442 gfx::PlatformCanvasWin* pcanvas_;
443
444 // When true (default), vcanvas_ and pcanvas_ contents are compared and
445 // verified to be identical.
446 bool compare_canvas_;
447 };
448
449
450 ////////////////////////////////////////////////////////////////////////////////
451 // Actual tests
452
453 TEST_F(VectorCanvasTest, Uninitialized) {
454 // Do a little mubadumba do get uninitialized stuff.
455 VectorCanvasTest::TearDown();
456
457 // The goal is not to verify that have the same uninitialized data.
458 compare_canvas_ = false;
459
460 context_ = new Context();
461 bitmap_ = new Bitmap(*context_, size_, size_);
462 vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_);
463 pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false);
464
465 // VectorCanvas default initialization is black.
466 // PlatformCanvas default initialization is almost white 0x01FFFEFD (invalid
467 // Skia color) in both Debug and Release. See magicTransparencyColor in
468 // platform_device.cc
469 EXPECT_EQ(0., ProcessImage(L"empty"));
470 }
471
472 TEST_F(VectorCanvasTest, BasicDrawing) {
473 EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.)
474 << L"clean";
475 EXPECT_EQ(0., ProcessImage(L"clean"));
476
477 // Clear white.
478 {
479 vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
480 pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode);
481 }
482 EXPECT_EQ(0., ProcessImage(L"drawARGB"));
483
484 // Diagonal line top-left to bottom-right.
485 {
486 SkPaint paint;
487 // Default color is black.
488 vcanvas_->drawLine(10, 10, 90, 90, paint);
489 pcanvas_->drawLine(10, 10, 90, 90, paint);
490 }
491 EXPECT_EQ(0., ProcessImage(L"drawLine_black"));
492
493 // Rect.
494 {
495 SkPaint paint;
496 paint.setColor(SK_ColorGREEN);
497 vcanvas_->drawRectCoords(25, 25, 75, 75, paint);
498 pcanvas_->drawRectCoords(25, 25, 75, 75, paint);
499 }
500 EXPECT_EQ(0., ProcessImage(L"drawRect_green"));
501
502 // A single-point rect doesn't leave any mark.
503 {
504 SkPaint paint;
505 paint.setColor(SK_ColorBLUE);
506 vcanvas_->drawRectCoords(5, 5, 5, 5, paint);
507 pcanvas_->drawRectCoords(5, 5, 5, 5, paint);
508 }
509 EXPECT_EQ(0., ProcessImage(L"drawRect_noop"));
510
511 // Rect.
512 {
513 SkPaint paint;
514 paint.setColor(SK_ColorBLUE);
515 vcanvas_->drawRectCoords(75, 50, 80, 55, paint);
516 pcanvas_->drawRectCoords(75, 50, 80, 55, paint);
517 }
518 EXPECT_EQ(0., ProcessImage(L"drawRect_noop"));
519
520 // Empty again
521 {
522 vcanvas_->drawPaint(SkPaint());
523 pcanvas_->drawPaint(SkPaint());
524 }
525 EXPECT_EQ(0., ProcessImage(L"drawPaint_black"));
526
527 // Horizontal line left to right.
528 {
529 SkPaint paint;
530 paint.setColor(SK_ColorRED);
531 vcanvas_->drawLine(10, 20, 90, 20, paint);
532 pcanvas_->drawLine(10, 20, 90, 20, paint);
533 }
534 EXPECT_EQ(0., ProcessImage(L"drawLine_left_to_right"));
535
536 // Vertical line downward.
537 {
538 SkPaint paint;
539 paint.setColor(SK_ColorRED);
540 vcanvas_->drawLine(30, 10, 30, 90, paint);
541 pcanvas_->drawLine(30, 10, 30, 90, paint);
542 }
543 EXPECT_EQ(0., ProcessImage(L"drawLine_red"));
544 }
545
546 TEST_F(VectorCanvasTest, Circles) {
547 // There is NO WAY to make them agree. At least verify that the output doesn't
548 // change across versions. This test is disabled. See bug 1060231.
549 compare_canvas_ = false;
550
551 // Stroked Circle.
552 {
553 SkPaint paint;
554 SkPath path;
555 path.addCircle(50, 75, 10);
556 paint.setStyle(SkPaint::kStroke_Style);
557 paint.setColor(SK_ColorMAGENTA);
558 vcanvas_->drawPath(path, paint);
559 pcanvas_->drawPath(path, paint);
560 }
561 EXPECT_EQ(0., ProcessImage(L"circle_stroke"));
562
563 // Filled Circle.
564 {
565 SkPaint paint;
566 SkPath path;
567 path.addCircle(50, 25, 10);
568 paint.setStyle(SkPaint::kFill_Style);
569 vcanvas_->drawPath(path, paint);
570 pcanvas_->drawPath(path, paint);
571 }
572 EXPECT_EQ(0., ProcessImage(L"circle_fill"));
573
574 // Stroked Circle over.
575 {
576 SkPaint paint;
577 SkPath path;
578 path.addCircle(50, 25, 10);
579 paint.setStyle(SkPaint::kStroke_Style);
580 paint.setColor(SK_ColorBLUE);
581 vcanvas_->drawPath(path, paint);
582 pcanvas_->drawPath(path, paint);
583 }
584 EXPECT_EQ(0., ProcessImage(L"circle_over_strike"));
585
586 // Stroke and Fill Circle.
587 {
588 SkPaint paint;
589 SkPath path;
590 path.addCircle(12, 50, 10);
591 paint.setStyle(SkPaint::kStrokeAndFill_Style);
592 paint.setColor(SK_ColorRED);
593 vcanvas_->drawPath(path, paint);
594 pcanvas_->drawPath(path, paint);
595 }
596 EXPECT_EQ(0., ProcessImage(L"circle_stroke_and_fill"));
597
598 // Line + Quad + Cubic.
599 {
600 SkPaint paint;
601 SkPath path;
602 paint.setStyle(SkPaint::kStroke_Style);
603 paint.setColor(SK_ColorGREEN);
604 path.moveTo(1, 1);
605 path.lineTo(60, 40);
606 path.lineTo(80, 80);
607 path.quadTo(20, 50, 10, 90);
608 path.quadTo(50, 20, 90, 10);
609 path.cubicTo(20, 40, 50, 50, 10, 10);
610 path.cubicTo(30, 20, 50, 50, 90, 10);
611 path.addRect(90, 90, 95, 96);
612 vcanvas_->drawPath(path, paint);
613 pcanvas_->drawPath(path, paint);
614 }
615 EXPECT_EQ(0., ProcessImage(L"mixed_stroke"));
616 }
617
618 TEST_F(VectorCanvasTest, LineOrientation) {
619 // There is NO WAY to make them agree. At least verify that the output doesn't
620 // change across versions. This test is disabled. See bug 1060231.
621 compare_canvas_ = false;
622
623 // Horizontal lines.
624 {
625 SkPaint paint;
626 paint.setColor(SK_ColorRED);
627 // Left to right.
628 vcanvas_->drawLine(10, 20, 90, 20, paint);
629 pcanvas_->drawLine(10, 20, 90, 20, paint);
630 // Right to left.
631 vcanvas_->drawLine(90, 30, 10, 30, paint);
632 pcanvas_->drawLine(90, 30, 10, 30, paint);
633 }
634 EXPECT_EQ(0., ProcessImage(L"horizontal"));
635
636 // Vertical lines.
637 {
638 SkPaint paint;
639 paint.setColor(SK_ColorRED);
640 // Top down.
641 vcanvas_->drawLine(20, 10, 20, 90, paint);
642 pcanvas_->drawLine(20, 10, 20, 90, paint);
643 // Bottom up.
644 vcanvas_->drawLine(30, 90, 30, 10, paint);
645 pcanvas_->drawLine(30, 90, 30, 10, paint);
646 }
647 EXPECT_EQ(0., ProcessImage(L"vertical"));
648
649 // Try again with a 180 degres rotation.
650 vcanvas_->rotate(180);
651 pcanvas_->rotate(180);
652
653 // Horizontal lines (rotated).
654 {
655 SkPaint paint;
656 paint.setColor(SK_ColorRED);
657 vcanvas_->drawLine(-10, -25, -90, -25, paint);
658 pcanvas_->drawLine(-10, -25, -90, -25, paint);
659 vcanvas_->drawLine(-90, -35, -10, -35, paint);
660 pcanvas_->drawLine(-90, -35, -10, -35, paint);
661 }
662 EXPECT_EQ(0., ProcessImage(L"horizontal_180"));
663
664 // Vertical lines (rotated).
665 {
666 SkPaint paint;
667 paint.setColor(SK_ColorRED);
668 vcanvas_->drawLine(-25, -10, -25, -90, paint);
669 pcanvas_->drawLine(-25, -10, -25, -90, paint);
670 vcanvas_->drawLine(-35, -90, -35, -10, paint);
671 pcanvas_->drawLine(-35, -90, -35, -10, paint);
672 }
673 EXPECT_EQ(0., ProcessImage(L"vertical_180"));
674 }
675
676 TEST_F(VectorCanvasTest, PathOrientation) {
677 // There is NO WAY to make them agree. At least verify that the output doesn't
678 // change across versions. This test is disabled. See bug 1060231.
679 compare_canvas_ = false;
680
681 // Horizontal lines.
682 {
683 SkPaint paint;
684 paint.setStyle(SkPaint::kStroke_Style);
685 paint.setColor(SK_ColorRED);
686 SkPath path;
687 SkPoint start;
688 start.set(10, 20);
689 SkPoint end;
690 end.set(90, 20);
691 path.moveTo(start);
692 path.lineTo(end);
693 vcanvas_->drawPath(path, paint);
694 pcanvas_->drawPath(path, paint);
695 }
696 EXPECT_EQ(0., ProcessImage(L"drawPath_ltr"));
697
698 // Horizontal lines.
699 {
700 SkPaint paint;
701 paint.setStyle(SkPaint::kStroke_Style);
702 paint.setColor(SK_ColorRED);
703 SkPath path;
704 SkPoint start;
705 start.set(90, 30);
706 SkPoint end;
707 end.set(10, 30);
708 path.moveTo(start);
709 path.lineTo(end);
710 vcanvas_->drawPath(path, paint);
711 pcanvas_->drawPath(path, paint);
712 }
713 EXPECT_EQ(0., ProcessImage(L"drawPath_rtl"));
714 }
715
716 TEST_F(VectorCanvasTest, DiagonalLines) {
717 SkPaint paint;
718 paint.setColor(SK_ColorRED);
719
720 vcanvas_->drawLine(10, 10, 90, 90, paint);
721 pcanvas_->drawLine(10, 10, 90, 90, paint);
722 EXPECT_EQ(0., ProcessImage(L"nw-se"));
723
724 // Starting here, there is NO WAY to make them agree. At least verify that the
725 // output doesn't change across versions. This test is disabled. See bug
726 // 1060231.
727 compare_canvas_ = false;
728
729 vcanvas_->drawLine(10, 95, 90, 15, paint);
730 pcanvas_->drawLine(10, 95, 90, 15, paint);
731 EXPECT_EQ(0., ProcessImage(L"sw-ne"));
732
733 vcanvas_->drawLine(90, 10, 10, 90, paint);
734 pcanvas_->drawLine(90, 10, 10, 90, paint);
735 EXPECT_EQ(0., ProcessImage(L"ne-sw"));
736
737 vcanvas_->drawLine(95, 90, 15, 10, paint);
738 pcanvas_->drawLine(95, 90, 15, 10, paint);
739 EXPECT_EQ(0., ProcessImage(L"se-nw"));
740 }
741
742 TEST_F(VectorCanvasTest, PathEffects) {
743 {
744 SkPaint paint;
745 SkScalar intervals[] = { 1, 1 };
746 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
747 0);
748 paint.setPathEffect(effect)->unref();
749 paint.setColor(SK_ColorMAGENTA);
750 paint.setStyle(SkPaint::kStroke_Style);
751
752 vcanvas_->drawLine(10, 10, 90, 10, paint);
753 pcanvas_->drawLine(10, 10, 90, 10, paint);
754 }
755 EXPECT_EQ(0., ProcessImage(L"dash_line"));
756
757
758 // Starting here, there is NO WAY to make them agree. At least verify that the
759 // output doesn't change across versions. This test is disabled. See bug
760 // 1060231.
761 compare_canvas_ = false;
762
763 {
764 SkPaint paint;
765 SkScalar intervals[] = { 3, 5 };
766 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
767 0);
768 paint.setPathEffect(effect)->unref();
769 paint.setColor(SK_ColorMAGENTA);
770 paint.setStyle(SkPaint::kStroke_Style);
771
772 SkPath path;
773 path.moveTo(10, 15);
774 path.lineTo(90, 15);
775 path.lineTo(90, 90);
776 vcanvas_->drawPath(path, paint);
777 pcanvas_->drawPath(path, paint);
778 }
779 EXPECT_EQ(0., ProcessImage(L"dash_path"));
780
781 {
782 SkPaint paint;
783 SkScalar intervals[] = { 2, 1 };
784 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
785 0);
786 paint.setPathEffect(effect)->unref();
787 paint.setColor(SK_ColorMAGENTA);
788 paint.setStyle(SkPaint::kStroke_Style);
789
790 vcanvas_->drawRectCoords(20, 20, 30, 30, paint);
791 pcanvas_->drawRectCoords(20, 20, 30, 30, paint);
792 }
793 EXPECT_EQ(0., ProcessImage(L"dash_rect"));
794
795 // This thing looks like it has been drawn by a 3 years old kid. I haven't
796 // filed a bug on this since I guess nobody is expecting this to look nice.
797 {
798 SkPaint paint;
799 SkScalar intervals[] = { 1, 1 };
800 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals),
801 0);
802 paint.setPathEffect(effect)->unref();
803 paint.setColor(SK_ColorMAGENTA);
804 paint.setStyle(SkPaint::kStroke_Style);
805
806 SkPath path;
807 path.addCircle(50, 75, 10);
808 vcanvas_->drawPath(path, paint);
809 pcanvas_->drawPath(path, paint);
810 EXPECT_EQ(0., ProcessImage(L"circle"));
811 }
812 }
813
814 TEST_F(VectorCanvasTest, Bitmaps) {
815 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
816 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
817 // really care about Windows 2000 pixel colors.
818 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
819 return;
820 {
821 SkBitmap bitmap;
822 LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap);
823 vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
824 pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
825 EXPECT_EQ(0., ProcessImage(L"opaque"));
826 }
827
828 {
829 SkBitmap bitmap;
830 LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap);
831 vcanvas_->drawBitmap(bitmap, 5, 15, NULL);
832 pcanvas_->drawBitmap(bitmap, 5, 15, NULL);
833 EXPECT_EQ(0., ProcessImage(L"alpha"));
834 }
835 }
836
837 TEST_F(VectorCanvasTest, ClippingRect) {
838 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
839 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
840 // really care about Windows 2000 pixel colors.
841 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
842 return;
843 SkBitmap bitmap;
844 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
845 SkRect rect;
846 rect.fLeft = 2;
847 rect.fTop = 2;
848 rect.fRight = 30.5f;
849 rect.fBottom = 30.5f;
850 vcanvas_->clipRect(rect);
851 pcanvas_->clipRect(rect);
852
853 vcanvas_->drawBitmap(bitmap, 13, 3, NULL);
854 pcanvas_->drawBitmap(bitmap, 13, 3, NULL);
855 EXPECT_EQ(0., ProcessImage(L"rect"));
856 }
857
858 TEST_F(VectorCanvasTest, ClippingPath) {
859 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
860 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
861 // really care about Windows 2000 pixel colors.
862 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
863 return;
864 SkBitmap bitmap;
865 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
866 SkPath path;
867 path.addCircle(20, 20, 10);
868 vcanvas_->clipPath(path);
869 pcanvas_->clipPath(path);
870
871 vcanvas_->drawBitmap(bitmap, 14, 3, NULL);
872 pcanvas_->drawBitmap(bitmap, 14, 3, NULL);
873 EXPECT_EQ(0., ProcessImage(L"path"));
874 }
875
876 TEST_F(VectorCanvasTest, ClippingCombined) {
877 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
878 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
879 // really care about Windows 2000 pixel colors.
880 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
881 return;
882 SkBitmap bitmap;
883 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
884
885 SkRect rect;
886 rect.fLeft = 2;
887 rect.fTop = 2;
888 rect.fRight = 30.5f;
889 rect.fBottom = 30.5f;
890 vcanvas_->clipRect(rect);
891 pcanvas_->clipRect(rect);
892 SkPath path;
893 path.addCircle(20, 20, 10);
894 vcanvas_->clipPath(path, SkRegion::kUnion_Op);
895 pcanvas_->clipPath(path, SkRegion::kUnion_Op);
896
897 vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
898 pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
899 EXPECT_EQ(0., ProcessImage(L"combined"));
900 }
901
902 TEST_F(VectorCanvasTest, ClippingIntersect) {
903 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
904 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
905 // really care about Windows 2000 pixel colors.
906 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
907 return;
908 SkBitmap bitmap;
909 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
910
911 SkRect rect;
912 rect.fLeft = 2;
913 rect.fTop = 2;
914 rect.fRight = 30.5f;
915 rect.fBottom = 30.5f;
916 vcanvas_->clipRect(rect);
917 pcanvas_->clipRect(rect);
918 SkPath path;
919 path.addCircle(23, 23, 15);
920 vcanvas_->clipPath(path);
921 pcanvas_->clipPath(path);
922
923 vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
924 pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
925 EXPECT_EQ(0., ProcessImage(L"intersect"));
926 }
927
928 TEST_F(VectorCanvasTest, ClippingClean) {
929 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
930 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
931 // really care about Windows 2000 pixel colors.
932 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
933 return;
934 SkBitmap bitmap;
935 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
936 {
937 SkRegion old_region(pcanvas_->getTotalClip());
938 SkRect rect;
939 rect.fLeft = 2;
940 rect.fTop = 2;
941 rect.fRight = 30.5f;
942 rect.fBottom = 30.5f;
943 vcanvas_->clipRect(rect);
944 pcanvas_->clipRect(rect);
945
946 vcanvas_->drawBitmap(bitmap, 15, 3, NULL);
947 pcanvas_->drawBitmap(bitmap, 15, 3, NULL);
948 EXPECT_EQ(0., ProcessImage(L"clipped"));
949 vcanvas_->clipRegion(old_region, SkRegion::kReplace_Op);
950 pcanvas_->clipRegion(old_region, SkRegion::kReplace_Op);
951 }
952 {
953 // Verify that the clipping region has been fixed back.
954 vcanvas_->drawBitmap(bitmap, 55, 3, NULL);
955 pcanvas_->drawBitmap(bitmap, 55, 3, NULL);
956 EXPECT_EQ(0., ProcessImage(L"unclipped"));
957 }
958 }
959
960 TEST_F(VectorCanvasTest, Matrix) {
961 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests
962 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't
963 // really care about Windows 2000 pixel colors.
964 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000)
965 return;
966 SkBitmap bitmap;
967 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap);
968 {
969 vcanvas_->translate(15, 3);
970 pcanvas_->translate(15, 3);
971 vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
972 pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
973 EXPECT_EQ(0., ProcessImage(L"translate1"));
974 }
975 {
976 vcanvas_->translate(-30, -23);
977 pcanvas_->translate(-30, -23);
978 vcanvas_->drawBitmap(bitmap, 0, 0, NULL);
979 pcanvas_->drawBitmap(bitmap, 0, 0, NULL);
980 EXPECT_EQ(0., ProcessImage(L"translate2"));
981 }
982 vcanvas_->resetMatrix();
983 pcanvas_->resetMatrix();
984
985 // For scaling and rotation, they use a different algorithm (nearest
986 // neighborhood vs smoothing). At least verify that the output doesn't change
987 // across versions.
988 compare_canvas_ = false;
989
990 {
991 vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
992 pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5));
993 vcanvas_->drawBitmap(bitmap, 1, 1, NULL);
994 pcanvas_->drawBitmap(bitmap, 1, 1, NULL);
995 EXPECT_EQ(0., ProcessImage(L"scale"));
996 }
997 vcanvas_->resetMatrix();
998 pcanvas_->resetMatrix();
999
1000 {
1001 vcanvas_->rotate(67);
1002 pcanvas_->rotate(67);
1003 vcanvas_->drawBitmap(bitmap, 20, -50, NULL);
1004 pcanvas_->drawBitmap(bitmap, 20, -50, NULL);
1005 EXPECT_EQ(0., ProcessImage(L"rotate"));
1006 }
1007 }
1008
OLDNEW
« no previous file with comments | « base/gfx/vector_canvas.cc ('k') | base/gfx/vector_device.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698