OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 | 360 |
361 // This function is called from unit tests, and all the parameters are supposed | 361 // This function is called from unit tests, and all the parameters are supposed |
362 // to be validated on the call site. | 362 // to be validated on the call site. |
363 ImageData* ImageData::CreateForTest( | 363 ImageData* ImageData::CreateForTest( |
364 const IntSize& size, | 364 const IntSize& size, |
365 DOMArrayBufferView* buffer_view, | 365 DOMArrayBufferView* buffer_view, |
366 const ImageDataColorSettings* color_settings) { | 366 const ImageDataColorSettings* color_settings) { |
367 return new ImageData(size, buffer_view, color_settings); | 367 return new ImageData(size, buffer_view, color_settings); |
368 } | 368 } |
369 | 369 |
| 370 bool ImageData::CompareImageDataColorSettingsForTest(ImageData* image_data_1, |
| 371 ImageData* image_data_2) { |
| 372 ImageDataColorSettings color_settings_1, color_settings_2; |
| 373 image_data_1->getColorSettings(color_settings_1); |
| 374 image_data_2->getColorSettings(color_settings_2); |
| 375 return color_settings_1.colorSpace() == color_settings_2.colorSpace() && |
| 376 color_settings_1.storageFormat() == color_settings_2.storageFormat(); |
| 377 } |
| 378 |
| 379 ImageData* ImageData::MakeCopy() { |
| 380 unsigned data_length = size_.Width() * size_.Height() * 4; |
| 381 DOMArrayBufferView* buffer_view = AllocateAndValidateDataArray( |
| 382 data_length, |
| 383 ImageData::GetImageDataStorageFormat(color_settings_.storageFormat())); |
| 384 if (!buffer_view) |
| 385 return nullptr; |
| 386 std::memcpy(buffer_view->View()->Buffer()->Data(), BufferBase()->Data(), |
| 387 data_length * buffer_view->TypeSize()); |
| 388 return new ImageData(size_, buffer_view, &color_settings_); |
| 389 } |
| 390 |
| 391 // Crops ImageData to the intersect of its size and the given rectangle. If the |
| 392 // intersection is empty or it cannot create the cropped ImageData it returns |
| 393 // nullptr. This function leaves the source ImageData intact. When crop_rect |
| 394 // covers all the ImageData and the copy parameter is false, "this" is returned. |
| 395 // Otherwise, a copy of the ImageData is returned. |
| 396 ImageData* ImageData::MakeSubset(const IntRect& crop_rect, bool enforce_copy) { |
| 397 IntRect src_rect(IntPoint(), size_); |
| 398 const IntRect dst_rect = Intersection(src_rect, crop_rect); |
| 399 if (dst_rect.IsEmpty()) |
| 400 return nullptr; |
| 401 if (src_rect == dst_rect) { |
| 402 if (enforce_copy) |
| 403 return MakeCopy(); |
| 404 return this; |
| 405 } |
| 406 |
| 407 unsigned data_size = 4 * dst_rect.Width() * dst_rect.Height(); |
| 408 DOMUint8ClampedArray* data_u8 = nullptr; |
| 409 DOMUint16Array* data_u16 = nullptr; |
| 410 DOMFloat32Array* data_f32 = nullptr; |
| 411 if (data_) |
| 412 data_u8 = AllocateAndValidateUint8ClampedArray(data_size); |
| 413 else if (data_u16_) |
| 414 data_u16 = AllocateAndValidateUint16Array(data_size); |
| 415 else if (data_f32_) |
| 416 data_f32 = AllocateAndValidateFloat32Array(data_size); |
| 417 |
| 418 int src_index = 0, dst_index = 0; |
| 419 for (int i = 0; i < dst_rect.Height(); i++) { |
| 420 src_index = ((i + dst_rect.X()) * src_rect.Width() + dst_rect.Y()) * 4; |
| 421 dst_index = i * dst_rect.Width() * 4; |
| 422 if (data_) { |
| 423 std::memcpy(data_u8->Data() + dst_index, data_->Data() + src_index, |
| 424 dst_rect.Width() * 4); |
| 425 } else if (data_u16_) { |
| 426 std::memcpy(data_u16->Data() + dst_index, data_u16_->Data() + src_index, |
| 427 dst_rect.Width() * 8); |
| 428 } else if (data_f32_) { |
| 429 std::memcpy(data_f32->Data() + dst_index, data_f32_->Data() + src_index, |
| 430 dst_rect.Width() * 16); |
| 431 } |
| 432 } |
| 433 |
| 434 if (data_) |
| 435 return new ImageData(dst_rect.Size(), data_u8, &color_settings_); |
| 436 if (data_u16_) |
| 437 return new ImageData(dst_rect.Size(), data_u16, &color_settings_); |
| 438 return new ImageData(dst_rect.Size(), data_f32, &color_settings_); |
| 439 } |
| 440 |
370 ScriptPromise ImageData::CreateImageBitmap(ScriptState* script_state, | 441 ScriptPromise ImageData::CreateImageBitmap(ScriptState* script_state, |
371 EventTarget& event_target, | 442 EventTarget& event_target, |
372 Optional<IntRect> crop_rect, | 443 Optional<IntRect> crop_rect, |
373 const ImageBitmapOptions& options, | 444 const ImageBitmapOptions& options, |
374 ExceptionState& exception_state) { | 445 ExceptionState& exception_state) { |
375 if ((crop_rect && | 446 if ((crop_rect && |
376 !ImageBitmap::IsSourceSizeValid(crop_rect->Width(), crop_rect->Height(), | 447 !ImageBitmap::IsSourceSizeValid(crop_rect->Width(), crop_rect->Height(), |
377 exception_state)) || | 448 exception_state)) || |
378 !ImageBitmap::IsSourceSizeValid(BitmapSourceSize().Width(), | 449 !ImageBitmap::IsSourceSizeValid(BitmapSourceSize().Width(), |
379 BitmapSourceSize().Height(), | 450 BitmapSourceSize().Height(), |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 // For ImageData, the color space is only specified by color settings. | 667 // For ImageData, the color space is only specified by color settings. |
597 // It cannot have a SkColorSpace. This doesn't mean anything. Fix this. | 668 // It cannot have a SkColorSpace. This doesn't mean anything. Fix this. |
598 sk_sp<SkColorSpace> ImageData::GetSkColorSpace() { | 669 sk_sp<SkColorSpace> ImageData::GetSkColorSpace() { |
599 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || | 670 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || |
600 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 671 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
601 return nullptr; | 672 return nullptr; |
602 | 673 |
603 return SkColorSpace::MakeSRGB(); | 674 return SkColorSpace::MakeSRGB(); |
604 } | 675 } |
605 | 676 |
606 // This function returns the proper SkColorSpace to color correct the pixels | |
607 // stored in ImageData before copying to the canvas. For now, it assumes that | |
608 // both ImageData and canvas use a linear gamma curve. | |
609 sk_sp<SkColorSpace> ImageData::GetSkColorSpace( | |
610 const CanvasColorSpace& color_space, | |
611 const CanvasPixelFormat& pixel_format) { | |
612 switch (color_space) { | |
613 case kLegacyCanvasColorSpace: | |
614 return (gfx::ColorSpace::CreateSRGB()).ToSkColorSpace(); | |
615 case kSRGBCanvasColorSpace: | |
616 if (pixel_format == kF16CanvasPixelFormat) | |
617 return (gfx::ColorSpace::CreateSCRGBLinear()).ToSkColorSpace(); | |
618 return (gfx::ColorSpace::CreateSRGB()).ToSkColorSpace(); | |
619 case kRec2020CanvasColorSpace: | |
620 return (gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT2020, | |
621 gfx::ColorSpace::TransferID::LINEAR)) | |
622 .ToSkColorSpace(); | |
623 case kP3CanvasColorSpace: | |
624 return (gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTEST432_1, | |
625 gfx::ColorSpace::TransferID::LINEAR)) | |
626 .ToSkColorSpace(); | |
627 } | |
628 NOTREACHED(); | |
629 return nullptr; | |
630 } | |
631 | |
632 sk_sp<SkColorSpace> ImageData::GetSkColorSpaceForTest( | |
633 const CanvasColorSpace& color_space, | |
634 const CanvasPixelFormat& pixel_format) { | |
635 return GetSkColorSpace(color_space, pixel_format); | |
636 } | |
637 | |
638 bool ImageData::ImageDataInCanvasColorSettings( | 677 bool ImageData::ImageDataInCanvasColorSettings( |
639 const CanvasColorSpace& canvas_color_space, | 678 const CanvasColorSpace& canvas_color_space, |
640 const CanvasPixelFormat& canvas_pixel_format, | 679 const CanvasPixelFormat& canvas_pixel_format, |
641 std::unique_ptr<uint8_t[]>& converted_pixels) { | 680 std::unique_ptr<uint8_t[]>& converted_pixels) { |
642 if (!data_ && !data_u16_ && !data_f32_) | 681 if (!data_ && !data_u16_ && !data_f32_) |
643 return false; | 682 return false; |
644 | 683 |
645 // If canvas and image data are both in the same color space and pixel format | 684 // If canvas and image data are both in the same color space and pixel format |
646 // is 8-8-8-8, just return the embedded data. | 685 // is 8-8-8-8, just return the embedded data. |
647 CanvasColorSpace image_data_color_space = | 686 CanvasColorSpace image_data_color_space = |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 } else if (data_f32_) { | 725 } else if (data_f32_) { |
687 src_data = static_cast<void*>(data_f32_->Data()); | 726 src_data = static_cast<void*>(data_f32_->Data()); |
688 DCHECK(src_data); | 727 DCHECK(src_data); |
689 src_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat; | 728 src_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F32_ColorFormat; |
690 } else { | 729 } else { |
691 NOTREACHED(); | 730 NOTREACHED(); |
692 } | 731 } |
693 | 732 |
694 sk_sp<SkColorSpace> src_color_space = nullptr; | 733 sk_sp<SkColorSpace> src_color_space = nullptr; |
695 if (data_) { | 734 if (data_) { |
696 src_color_space = ImageData::GetSkColorSpace(image_data_color_space, | 735 src_color_space = |
697 kRGBA8CanvasPixelFormat); | 736 CanvasColorParams(image_data_color_space, kRGBA8CanvasPixelFormat) |
| 737 .GetSkColorSpaceForSkSurfaces(); |
698 } else { | 738 } else { |
699 src_color_space = ImageData::GetSkColorSpace(image_data_color_space, | 739 src_color_space = |
700 kF16CanvasPixelFormat); | 740 CanvasColorParams(image_data_color_space, kF16CanvasPixelFormat) |
| 741 .GetSkColorSpaceForSkSurfaces(); |
701 } | 742 } |
702 | 743 |
703 sk_sp<SkColorSpace> dst_color_space = | 744 sk_sp<SkColorSpace> dst_color_space = |
704 ImageData::GetSkColorSpace(canvas_color_space, canvas_pixel_format); | 745 CanvasColorParams(canvas_color_space, canvas_pixel_format) |
705 | 746 .GetSkColorSpaceForSkSurfaces(); |
706 SkColorSpaceXform::ColorFormat dst_color_format = | 747 SkColorSpaceXform::ColorFormat dst_color_format = |
707 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; | 748 SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; |
708 if (canvas_pixel_format == kF16CanvasPixelFormat) | 749 if (canvas_pixel_format == kF16CanvasPixelFormat) |
709 dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; | 750 dst_color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; |
710 | 751 |
711 if (SkColorSpace::Equals(src_color_space.get(), dst_color_space.get()) && | 752 if (SkColorSpace::Equals(src_color_space.get(), dst_color_space.get()) && |
712 src_color_format == dst_color_format) | 753 src_color_format == dst_color_format) |
713 return static_cast<unsigned char*>(src_data); | 754 return static_cast<unsigned char*>(src_data); |
714 | 755 |
715 std::unique_ptr<SkColorSpaceXform> xform = | 756 std::unique_ptr<SkColorSpaceXform> xform = |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 SECURITY_CHECK(static_cast<unsigned>(size.Width() * size.Height() * 4) <= | 820 SECURITY_CHECK(static_cast<unsigned>(size.Width() * size.Height() * 4) <= |
780 data_f32_->length()); | 821 data_f32_->length()); |
781 break; | 822 break; |
782 | 823 |
783 default: | 824 default: |
784 NOTREACHED(); | 825 NOTREACHED(); |
785 } | 826 } |
786 } | 827 } |
787 | 828 |
788 } // namespace blink | 829 } // namespace blink |
OLD | NEW |