| 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..a125cc96892163f884919ecaa22cf3635ae6e514 100644
|
| --- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
|
| +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
|
| @@ -35,8 +35,11 @@
|
| namespace blink {
|
|
|
| BaseRenderingContext2D::BaseRenderingContext2D()
|
| - : m_clipAntialiasing(NotAntiAliased) {
|
| + : m_clipAntialiasing(NotAntiAliased), m_isColorManaged(false) {
|
| m_stateStack.push_back(CanvasRenderingContext2DState::create());
|
| + m_isColorManaged =
|
| + RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() &&
|
| + RuntimeEnabledFeatures::colorCorrectRenderingEnabled();
|
| }
|
|
|
| BaseRenderingContext2D::~BaseRenderingContext2D() {}
|
| @@ -1496,10 +1499,38 @@ bool BaseRenderingContext2D::computeDirtyRect(
|
| return true;
|
| }
|
|
|
| +bool BaseRenderingContext2D::colorSettingsAsImageDataColorSettings(
|
| + ImageDataColorSettings& colorSettings) const {
|
| + if (!m_isColorManaged)
|
| + 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 (m_isColorManaged) {
|
| + 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 +1548,14 @@ ImageData* BaseRenderingContext2D::createImageData(
|
| }
|
|
|
| IntSize size(abs(sw), abs(sh));
|
| -
|
| - ImageData* result = ImageData::create(size);
|
| + ImageData* result = nullptr;
|
| + if (m_isColorManaged) {
|
| + 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,19 @@ ImageData* BaseRenderingContext2D::getImageData(
|
| timer.emplace(scopedUsCounterCPU);
|
| }
|
|
|
| + ImageDataColorSettings colorSettings;
|
| + bool validColorSettings = false;
|
| + if (m_isColorManaged)
|
| + validColorSettings = 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 (validColorSettings)
|
| + 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 +1634,39 @@ ImageData* BaseRenderingContext2D::getImageData(
|
| return nullptr;
|
| }
|
|
|
| - DOMArrayBuffer* arrayBuffer = DOMArrayBuffer::create(contents);
|
| + DOMArrayBuffer* arrayBuffer = nullptr;
|
| + DOMArrayBufferView* arrayBufferView = nullptr;
|
| + DOMFloat32Array* dataArray = nullptr;
|
| +
|
| + if (m_isColorManaged) {
|
| + 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 +1690,28 @@ void BaseRenderingContext2D::putImageData(ImageData* data,
|
| ExceptionState& exceptionState) {
|
| m_usageCounters.numPutImageDataCalls++;
|
| m_usageCounters.areaPutImageDataCalls += dirtyWidth * dirtyHeight;
|
| - if (data->data()->bufferBase()->isNeutered()) {
|
| +
|
| + bool dataIsNeutered = false;
|
| + if (m_isColorManaged) {
|
| + 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 +1761,22 @@ 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 (m_isColorManaged) {
|
| + 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);
|
| }
|
|
|
|
|