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); |
} |