Changeset 277569 in webkit


Ignore:
Timestamp:
May 16, 2021 8:21:34 AM (14 months ago)
Author:
weinig@apple.com
Message:

Add support for creating/accessing/setting non-sRGB ImageData via canvas
https://bugs.webkit.org/show_bug.cgi?id=225841

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

  • web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3-expected.txt:

Update result to passing.

Source/WebCore:

Test: fast/canvas/canvas-color-space-display-p3-ImageData.html

Add support for accessing non-sRGB (only DisplayP3 for now due
to the specification, but the support is general) pixel data in
HTML canvas.

Updates ImageData constructors and CanvasImageData operations to
take optional ImageDataSettings dictionaries, which contain an
optional color space (otherwise defaulting back to sRGB).

  • CMakeLists.txt:
  • DerivedSources-input.xcfilelist:
  • DerivedSources-output.xcfilelist:
  • DerivedSources.make:
  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • html/ImageDataSettings.h: Added.
  • html/ImageDataSettings.idl: Added.

Add new ImageDataSettings.idl and related files.

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneDeserializer::readImageBitmap):
Fixes FIXME and uses PixelBuffer directly rather than allocating
an unnecessary ImageData. This was done now since the relevent
ImageData constructor has gone away.

  • html/ImageData.cpp:

(WebCore::computeDataSize):
(WebCore::ImageData::computeColorSpace):
(WebCore::ImageData::create):
(WebCore::ImageData::createUninitialized):
(WebCore::ImageData::ImageData):
(WebCore::ImageData::pixelBuffer const):
(WebCore::ImageData::dataSize): Deleted.
(WebCore::ImageData::deepClone const): Deleted.

  • html/ImageData.h:

(WebCore::ImageData::size const):
(WebCore::ImageData::width const):
(WebCore::ImageData::height const):
(WebCore::ImageData::data const):
(WebCore::ImageData::colorSpace const):
(WebCore::ImageData::pixelBuffer const): Deleted.

  • Reworked ImageData to no longer store a PixelBuffer, which has extraneous information in it, but rather to store just what it needs IntSize, Ref<JSC::Uint8ClampedArray>, and now PredefinedColorSpace.
  • Updates create functions for new optional ImageDataSettings.
  • Adds createUninitialized which follows spec language for ImageData creation and is used by CanvasRenderingContext2D to create ImageData objects of with the right color spaces, allowing for fallback to the canvas' own color space when no ImageDataSettings color space is provided. It is uninitialized and therefore requires the client to initialize the data to allow for support for no alpha support in the future, which requires a non-zero initialization pattern.
  • html/ImageData.idl:

Add optional ImageDataSettings parameters and the new colorSpace attribute.

  • html/canvas/CanvasImageData.idl:

Add optional ImageDataSettings parameters.

  • html/canvas/CanvasRenderingContext2DBase.h:
  • html/canvas/CanvasRenderingContext2DBase.cpp:

(WebCore::initializeEmptyImageData):
Add helper to initialize the ImageData buffer. Right now it always calls
zeroFill(), but in the future it will need to do more.

(WebCore::CanvasRenderingContext2DBase::createImageData const):
Update to account for this function being able to throw an exception (when
out of memory) and use the new createUninitialized/initializeEmptyImageData
to create a correctly color spaced ImageData.

(WebCore::CanvasRenderingContext2DBase::createImageData const):
Update for new optional ImageDataSettings and use the new createUninitialized
initializeEmptyImageData to create a correctly color spaced ImageData.

(WebCore::CanvasRenderingContext2DBase::getImageData const):
Moves parameter checks to the begining to match the spec, and uses new
createUninitialized/initializeEmptyImageData to create a correctly color
spaced ImageData. Also, use the ImageData's color space when getting
the pixel buffer to actually return the right data!

  • html/canvas/PredefinedColorSpace.cpp:

(WebCore::toPredefinedColorSpace):

  • html/canvas/PredefinedColorSpace.h:

Add conversion function from DestinationColorSpace to PredefinedColorSpace.
Since DestinationColorSpace is a superset of PredefinedColorSpace, this can
fail, so this conversion returns an Optional.

  • inspector/InspectorCanvas.cpp:
  • inspector/InspectorCanvasCallTracer.cpp:
  • inspector/InspectorCanvasCallTracer.h:

Stub out inspector support for ImageDataSettings.

  • platform/graphics/ImageBufferBackend.cpp:

(WebCore::ImageBufferBackend::getPixelBuffer const):
Use the ImageBuffer's actual color space as the source color space
rather than hard coding sRGB. This allows the color space conversion
to take place. Also remove some unnecessary temporary variables.

(WebCore::ImageBufferBackend::putPixelBuffer):
Use the ImageBuffer's actual color space as the destination color space
rather than hard coding sRGB. This allows the color space conversion
to take place. Also remove some unnecessary temporary variables.

  • platform/graphics/PixelBuffer.cpp:

(WebCore::PixelBuffer::tryCreate):
(WebCore::PixelBuffer::PixelBuffer):

  • platform/graphics/PixelBuffer.h:

(WebCore::PixelBuffer::takeData):
Add a few helpers to allow creationg to/from PixelBuffer
a bit easier.

  • platform/graphics/PixelBufferConversion.cpp:

(WebCore::convertImagePixelsAccelerated):
Fix incorrect assertion. We want to assert that there is no error, not that
there is one.

  • platform/graphics/filters/FilterEffect.cpp:

(WebCore::FilterEffect::convertImageBufferToColorSpace):
(WebCore::FilterEffect::copyUnmultipliedResult):
(WebCore::FilterEffect::copyPremultipliedResult):
(WebCore::FilterEffect::createUnmultipliedImageResult):
(WebCore::FilterEffect::createPremultipliedImageResult):
Stop hard coding SRGB for PixelBuffer color spaces and use the appropriate
color space for the task. We still do color space conversion through ImageBuffer
so we should come back and simplify code here to not always require that.

  • testing/Internals.cpp:

(WebCore::Internals::videoSampleAvailable):
(WebCore::Internals::loadArtworkImage):
Update to specify a color space to maintain existing behavior.

Source/WebKitLegacy/win:

Add support for tests enabling the CanvasColorSpaceEnabled preference.

  • WebPreferences.cpp:

(WebPreferences::canvasColorSpaceEnabled):

  • WebPreferences.h:
  • WebView.cpp:

(WebView::notifyPreferencesChanged):

LayoutTests:

Remove wide-gamut-canvas now that they should pass.

  • fast/canvas/canvas-color-space-display-p3-ImageData-expected.txt: Added.
  • fast/canvas/canvas-color-space-display-p3-ImageData.html: Added.

Add new test exercising getImageData and putImageData with non-sRGB canvases
and non-sRGB ImageData.

  • fast/canvas/canvas-imageData-expected.txt:

Update results for updated error messages, which are a bit worse due additional
ambiguity in signatures.

  • platform/glib/TestExpectations:

Mark new test as failing on glib due to lack of display-p3 support.

  • platform/win/TestExpectations:

Mark new test as failing on Windows due to lack of display-p3 support.
Unskip CanvasRenderingContext2DSettings-colorSpace-enabled.html which
should now pass due to adding manual preferences support in WebKitLegacy/win.

  • storage/indexeddb/modern/objectstore-autoincrement-types-expected.txt:

Update results due to new attribute in ImageData that is auto printed.

Location:
trunk
Files:
2 added
37 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r277566 r277569  
     12021-05-16  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for creating/accessing/setting non-sRGB ImageData via canvas
     4        https://bugs.webkit.org/show_bug.cgi?id=225841
     5
     6        Reviewed by Darin Adler.
     7
     8        * TestExpectations:
     9        Remove wide-gamut-canvas now that they should pass.
     10
     11        * fast/canvas/canvas-color-space-display-p3-ImageData-expected.txt: Added.
     12        * fast/canvas/canvas-color-space-display-p3-ImageData.html: Added.
     13        Add new test exercising getImageData and putImageData with non-sRGB canvases
     14        and non-sRGB ImageData.
     15 
     16        * fast/canvas/canvas-imageData-expected.txt:
     17        Update results for updated error messages, which are a bit worse due additional
     18        ambiguity in signatures.
     19
     20        * platform/glib/TestExpectations:
     21        Mark new test as failing on glib due to lack of display-p3 support.
     22
     23        * platform/win/TestExpectations:
     24        Mark new test as failing on Windows due to lack of display-p3 support.
     25        Unskip CanvasRenderingContext2DSettings-colorSpace-enabled.html which
     26        should now pass due to adding manual preferences support in WebKitLegacy/win.
     27
     28        * storage/indexeddb/modern/objectstore-autoincrement-types-expected.txt:
     29        Update results due to new attribute in ImageData that is auto printed.
     30
    1312021-05-16  Tim Nguyen  <ntim@apple.com>
    232
  • trunk/LayoutTests/TestExpectations

    r277566 r277569  
    39953995imported/w3c/web-platform-tests/html/canvas/element/drawing-images-to-the-canvas/image-orientation/drawImage-from-element.tentative.html [ ImageOnlyFailure ]
    39963996
    3997 # Sometimes prints weird output at the beginning of the tests.
    3998 imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas [ Failure Pass ]
    3999 
    40003997# CSS Masonry Layout not supported.
    40013998imported/w3c/web-platform-tests/css/css-grid/masonry.tentative [ Skip ]
  • trunk/LayoutTests/fast/canvas/canvas-imageData-expected.txt

    r223611 r277569  
    1515PASS new ImageData(null, 20) threw exception IndexSizeError: The index is not in the allowed range..
    1616PASS new ImageData(32768, 32768) threw exception RangeError: Cannot allocate a buffer of this size.
    17 PASS new ImageData(null, 20, 20) threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
    18 PASS new ImageData(imageData, 20, 20) threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
     17PASS new ImageData(null, 20, 20) threw exception TypeError: Type error.
     18PASS new ImageData(imageData, 20, 20) threw exception TypeError: Type error.
    1919PASS new ImageData(imageData, 0) threw exception IndexSizeError: The index is not in the allowed range..
    20 PASS new ImageData(imageData, 20, 0) threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
    21 PASS new ImageData(imageData, 0, 20) threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
    22 PASS new ImageData(imageData, 10, 5) threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
     20PASS new ImageData(imageData, 20, 0) threw exception TypeError: Type error.
     21PASS new ImageData(imageData, 0, 20) threw exception TypeError: Type error.
     22PASS new ImageData(imageData, 10, 5) threw exception TypeError: Type error.
    2323PASS new ImageData(imageData.data, 10, 5) threw exception IndexSizeError: sh value is not equal to height.
    2424PASS new ImageData(imageData.data, -10, 5) threw exception IndexSizeError: Length is not a multiple of sw.
    2525PASS new ImageData(imageData.data, 10, -10) threw exception IndexSizeError: sh value is not equal to height.
    2626PASS new ImageData(new Uint8ClampedArray([1,2,3,4,5,6,7,8]),536870913,2); threw exception IndexSizeError: Length is not a multiple of sw.
    27 PASS new ImageData({},2,2); threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
    28 PASS new ImageData(undefined,2,2); threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
    29 PASS new ImageData("none",2,2); threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
    30 PASS new ImageData(0,2,2); threw exception TypeError: Argument 1 ('data') to the ImageData constructor must be an instance of Uint8ClampedArray.
     27PASS new ImageData({},2,2); threw exception TypeError: Type error.
     28PASS new ImageData(undefined,2,2); threw exception TypeError: Type error.
     29PASS new ImageData("none",2,2); threw exception TypeError: Type error.
     30PASS new ImageData(0,2,2); threw exception TypeError: Type error.
    3131PASS new ImageData(imageData.data, 32768, 32768) threw exception IndexSizeError: Length is not a multiple of sw.
    3232PASS new ImageData(imageData.data, Infinity, Infinity) threw exception IndexSizeError: Length is not a multiple of sw.
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r277547 r277569  
     12021-05-16  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for creating/accessing/setting non-sRGB ImageData via canvas
     4        https://bugs.webkit.org/show_bug.cgi?id=225841
     5
     6        Reviewed by Darin Adler.
     7
     8        * web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3-expected.txt:
     9        Update result to passing.
     10
    1112021-05-15  Said Abou-Hallawa  <said@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/wide-gamut-canvas/2d.color.space.p3.to.p3-expected.txt

    r276776 r277569  
    33Actual output:
    44
    5 FAIL test getImageData with display-p3 and uint8 from display p3 uint8 canvas assert_approx_equals: expected 62 +/- 2 but got 50
     5PASS test getImageData with display-p3 and uint8 from display p3 uint8 canvas
    66
  • trunk/LayoutTests/platform/glib/TestExpectations

    r277432 r277569  
    23592359
    23602360webkit.org/b/225423 fast/canvas/canvas-color-space-display-p3.html [ ImageOnlyFailure ]
     2361webkit.org/b/225423 fast/canvas/canvas-color-space-display-p3-ImageData.html [ Failure ]
    23612362webkit.org/b/225423 fast/canvas/canvas-composite-text-alpha.html [ Failure ]
    23622363
  • trunk/LayoutTests/platform/win/TestExpectations

    r277547 r277569  
    46364636fast/text/line-break-with-locale.html [ ImageOnlyFailure ]
    46374637
    4638 fast/canvas/CanvasRenderingContext2DSettings-colorSpace-enabled.html [ Skip ]
     4638# Non-SRGB color spaces are not currently supported by the Windows port.
     4639fast/canvas/canvas-color-space-display-p3.html [ Skip ]
     4640fast/canvas/canvas-color-space-display-p3-ImageData.html [ Skip ]
  • trunk/LayoutTests/storage/indexeddb/modern/objectstore-autoincrement-types-expected.txt

    r259900 r277569  
    2727PASS request.result.width is imageData.width
    2828PASS request.result.height is imageData.height
     29PASS request.result.colorSpace is imageData.colorSpace
    2930PASS key is 4
    3031PASS request.result.primaryKey is fileList.primaryKey
     
    4142PASS request.result[2].width is imageData.width
    4243PASS request.result[2].height is imageData.height
     44PASS request.result[2].colorSpace is imageData.colorSpace
    4345PASS request.result[3].primaryKey is fileList.primaryKey
    4446PASS request.result[3].length is fileList.length
  • trunk/Source/WebCore/CMakeLists.txt

    r277530 r277569  
    10181018    html/ImageBitmapOptions.idl
    10191019    html/ImageData.idl
     1020    html/ImageDataSettings.idl
    10201021    html/MediaController.idl
    10211022    html/MediaEncryptedEvent.idl
  • trunk/Source/WebCore/ChangeLog

    r277568 r277569  
     12021-05-16  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for creating/accessing/setting non-sRGB ImageData via canvas
     4        https://bugs.webkit.org/show_bug.cgi?id=225841
     5
     6        Reviewed by Darin Adler.
     7
     8        Test: fast/canvas/canvas-color-space-display-p3-ImageData.html
     9
     10        Add support for accessing non-sRGB (only DisplayP3 for now due
     11        to the specification, but the support is general) pixel data in
     12        HTML canvas.
     13
     14        Updates ImageData constructors and CanvasImageData operations to
     15        take optional ImageDataSettings dictionaries, which contain an
     16        optional color space (otherwise defaulting back to sRGB).
     17
     18        * CMakeLists.txt:
     19        * DerivedSources-input.xcfilelist:
     20        * DerivedSources-output.xcfilelist:
     21        * DerivedSources.make:
     22        * Sources.txt:
     23        * WebCore.xcodeproj/project.pbxproj:
     24        * html/ImageDataSettings.h: Added.
     25        * html/ImageDataSettings.idl: Added.
     26        Add new ImageDataSettings.idl and related files.
     27
     28        * bindings/js/SerializedScriptValue.cpp:
     29        (WebCore::CloneDeserializer::readImageBitmap):
     30        Fixes FIXME and uses PixelBuffer directly rather than allocating
     31        an unnecessary ImageData. This was done now since the relevent
     32        ImageData constructor has gone away.
     33
     34        * html/ImageData.cpp:
     35        (WebCore::computeDataSize):
     36        (WebCore::ImageData::computeColorSpace):
     37        (WebCore::ImageData::create):
     38        (WebCore::ImageData::createUninitialized):
     39        (WebCore::ImageData::ImageData):
     40        (WebCore::ImageData::pixelBuffer const):
     41        (WebCore::ImageData::dataSize): Deleted.
     42        (WebCore::ImageData::deepClone const): Deleted.
     43        * html/ImageData.h:
     44        (WebCore::ImageData::size const):
     45        (WebCore::ImageData::width const):
     46        (WebCore::ImageData::height const):
     47        (WebCore::ImageData::data const):
     48        (WebCore::ImageData::colorSpace const):
     49        (WebCore::ImageData::pixelBuffer const): Deleted.
     50
     51        - Reworked ImageData to no longer store a PixelBuffer, which has
     52          extraneous information in it, but rather to store just what it
     53          needs IntSize, Ref<JSC::Uint8ClampedArray>, and now PredefinedColorSpace.
     54        - Updates create functions for new optional ImageDataSettings.
     55        - Adds createUninitialized which follows spec language for ImageData creation
     56          and is used by CanvasRenderingContext2D to create ImageData objects of with
     57          the right color spaces, allowing for fallback to the canvas' own color space
     58          when no ImageDataSettings color space is provided. It is uninitialized and
     59          therefore requires the client to initialize the data to allow for support for
     60          no alpha support in the future, which requires a non-zero initialization pattern.
     61
     62        * html/ImageData.idl:
     63        Add optional ImageDataSettings parameters and the new colorSpace attribute.
     64
     65        * html/canvas/CanvasImageData.idl:
     66        Add optional ImageDataSettings parameters.
     67
     68        * html/canvas/CanvasRenderingContext2DBase.h:
     69        * html/canvas/CanvasRenderingContext2DBase.cpp:
     70        (WebCore::initializeEmptyImageData):
     71        Add helper to initialize the ImageData buffer. Right now it always calls
     72        zeroFill(), but in the future it will need to do more.
     73       
     74        (WebCore::CanvasRenderingContext2DBase::createImageData const):
     75        Update to account for this function being able to throw an exception (when
     76        out of memory) and use the new createUninitialized/initializeEmptyImageData
     77        to create a correctly color spaced ImageData.
     78
     79        (WebCore::CanvasRenderingContext2DBase::createImageData const):
     80        Update for new optional ImageDataSettings and use the new createUninitialized
     81        initializeEmptyImageData to create a correctly color spaced ImageData.
     82
     83        (WebCore::CanvasRenderingContext2DBase::getImageData const):
     84        Moves parameter checks to the begining to match the spec, and uses new
     85        createUninitialized/initializeEmptyImageData to create a correctly color
     86        spaced ImageData. Also, use the ImageData's color space when getting
     87        the pixel buffer to actually return the right data!
     88
     89        * html/canvas/PredefinedColorSpace.cpp:
     90        (WebCore::toPredefinedColorSpace):
     91        * html/canvas/PredefinedColorSpace.h:
     92        Add conversion function from DestinationColorSpace to PredefinedColorSpace.
     93        Since DestinationColorSpace is a superset of PredefinedColorSpace, this can
     94        fail, so this conversion returns an Optional.
     95
     96        * inspector/InspectorCanvas.cpp:
     97        * inspector/InspectorCanvasCallTracer.cpp:
     98        * inspector/InspectorCanvasCallTracer.h:
     99        Stub out inspector support for ImageDataSettings.
     100
     101        * platform/graphics/ImageBufferBackend.cpp:
     102        (WebCore::ImageBufferBackend::getPixelBuffer const):
     103        Use the ImageBuffer's actual color space as the source color space
     104        rather than hard coding sRGB. This allows the color space conversion
     105        to take place. Also remove some unnecessary temporary variables.
     106
     107        (WebCore::ImageBufferBackend::putPixelBuffer):
     108        Use the ImageBuffer's actual color space as the destination color space
     109        rather than hard coding sRGB. This allows the color space conversion
     110        to take place. Also remove some unnecessary temporary variables.
     111
     112        * platform/graphics/PixelBuffer.cpp:
     113        (WebCore::PixelBuffer::tryCreate):
     114        (WebCore::PixelBuffer::PixelBuffer):
     115        * platform/graphics/PixelBuffer.h:
     116        (WebCore::PixelBuffer::takeData):
     117        Add a few helpers to allow creationg to/from PixelBuffer
     118        a bit easier.
     119
     120        * platform/graphics/PixelBufferConversion.cpp:
     121        (WebCore::convertImagePixelsAccelerated):
     122        Fix incorrect assertion. We want to assert that there is no error, not that
     123        there is one.
     124
     125        * platform/graphics/filters/FilterEffect.cpp:
     126        (WebCore::FilterEffect::convertImageBufferToColorSpace):
     127        (WebCore::FilterEffect::copyUnmultipliedResult):
     128        (WebCore::FilterEffect::copyPremultipliedResult):
     129        (WebCore::FilterEffect::createUnmultipliedImageResult):
     130        (WebCore::FilterEffect::createPremultipliedImageResult):
     131        Stop hard coding SRGB for PixelBuffer color spaces and use the appropriate
     132        color space for the task. We still do color space conversion through ImageBuffer
     133        so we should come back and simplify code here to not always require that.
     134
     135        * testing/Internals.cpp:
     136        (WebCore::Internals::videoSampleAvailable):
     137        (WebCore::Internals::loadArtworkImage):
     138        Update to specify a color space to maintain existing behavior.
     139
    11402021-05-16  Alan Bujtas  <zalan@apple.com>
    2141
  • trunk/Source/WebCore/DerivedSources-input.xcfilelist

    r277024 r277569  
    10371037$(PROJECT_DIR)/html/ImageBitmapOptions.idl
    10381038$(PROJECT_DIR)/html/ImageData.idl
     1039$(PROJECT_DIR)/html/ImageDataSettings.idl
    10391040$(PROJECT_DIR)/html/MediaController.idl
    10401041$(PROJECT_DIR)/html/MediaEncryptedEvent.idl
  • trunk/Source/WebCore/DerivedSources-output.xcfilelist

    r277024 r277569  
    11811181$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSImageData.cpp
    11821182$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSImageData.h
     1183$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSImageDataSettings.cpp
     1184$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSImageDataSettings.h
    11831185$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSImageSmoothingQuality.cpp
    11841186$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSImageSmoothingQuality.h
  • trunk/Source/WebCore/DerivedSources.make

    r277530 r277569  
    891891    $(WebCore)/html/ImageBitmapOptions.idl \
    892892    $(WebCore)/html/ImageData.idl \
     893    $(WebCore)/html/ImageDataSettings.idl \
    893894    $(WebCore)/html/MediaController.idl \
    894895    $(WebCore)/html/MediaEncryptedEvent.idl \
  • trunk/Source/WebCore/Sources.txt

    r277556 r277569  
    32083208JSImageBitmapRenderingContextSettings.cpp
    32093209JSImageData.cpp
     3210JSImageDataSettings.cpp
    32103211JSImageSmoothingQuality.cpp
    32113212JSInputEvent.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r277556 r277569  
    41044104                BC97E23A109144950010D361 /* HTMLAllCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = BC97E238109144950010D361 /* HTMLAllCollection.h */; };
    41054105                BC97E413109154FA0010D361 /* JSHTMLAllCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = BC97E411109154FA0010D361 /* JSHTMLAllCollection.h */; };
     4106                BCA088F5264E1C08003E2A6C /* ImageDataSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA088F2264E1BF9003E2A6C /* ImageDataSettings.h */; settings = {ATTRIBUTES = (Private, ); }; };
    41064107                BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */; };
    41074108                BCA257151293C010007A263D /* VerticalPositionCache.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA257141293C010007A263D /* VerticalPositionCache.h */; };
     
    1433214333                BC9A6145146859D9006057FD /* make_event_factory.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = make_event_factory.pl; sourceTree = "<group>"; };
    1433314334                BC9A6146146859D9006057FD /* make_names.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = make_names.pl; sourceTree = "<group>"; };
     14335                BCA088F2264E1BF9003E2A6C /* ImageDataSettings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageDataSettings.h; sourceTree = "<group>"; };
     14336                BCA088F4264E1BF9003E2A6C /* ImageDataSettings.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = ImageDataSettings.idl; sourceTree = "<group>"; };
    1433414337                BCA169A00BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLTableCaptionElement.cpp; sourceTree = "<group>"; };
    1433514338                BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLTableCaptionElement.h; sourceTree = "<group>"; };
     
    2395123954                                A77979140D6B9D0C003851B9 /* ImageData.h */,
    2395223955                                A77979150D6B9D0C003851B9 /* ImageData.idl */,
     23956                                BCA088F2264E1BF9003E2A6C /* ImageDataSettings.h */,
     23957                                BCA088F4264E1BF9003E2A6C /* ImageDataSettings.idl */,
    2395323958                                97205AB11239291000B17380 /* ImageDocument.cpp */,
    2395423959                                97205AB21239291000B17380 /* ImageDocument.h */,
     
    3291632921                                CD3E21DD2183444A00E66F55 /* ImageBufferUtilitiesCG.h in Headers */,
    3291732922                                A779791A0D6B9D0C003851B9 /* ImageData.h in Headers */,
     32923                                BCA088F5264E1C08003E2A6C /* ImageDataSettings.h in Headers */,
    3291832924                                CD19FEA81F573972000C42FB /* ImageDecoder.h in Headers */,
    3291932925                                CD19FEAE1F574B6D000C42FB /* ImageDecoderAVFObjC.h in Headers */,
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r277560 r277569  
    31423142        }
    31433143
    3144         auto array = Uint8ClampedArray::tryCreate(WTFMove(arrayBuffer), 0, arrayBuffer->byteLength());
    3145         if (!array) {
    3146             fail();
    3147             return JSValue();
    3148         }
    3149 
    31503144        IntSize logicalSize = IntSize(logicalWidth, logicalHeight);
    31513145        IntSize imageDataSize = logicalSize;
    31523146        imageDataSize.scale(resolutionScale);
    3153 
    3154         // FIXME: Creating this ImageData is not necessary. We should skip right to creating a PixelBuffer directly.
    3155         auto imageData = ImageData::create(imageDataSize, array.releaseNonNull());
    3156         if (!imageData) {
    3157             fail();
    3158             return JSValue();
    3159         }
    31603147
    31613148        auto buffer = ImageBitmap::createImageBuffer(*scriptExecutionContextFromExecState(m_lexicalGlobalObject), logicalSize, RenderingMode::Unaccelerated, resolutionScale);
     
    31653152        }
    31663153
    3167         buffer->putPixelBuffer(imageData->pixelBuffer(), { IntPoint::zero(), logicalSize });
     3154        PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     3155        auto pixelBuffer = PixelBuffer::tryCreate(format, imageDataSize, arrayBuffer.releaseNonNull());
     3156        if (!pixelBuffer) {
     3157            fail();
     3158            return JSValue();
     3159        }
     3160
     3161        buffer->putPixelBuffer(WTFMove(*pixelBuffer), { IntPoint::zero(), logicalSize });
    31683162
    31693163        auto bitmap = ImageBitmap::create(ImageBitmapBacking(WTFMove(buffer), OptionSet<SerializationState>::fromRaw(serializationState)));
  • trunk/Source/WebCore/html/ImageData.cpp

    r277450 r277569  
    3636namespace WebCore {
    3737
    38 Checked<unsigned, RecordOverflow> ImageData::dataSize(const IntSize& size)
     38static Checked<unsigned, RecordOverflow> computeDataSize(const IntSize& size)
    3939{
    4040    Checked<unsigned, RecordOverflow> checkedDataSize = 4;
     
    4444}
    4545
     46PredefinedColorSpace ImageData::computeColorSpace(Optional<ImageDataSettings> settings, PredefinedColorSpace defaultColorSpace)
     47{
     48    if (settings && settings->colorSpace)
     49        return *settings->colorSpace;
     50    return defaultColorSpace;
     51}
     52
    4653Ref<ImageData> ImageData::create(PixelBuffer&& pixelBuffer)
    4754{
    48     return adoptRef(*new ImageData(WTFMove(pixelBuffer)));
     55    auto colorSpace = toPredefinedColorSpace(pixelBuffer.format().colorSpace);
     56    return adoptRef(*new ImageData(pixelBuffer.size(), pixelBuffer.takeData(), *colorSpace));
    4957}
    5058
     
    5361    if (!pixelBuffer)
    5462        return nullptr;
    55     return ImageData::create(WTFMove(*pixelBuffer));
     63    return create(WTFMove(*pixelBuffer));
    5664}
    5765
    5866RefPtr<ImageData> ImageData::create(const IntSize& size)
    5967{
    60     auto dataSize = ImageData::dataSize(size);
     68    auto dataSize = computeDataSize(size);
    6169    if (dataSize.hasOverflowed())
    6270        return nullptr;
     
    6472    if (!byteArray)
    6573        return nullptr;
    66    
    67     return adoptRef(*new ImageData({ { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB }, size, byteArray.releaseNonNull() }));
     74    return adoptRef(*new ImageData(size, byteArray.releaseNonNull(), PredefinedColorSpace::SRGB));
    6875}
    6976
    70 RefPtr<ImageData> ImageData::create(const IntSize& size, Ref<Uint8ClampedArray>&& byteArray)
     77RefPtr<ImageData> ImageData::create(const IntSize& size, Ref<Uint8ClampedArray>&& byteArray, PredefinedColorSpace colorSpace)
    7178{
    72     auto dataSize = ImageData::dataSize(size);
    73     if (dataSize.hasOverflowed() || dataSize.unsafeGet() > byteArray->length())
     79    auto dataSize = computeDataSize(size);
     80    if (dataSize.hasOverflowed() || dataSize.unsafeGet() != byteArray->length())
    7481        return nullptr;
    7582
    76     return adoptRef(*new ImageData({ { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB }, size, WTFMove(byteArray) }));
     83    return adoptRef(*new ImageData(size, WTFMove(byteArray), colorSpace));
    7784}
    7885
    79 ExceptionOr<Ref<ImageData>> ImageData::create(unsigned sw, unsigned sh)
     86ExceptionOr<Ref<ImageData>> ImageData::createUninitialized(unsigned rows, unsigned pixelsPerRow, PredefinedColorSpace defaultColorSpace, Optional<ImageDataSettings> settings)
     87{
     88    IntSize size(rows, pixelsPerRow);
     89    auto dataSize = computeDataSize(size);
     90    if (dataSize.hasOverflowed())
     91        return Exception { RangeError, "Cannot allocate a buffer of this size"_s };
     92
     93    auto byteArray = Uint8ClampedArray::tryCreateUninitialized(dataSize.unsafeGet());
     94    if (!byteArray) {
     95        // FIXME: Does this need to be a "real" out of memory error with setOutOfMemoryError called on it?
     96        return Exception { RangeError, "Out of memory"_s };
     97    }
     98
     99    auto colorSpace = computeColorSpace(settings, defaultColorSpace);
     100    return adoptRef(*new ImageData(size, byteArray.releaseNonNull(), colorSpace));
     101}
     102
     103ExceptionOr<Ref<ImageData>> ImageData::create(unsigned sw, unsigned sh, Optional<ImageDataSettings> settings)
    80104{
    81105    if (!sw || !sh)
    82106        return Exception { IndexSizeError };
     107
    83108    IntSize size(sw, sh);
    84     auto dataSize = ImageData::dataSize(size);
     109    auto dataSize = computeDataSize(size);
    85110    if (dataSize.hasOverflowed())
    86111        return Exception { RangeError, "Cannot allocate a buffer of this size"_s };
     112
    87113    auto byteArray = Uint8ClampedArray::tryCreateUninitialized(dataSize.unsafeGet());
    88114    if (!byteArray) {
     
    91117    }
    92118    byteArray->zeroFill();
    93     return adoptRef(*new ImageData({ { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB }, size, byteArray.releaseNonNull() }));
     119
     120    auto colorSpace = computeColorSpace(settings);
     121    return adoptRef(*new ImageData(size, byteArray.releaseNonNull(), colorSpace));
    94122}
    95123
    96 ExceptionOr<Ref<ImageData>> ImageData::create(Ref<Uint8ClampedArray>&& byteArray, unsigned sw, Optional<unsigned> sh)
     124ExceptionOr<Ref<ImageData>> ImageData::create(Ref<Uint8ClampedArray>&& byteArray, unsigned sw, Optional<unsigned> sh, Optional<ImageDataSettings> settings)
    97125{
    98126    unsigned length = byteArray->length();
     
    108136        return Exception { IndexSizeError, "sh value is not equal to height"_s };
    109137
    110     auto result = create(IntSize(sw, height), WTFMove(byteArray));
    111     if (!result)
     138    IntSize size(sw, height);
     139    auto dataSize = computeDataSize(size);
     140    if (dataSize.hasOverflowed() || dataSize.unsafeGet() != byteArray->length())
    112141        return Exception { RangeError };
    113     return result.releaseNonNull();
     142
     143    auto colorSpace = computeColorSpace(settings);
     144    return adoptRef(*new ImageData(size, WTFMove(byteArray), colorSpace));
    114145}
    115146
    116 ImageData::ImageData(PixelBuffer&& pixelBuffer)
    117     : m_pixelBuffer(WTFMove(pixelBuffer))
     147ImageData::ImageData(const IntSize& size, Ref<JSC::Uint8ClampedArray>&& data, PredefinedColorSpace colorSpace)
     148    : m_size(size)
     149    , m_data(WTFMove(data))
     150    , m_colorSpace(colorSpace)
    118151{
    119152}
     
    121154ImageData::~ImageData() = default;
    122155
    123 Ref<ImageData> ImageData::deepClone() const
     156PixelBuffer ImageData::pixelBuffer() const
    124157{
    125     return adoptRef(*new ImageData(m_pixelBuffer.deepClone()));
     158    PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, toDestinationColorSpace(m_colorSpace) };
     159    return { format, m_size, m_data.get() };
    126160}
    127161
  • trunk/Source/WebCore/html/ImageData.h

    r277450 r277569  
    3030
    3131#include "ExceptionOr.h"
     32#include "ImageDataSettings.h"
     33#include "IntSize.h"
    3234#include "PixelBuffer.h"
     35#include "PredefinedColorSpace.h"
     36#include <JavaScriptCore/Uint8ClampedArray.h>
     37#include <wtf/Forward.h>
    3338
    3439namespace WebCore {
     
    3944    WEBCORE_EXPORT static RefPtr<ImageData> create(Optional<PixelBuffer>&&);
    4045    WEBCORE_EXPORT static RefPtr<ImageData> create(const IntSize&);
    41     WEBCORE_EXPORT static RefPtr<ImageData> create(const IntSize&, Ref<Uint8ClampedArray>&&);
    42     WEBCORE_EXPORT static ExceptionOr<Ref<ImageData>> create(unsigned sw, unsigned sh);
    43     WEBCORE_EXPORT static ExceptionOr<Ref<ImageData>> create(Ref<Uint8ClampedArray>&&, unsigned sw, Optional<unsigned> sh);
     46    WEBCORE_EXPORT static RefPtr<ImageData> create(const IntSize&, Ref<Uint8ClampedArray>&&, PredefinedColorSpace);
     47    WEBCORE_EXPORT static ExceptionOr<Ref<ImageData>> createUninitialized(unsigned rows, unsigned pixelsPerRow, PredefinedColorSpace defaultColorSpace, Optional<ImageDataSettings> = WTF::nullopt);
     48    WEBCORE_EXPORT static ExceptionOr<Ref<ImageData>> create(unsigned sw, unsigned sh, Optional<ImageDataSettings>);
     49    WEBCORE_EXPORT static ExceptionOr<Ref<ImageData>> create(Ref<Uint8ClampedArray>&&, unsigned sw, Optional<unsigned> sh, Optional<ImageDataSettings>);
     50
    4451    WEBCORE_EXPORT ~ImageData();
    4552
    46     const IntSize& size() const { return m_pixelBuffer.size(); }
    47     int width() const { return m_pixelBuffer.size().width(); }
    48     int height() const { return m_pixelBuffer.size().height(); }
     53    static PredefinedColorSpace computeColorSpace(Optional<ImageDataSettings>, PredefinedColorSpace defaultColorSpace = PredefinedColorSpace::SRGB);
    4954
    50     Uint8ClampedArray& data() const { return m_pixelBuffer.data(); }
     55    const IntSize& size() const { return m_size; }
    5156
    52     Ref<ImageData> deepClone() const;
     57    int width() const { return m_size.width(); }
     58    int height() const { return m_size.height(); }
     59    Uint8ClampedArray& data() const { return m_data.get(); }
     60    PredefinedColorSpace colorSpace() const { return m_colorSpace; }
    5361
    54     const PixelBuffer& pixelBuffer() const { return m_pixelBuffer; }
     62    PixelBuffer pixelBuffer() const;
    5563
    5664private:
    57     explicit ImageData(PixelBuffer&&);
     65    explicit ImageData(const IntSize&, Ref<JSC::Uint8ClampedArray>&&, PredefinedColorSpace);
    5866
    59     static Checked<unsigned, RecordOverflow> dataSize(const IntSize&);
    60 
    61     PixelBuffer m_pixelBuffer;
     67    IntSize m_size;
     68    Ref<JSC::Uint8ClampedArray> m_data;
     69    PredefinedColorSpace m_colorSpace;
    6270};
    6371
    64 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const ImageData&);
     72WEBCORE_EXPORT TextStream& operator<<(TextStream&, const ImageData&);
    6573
    6674} // namespace WebCore
  • trunk/Source/WebCore/html/ImageData.idl

    r267007 r277569  
    11/*
    2  * Copyright (C) 2008-2009, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333    ImplementationLacksVTable
    3434] interface ImageData {
    35     constructor(unsigned long sw, unsigned long sh);
    36     constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh);
     35    constructor(unsigned long sw, unsigned long sh, optional ImageDataSettings settings);
     36    constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh, optional ImageDataSettings settings);
    3737
    3838    readonly attribute unsigned long width;
    3939    readonly attribute unsigned long height;
    4040    readonly attribute Uint8ClampedArray data;
     41    [EnabledBySetting=CanvasColorSpace] readonly attribute PredefinedColorSpace colorSpace;
    4142};
  • trunk/Source/WebCore/html/ImageDataSettings.h

    r277568 r277569  
    2424 */
    2525
    26 #include "config.h"
     26#pragma once
     27
    2728#include "PredefinedColorSpace.h"
    28 
    29 #include "ColorSpace.h"
     29#include <wtf/Optional.h>
    3030
    3131namespace WebCore {
    3232
    33 DestinationColorSpace toDestinationColorSpace(PredefinedColorSpace colorSpace)
    34 {
    35     switch (colorSpace) {
    36     case PredefinedColorSpace::SRGB:
    37         return DestinationColorSpace::SRGB;
    38 #if ENABLE(DESTINATION_COLOR_SPACE_DISPLAY_P3)
    39     case PredefinedColorSpace::DisplayP3:
    40         return DestinationColorSpace::DisplayP3;
    41 #endif
    42     }
     33struct ImageDataSettings {
     34    Optional<PredefinedColorSpace> colorSpace;
     35};
    4336
    44     ASSERT_NOT_REACHED();
    45     return DestinationColorSpace::SRGB;
    46 }
    47 
    48 }
     37} // namespace WebCore
  • trunk/Source/WebCore/html/ImageDataSettings.idl

    r277568 r277569  
    2424 */
    2525
    26 #include "config.h"
    27 #include "PredefinedColorSpace.h"
    28 
    29 #include "ColorSpace.h"
    30 
    31 namespace WebCore {
    32 
    33 DestinationColorSpace toDestinationColorSpace(PredefinedColorSpace colorSpace)
    34 {
    35     switch (colorSpace) {
    36     case PredefinedColorSpace::SRGB:
    37         return DestinationColorSpace::SRGB;
    38 #if ENABLE(DESTINATION_COLOR_SPACE_DISPLAY_P3)
    39     case PredefinedColorSpace::DisplayP3:
    40         return DestinationColorSpace::DisplayP3;
    41 #endif
    42     }
    43 
    44     ASSERT_NOT_REACHED();
    45     return DestinationColorSpace::SRGB;
    46 }
    47 
    48 }
     26// https://html.spec.whatwg.org/multipage/canvas.html#imagedatasettings
     27dictionary ImageDataSettings {
     28    [EnabledBySetting=CanvasColorSpace] PredefinedColorSpace colorSpace;
     29};
  • trunk/Source/WebCore/html/canvas/CanvasImageData.idl

    r276877 r277569  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727interface mixin CanvasImageData {
    2828    // pixel manipulation
    29     ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh);
     29    ImageData createImageData([EnforceRange] long sw, [EnforceRange] long sh, optional ImageDataSettings settings);
    3030    ImageData createImageData(ImageData imagedata);
    31     ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh);
     31    ImageData getImageData([EnforceRange] long sx, [EnforceRange] long sy, [EnforceRange] long sw, [EnforceRange] long sh, optional ImageDataSettings settings);
    3232    undefined putImageData(ImageData imagedata, [EnforceRange] long dx, [EnforceRange] long dy);
    3333    undefined putImageData(ImageData imagedata, [EnforceRange] long dx, [EnforceRange] long dy, [EnforceRange] long dirtyX, [EnforceRange] long dirtyY, [EnforceRange] long dirtyWidth, [EnforceRange] long dirtyHeight);
  • trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp

    r277547 r277569  
    21612161}
    21622162
    2163 static RefPtr<ImageData> createEmptyImageData(const IntSize& size)
    2164 {
    2165     auto data = ImageData::create(size);
    2166     if (data)
    2167         data->data().zeroFill();
    2168     return data;
    2169 }
    2170 
    2171 RefPtr<ImageData> CanvasRenderingContext2DBase::createImageData(ImageData& imageData) const
    2172 {
    2173     return createEmptyImageData(imageData.size());
    2174 }
    2175 
    2176 ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2DBase::createImageData(int sw, int sh) const
     2163static void initializeEmptyImageData(const ImageData& imageData)
     2164{
     2165    imageData.data().zeroFill();
     2166}
     2167
     2168ExceptionOr<Ref<ImageData>> CanvasRenderingContext2DBase::createImageData(ImageData& existingImageData) const
     2169{
     2170    auto newImageData = ImageData::createUninitialized(existingImageData.width(), existingImageData.height(), existingImageData.colorSpace());
     2171    if (!newImageData.hasException())
     2172        initializeEmptyImageData(newImageData.returnValue());
     2173    return newImageData;
     2174}
     2175
     2176ExceptionOr<Ref<ImageData>> CanvasRenderingContext2DBase::createImageData(int sw, int sh, Optional<ImageDataSettings> settings) const
    21772177{
    21782178    if (!sw || !sh)
    21792179        return Exception { IndexSizeError };
    21802180
    2181     IntSize size { std::abs(sw), std::abs(sh) };
    2182     return createEmptyImageData(size);
    2183 }
    2184 
    2185 ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2DBase::getImageData(int sx, int sy, int sw, int sh) const
    2186 {
     2181    auto imageData = ImageData::createUninitialized(std::abs(sw), std::abs(sh), m_settings.colorSpace, settings);
     2182    if (!imageData.hasException())
     2183        initializeEmptyImageData(imageData.returnValue());
     2184    return imageData;
     2185}
     2186
     2187ExceptionOr<Ref<ImageData>> CanvasRenderingContext2DBase::getImageData(int sx, int sy, int sw, int sh, Optional<ImageDataSettings> settings) const
     2188{
     2189    if (!sw || !sh)
     2190        return Exception { IndexSizeError };
     2191
    21872192    if (!canvasBase().originClean()) {
    21882193        static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("Unable to get image data from canvas because the canvas has been tainted by cross-origin data."));
     
    21902195        return Exception { SecurityError };
    21912196    }
    2192 
    2193     if (!sw || !sh)
    2194         return Exception { IndexSizeError };
    21952197
    21962198    if (sw < 0) {
     
    22062208
    22072209    ImageBuffer* buffer = canvasBase().buffer();
    2208     if (!buffer)
    2209         return createEmptyImageData(imageDataRect.size());
    2210 
    2211     PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     2210    if (!buffer) {
     2211        auto imageData = ImageData::createUninitialized(imageDataRect.width(), imageDataRect.height(), m_settings.colorSpace, settings);
     2212        if (!imageData.hasException())
     2213            initializeEmptyImageData(imageData.returnValue());
     2214        return imageData;
     2215    }
     2216
     2217    auto computedColorSpace = ImageData::computeColorSpace(settings, m_settings.colorSpace);
     2218
     2219    PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, toDestinationColorSpace(computedColorSpace) };
    22122220    auto pixelBuffer = buffer->getPixelBuffer(format, imageDataRect);
    22132221    if (!pixelBuffer) {
     
    22162224        return Exception { InvalidStateError };
    22172225    }
     2226
     2227    ASSERT(pixelBuffer->format().colorSpace == toDestinationColorSpace(computedColorSpace));
    22182228
    22192229    return { { ImageData::create(WTFMove(*pixelBuffer)) } };
  • trunk/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.h

    r277547 r277569  
    4444#include "GraphicsTypes.h"
    4545#include "ImageBuffer.h"
     46#include "ImageDataSettings.h"
    4647#include "ImageSmoothingQuality.h"
    4748#include "Path.h"
     
    193194    ExceptionOr<RefPtr<CanvasPattern>> createPattern(CanvasImageSource&&, const String& repetition);
    194195
    195     RefPtr<ImageData> createImageData(ImageData&) const;
    196     ExceptionOr<RefPtr<ImageData>> createImageData(int width, int height) const;
    197     ExceptionOr<RefPtr<ImageData>> getImageData(int sx, int sy, int sw, int sh) const;
     196    ExceptionOr<Ref<ImageData>> createImageData(ImageData&) const;
     197    ExceptionOr<Ref<ImageData>> createImageData(int width, int height, Optional<ImageDataSettings>) const;
     198    ExceptionOr<Ref<ImageData>> getImageData(int sx, int sy, int sw, int sh, Optional<ImageDataSettings>) const;
    198199    void putImageData(ImageData&, int dx, int dy);
    199200    void putImageData(ImageData&, int dx, int dy, int dirtyX, int dirtyY, int dirtyWidth, int dirtyHeight);
  • trunk/Source/WebCore/html/canvas/PredefinedColorSpace.cpp

    r277024 r277569  
    2828
    2929#include "ColorSpace.h"
     30#include <wtf/Optional.h>
    3031
    3132namespace WebCore {
     
    4647}
    4748
     49Optional<PredefinedColorSpace> toPredefinedColorSpace(DestinationColorSpace colorSpace)
     50{
     51    switch (colorSpace) {
     52    case DestinationColorSpace::SRGB:
     53        return PredefinedColorSpace::SRGB;
     54#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
     55    case DestinationColorSpace::LinearSRGB:
     56        return WTF::nullopt;
     57#endif
     58#if ENABLE(DESTINATION_COLOR_SPACE_DISPLAY_P3)
     59    case DestinationColorSpace::DisplayP3:
     60        return PredefinedColorSpace::DisplayP3;
     61#endif
     62    }
     63
     64    ASSERT_NOT_REACHED();
     65    return WTF::nullopt;
    4866}
     67
     68}
  • trunk/Source/WebCore/html/canvas/PredefinedColorSpace.h

    r277024 r277569  
    2727
    2828#include <wtf/EnumTraits.h>
     29#include <wtf/Forward.h>
    2930
    3031namespace WebCore {
     
    4041
    4142DestinationColorSpace toDestinationColorSpace(PredefinedColorSpace);
     43Optional<PredefinedColorSpace> toPredefinedColorSpace(DestinationColorSpace);
    4244
    4345}
  • trunk/Source/WebCore/inspector/InspectorCanvas.cpp

    r277237 r277569  
    429429}
    430430
     431Optional<InspectorCanvasCallTracer::ProcessedArgument> InspectorCanvas::processArgument(ImageDataSettings&)
     432{
     433    // FIXME: Implement.
     434    return WTF::nullopt;
     435}
     436
    431437Optional<InspectorCanvasCallTracer::ProcessedArgument> InspectorCanvas::processArgument(ImageSmoothingQuality argument)
    432438{
  • trunk/Source/WebCore/inspector/InspectorCanvasCallTracer.cpp

    r273865 r277569  
    3838#include "HTMLVideoElement.h"
    3939#include "ImageData.h"
     40#include "ImageDataSettings.h"
    4041#include "InspectorCanvasAgent.h"
    4142#include "InspectorInstrumentation.h"
  • trunk/Source/WebCore/inspector/InspectorCanvasCallTracer.h

    r273865 r277569  
    7171class WebGLVertexArrayObject;
    7272struct DOMMatrix2DInit;
     73struct ImageDataSettings;
    7374enum class RecordingSwizzleType : int;
    7475enum class CanvasDirection;
     
    151152    macro(ImageBitmap*) \
    152153    macro(ImageData*) \
     154    macro(ImageDataSettings&) \
    153155    macro(ImageSmoothingQuality) \
    154156    macro(Optional<float>&) \
  • trunk/Source/WebCore/platform/graphics/ImageBufferBackend.cpp

    r277525 r277569  
    117117Optional<PixelBuffer> ImageBufferBackend::getPixelBuffer(const PixelBufferFormat& destinationFormat, const IntRect& sourceRect, void* data) const
    118118{
     119    ASSERT(PixelBuffer::supportedPixelFormat(destinationFormat.pixelFormat));
     120
    119121    auto sourceRectScaled = toBackendCoordinates(sourceRect);
    120122
     
    123125        return WTF::nullopt;
    124126
    125     IntRect sourceRectClipped = intersection(backendRect(), sourceRectScaled);
    126     IntRect destinationRect = { IntPoint::zero(), sourceRectClipped.size() };
     127    auto sourceRectClipped = intersection(backendRect(), sourceRectScaled);
     128    IntRect destinationRect { IntPoint::zero(), sourceRectClipped.size() };
    127129
    128130    if (sourceRectScaled.x() < 0)
     
    135137        pixelBuffer->data().zeroFill();
    136138
    137     unsigned sourceBytesPerRow = bytesPerRow();
    138     const uint8_t* sourceRows = reinterpret_cast<uint8_t*>(data) + sourceRectClipped.y() * sourceBytesPerRow + sourceRectClipped.x() * 4;
    139 
    140     unsigned destinationBytesPerRow = 4 * sourceRectScaled.width();
    141     uint8_t* destinationRows = pixelBuffer->data().data() + destinationRect.y() * destinationBytesPerRow + destinationRect.x() * 4;
    142 
    143     PixelBufferFormat sourceFormat { AlphaPremultiplication::Premultiplied, pixelFormat(), DestinationColorSpace::SRGB };
    144 
    145139    ConstPixelBufferConversionView source;
    146     source.format = sourceFormat;
    147     source.bytesPerRow = sourceBytesPerRow;
    148     source.rows = sourceRows;
     140    source.format = { AlphaPremultiplication::Premultiplied, pixelFormat(), colorSpace() };
     141    source.bytesPerRow = bytesPerRow();
     142    source.rows = reinterpret_cast<uint8_t*>(data) + sourceRectClipped.y() * source.bytesPerRow + sourceRectClipped.x() * 4;
    149143   
    150144    PixelBufferConversionView destination;
    151145    destination.format = destinationFormat;
    152     destination.bytesPerRow = destinationBytesPerRow;
    153     destination.rows = destinationRows;
     146    destination.bytesPerRow = 4 * sourceRectScaled.width();
     147    destination.rows = pixelBuffer->data().data() + destinationRect.y() * destination.bytesPerRow + destinationRect.x() * 4;
    154148
    155149    convertImagePixels(source, destination, destinationRect.size());
     
    160154void ImageBufferBackend::putPixelBuffer(const PixelBuffer& sourcePixelBuffer, const IntRect& sourceRect, const IntPoint& destinationPoint, AlphaPremultiplication destinationAlphaFormat, void* data)
    161155{
    162     // FIXME: Add support for non-RGBA8 pixel formats.
    163     ASSERT(sourcePixelBuffer.format().pixelFormat == PixelFormat::RGBA8);
    164 
    165156    auto sourceRectScaled = toBackendCoordinates(sourceRect);
    166157    auto destinationPointScaled = toBackendCoordinates(destinationPoint);
    167158
    168     IntRect sourceRectClipped = intersection({ IntPoint::zero(), sourcePixelBuffer.size() }, sourceRectScaled);
    169     IntRect destinationRect = sourceRectClipped;
     159    auto sourceRectClipped = intersection({ IntPoint::zero(), sourcePixelBuffer.size() }, sourceRectScaled);
     160    auto destinationRect = sourceRectClipped;
    170161    destinationRect.moveBy(destinationPointScaled);
    171162
     
    179170    sourceRectClipped.setSize(destinationRect.size());
    180171
    181     unsigned sourceBytesPerRow = 4 * sourcePixelBuffer.size().width();
    182     const uint8_t* sourceRows = sourcePixelBuffer.data().data() + sourceRectClipped.y() * sourceBytesPerRow + sourceRectClipped.x() * 4;
     172    ConstPixelBufferConversionView source;
     173    source.format = sourcePixelBuffer.format();
     174    source.bytesPerRow = 4 * sourcePixelBuffer.size().width();
     175    source.rows = sourcePixelBuffer.data().data() + sourceRectClipped.y() * source.bytesPerRow + sourceRectClipped.x() * 4;
    183176
    184     unsigned destinationBytesPerRow = bytesPerRow();
    185     uint8_t* destinationRows = reinterpret_cast<uint8_t*>(data) + destinationRect.y() * destinationBytesPerRow + destinationRect.x() * 4;
    186 
    187     PixelBufferFormat sourceFormat = sourcePixelBuffer.format();
    188     PixelBufferFormat destinationFormat { destinationAlphaFormat, pixelFormat(), DestinationColorSpace::SRGB };
    189 
    190     ConstPixelBufferConversionView source;
    191     source.format = sourceFormat;
    192     source.bytesPerRow = sourceBytesPerRow;
    193     source.rows = sourceRows;
    194    
    195177    PixelBufferConversionView destination;
    196     destination.format = destinationFormat;
    197     destination.bytesPerRow = destinationBytesPerRow;
    198     destination.rows = destinationRows;
     178    destination.format = { destinationAlphaFormat, pixelFormat(), colorSpace() };
     179    destination.bytesPerRow = bytesPerRow();
     180    destination.rows = reinterpret_cast<uint8_t*>(data) + destinationRect.y() * destination.bytesPerRow + destinationRect.x() * 4;
    199181
    200182    convertImagePixels(source, destination, destinationRect.size());
  • trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp

    r277450 r277569  
    3232namespace WebCore {
    3333
     34bool PixelBuffer::supportedPixelFormat(PixelFormat pixelFormat)
     35{
     36    switch (pixelFormat) {
     37    case PixelFormat::RGBA8:
     38    case PixelFormat::BGRA8:
     39        return true;
     40
     41    case PixelFormat::RGB10:
     42    case PixelFormat::RGB10A8:
     43        return false;
     44    }
     45}
     46
    3447Checked<unsigned, RecordOverflow> PixelBuffer::computeBufferSize(const PixelBufferFormat& format, const IntSize& size)
    3548{
    36     // NOTE: Only 8-bit formats are currently supported.
    37     ASSERT_UNUSED(format, format.pixelFormat == PixelFormat::RGBA8 || format.pixelFormat == PixelFormat::BGRA8);
     49    ASSERT_UNUSED(format, supportedPixelFormat(format.pixelFormat));
    3850
    3951    constexpr unsigned bytesPerPixel = 4;
     
    4456Optional<PixelBuffer> PixelBuffer::tryCreateForDecoding(const PixelBufferFormat& format, const IntSize& size, unsigned dataByteLength)
    4557{
    46     ASSERT(format.pixelFormat == PixelFormat::RGBA8 || format.pixelFormat == PixelFormat::BGRA8);
     58    ASSERT(supportedPixelFormat(format.pixelFormat));
    4759    ASSERT(computeBufferSize(format, size).unsafeGet() == dataByteLength);
    4860
     
    5567Optional<PixelBuffer> PixelBuffer::tryCreate(const PixelBufferFormat& format, const IntSize& size)
    5668{
    57     // NOTE: Only 8-bit formats are currently supported.
    58     ASSERT(format.pixelFormat == PixelFormat::RGBA8 || format.pixelFormat == PixelFormat::BGRA8);
     69    ASSERT(supportedPixelFormat(format.pixelFormat));
    5970
    6071    auto bufferSize = computeBufferSize(format, size);
     
    6778}
    6879
     80Optional<PixelBuffer> PixelBuffer::tryCreate(const PixelBufferFormat& format, const IntSize& size, Ref<JSC::ArrayBuffer>&& arrayBuffer)
     81{
     82    ASSERT(supportedPixelFormat(format.pixelFormat));
     83
     84    auto bufferSize = computeBufferSize(format, size);
     85    if (bufferSize.hasOverflowed())
     86        return WTF::nullopt;
     87    if (bufferSize.unsafeGet() != arrayBuffer->byteLength())
     88        return WTF::nullopt;
     89    auto pixelArray = Uint8ClampedArray::tryCreate(WTFMove(arrayBuffer), 0, bufferSize.unsafeGet());
     90    if (!pixelArray)
     91        return WTF::nullopt;
     92    return { { format, size, pixelArray.releaseNonNull() } };
     93}
     94
    6995PixelBuffer::PixelBuffer(const PixelBufferFormat& format, const IntSize& size, Ref<JSC::Uint8ClampedArray>&& data)
    7096    : m_format { format }
    7197    , m_size { size }
    7298    , m_data { WTFMove(data) }
     99{
     100    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION((m_size.area() * 4).unsafeGet() <= m_data->length());
     101}
     102
     103PixelBuffer::PixelBuffer(const PixelBufferFormat& format, const IntSize& size, JSC::Uint8ClampedArray& data)
     104    : m_format { format }
     105    , m_size { size }
     106    , m_data { data }
    73107{
    74108    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION((m_size.area() * 4).unsafeGet() <= m_data->length());
  • trunk/Source/WebCore/platform/graphics/PixelBuffer.h

    r277450 r277569  
    4242    WTF_MAKE_NONCOPYABLE(PixelBuffer);
    4343public:
     44    static bool supportedPixelFormat(PixelFormat);
     45
    4446    WEBCORE_EXPORT static Optional<PixelBuffer> tryCreate(const PixelBufferFormat&, const IntSize&);
     47    WEBCORE_EXPORT static Optional<PixelBuffer> tryCreate(const PixelBufferFormat&, const IntSize&, Ref<JSC::ArrayBuffer>&&);
    4548
    4649    PixelBuffer(const PixelBufferFormat&, const IntSize&, Ref<JSC::Uint8ClampedArray>&&);
     50    PixelBuffer(const PixelBufferFormat&, const IntSize&, JSC::Uint8ClampedArray&);
    4751    WEBCORE_EXPORT ~PixelBuffer();
    4852
     
    5357    const IntSize& size() const { return m_size; }
    5458    JSC::Uint8ClampedArray& data() const { return m_data.get(); }
     59
     60    Ref<JSC::Uint8ClampedArray>&& takeData() { return WTFMove(m_data); }
    5561
    5662    PixelBuffer deepClone() const;
  • trunk/Source/WebCore/platform/graphics/PixelBufferConversion.cpp

    r277525 r277569  
    107107        vImage_Error converterCreateError = kvImageNoError;
    108108        auto converter = adoptCF(vImageConverter_CreateWithCGImageFormat(&sourceCGImageFormat, &destinationCGImageFormat, nullptr, kvImageNoFlags, &converterCreateError));
    109         ASSERT_WITH_MESSAGE_UNUSED(converterCreateError, converterCreateError != kvImageNoError, "vImageConverter creation failed with error: %zd", converterCreateError);
     109        ASSERT_WITH_MESSAGE_UNUSED(converterCreateError, converterCreateError == kvImageNoError, "vImageConverter creation failed with error: %zd", converterCreateError);
    110110
    111111        vImage_Error converterConvertError = vImageConvert_AnyToAny(converter.get(), &sourceVImageBuffer, &destinationVImageBuffer, nullptr, kvImageNoFlags);
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp

    r277525 r277569  
    469469    convertedBuffer->context().drawImageBuffer(inputBuffer, rect);
    470470   
    471     PixelBufferFormat format { outputAlphaFormat, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     471    PixelBufferFormat format { outputAlphaFormat, PixelFormat::RGBA8, targetColorSpace };
    472472    return convertedBuffer->getPixelBuffer(format, rect);
    473473}
     
    505505                return;
    506506            }
    507             PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     507
     508            ASSERT(m_imageBufferResult->colorSpace() == m_resultColorSpace);
     509            PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    508510            m_unmultipliedImageResult = m_imageBufferResult->getPixelBuffer(format, { IntPoint(), m_absolutePaintRect.size() });
    509511            if (!m_unmultipliedImageResult)
     
    513515            ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
    514516            inputSize.scale(m_filter.filterScale());
    515             PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     517           
     518            ASSERT(m_premultipliedImageResult->format().colorSpace == m_resultColorSpace);
     519            PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    516520            m_unmultipliedImageResult = PixelBuffer::tryCreate(format, inputSize);
    517521            if (!m_unmultipliedImageResult)
     
    540544                return;
    541545            }
    542             PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     546
     547            ASSERT(m_imageBufferResult->colorSpace() == m_resultColorSpace);
     548            PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    543549            m_premultipliedImageResult = m_imageBufferResult->getPixelBuffer(format, { IntPoint(), m_absolutePaintRect.size() });
    544550            if (!m_premultipliedImageResult)
     
    548554            ASSERT(!ImageBuffer::sizeNeedsClamping(inputSize));
    549555            inputSize.scale(m_filter.filterScale());
    550             PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     556
     557            ASSERT(m_unmultipliedImageResult->format().colorSpace == m_resultColorSpace);
     558            PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    551559            m_premultipliedImageResult = PixelBuffer::tryCreate(format, inputSize);
    552560            if (!m_premultipliedImageResult)
     
    591599    ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
    592600    resultSize.scale(m_filter.filterScale());
    593     PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     601    PixelBufferFormat format { AlphaPremultiplication::Unpremultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    594602    m_unmultipliedImageResult = PixelBuffer::tryCreate(format, resultSize);
    595603    return m_unmultipliedImageResult;
     
    610618    ASSERT(!ImageBuffer::sizeNeedsClamping(resultSize));
    611619    resultSize.scale(m_filter.filterScale());
    612     PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, DestinationColorSpace::SRGB };
     620    PixelBufferFormat format { AlphaPremultiplication::Premultiplied, PixelFormat::RGBA8, m_resultColorSpace };
    613621    m_premultipliedImageResult = PixelBuffer::tryCreate(format, resultSize);
    614622    return m_premultipliedImageResult;
  • trunk/Source/WebCore/testing/Internals.cpp

    r277530 r277569  
    53325332        return;
    53335333   
    5334     auto imageData = ImageData::create(rgba.releaseNonNull(), videoSettings.width(), videoSettings.height());
     5334    auto imageData = ImageData::create(rgba.releaseNonNull(), videoSettings.width(), videoSettings.height(), { { PredefinedColorSpace::SRGB } });
    53355335    if (!imageData.hasException())
    53365336        m_nextTrackFramePromise->resolve(imageData.releaseReturnValue());
     
    62046204    m_artworkLoader = makeUnique<ArtworkImageLoader>(*contextDocument(), url, [this](Image* image) {
    62056205        if (image) {
    6206             auto imageData = ImageData::create(unsigned(image->width()), unsigned(image->height()));
     6206            auto imageData = ImageData::create(image->width(), image->height(), { { PredefinedColorSpace::SRGB } });
    62076207            if (!imageData.hasException())
    62086208                m_artworkImagePromise->resolve(imageData.releaseReturnValue());
  • trunk/Source/WebKitLegacy/win/ChangeLog

    r277564 r277569  
     12021-05-16  Sam Weinig  <weinig@apple.com>
     2
     3        Add support for creating/accessing/setting non-sRGB ImageData via canvas
     4        https://bugs.webkit.org/show_bug.cgi?id=225841
     5
     6        Reviewed by Darin Adler.
     7
     8        Add support for tests enabling the CanvasColorSpaceEnabled preference.
     9
     10        * WebPreferences.cpp:
     11        (WebPreferences::canvasColorSpaceEnabled):
     12        * WebPreferences.h:
     13        * WebView.cpp:
     14        (WebView::notifyPreferencesChanged):
     15
    1162021-05-15  Ryosuke Niwa  <rniwa@webkit.org>
    217
  • trunk/Source/WebKitLegacy/win/WebPreferences.cpp

    r274810 r277569  
    26322632    return S_OK;
    26332633}
     2634
     2635bool WebPreferences::canvasColorSpaceEnabled()
     2636{
     2637    return boolValueForKey("WebKitCanvasColorSpaceEnabled");
     2638}
     2639
  • trunk/Source/WebKitLegacy/win/WebPreferences.h

    r274810 r277569  
    344344    HRESULT postPreferencesChangesNotification();
    345345
     346    // The following preference accessors are not exposed via IWebPreferences* as they are only
     347    // needed for testing purposes and can be toggled via the set*PreferenceForTesting functions.
     348    bool canvasColorSpaceEnabled();
     349
    346350private:
    347351    WebPreferences();
  • trunk/Source/WebKitLegacy/win/WebView.cpp

    r277564 r277569  
    56685668    settings.setOverscrollBehaviorEnabled(!!enabled);
    56695669
     5670    settings.setCanvasColorSpaceEnabled(m_preferences->canvasColorSpaceEnabled());
     5671
    56705672    return S_OK;
    56715673}
Note: See TracChangeset for help on using the changeset viewer.