| OLD | NEW |
| (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 | |
| OLD | NEW |