Chromium Code Reviews| Index: third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp |
| diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp |
| index 9653160eccf6da95850252b47b4b17683b287e83..efe91b9f0e761ed79b3a0cf083c89c6b967d6cbf 100644 |
| --- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp |
| +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp |
| @@ -36,8 +36,11 @@ |
| namespace blink { |
| BaseRenderingContext2D::BaseRenderingContext2D() |
| - : clip_antialiasing_(kNotAntiAliased) { |
| + : clip_antialiasing_(kNotAntiAliased), color_management_enabled_(false) { |
| state_stack_.push_back(CanvasRenderingContext2DState::Create()); |
| + color_management_enabled_ = |
| + RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
| } |
| BaseRenderingContext2D::~BaseRenderingContext2D() {} |
| @@ -1506,10 +1509,26 @@ bool BaseRenderingContext2D::ComputeDirtyRect( |
| return true; |
| } |
| +ImageDataColorSettings |
| +BaseRenderingContext2D::GetColorSettingsAsImageDataColorSettings() const { |
| + ImageDataColorSettings color_settings; |
| + color_settings.setColorSpace(ColorSpaceAsString()); |
| + if (PixelFormat() == kF16CanvasPixelFormat) |
| + color_settings.setStorageFormat(kFloat32ArrayStorageFormatName); |
| + return color_settings; |
| +} |
| + |
| ImageData* BaseRenderingContext2D::createImageData( |
| ImageData* image_data, |
| ExceptionState& exception_state) const { |
| - ImageData* result = ImageData::Create(image_data->size()); |
| + ImageData* result = nullptr; |
| + if (color_management_enabled_) { |
| + ImageDataColorSettings color_settings = |
| + GetColorSettingsAsImageDataColorSettings(); |
| + result = ImageData::Create(image_data->size(), &color_settings); |
| + } else { |
| + result = ImageData::Create(image_data->size()); |
| + } |
| if (!result) |
| exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| return result; |
| @@ -1527,13 +1546,39 @@ ImageData* BaseRenderingContext2D::createImageData( |
| } |
| IntSize size(abs(sw), abs(sh)); |
| + ImageData* result = nullptr; |
| + if (color_management_enabled_) { |
| + ImageDataColorSettings color_settings = |
| + GetColorSettingsAsImageDataColorSettings(); |
| + result = ImageData::Create(size, &color_settings); |
| + } else { |
| + result = ImageData::Create(size); |
| + } |
| - ImageData* result = ImageData::Create(size); |
| if (!result) |
| exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| return result; |
| } |
| +ImageData* BaseRenderingContext2D::createImageData( |
| + unsigned width, |
| + unsigned height, |
| + ImageDataColorSettings& color_settings, |
| + ExceptionState& exception_state) const { |
| + return ImageData::createImageData(width, height, color_settings, |
| + exception_state); |
| +} |
| + |
| +ImageData* BaseRenderingContext2D::createImageData( |
| + ImageDataArray& data_array, |
| + unsigned width, |
| + unsigned height, |
| + ImageDataColorSettings& color_settings, |
| + ExceptionState& exception_state) const { |
| + return ImageData::createImageData(data_array, width, height, color_settings, |
| + exception_state); |
| +} |
| + |
| ImageData* BaseRenderingContext2D::getImageData( |
| int sx, |
| int sy, |
| @@ -1596,8 +1641,14 @@ ImageData* BaseRenderingContext2D::getImageData( |
| IntRect image_data_rect(sx, sy, sw, sh); |
| ImageBuffer* buffer = GetImageBuffer(); |
| + ImageDataColorSettings color_settings = |
| + GetColorSettingsAsImageDataColorSettings(); |
| if (!buffer || isContextLost()) { |
| - ImageData* result = ImageData::Create(image_data_rect.size()); |
| + ImageData* result = nullptr; |
| + if (color_management_enabled_) |
| + result = ImageData::Create(image_data_rect.size(), &color_settings); |
| + else |
| + result = ImageData::Create(image_data_rect.size()); |
| if (!result) |
| exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| return result; |
| @@ -1611,10 +1662,20 @@ ImageData* BaseRenderingContext2D::getImageData( |
| NeedsFinalizeFrame(); |
| - DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); |
| - return ImageData::Create(image_data_rect.size(), |
| - DOMUint8ClampedArray::Create( |
| - array_buffer, 0, array_buffer->ByteLength())); |
| + if (!color_management_enabled_ || |
| + ImageData::GetImageDataStorageFormat(color_settings.storageFormat()) == |
| + kUint8ClampedArrayStorageFormat) { |
| + DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); |
| + return ImageData::Create(image_data_rect.size(), |
| + DOMUint8ClampedArray::Create( |
| + array_buffer, 0, array_buffer->ByteLength())); |
| + } |
| + |
| + DOMArrayBufferView* array_buffer_view = |
| + ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
| + contents, PixelFormat(), kFloat32ArrayStorageFormat); |
| + return ImageData::Create(image_data_rect.size(), array_buffer_view, |
| + &color_settings); |
| } |
| void BaseRenderingContext2D::putImageData(ImageData* data, |
| @@ -1636,14 +1697,30 @@ void BaseRenderingContext2D::putImageData(ImageData* data, |
| if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) { |
| return; |
| } |
| - |
| usage_counters_.num_put_image_data_calls++; |
| usage_counters_.area_put_image_data_calls += dirty_width * dirty_height; |
| - if (data->data()->BufferBase()->IsNeutered()) { |
| + |
| + bool data_is_neutered = false; |
| + if (color_management_enabled_) { |
| + data_is_neutered = |
| + (data->dataUnion().isUint8ClampedArray() && |
|
Justin Novosad
2017/04/11 21:28:05
This block of code is not fun to read. Let's hide
zakerinasab
2017/04/15 07:04:42
Done.
|
| + data->dataUnion() |
| + .getAsUint8ClampedArray() |
| + ->BufferBase() |
| + ->IsNeutered()) || |
| + (data->dataUnion().isUint16Array() && |
| + data->dataUnion().getAsUint16Array()->BufferBase()->IsNeutered()) || |
| + (data->dataUnion().isFloat32Array() && |
| + data->dataUnion().getAsFloat32Array()->BufferBase()->IsNeutered()); |
| + } else { |
| + data_is_neutered = data->data()->BufferBase()->IsNeutered(); |
| + } |
| + if (data_is_neutered) { |
| exception_state.ThrowDOMException(kInvalidStateError, |
| "The source data has been neutered."); |
| return; |
| } |
| + |
| ImageBuffer* buffer = GetImageBuffer(); |
| if (!buffer) |
| return; |
| @@ -1693,10 +1770,21 @@ void BaseRenderingContext2D::putImageData(ImageData* data, |
| CheckOverdraw(dest_rect, 0, CanvasRenderingContext2DState::kNoImage, |
| kUntransformedUnclippedFill); |
| - buffer->PutByteArray(kUnmultiplied, data->data()->Data(), |
| - IntSize(data->width(), data->height()), source_rect, |
| - IntPoint(dest_offset)); |
| - |
| + if (color_management_enabled_) { |
| + unsigned data_length = data->width() * data->height(); |
| + if (PixelFormat() == kF16CanvasPixelFormat) |
| + data_length *= 2; |
| + std::unique_ptr<uint8_t[]> converted_pixels(new uint8_t[4 * data_length]); |
| + data->ImageDataInCanvasColorSettings(ColorSpace(), PixelFormat(), |
| + converted_pixels); |
| + buffer->PutByteArray(kUnmultiplied, converted_pixels.get(), |
| + IntSize(data->width(), data->height()), source_rect, |
| + IntPoint(dest_offset)); |
| + } else { |
| + buffer->PutByteArray(kUnmultiplied, data->data()->Data(), |
| + IntSize(data->width(), data->height()), source_rect, |
| + IntPoint(dest_offset)); |
| + } |
| DidDraw(dest_rect); |
| } |