| 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 "VectorCanvas.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().width() << ", " | |
| 359 << image.size().height() << ", " << image.row_length() << ")"; | |
| 360 } | |
| 361 | |
| 362 // Runs simultaneously the same drawing commands on VectorCanvas and | |
| 363 // PlatformCanvas and compare the results. | |
| 364 class VectorCanvasTest : public ImageTest { | |
| 365 public: | |
| 366 typedef ImageTest parent; | |
| 367 | |
| 368 VectorCanvasTest() : parent(L"base", CurrentMode()), compare_canvas_(true) { | |
| 369 } | |
| 370 | |
| 371 protected: | |
| 372 virtual void SetUp() { | |
| 373 parent::SetUp(); | |
| 374 Init(100); | |
| 375 number_ = 0; | |
| 376 } | |
| 377 | |
| 378 virtual void TearDown() { | |
| 379 delete pcanvas_; | |
| 380 pcanvas_ = NULL; | |
| 381 | |
| 382 delete vcanvas_; | |
| 383 vcanvas_ = NULL; | |
| 384 | |
| 385 delete bitmap_; | |
| 386 bitmap_ = NULL; | |
| 387 | |
| 388 delete context_; | |
| 389 context_ = NULL; | |
| 390 | |
| 391 parent::TearDown(); | |
| 392 } | |
| 393 | |
| 394 void Init(int size) { | |
| 395 size_ = size; | |
| 396 context_ = new Context(); | |
| 397 bitmap_ = new Bitmap(*context_, size_, size_); | |
| 398 vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_); | |
| 399 pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false); | |
| 400 | |
| 401 // Clear white. | |
| 402 vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); | |
| 403 pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); | |
| 404 } | |
| 405 | |
| 406 // Compares both canvas and returns the pixel difference in percentage between | |
| 407 // both images. 0 on success and ]0, 100] on failure. | |
| 408 double ProcessImage(const std::wstring& filename) { | |
| 409 std::wstring number(StringPrintf(L"%02d_", number_++)); | |
| 410 double diff1 = parent::ProcessCanvas(*vcanvas_, number + L"vc_" + filename); | |
| 411 double diff2 = parent::ProcessCanvas(*pcanvas_, number + L"pc_" + filename); | |
| 412 if (!compare_canvas_) | |
| 413 return std::max(diff1, diff2); | |
| 414 | |
| 415 Image image1(*vcanvas_); | |
| 416 Image image2(*pcanvas_); | |
| 417 double diff = image1.PercentageDifferent(image2); | |
| 418 return std::max(std::max(diff1, diff2), diff); | |
| 419 } | |
| 420 | |
| 421 // Returns COMPARE, which is the default. If kGenerateSwitch command | |
| 422 // line argument is used to start this process, GENERATE is returned instead. | |
| 423 static ProcessAction CurrentMode() { | |
| 424 return CommandLine().HasSwitch(kGenerateSwitch) ? GENERATE : COMPARE; | |
| 425 } | |
| 426 | |
| 427 // Length in x and y of the square canvas. | |
| 428 int size_; | |
| 429 | |
| 430 // Current image number in the current test. Used to number of test files. | |
| 431 int number_; | |
| 432 | |
| 433 // A temporary HDC to draw into. | |
| 434 Context* context_; | |
| 435 | |
| 436 // Bitmap created inside context_. | |
| 437 Bitmap* bitmap_; | |
| 438 | |
| 439 // Vector based canvas. | |
| 440 gfx::VectorCanvas* vcanvas_; | |
| 441 | |
| 442 // Pixel based canvas. | |
| 443 gfx::PlatformCanvasWin* pcanvas_; | |
| 444 | |
| 445 // When true (default), vcanvas_ and pcanvas_ contents are compared and | |
| 446 // verified to be identical. | |
| 447 bool compare_canvas_; | |
| 448 }; | |
| 449 | |
| 450 | |
| 451 //////////////////////////////////////////////////////////////////////////////// | |
| 452 // Actual tests | |
| 453 | |
| 454 TEST_F(VectorCanvasTest, Uninitialized) { | |
| 455 // Do a little mubadumba do get uninitialized stuff. | |
| 456 VectorCanvasTest::TearDown(); | |
| 457 | |
| 458 // The goal is not to verify that have the same uninitialized data. | |
| 459 compare_canvas_ = false; | |
| 460 | |
| 461 context_ = new Context(); | |
| 462 bitmap_ = new Bitmap(*context_, size_, size_); | |
| 463 vcanvas_ = new gfx::VectorCanvas(context_->context(), size_, size_); | |
| 464 pcanvas_ = new gfx::PlatformCanvasWin(size_, size_, false); | |
| 465 | |
| 466 // VectorCanvas default initialization is black. | |
| 467 // PlatformCanvas default initialization is almost white 0x01FFFEFD (invalid | |
| 468 // Skia color) in both Debug and Release. See magicTransparencyColor in | |
| 469 // platform_device.cc | |
| 470 EXPECT_EQ(0., ProcessImage(L"empty")); | |
| 471 } | |
| 472 | |
| 473 TEST_F(VectorCanvasTest, BasicDrawing) { | |
| 474 EXPECT_EQ(Image(*vcanvas_).PercentageDifferent(Image(*pcanvas_)), 0.) | |
| 475 << L"clean"; | |
| 476 EXPECT_EQ(0., ProcessImage(L"clean")); | |
| 477 | |
| 478 // Clear white. | |
| 479 { | |
| 480 vcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); | |
| 481 pcanvas_->drawARGB(255, 255, 255, 255, SkPorterDuff::kSrc_Mode); | |
| 482 } | |
| 483 EXPECT_EQ(0., ProcessImage(L"drawARGB")); | |
| 484 | |
| 485 // Diagonal line top-left to bottom-right. | |
| 486 { | |
| 487 SkPaint paint; | |
| 488 // Default color is black. | |
| 489 vcanvas_->drawLine(10, 10, 90, 90, paint); | |
| 490 pcanvas_->drawLine(10, 10, 90, 90, paint); | |
| 491 } | |
| 492 EXPECT_EQ(0., ProcessImage(L"drawLine_black")); | |
| 493 | |
| 494 // Rect. | |
| 495 { | |
| 496 SkPaint paint; | |
| 497 paint.setColor(SK_ColorGREEN); | |
| 498 vcanvas_->drawRectCoords(25, 25, 75, 75, paint); | |
| 499 pcanvas_->drawRectCoords(25, 25, 75, 75, paint); | |
| 500 } | |
| 501 EXPECT_EQ(0., ProcessImage(L"drawRect_green")); | |
| 502 | |
| 503 // A single-point rect doesn't leave any mark. | |
| 504 { | |
| 505 SkPaint paint; | |
| 506 paint.setColor(SK_ColorBLUE); | |
| 507 vcanvas_->drawRectCoords(5, 5, 5, 5, paint); | |
| 508 pcanvas_->drawRectCoords(5, 5, 5, 5, paint); | |
| 509 } | |
| 510 EXPECT_EQ(0., ProcessImage(L"drawRect_noop")); | |
| 511 | |
| 512 // Rect. | |
| 513 { | |
| 514 SkPaint paint; | |
| 515 paint.setColor(SK_ColorBLUE); | |
| 516 vcanvas_->drawRectCoords(75, 50, 80, 55, paint); | |
| 517 pcanvas_->drawRectCoords(75, 50, 80, 55, paint); | |
| 518 } | |
| 519 EXPECT_EQ(0., ProcessImage(L"drawRect_noop")); | |
| 520 | |
| 521 // Empty again | |
| 522 { | |
| 523 vcanvas_->drawPaint(SkPaint()); | |
| 524 pcanvas_->drawPaint(SkPaint()); | |
| 525 } | |
| 526 EXPECT_EQ(0., ProcessImage(L"drawPaint_black")); | |
| 527 | |
| 528 // Horizontal line left to right. | |
| 529 { | |
| 530 SkPaint paint; | |
| 531 paint.setColor(SK_ColorRED); | |
| 532 vcanvas_->drawLine(10, 20, 90, 20, paint); | |
| 533 pcanvas_->drawLine(10, 20, 90, 20, paint); | |
| 534 } | |
| 535 EXPECT_EQ(0., ProcessImage(L"drawLine_left_to_right")); | |
| 536 | |
| 537 // Vertical line downward. | |
| 538 { | |
| 539 SkPaint paint; | |
| 540 paint.setColor(SK_ColorRED); | |
| 541 vcanvas_->drawLine(30, 10, 30, 90, paint); | |
| 542 pcanvas_->drawLine(30, 10, 30, 90, paint); | |
| 543 } | |
| 544 EXPECT_EQ(0., ProcessImage(L"drawLine_red")); | |
| 545 } | |
| 546 | |
| 547 TEST_F(VectorCanvasTest, Circles) { | |
| 548 // There is NO WAY to make them agree. At least verify that the output doesn't | |
| 549 // change across versions. This test is disabled. See bug 1060231. | |
| 550 compare_canvas_ = false; | |
| 551 | |
| 552 // Stroked Circle. | |
| 553 { | |
| 554 SkPaint paint; | |
| 555 SkPath path; | |
| 556 path.addCircle(50, 75, 10); | |
| 557 paint.setStyle(SkPaint::kStroke_Style); | |
| 558 paint.setColor(SK_ColorMAGENTA); | |
| 559 vcanvas_->drawPath(path, paint); | |
| 560 pcanvas_->drawPath(path, paint); | |
| 561 } | |
| 562 EXPECT_EQ(0., ProcessImage(L"circle_stroke")); | |
| 563 | |
| 564 // Filled Circle. | |
| 565 { | |
| 566 SkPaint paint; | |
| 567 SkPath path; | |
| 568 path.addCircle(50, 25, 10); | |
| 569 paint.setStyle(SkPaint::kFill_Style); | |
| 570 vcanvas_->drawPath(path, paint); | |
| 571 pcanvas_->drawPath(path, paint); | |
| 572 } | |
| 573 EXPECT_EQ(0., ProcessImage(L"circle_fill")); | |
| 574 | |
| 575 // Stroked Circle over. | |
| 576 { | |
| 577 SkPaint paint; | |
| 578 SkPath path; | |
| 579 path.addCircle(50, 25, 10); | |
| 580 paint.setStyle(SkPaint::kStroke_Style); | |
| 581 paint.setColor(SK_ColorBLUE); | |
| 582 vcanvas_->drawPath(path, paint); | |
| 583 pcanvas_->drawPath(path, paint); | |
| 584 } | |
| 585 EXPECT_EQ(0., ProcessImage(L"circle_over_strike")); | |
| 586 | |
| 587 // Stroke and Fill Circle. | |
| 588 { | |
| 589 SkPaint paint; | |
| 590 SkPath path; | |
| 591 path.addCircle(12, 50, 10); | |
| 592 paint.setStyle(SkPaint::kStrokeAndFill_Style); | |
| 593 paint.setColor(SK_ColorRED); | |
| 594 vcanvas_->drawPath(path, paint); | |
| 595 pcanvas_->drawPath(path, paint); | |
| 596 } | |
| 597 EXPECT_EQ(0., ProcessImage(L"circle_stroke_and_fill")); | |
| 598 | |
| 599 // Line + Quad + Cubic. | |
| 600 { | |
| 601 SkPaint paint; | |
| 602 SkPath path; | |
| 603 paint.setStyle(SkPaint::kStroke_Style); | |
| 604 paint.setColor(SK_ColorGREEN); | |
| 605 path.moveTo(1, 1); | |
| 606 path.lineTo(60, 40); | |
| 607 path.lineTo(80, 80); | |
| 608 path.quadTo(20, 50, 10, 90); | |
| 609 path.quadTo(50, 20, 90, 10); | |
| 610 path.cubicTo(20, 40, 50, 50, 10, 10); | |
| 611 path.cubicTo(30, 20, 50, 50, 90, 10); | |
| 612 path.addRect(90, 90, 95, 96); | |
| 613 vcanvas_->drawPath(path, paint); | |
| 614 pcanvas_->drawPath(path, paint); | |
| 615 } | |
| 616 EXPECT_EQ(0., ProcessImage(L"mixed_stroke")); | |
| 617 } | |
| 618 | |
| 619 TEST_F(VectorCanvasTest, LineOrientation) { | |
| 620 // There is NO WAY to make them agree. At least verify that the output doesn't | |
| 621 // change across versions. This test is disabled. See bug 1060231. | |
| 622 compare_canvas_ = false; | |
| 623 | |
| 624 // Horizontal lines. | |
| 625 { | |
| 626 SkPaint paint; | |
| 627 paint.setColor(SK_ColorRED); | |
| 628 // Left to right. | |
| 629 vcanvas_->drawLine(10, 20, 90, 20, paint); | |
| 630 pcanvas_->drawLine(10, 20, 90, 20, paint); | |
| 631 // Right to left. | |
| 632 vcanvas_->drawLine(90, 30, 10, 30, paint); | |
| 633 pcanvas_->drawLine(90, 30, 10, 30, paint); | |
| 634 } | |
| 635 EXPECT_EQ(0., ProcessImage(L"horizontal")); | |
| 636 | |
| 637 // Vertical lines. | |
| 638 { | |
| 639 SkPaint paint; | |
| 640 paint.setColor(SK_ColorRED); | |
| 641 // Top down. | |
| 642 vcanvas_->drawLine(20, 10, 20, 90, paint); | |
| 643 pcanvas_->drawLine(20, 10, 20, 90, paint); | |
| 644 // Bottom up. | |
| 645 vcanvas_->drawLine(30, 90, 30, 10, paint); | |
| 646 pcanvas_->drawLine(30, 90, 30, 10, paint); | |
| 647 } | |
| 648 EXPECT_EQ(0., ProcessImage(L"vertical")); | |
| 649 | |
| 650 // Try again with a 180 degres rotation. | |
| 651 vcanvas_->rotate(180); | |
| 652 pcanvas_->rotate(180); | |
| 653 | |
| 654 // Horizontal lines (rotated). | |
| 655 { | |
| 656 SkPaint paint; | |
| 657 paint.setColor(SK_ColorRED); | |
| 658 vcanvas_->drawLine(-10, -25, -90, -25, paint); | |
| 659 pcanvas_->drawLine(-10, -25, -90, -25, paint); | |
| 660 vcanvas_->drawLine(-90, -35, -10, -35, paint); | |
| 661 pcanvas_->drawLine(-90, -35, -10, -35, paint); | |
| 662 } | |
| 663 EXPECT_EQ(0., ProcessImage(L"horizontal_180")); | |
| 664 | |
| 665 // Vertical lines (rotated). | |
| 666 { | |
| 667 SkPaint paint; | |
| 668 paint.setColor(SK_ColorRED); | |
| 669 vcanvas_->drawLine(-25, -10, -25, -90, paint); | |
| 670 pcanvas_->drawLine(-25, -10, -25, -90, paint); | |
| 671 vcanvas_->drawLine(-35, -90, -35, -10, paint); | |
| 672 pcanvas_->drawLine(-35, -90, -35, -10, paint); | |
| 673 } | |
| 674 EXPECT_EQ(0., ProcessImage(L"vertical_180")); | |
| 675 } | |
| 676 | |
| 677 TEST_F(VectorCanvasTest, PathOrientation) { | |
| 678 // There is NO WAY to make them agree. At least verify that the output doesn't | |
| 679 // change across versions. This test is disabled. See bug 1060231. | |
| 680 compare_canvas_ = false; | |
| 681 | |
| 682 // Horizontal lines. | |
| 683 { | |
| 684 SkPaint paint; | |
| 685 paint.setStyle(SkPaint::kStroke_Style); | |
| 686 paint.setColor(SK_ColorRED); | |
| 687 SkPath path; | |
| 688 SkPoint start; | |
| 689 start.set(10, 20); | |
| 690 SkPoint end; | |
| 691 end.set(90, 20); | |
| 692 path.moveTo(start); | |
| 693 path.lineTo(end); | |
| 694 vcanvas_->drawPath(path, paint); | |
| 695 pcanvas_->drawPath(path, paint); | |
| 696 } | |
| 697 EXPECT_EQ(0., ProcessImage(L"drawPath_ltr")); | |
| 698 | |
| 699 // Horizontal lines. | |
| 700 { | |
| 701 SkPaint paint; | |
| 702 paint.setStyle(SkPaint::kStroke_Style); | |
| 703 paint.setColor(SK_ColorRED); | |
| 704 SkPath path; | |
| 705 SkPoint start; | |
| 706 start.set(90, 30); | |
| 707 SkPoint end; | |
| 708 end.set(10, 30); | |
| 709 path.moveTo(start); | |
| 710 path.lineTo(end); | |
| 711 vcanvas_->drawPath(path, paint); | |
| 712 pcanvas_->drawPath(path, paint); | |
| 713 } | |
| 714 EXPECT_EQ(0., ProcessImage(L"drawPath_rtl")); | |
| 715 } | |
| 716 | |
| 717 TEST_F(VectorCanvasTest, DiagonalLines) { | |
| 718 SkPaint paint; | |
| 719 paint.setColor(SK_ColorRED); | |
| 720 | |
| 721 vcanvas_->drawLine(10, 10, 90, 90, paint); | |
| 722 pcanvas_->drawLine(10, 10, 90, 90, paint); | |
| 723 EXPECT_EQ(0., ProcessImage(L"nw-se")); | |
| 724 | |
| 725 // Starting here, there is NO WAY to make them agree. At least verify that the | |
| 726 // output doesn't change across versions. This test is disabled. See bug | |
| 727 // 1060231. | |
| 728 compare_canvas_ = false; | |
| 729 | |
| 730 vcanvas_->drawLine(10, 95, 90, 15, paint); | |
| 731 pcanvas_->drawLine(10, 95, 90, 15, paint); | |
| 732 EXPECT_EQ(0., ProcessImage(L"sw-ne")); | |
| 733 | |
| 734 vcanvas_->drawLine(90, 10, 10, 90, paint); | |
| 735 pcanvas_->drawLine(90, 10, 10, 90, paint); | |
| 736 EXPECT_EQ(0., ProcessImage(L"ne-sw")); | |
| 737 | |
| 738 vcanvas_->drawLine(95, 90, 15, 10, paint); | |
| 739 pcanvas_->drawLine(95, 90, 15, 10, paint); | |
| 740 EXPECT_EQ(0., ProcessImage(L"se-nw")); | |
| 741 } | |
| 742 | |
| 743 TEST_F(VectorCanvasTest, PathEffects) { | |
| 744 { | |
| 745 SkPaint paint; | |
| 746 SkScalar intervals[] = { 1, 1 }; | |
| 747 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), | |
| 748 0); | |
| 749 paint.setPathEffect(effect)->unref(); | |
| 750 paint.setColor(SK_ColorMAGENTA); | |
| 751 paint.setStyle(SkPaint::kStroke_Style); | |
| 752 | |
| 753 vcanvas_->drawLine(10, 10, 90, 10, paint); | |
| 754 pcanvas_->drawLine(10, 10, 90, 10, paint); | |
| 755 } | |
| 756 EXPECT_EQ(0., ProcessImage(L"dash_line")); | |
| 757 | |
| 758 | |
| 759 // Starting here, there is NO WAY to make them agree. At least verify that the | |
| 760 // output doesn't change across versions. This test is disabled. See bug | |
| 761 // 1060231. | |
| 762 compare_canvas_ = false; | |
| 763 | |
| 764 { | |
| 765 SkPaint paint; | |
| 766 SkScalar intervals[] = { 3, 5 }; | |
| 767 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), | |
| 768 0); | |
| 769 paint.setPathEffect(effect)->unref(); | |
| 770 paint.setColor(SK_ColorMAGENTA); | |
| 771 paint.setStyle(SkPaint::kStroke_Style); | |
| 772 | |
| 773 SkPath path; | |
| 774 path.moveTo(10, 15); | |
| 775 path.lineTo(90, 15); | |
| 776 path.lineTo(90, 90); | |
| 777 vcanvas_->drawPath(path, paint); | |
| 778 pcanvas_->drawPath(path, paint); | |
| 779 } | |
| 780 EXPECT_EQ(0., ProcessImage(L"dash_path")); | |
| 781 | |
| 782 { | |
| 783 SkPaint paint; | |
| 784 SkScalar intervals[] = { 2, 1 }; | |
| 785 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), | |
| 786 0); | |
| 787 paint.setPathEffect(effect)->unref(); | |
| 788 paint.setColor(SK_ColorMAGENTA); | |
| 789 paint.setStyle(SkPaint::kStroke_Style); | |
| 790 | |
| 791 vcanvas_->drawRectCoords(20, 20, 30, 30, paint); | |
| 792 pcanvas_->drawRectCoords(20, 20, 30, 30, paint); | |
| 793 } | |
| 794 EXPECT_EQ(0., ProcessImage(L"dash_rect")); | |
| 795 | |
| 796 // This thing looks like it has been drawn by a 3 years old kid. I haven't | |
| 797 // filed a bug on this since I guess nobody is expecting this to look nice. | |
| 798 { | |
| 799 SkPaint paint; | |
| 800 SkScalar intervals[] = { 1, 1 }; | |
| 801 SkPathEffect* effect = new SkDashPathEffect(intervals, arraysize(intervals), | |
| 802 0); | |
| 803 paint.setPathEffect(effect)->unref(); | |
| 804 paint.setColor(SK_ColorMAGENTA); | |
| 805 paint.setStyle(SkPaint::kStroke_Style); | |
| 806 | |
| 807 SkPath path; | |
| 808 path.addCircle(50, 75, 10); | |
| 809 vcanvas_->drawPath(path, paint); | |
| 810 pcanvas_->drawPath(path, paint); | |
| 811 EXPECT_EQ(0., ProcessImage(L"circle")); | |
| 812 } | |
| 813 } | |
| 814 | |
| 815 TEST_F(VectorCanvasTest, Bitmaps) { | |
| 816 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 817 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 818 // really care about Windows 2000 pixel colors. | |
| 819 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 820 return; | |
| 821 { | |
| 822 SkBitmap bitmap; | |
| 823 LoadPngFileToSkBitmap(test_file(L"bitmap_opaque.png"), &bitmap); | |
| 824 vcanvas_->drawBitmap(bitmap, 13, 3, NULL); | |
| 825 pcanvas_->drawBitmap(bitmap, 13, 3, NULL); | |
| 826 EXPECT_EQ(0., ProcessImage(L"opaque")); | |
| 827 } | |
| 828 | |
| 829 { | |
| 830 SkBitmap bitmap; | |
| 831 LoadPngFileToSkBitmap(test_file(L"bitmap_alpha.png"), &bitmap); | |
| 832 vcanvas_->drawBitmap(bitmap, 5, 15, NULL); | |
| 833 pcanvas_->drawBitmap(bitmap, 5, 15, NULL); | |
| 834 EXPECT_EQ(0., ProcessImage(L"alpha")); | |
| 835 } | |
| 836 } | |
| 837 | |
| 838 TEST_F(VectorCanvasTest, ClippingRect) { | |
| 839 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 840 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 841 // really care about Windows 2000 pixel colors. | |
| 842 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 843 return; | |
| 844 SkBitmap bitmap; | |
| 845 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); | |
| 846 SkRect rect; | |
| 847 rect.fLeft = 2; | |
| 848 rect.fTop = 2; | |
| 849 rect.fRight = 30.5f; | |
| 850 rect.fBottom = 30.5f; | |
| 851 vcanvas_->clipRect(rect); | |
| 852 pcanvas_->clipRect(rect); | |
| 853 | |
| 854 vcanvas_->drawBitmap(bitmap, 13, 3, NULL); | |
| 855 pcanvas_->drawBitmap(bitmap, 13, 3, NULL); | |
| 856 EXPECT_EQ(0., ProcessImage(L"rect")); | |
| 857 } | |
| 858 | |
| 859 TEST_F(VectorCanvasTest, ClippingPath) { | |
| 860 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 861 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 862 // really care about Windows 2000 pixel colors. | |
| 863 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 864 return; | |
| 865 SkBitmap bitmap; | |
| 866 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); | |
| 867 SkPath path; | |
| 868 path.addCircle(20, 20, 10); | |
| 869 vcanvas_->clipPath(path); | |
| 870 pcanvas_->clipPath(path); | |
| 871 | |
| 872 vcanvas_->drawBitmap(bitmap, 14, 3, NULL); | |
| 873 pcanvas_->drawBitmap(bitmap, 14, 3, NULL); | |
| 874 EXPECT_EQ(0., ProcessImage(L"path")); | |
| 875 } | |
| 876 | |
| 877 TEST_F(VectorCanvasTest, ClippingCombined) { | |
| 878 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 879 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 880 // really care about Windows 2000 pixel colors. | |
| 881 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 882 return; | |
| 883 SkBitmap bitmap; | |
| 884 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); | |
| 885 | |
| 886 SkRect rect; | |
| 887 rect.fLeft = 2; | |
| 888 rect.fTop = 2; | |
| 889 rect.fRight = 30.5f; | |
| 890 rect.fBottom = 30.5f; | |
| 891 vcanvas_->clipRect(rect); | |
| 892 pcanvas_->clipRect(rect); | |
| 893 SkPath path; | |
| 894 path.addCircle(20, 20, 10); | |
| 895 vcanvas_->clipPath(path, SkRegion::kUnion_Op); | |
| 896 pcanvas_->clipPath(path, SkRegion::kUnion_Op); | |
| 897 | |
| 898 vcanvas_->drawBitmap(bitmap, 15, 3, NULL); | |
| 899 pcanvas_->drawBitmap(bitmap, 15, 3, NULL); | |
| 900 EXPECT_EQ(0., ProcessImage(L"combined")); | |
| 901 } | |
| 902 | |
| 903 TEST_F(VectorCanvasTest, ClippingIntersect) { | |
| 904 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 905 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 906 // really care about Windows 2000 pixel colors. | |
| 907 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 908 return; | |
| 909 SkBitmap bitmap; | |
| 910 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); | |
| 911 | |
| 912 SkRect rect; | |
| 913 rect.fLeft = 2; | |
| 914 rect.fTop = 2; | |
| 915 rect.fRight = 30.5f; | |
| 916 rect.fBottom = 30.5f; | |
| 917 vcanvas_->clipRect(rect); | |
| 918 pcanvas_->clipRect(rect); | |
| 919 SkPath path; | |
| 920 path.addCircle(23, 23, 15); | |
| 921 vcanvas_->clipPath(path); | |
| 922 pcanvas_->clipPath(path); | |
| 923 | |
| 924 vcanvas_->drawBitmap(bitmap, 15, 3, NULL); | |
| 925 pcanvas_->drawBitmap(bitmap, 15, 3, NULL); | |
| 926 EXPECT_EQ(0., ProcessImage(L"intersect")); | |
| 927 } | |
| 928 | |
| 929 TEST_F(VectorCanvasTest, ClippingClean) { | |
| 930 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 931 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 932 // really care about Windows 2000 pixel colors. | |
| 933 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 934 return; | |
| 935 SkBitmap bitmap; | |
| 936 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); | |
| 937 { | |
| 938 SkRegion old_region(pcanvas_->getTotalClip()); | |
| 939 SkRect rect; | |
| 940 rect.fLeft = 2; | |
| 941 rect.fTop = 2; | |
| 942 rect.fRight = 30.5f; | |
| 943 rect.fBottom = 30.5f; | |
| 944 vcanvas_->clipRect(rect); | |
| 945 pcanvas_->clipRect(rect); | |
| 946 | |
| 947 vcanvas_->drawBitmap(bitmap, 15, 3, NULL); | |
| 948 pcanvas_->drawBitmap(bitmap, 15, 3, NULL); | |
| 949 EXPECT_EQ(0., ProcessImage(L"clipped")); | |
| 950 vcanvas_->clipRegion(old_region, SkRegion::kReplace_Op); | |
| 951 pcanvas_->clipRegion(old_region, SkRegion::kReplace_Op); | |
| 952 } | |
| 953 { | |
| 954 // Verify that the clipping region has been fixed back. | |
| 955 vcanvas_->drawBitmap(bitmap, 55, 3, NULL); | |
| 956 pcanvas_->drawBitmap(bitmap, 55, 3, NULL); | |
| 957 EXPECT_EQ(0., ProcessImage(L"unclipped")); | |
| 958 } | |
| 959 } | |
| 960 | |
| 961 TEST_F(VectorCanvasTest, Matrix) { | |
| 962 // ICM is enabled on VectorCanvas only on Windows 2000 so bitmap-based tests | |
| 963 // can't compare the pixels between PlatformCanvas and VectorCanvas. We don't | |
| 964 // really care about Windows 2000 pixel colors. | |
| 965 if (win_util::GetWinVersion() <= win_util::WINVERSION_2000) | |
| 966 return; | |
| 967 SkBitmap bitmap; | |
| 968 LoadPngFileToSkBitmap(test_file(L"..\\bitmaps\\bitmap_opaque.png"), &bitmap); | |
| 969 { | |
| 970 vcanvas_->translate(15, 3); | |
| 971 pcanvas_->translate(15, 3); | |
| 972 vcanvas_->drawBitmap(bitmap, 0, 0, NULL); | |
| 973 pcanvas_->drawBitmap(bitmap, 0, 0, NULL); | |
| 974 EXPECT_EQ(0., ProcessImage(L"translate1")); | |
| 975 } | |
| 976 { | |
| 977 vcanvas_->translate(-30, -23); | |
| 978 pcanvas_->translate(-30, -23); | |
| 979 vcanvas_->drawBitmap(bitmap, 0, 0, NULL); | |
| 980 pcanvas_->drawBitmap(bitmap, 0, 0, NULL); | |
| 981 EXPECT_EQ(0., ProcessImage(L"translate2")); | |
| 982 } | |
| 983 vcanvas_->resetMatrix(); | |
| 984 pcanvas_->resetMatrix(); | |
| 985 | |
| 986 // For scaling and rotation, they use a different algorithm (nearest | |
| 987 // neighborhood vs smoothing). At least verify that the output doesn't change | |
| 988 // across versions. | |
| 989 compare_canvas_ = false; | |
| 990 | |
| 991 { | |
| 992 vcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5)); | |
| 993 pcanvas_->scale(SkDoubleToScalar(1.9), SkDoubleToScalar(1.5)); | |
| 994 vcanvas_->drawBitmap(bitmap, 1, 1, NULL); | |
| 995 pcanvas_->drawBitmap(bitmap, 1, 1, NULL); | |
| 996 EXPECT_EQ(0., ProcessImage(L"scale")); | |
| 997 } | |
| 998 vcanvas_->resetMatrix(); | |
| 999 pcanvas_->resetMatrix(); | |
| 1000 | |
| 1001 { | |
| 1002 vcanvas_->rotate(67); | |
| 1003 pcanvas_->rotate(67); | |
| 1004 vcanvas_->drawBitmap(bitmap, 20, -50, NULL); | |
| 1005 pcanvas_->drawBitmap(bitmap, 20, -50, NULL); | |
| 1006 EXPECT_EQ(0., ProcessImage(L"rotate")); | |
| 1007 } | |
| 1008 } | |
| 1009 | |
| OLD | NEW |