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 e7f9f3bfe590b13529a01cfe7c89a7f8c9b4eff0..ef14d6bd566625d46c4e7952b526f7bdf9422565 100644 |
| --- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp |
| +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp |
| @@ -1496,10 +1496,40 @@ bool BaseRenderingContext2D::computeDirtyRect( |
| return true; |
| } |
| +bool BaseRenderingContext2D::colorSettingsAsImageDataColorSettings( |
| + ImageDataColorSettings& colorSettings) const { |
| + if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || |
| + !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
| + return false; |
| + colorSettings.setColorSpace(renderingContext()->colorSpaceAsString()); |
| + switch (renderingContext()->pixelFormat()) { |
| + case kRGBA8CanvasPixelFormat: |
| + colorSettings.setStorageFormat(kUint8ClampedArrayStorageFormatName); |
| + break; |
| + case kF16CanvasPixelFormat: |
| + colorSettings.setStorageFormat(kFloat32ArrayStorageFormatName); |
| + break; |
| + case kRGB10A2CanvasPixelFormat: |
| + case kRGBA12CanvasPixelFormat: |
| + default: |
| + NOTREACHED(); |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| ImageData* BaseRenderingContext2D::createImageData( |
| ImageData* imageData, |
| ExceptionState& exceptionState) const { |
| - ImageData* result = ImageData::create(imageData->size()); |
| + ImageData* result = nullptr; |
| + if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { |
| + ImageDataColorSettings colorSettings; |
| + if (colorSettingsAsImageDataColorSettings(colorSettings)) |
| + result = ImageData::create(imageData->size(), &colorSettings); |
| + } else { |
| + result = ImageData::create(imageData->size()); |
| + } |
| if (!result) |
| exceptionState.throwRangeError("Out of memory at ImageData creation"); |
| return result; |
| @@ -1517,8 +1547,15 @@ ImageData* BaseRenderingContext2D::createImageData( |
| } |
| IntSize size(abs(sw), abs(sh)); |
| - |
| - ImageData* result = ImageData::create(size); |
| + ImageData* result = nullptr; |
| + if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { |
| + ImageDataColorSettings colorSettings; |
| + if (colorSettingsAsImageDataColorSettings(colorSettings)) |
| + result = ImageData::create(size, &colorSettings); |
| + } else { |
| + result = ImageData::create(size); |
| + } |
| if (!result) |
| exceptionState.throwRangeError("Out of memory at ImageData creation"); |
| return result; |
| @@ -1573,11 +1610,21 @@ ImageData* BaseRenderingContext2D::getImageData( |
| timer.emplace(scopedUsCounterCPU); |
| } |
| + ImageDataColorSettings colorSettings; |
| + bool canvasIsColorManaged = |
| + RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
| + if (canvasIsColorManaged) |
| + canvasIsColorManaged = colorSettingsAsImageDataColorSettings(colorSettings); |
| IntRect imageDataRect(sx, sy, sw, sh); |
| DVLOG(1) << sx << ", " << sy << ", " << sw << ", " << sh; |
| ImageBuffer* buffer = imageBuffer(); |
| if (!buffer || isContextLost()) { |
| - ImageData* result = ImageData::create(imageDataRect.size()); |
| + ImageData* result = nullptr; |
| + if (canvasIsColorManaged) |
| + result = ImageData::create(imageDataRect.size(), &colorSettings); |
| + else |
| + result = ImageData::create(imageDataRect.size()); |
| if (!result) |
| exceptionState.throwRangeError("Out of memory at ImageData creation"); |
| return result; |
| @@ -1589,7 +1636,39 @@ ImageData* BaseRenderingContext2D::getImageData( |
| return nullptr; |
| } |
| - DOMArrayBuffer* arrayBuffer = DOMArrayBuffer::create(contents); |
| + DOMArrayBuffer* arrayBuffer = nullptr; |
| + DOMArrayBufferView* arrayBufferView = nullptr; |
| + DOMFloat32Array* dataArray = nullptr; |
| + |
| + if (canvasIsColorManaged) { |
| + ImageDataStorageFormat storageFormat = |
| + ImageData::imageDataStorageFormat(colorSettings.storageFormat()); |
| + switch (storageFormat) { |
| + case kUint8ClampedArrayStorageFormat: |
| + arrayBuffer = DOMArrayBuffer::create(contents); |
| + return ImageData::create( |
| + imageDataRect.size(), |
| + DOMUint8ClampedArray::create(arrayBuffer, 0, |
| + arrayBuffer->byteLength())); |
| + break; |
| + case kUint16ArrayStorageFormat: |
| + NOTREACHED(); |
| + break; |
| + case kFloat32ArrayStorageFormat: |
| + arrayBufferView = ImageData:: |
| + convertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
| + contents, renderingContext()->pixelFormat(), storageFormat); |
| + dataArray = const_cast<DOMFloat32Array*>( |
| + static_cast<const DOMFloat32Array*>(arrayBufferView)); |
| + return ImageData::create(imageDataRect.size(), arrayBufferView, |
| + &colorSettings); |
| + default: |
| + NOTREACHED(); |
| + } |
| + return nullptr; |
| + } |
| + |
| + arrayBuffer = DOMArrayBuffer::create(contents); |
| return ImageData::create( |
| imageDataRect.size(), |
| DOMUint8ClampedArray::create(arrayBuffer, 0, arrayBuffer->byteLength())); |
| @@ -1613,11 +1692,32 @@ void BaseRenderingContext2D::putImageData(ImageData* data, |
| ExceptionState& exceptionState) { |
| m_usageCounters.numPutImageDataCalls++; |
| m_usageCounters.areaPutImageDataCalls += dirtyWidth * dirtyHeight; |
| - if (data->data()->bufferBase()->isNeutered()) { |
| + |
| + bool canvasIsColorManaged = |
| + RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
|
Justin Novosad
2017/04/06 19:01:04
This check is copied in many placed, perhaps we co
zakerinasab
2017/04/11 19:52:59
Done.
|
| + |
| + bool dataIsNeutered = false; |
| + if (canvasIsColorManaged) { |
| + dataIsNeutered = |
| + (data->dataUnion().isUint8ClampedArray() && |
| + data->dataUnion() |
| + .getAsUint8ClampedArray() |
| + ->bufferBase() |
| + ->isNeutered()) || |
| + (data->dataUnion().isUint16Array() && |
| + data->dataUnion().getAsUint16Array()->bufferBase()->isNeutered()) || |
| + (data->dataUnion().isFloat32Array() && |
| + data->dataUnion().getAsFloat32Array()->bufferBase()->isNeutered()); |
| + } else { |
| + dataIsNeutered = data->data()->bufferBase()->isNeutered(); |
| + } |
| + if (dataIsNeutered) { |
| exceptionState.throwDOMException(InvalidStateError, |
| "The source data has been neutered."); |
| return; |
| } |
| + |
| ImageBuffer* buffer = imageBuffer(); |
| if (!buffer) |
| return; |
| @@ -1667,10 +1767,23 @@ void BaseRenderingContext2D::putImageData(ImageData* data, |
| checkOverdraw(destRect, 0, CanvasRenderingContext2DState::NoImage, |
| UntransformedUnclippedFill); |
| - buffer->putByteArray(Unmultiplied, data->data()->data(), |
| - IntSize(data->width(), data->height()), sourceRect, |
| - IntPoint(destOffset)); |
| - |
| + if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { |
| + unsigned dataLength = data->width() * data->height(); |
| + if (renderingContext()->pixelFormat() == kF16CanvasPixelFormat) |
| + dataLength *= 2; |
| + std::unique_ptr<uint8_t[]> convertedPixels(new uint8_t[4 * dataLength]); |
| + data->imageDataInCanvasColorSettings(renderingContext()->colorSpace(), |
| + renderingContext()->pixelFormat(), |
| + convertedPixels); |
| + buffer->putByteArray(Unmultiplied, convertedPixels.get(), |
| + IntSize(data->width(), data->height()), sourceRect, |
| + IntPoint(destOffset)); |
| + } else { |
| + buffer->putByteArray(Unmultiplied, data->data()->data(), |
| + IntSize(data->width(), data->height()), sourceRect, |
| + IntPoint(destOffset)); |
| + } |
| didDraw(destRect); |
| } |