OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/html/ImageData.h" | 5 #include "core/html/ImageData.h" |
6 | 6 |
7 #include "core/dom/ExceptionCode.h" | 7 #include "core/dom/ExceptionCode.h" |
8 #include "platform/geometry/IntSize.h" | 8 #include "platform/geometry/IntSize.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "third_party/skia/include/core/SkColorSpaceXform.h" | 10 #include "third_party/skia/include/core/SkColorSpaceXform.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( | 31 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( |
32 color_correct_rendering); | 32 color_correct_rendering); |
33 } | 33 } |
34 | 34 |
35 bool experimental_canvas_features; | 35 bool experimental_canvas_features; |
36 bool color_correct_rendering; | 36 bool color_correct_rendering; |
37 }; | 37 }; |
38 | 38 |
39 TEST_F(ImageDataTest, NegativeAndZeroIntSizeTest) { | 39 TEST_F(ImageDataTest, NegativeAndZeroIntSizeTest) { |
40 ImageData* image_data; | 40 ImageData* image_data; |
41 | 41 // Test scenarios |
42 image_data = ImageData::Create(IntSize(0, 10)); | 42 const int num_test_cases = 6; |
43 EXPECT_EQ(image_data, nullptr); | 43 const IntSize image_data_sizes[6] = {IntSize(0, 10), IntSize(10, 0), |
44 | 44 IntSize(0, 0), IntSize(-1, 10), |
45 image_data = ImageData::Create(IntSize(10, 0)); | 45 IntSize(10, -1), IntSize(-1, -1)}; |
46 EXPECT_EQ(image_data, nullptr); | 46 for (int i = 1; i < num_test_cases; i++) { |
47 | 47 image_data = ImageData::Create(image_data_sizes[i]); |
48 image_data = ImageData::Create(IntSize(0, 0)); | 48 EXPECT_EQ(image_data, nullptr); |
49 EXPECT_EQ(image_data, nullptr); | 49 } |
50 | |
51 image_data = ImageData::Create(IntSize(-1, 10)); | |
52 EXPECT_EQ(image_data, nullptr); | |
53 | |
54 image_data = ImageData::Create(IntSize(10, -1)); | |
55 EXPECT_EQ(image_data, nullptr); | |
56 | |
57 image_data = ImageData::Create(IntSize(-1, -1)); | |
58 EXPECT_EQ(image_data, nullptr); | |
59 } | 50 } |
60 | 51 |
61 // Under asan_clang_phone, the test crashes after the memory allocation | 52 // Under asan_clang_phone, the test crashes after the memory allocation |
62 // is not successful. It is probably related to the value of | 53 // is not successful. It is probably related to the value of |
63 // allocator_may_return_null on trybots, which in this case causes ASAN | 54 // allocator_may_return_null on trybots, which in this case causes ASAN |
64 // to terminate the process instead of returning null. | 55 // to terminate the process instead of returning null. |
65 // crbug.com/704948 | 56 // crbug.com/704948 |
66 #if defined(ADDRESS_SANITIZER) | 57 #if defined(ADDRESS_SANITIZER) |
67 #define MAYBE_CreateImageDataTooBig DISABLED_CreateImageDataTooBig | 58 #define MAYBE_CreateImageDataTooBig DISABLED_CreateImageDataTooBig |
68 #else | 59 #else |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 return false; | 234 return false; |
244 } | 235 } |
245 | 236 |
246 SkColorSpaceXform::ColorFormat dst_color_format = | 237 SkColorSpaceXform::ColorFormat dst_color_format = |
247 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; | 238 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; |
248 if (dst_pixel_format == kF16CanvasPixelFormat) | 239 if (dst_pixel_format == kF16CanvasPixelFormat) |
249 dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; | 240 dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; |
250 | 241 |
251 sk_sp<SkColorSpace> src_sk_color_space = nullptr; | 242 sk_sp<SkColorSpace> src_sk_color_space = nullptr; |
252 if (u8_array) { | 243 if (u8_array) { |
253 src_sk_color_space = ImageData::GetSkColorSpaceForTest( | 244 src_sk_color_space = |
254 src_color_space, kRGBA8CanvasPixelFormat); | 245 CanvasColorParams(src_color_space, kRGBA8CanvasPixelFormat) |
| 246 .GetSkColorSpaceForSkSurfaces(); |
255 } else { | 247 } else { |
256 src_sk_color_space = ImageData::GetSkColorSpaceForTest( | 248 src_sk_color_space = |
257 src_color_space, kF16CanvasPixelFormat); | 249 CanvasColorParams(src_color_space, kF16CanvasPixelFormat) |
| 250 .GetSkColorSpaceForSkSurfaces(); |
258 } | 251 } |
259 | 252 |
260 sk_sp<SkColorSpace> dst_sk_color_space = | 253 sk_sp<SkColorSpace> dst_sk_color_space = |
261 ImageData::GetSkColorSpaceForTest(dst_color_space, dst_pixel_format); | 254 CanvasColorParams(dst_color_space, dst_pixel_format) |
| 255 .GetSkColorSpaceForSkSurfaces(); |
262 | 256 |
263 // When the input dataArray is in Uint16, we normally should convert the | 257 // When the input dataArray is in Uint16, we normally should convert the |
264 // values from Little Endian to Big Endian before passing the buffer to | 258 // values from Little Endian to Big Endian before passing the buffer to |
265 // SkColorSpaceXform::apply. However, in this test scenario we are creating | 259 // SkColorSpaceXform::apply. However, in this test scenario we are creating |
266 // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257, | 260 // the Uin16 dataArray by multiplying a Uint8Clamped array members by 257, |
267 // hence the Big Endian and Little Endian representations are the same. | 261 // hence the Big Endian and Little Endian representations are the same. |
268 | 262 |
269 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New( | 263 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New( |
270 src_sk_color_space.get(), dst_sk_color_space.get()); | 264 src_sk_color_space.get(), dst_sk_color_space.get()); |
271 | 265 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 EXPECT_EQ(0, | 387 EXPECT_EQ(0, |
394 memcmp(pixels_converted_manually.get(), | 388 memcmp(pixels_converted_manually.get(), |
395 pixels_converted_in_image_data.get(), output_length)); | 389 pixels_converted_in_image_data.get(), output_length)); |
396 } | 390 } |
397 } | 391 } |
398 } | 392 } |
399 delete[] u16_pixels; | 393 delete[] u16_pixels; |
400 delete[] f32_pixels; | 394 delete[] f32_pixels; |
401 } | 395 } |
402 | 396 |
| 397 // This test examines ImageData::CropRect() |
| 398 TEST_F(ImageDataTest, TestCropRect) { |
| 399 const int num_image_data_storage_formats = 3; |
| 400 ImageDataStorageFormat image_data_storage_formats[] = { |
| 401 kUint8ClampedArrayStorageFormat, kUint16ArrayStorageFormat, |
| 402 kFloat32ArrayStorageFormat, |
| 403 }; |
| 404 String image_data_storage_format_names[] = { |
| 405 kUint8ClampedArrayStorageFormatName, kUint16ArrayStorageFormatName, |
| 406 kFloat32ArrayStorageFormatName, |
| 407 }; |
| 408 |
| 409 // Source pixels |
| 410 unsigned width = 20; |
| 411 unsigned height = 20; |
| 412 unsigned data_length = width * height * 4; |
| 413 uint8_t* u8_pixels = new uint8_t[data_length]; |
| 414 uint16_t* u16_pixels = new uint16_t[data_length]; |
| 415 float* f32_pixels = new float[data_length]; |
| 416 |
| 417 // Test scenarios |
| 418 const int num_test_cases = 12; |
| 419 const IntRect crop_rects[12] = { |
| 420 IntRect(3, 4, 5, 6), IntRect(3, 4, 5, 6), IntRect(10, 10, 20, 20), |
| 421 IntRect(10, 10, 20, 20), IntRect(0, 0, 20, 20), IntRect(0, 0, 20, 20), |
| 422 IntRect(0, 0, 10, 10), IntRect(0, 0, 10, 10), IntRect(0, 0, 10, 0), |
| 423 IntRect(0, 0, 0, 10), IntRect(10, 0, 10, 10), IntRect(0, 10, 10, 10), |
| 424 }; |
| 425 const bool crop_flips[12] = {true, false, true, false, true, false, |
| 426 true, false, false, false, false, false}; |
| 427 |
| 428 // Fill the pixels with numbers related to their positions |
| 429 unsigned set_value = 0; |
| 430 unsigned expected_value = 0; |
| 431 float fexpected_value = 0; |
| 432 unsigned index = 0, row_index = 0; |
| 433 for (unsigned i = 0; i < height; i++) |
| 434 for (unsigned j = 0; j < width; j++) |
| 435 for (unsigned k = 0; k < 4; k++) { |
| 436 index = i * width * 4 + j * 4 + k; |
| 437 set_value = (i + 1) * (j + 1) * (k + 1); |
| 438 u8_pixels[index] = set_value % 255; |
| 439 u16_pixels[index] = (set_value * 257) % 65535; |
| 440 f32_pixels[index] = (set_value % 255) / 255.0f; |
| 441 } |
| 442 |
| 443 // Create ImageData objects |
| 444 DOMArrayBufferView* data_array = nullptr; |
| 445 |
| 446 DOMUint8ClampedArray* data_u8 = |
| 447 DOMUint8ClampedArray::Create(u8_pixels, data_length); |
| 448 DCHECK(data_u8); |
| 449 EXPECT_EQ(data_length, data_u8->length()); |
| 450 DOMUint16Array* data_u16 = DOMUint16Array::Create(u16_pixels, data_length); |
| 451 DCHECK(data_u16); |
| 452 EXPECT_EQ(data_length, data_u16->length()); |
| 453 DOMFloat32Array* data_f32 = DOMFloat32Array::Create(f32_pixels, data_length); |
| 454 DCHECK(data_f32); |
| 455 EXPECT_EQ(data_length, data_f32->length()); |
| 456 |
| 457 ImageData* image_data = nullptr; |
| 458 ImageData* cropped_image_data = nullptr; |
| 459 |
| 460 bool test_passed = true; |
| 461 for (int i = 0; i < num_image_data_storage_formats; i++) { |
| 462 if (image_data_storage_formats[i] == kUint8ClampedArrayStorageFormat) |
| 463 data_array = static_cast<DOMArrayBufferView*>(data_u8); |
| 464 else if (image_data_storage_formats[i] == kUint16ArrayStorageFormat) |
| 465 data_array = static_cast<DOMArrayBufferView*>(data_u16); |
| 466 else |
| 467 data_array = static_cast<DOMArrayBufferView*>(data_f32); |
| 468 |
| 469 ImageDataColorSettings color_settings; |
| 470 color_settings.setStorageFormat(image_data_storage_format_names[i]); |
| 471 image_data = ImageData::CreateForTest(IntSize(width, height), data_array, |
| 472 &color_settings); |
| 473 for (int j = 0; j < num_test_cases; j++) { |
| 474 // Test the size of the cropped image data |
| 475 IntRect src_rect(IntPoint(), image_data->Size()); |
| 476 IntRect crop_rect = Intersection(src_rect, crop_rects[j]); |
| 477 |
| 478 cropped_image_data = image_data->CropRect(crop_rects[j], crop_flips[j]); |
| 479 if (crop_rect.IsEmpty()) { |
| 480 EXPECT_FALSE(cropped_image_data); |
| 481 continue; |
| 482 } |
| 483 EXPECT_TRUE(cropped_image_data->Size() == crop_rect.Size()); |
| 484 |
| 485 // Test the content |
| 486 for (int k = 0; k < crop_rect.Height(); k++) |
| 487 for (int m = 0; m < crop_rect.Width(); m++) |
| 488 for (int n = 0; n < 4; n++) { |
| 489 row_index = crop_flips[j] ? (crop_rect.Height() - k - 1) : k; |
| 490 index = |
| 491 row_index * cropped_image_data->Size().Width() * 4 + m * 4 + n; |
| 492 expected_value = |
| 493 (k + crop_rect.X() + 1) * (m + crop_rect.Y() + 1) * (n + 1); |
| 494 if (image_data_storage_formats[i] == |
| 495 kUint8ClampedArrayStorageFormat) |
| 496 expected_value %= 255; |
| 497 else if (image_data_storage_formats[i] == kUint16ArrayStorageFormat) |
| 498 expected_value = (expected_value * 257) % 65535; |
| 499 else |
| 500 fexpected_value = (expected_value % 255) / 255.0f; |
| 501 |
| 502 if (image_data_storage_formats[i] == |
| 503 kUint8ClampedArrayStorageFormat) { |
| 504 if (cropped_image_data->data()->Data()[index] != expected_value) { |
| 505 test_passed = false; |
| 506 break; |
| 507 } |
| 508 } else if (image_data_storage_formats[i] == |
| 509 kUint16ArrayStorageFormat) { |
| 510 if (cropped_image_data->dataUnion() |
| 511 .getAsUint16Array() |
| 512 .View() |
| 513 ->Data()[index] != expected_value) { |
| 514 test_passed = false; |
| 515 break; |
| 516 } |
| 517 } else { |
| 518 if (cropped_image_data->dataUnion() |
| 519 .getAsFloat32Array() |
| 520 .View() |
| 521 ->Data()[index] != fexpected_value) { |
| 522 test_passed = false; |
| 523 break; |
| 524 } |
| 525 } |
| 526 } |
| 527 EXPECT_TRUE(test_passed); |
| 528 } |
| 529 } |
| 530 |
| 531 delete[] u8_pixels; |
| 532 delete[] u16_pixels; |
| 533 delete[] f32_pixels; |
| 534 } |
| 535 |
403 } // namspace | 536 } // namspace |
404 } // namespace blink | 537 } // namespace blink |
OLD | NEW |