summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/canvas/element/manual
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/canvas/element/manual')
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/README.md1
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001-ref.htm22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001.htm26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm32
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001.htm35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow-ref.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm11
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001.htm32
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/canvas-with-padding.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false.html14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false.html18
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/getContextAttributes.html46
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false.html13
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false.html17
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas.html203
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self.html17
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html11
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_crossorigin.sub.html61
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_html_image.html268
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_1.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_with_foreign_object_does_not_taint.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none.tentative.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none.tentative.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height.tentative.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap.tentative.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob-ref.html10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob.tentative.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none.tentative.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none.tentative.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-ref.html12
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height.tentative.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element.tentative.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect-ref.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect.tentative.html25
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm31
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html66
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html68
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html69
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html88
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html88
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math-ref.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm59
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-expected.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation-expected.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-fillStyle-opacity.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle-expected.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur-expected.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur.html29
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-expected.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-globalAlpha.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes-expected.html48
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-expected.html66
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-crash.html14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur-expected.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer-expected.html65
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer.html62
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix-expected.html77
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix.html60
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion-expected.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion.html58
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion-expected.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-sequence-conversion.html55
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/image-smoothing/imagesmoothing.html119
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-ImageBitmap-close.html89
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-resize.html170
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-video-resize.html62
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/common.sub.js168
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-blob-invalidtype.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-bounds.html67
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-colorSpaceConversion.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage-closed.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage.html87
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation.html121
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation_none.html61
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-flipY.html73
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-in-worker-transfer.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-invalid-args.html239
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-origin.sub.html47
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-serializable.html52
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-sizeOverflow.html52
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-transfer.html53
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-worker.js17
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation-expected.html18
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped-expected.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imagebitmap-replication-exif-orientation.html146
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_1.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_2.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_3.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_4.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_5.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_6.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_7.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_8.jpgbin0 -> 1227 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/serialize-worker.js3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/transfer-worker.js3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/imagebitmap/worker-onmessage-noop.js3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers-expected.html14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers.html20
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers-expected.html14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001-ref.htm11
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001.htm37
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_a.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_ref.html15
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/line-styles/setLineDash.html104
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm60
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm34
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html11
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html191
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected-ref.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch-ref.html19
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.condensed.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.expanded.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-condensed.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-expanded.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.normal.html30
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-condensed.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-expanded.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-condensed.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-expanded.html27
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001-ref.htm22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001.htm33
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.state.saverestore.imageSmoothingEnabled.html47
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.zero.size.canvas.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001-ref.htm11
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001.htm42
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/2d.transformation.getTransform.html39
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001-ref.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001-ref.htm11
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001.htm31
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/transform_a.html22
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/transformations/transform_ref.html16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm10
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1.htm14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2.htm15
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm13
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3.htm16
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm14
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4.htm17
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/ImageData-fidelity.html126
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-Blob.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageBitmap.html47
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageData.html46
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-canvas.html53
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-cloned.html70
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-image.html44
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html57
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html52
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage.https.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-canvas.html44
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-image.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-settings.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3.js283
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/imagedata-no-color-settings-crash.html26
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000CC.pngbin0 -> 575 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000FF.pngbin0 -> 562 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000CCCC.pngbin0 -> 560 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000FFFF.pngbin0 -> 554 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000CC.pngbin0 -> 575 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000FF.pngbin0 -> 562 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000CCCC.pngbin0 -> 575 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000FFFF.pngbin0 -> 562 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-0.7333-0-0.svg3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-1-0-0.svg3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000CC.pngbin0 -> 620 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000FF.pngbin0 -> 607 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000CCCC.pngbin0 -> 605 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000FFFF.pngbin0 -> 599 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000CC.pngbin0 -> 620 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000FF.pngbin0 -> 607 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000CCCC.pngbin0 -> 620 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000FFFF.pngbin0 -> 607 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-BE000000.jpgbin0 -> 55590 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-FF000000.jpgbin0 -> 55590 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.mp4bin0 -> 3275 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.webmbin0 -> 604 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.mp4bin0 -> 3275 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.webmbin0 -> 605 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-p3d65.pngbin0 -> 5912 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-rec2020.pngbin0 -> 6136 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-srgb.pngbin0 -> 5319 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.avifbin0 -> 529 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.bmpbin0 -> 1738 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.icobin0 -> 1742 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.pngbin0 -> 5319 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.webpbin0 -> 252 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.avifbin0 -> 330 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.bmpbin0 -> 1738 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.gifbin0 -> 117 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.icobin0 -> 1742 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.jpgbin0 -> 898 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.pngbin0 -> 163 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.svg6
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.webpbin0 -> 208 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.pngbin0 -> 3164 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.pngbin0 -> 3175 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_opaque.pngbin0 -> 3262 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_transparent.pngbin0 -> 3271 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_opaque.pngbin0 -> 3338 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_transparent.pngbin0 -> 3347 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_opaque.pngbin0 -> 3144 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_transparent.pngbin0 -> 3153 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.pngbin0 -> 3165 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.pngbin0 -> 3174 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.pngbin0 -> 3265 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.pngbin0 -> 3272 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.pngbin0 -> 3339 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.pngbin0 -> 3348 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.pngbin0 -> 3147 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.pngbin0 -> 3153 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.pngbin0 -> 2868 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.pngbin0 -> 2876 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_opaque.pngbin0 -> 2867 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_transparent.pngbin0 -> 2672 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.pngbin0 -> 3173 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.pngbin0 -> 3177 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_opaque.pngbin0 -> 3250 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_transparent.pngbin0 -> 3255 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_opaque.pngbin0 -> 3325 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_transparent.pngbin0 -> 3331 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_opaque.pngbin0 -> 3132 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_transparent.pngbin0 -> 3136 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_opaque.pngbin0 -> 2853 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_transparent.pngbin0 -> 2857 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.mp4bin0 -> 1600 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.svg3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.webmbin0 -> 604 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000CC.pngbin0 -> 243 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000FF.pngbin0 -> 230 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000CCCC.pngbin0 -> 228 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000FFFF.pngbin0 -> 222 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000.svg3
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000CC.pngbin0 -> 243 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000FF.pngbin0 -> 230 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.mp4bin0 -> 1600 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.webmbin0 -> 605 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000CCCC.pngbin0 -> 243 bytes
-rw-r--r--testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000FFFF.pngbin0 -> 230 bytes
280 files changed, 7560 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/element/manual/README.md b/testing/web-platform/tests/html/canvas/element/manual/README.md
new file mode 100644
index 0000000000..68d877200b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/README.md
@@ -0,0 +1 @@
+This folder contains tests that were manually added to the repository. All other tests have been autogenerated by html/canvas/tools/build.sh \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001-ref.htm
new file mode 100644
index 0000000000..31ddfcafd9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001-ref.htm
@@ -0,0 +1,22 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: arcTo() adds to subpath if same point</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+ ctx.moveTo(0, 50);
+
+ ctx.lineTo(100, 50);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: If x1,y1 and x2,y2 are the same point, then arcTo must add x1,y1 to the subpath, and connect that point to x0,y0 with a straight line.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas (test ref).</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001.htm b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001.htm
new file mode 100644
index 0000000000..c3f2fb6f43
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_arcto_001.htm
@@ -0,0 +1,26 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: arcTo() adds to subpath if same point</title>
+ <link rel="match" href="canvas_complexshapes_arcto_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-arcto" />
+ <meta name="assert" content="If x1,y1 and x2,y2 are the same point, then arcTo must add x1,y1 to the subpath, and connect that point to x0,y0 with a straight line." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+ ctx.moveTo(0, 50);
+
+ // Since (x1, y1) and (x2, y2) are the same point, (x1, y1) must be added to the subpath, thus creating a line.
+ ctx.arcTo(100, 50, 100, 50, 10);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: If x1,y1 and x2,y2 are the same point, then arcTo must add x1,y1 to the subpath, and connect that point to x0,y0 with a straight line.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm
new file mode 100644
index 0000000000..6be08c0b3c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm
@@ -0,0 +1,32 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: bezierCurveTo() must ensure subpaths</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ ctx.moveTo(65,25)
+ ctx.bezierCurveTo(65, 25, 65, 25, 65, 65);
+ ctx.stroke();
+ ctx.beginPath();
+
+ ctx.moveTo(35,25)
+ ctx.bezierCurveTo(35, 25, 35, 25, 35, 65);
+ ctx.stroke();
+ ctx.beginPath();
+
+ ctx.moveTo(0,75)
+ ctx.bezierCurveTo(0, 75, 50, 150, 100, 75);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) must ensure there is a subpath for the point (cp1x,cp1y) if the context has no subpaths, then it must connect the last point in the subpath to the point (x,y).</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas (ref test).</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001.htm b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001.htm
new file mode 100644
index 0000000000..d04926ebac
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/building-paths/canvas_complexshapes_beziercurveto_001.htm
@@ -0,0 +1,35 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: bezierCurveTo() must ensure subpaths</title>
+ <link rel="match" href="canvas_complexshapes_beziercurveto_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto" />
+ <meta name="assert" content="bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) must ensure there is a subpath for the point (cp1x,cp1y) if the context has no subpaths, then it must connect the last point in the subpath to the point (x,y)." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Since the canvas has no subpaths, a virtual moveTo must be performed to (65,25) before creating the bezier.
+ ctx.bezierCurveTo(65, 25, 65, 25, 65, 65);
+ ctx.stroke();
+ ctx.beginPath();
+
+ // Since the canvas has no subpaths, a virtual moveTo must be performed to (35,25) before creating the bezier.
+ ctx.bezierCurveTo(35, 25, 35, 25, 35, 65);
+ ctx.stroke();
+ ctx.beginPath();
+
+ // Since the canvas has no subpaths, a virtual moveTo must be performed to (0,75) before creating the bezier.
+ ctx.bezierCurveTo(0, 75, 50, 150, 100, 75);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) must ensure there is a subpath for the point (cp1x,cp1y) if the context has no subpaths, then it must connect the last point in the subpath to the point (x,y).</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow-ref.html b/testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow-ref.html
new file mode 100644
index 0000000000..3ff0ed291d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow-ref.html
@@ -0,0 +1,15 @@
+<body>
+<script>
+var canvas, ctx;
+canvas = document.createElement("canvas");
+canvas.width = 100;
+canvas.height = 100;
+document.body.appendChild(canvas);
+
+ctx = canvas.getContext("2d");
+ctx.globalAlpha = 0.5;
+ctx.shadowOffsetX = -canvas.width;
+ctx.shadowColor = 'red';
+ctx.fillRect(canvas.width,0,canvas.width,canvas.height);
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow.html b/testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow.html
new file mode 100644
index 0000000000..1df227ce0b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/compositing/alpha_filter_shadow.html
@@ -0,0 +1,16 @@
+<body>
+<script>
+var canvas, ctx;
+canvas = document.createElement("canvas");
+canvas.width = 100;
+canvas.height = 100;
+document.body.appendChild(canvas);
+
+ctx = canvas.getContext("2d");
+ctx.globalAlpha = 0.5;
+ctx.shadowOffsetX = -canvas.width;
+ctx.shadowColor = 'red';
+ctx.filter = 'sepia(0)';
+ctx.fillRect(canvas.width,0,canvas.width,canvas.height);
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm
new file mode 100644
index 0000000000..70196fb36a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: globalCompositeOperation "destination-over"</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: If the globalCompositeOperation is set to "destination-over", display the destination image wherever the destination image is opaque.</p>
+ <div><img alt='black rectangle' src="/images/black-rectangle.png"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001.htm b/testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001.htm
new file mode 100644
index 0000000000..8d6208eb32
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/compositing/canvas_compositing_globalcompositeoperation_001.htm
@@ -0,0 +1,32 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: globalCompositeOperation "destination-over"</title>
+ <link rel="match" href="canvas_compositing_globalcompositeoperation_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-globalcompositeoperation" />
+ <meta name="assert" content="If the globalCompositeOperation is set to 'destination-over', display the destination image wherever the destination image is opaque." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Source image.
+ ctx.fillStyle = "rgba(0, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Assign the globalCompositeOperation.
+ ctx.globalCompositeOperation = "destination-over";
+
+ // Destination image.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 100, 50);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: If the globalCompositeOperation is set to "destination-over", display the destination image wherever the destination image is opaque.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/canvas-with-padding.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/canvas-with-padding.html
new file mode 100644
index 0000000000..5a93ef680a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/canvas-with-padding.html
@@ -0,0 +1,10 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<canvas id='c' style="padding-right: 4294967292; border-right: 124px solid black;"></canvas>
+<script>
+ test(function(t) {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
+ ctx.getImageData(0, 0, 1, 1);
+ }, '// The test case passes by not crashing.')
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false-ref.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false-ref.html
new file mode 100644
index 0000000000..eccfc4e2cc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, fillRect with semi-transparent color.</title>
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d");
+ctx.fillStyle = 'black';
+ctx.fillRect(-1, -1, 102, 102);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false.html
new file mode 100644
index 0000000000..a328fbf97a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/clearRect_alpha_false.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, clearRect</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/#concept-canvas-alpha">
+<link rel="match" href="clearRect_alpha_false-ref.html">
+<meta name="assert" content="Canvas pixels remain opaque black when drawing semi-transparent rectangle.">
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d", {alpha: false});
+ctx.fillColor = 'red';
+ctx.fillRect(25, 25, 50, 25);
+ctx.clearRect(24, 24, 52, 52);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false-ref.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false-ref.html
new file mode 100644
index 0000000000..2c9e5620b2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, drawing a transparent image.</title>
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d");
+ctx.fillStyle = 'black';
+ctx.fillRect(-1, -1, 102, 102);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false.html
new file mode 100644
index 0000000000..64f38bceb1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/drawImage_alpha_false.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, drawing a transparent image</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/#concept-canvas-alpha">
+<link rel="match" href="drawImage_alpha_false-ref.html">
+<meta name="assert" content="Canvas pixels remain opaque black when drawing a transparent image.">
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const source = document.createElement('canvas');
+source.width = source.height = 20;
+const source_ctx = source.getContext("2d"); // leave default transparent content
+
+const ctx = document.getElementById("c").getContext("2d", {alpha: false});
+ctx.globalCompositOperation = 'copy';
+ctx.drawImage(source, 0, 0);
+ctx.globalCompositOperation = 'source-over';
+ctx.drawImage(source, 20, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false-ref.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false-ref.html
new file mode 100644
index 0000000000..eccfc4e2cc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, fillRect with semi-transparent color.</title>
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d");
+ctx.fillStyle = 'black';
+ctx.fillRect(-1, -1, 102, 102);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false.html
new file mode 100644
index 0000000000..143756eb0c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fillRect_alpha_false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, fillRect with semi-transparent color.</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/#concept-canvas-alpha">
+<link rel="match" href="fillRect_alpha_false-ref.html">
+<meta name="assert" content="Canvas pixels remain opaque black when drawing semi-transparent rectangle.">
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d", {alpha: false});
+ctx.fillColor = "rgba(0, 0, 0, 0.5)";
+ctx.fillRect(25, 25, 50, 50);
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false-ref.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false-ref.html
new file mode 100644
index 0000000000..03265a656e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, path fill with transparent color and 'copy' composite operation.</title>
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d");
+ctx.fillStyle = 'black';
+ctx.fillRect(-1, -1, 102, 102);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false.html
new file mode 100644
index 0000000000..7872a79380
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/fill_alpha_false.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase, path fill with transparent color and 'copy' composite operation.</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/#concept-canvas-alpha">
+<link rel="match" href="fill_alpha_false-ref.html">
+<meta name="assert" content="Canvas pixels remain opaque black when filling path with tranparent pixels and 'copy' compisite op.">
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d", {alpha: false});
+ctx.fillColor = 'red';
+ctx.fillRect(25, 25, 50, 25); // will be overwritten.
+ctx.fillColor = "rgba(0, 0, 0, 0.0)";
+ctx.globalCompositeOperation = 'copy';
+ctx.rect(25, 25, 50, 50);
+ctx.fill();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/getContextAttributes.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/getContextAttributes.html
new file mode 100644
index 0000000000..47b3d96233
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/getContextAttributes.html
@@ -0,0 +1,46 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+
+var testScenarios = [
+ {testDescription: "Test default context creation attributes",
+ canvasContextAttributes: {},
+ expectedContextAttributes: {alpha: true, desynchronized: false, willReadFrequently: false}},
+ {testDescription: "Test context creation attributes alpha: true",
+ canvasContextAttributes: {alpha: true},
+ expectedContextAttributes: {alpha: true}},
+ {testDescription: "Test context creation attributes alpha: false",
+ canvasContextAttributes: {alpha: false},
+ expectedContextAttributes: {alpha: false}},
+ {testDescription: "Test context creation attributes desynchronized: false",
+ canvasContextAttributes: {desynchronized: false},
+ expectedContextAttributes: {desynchronized: false}},
+ {testDescription: "Test context creation attributes willReadFrequently: true",
+ canvasContextAttributes: {willReadFrequently: true},
+ expectedContextAttributes: {willReadFrequently: true}},
+];
+
+function runTestScenario(testScenario) {
+ var t = test(function() {
+ var canvas = document. createElement('canvas');
+ var ctx = canvas.getContext('2d', testScenario.canvasContextAttributes);
+ var contextAttributes = ctx.getContextAttributes();
+ if (testScenario.expectedContextAttributes.alpha !== undefined) {
+ assert_equals(contextAttributes.alpha,
+ testScenario.expectedContextAttributes.alpha);
+ }
+ if (testScenario.expectedContextAttributes.desynchronized !== undefined) {
+ assert_equals(contextAttributes.desynchronized,
+ testScenario.expectedContextAttributes.desynchronized);
+ }
+ }, testScenario.testDescription);
+}
+
+function runAllTests() {
+ for (var i = 0; i < testScenarios.length; i++)
+ runTestScenario(testScenarios[i]);
+}
+
+runAllTests();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false-ref.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false-ref.html
new file mode 100644
index 0000000000..b67513c464
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase context creation parameter is initialized with solid black.</title>
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d");
+ctx.fillStyle = 'black';
+ctx.fillRect(-1, -1, 102, 102);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false.html
new file mode 100644
index 0000000000..9e86e5ce2c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/initial_color_alpha_false.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase context creation parameter is initialized with solid black.</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/#concept-canvas-alpha">
+<link rel="match" href="initial_color_alpha_false-ref.html">
+<meta name="assert" content="Canvas pixels are initialized to opaque black when alpha attribute is false.">
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+document.getElementById("c").getContext("2d", {alpha: false});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false-ref.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false-ref.html
new file mode 100644
index 0000000000..d663131148
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase context creation parameter is re-initialized with solid black.</title>
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const ctx = document.getElementById("c").getContext("2d");
+ctx.fillStyle = 'black';
+ctx.fillRect(-1, -1, 102, 102);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false.html b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false.html
new file mode 100644
index 0000000000..191975e0f4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/context-attributes/reset_color_alpha_false.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext 2D with alpha=flase context creation parameter is re-initialized with solid black.</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/#concept-canvas-alpha">
+<link rel="match" href="reset_color_alpha_false-ref.html">
+<meta name="assert" content="Canvas pixels are re-initialized to opaque black upon context reset.">
+<p>Test passes if a 100x100 black square is displayed below.</p>
+<canvas id="c" width=100 height=100></canvas>
+<script>
+const canvas = document.getElementById("c");
+const ctx = canvas.getContext("2d", {alpha: false});
+ctx.fillColor = 'red';
+ctx.fillRect(25, 25, 50, 50);
+canvas.width = canvas.width;
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas.html
new file mode 100644
index 0000000000..36bd085136
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas.html
@@ -0,0 +1,203 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<canvas id="dest" height="100" width="100"></canvas>
+
+<script>
+var sourceCanvasWidth = sourceCanvasHeight = 50;
+var destCanvasWidth = destCanvasHeight = 100;
+var blueRect = {x: 0, y: 0, w: 50, h: 50};
+var blackRect = {x: 5, y: 5, w: 40, h: 40};
+var redPixel = [255, 0, 0, 255];
+var bluePixel = [0, 0, 255, 255];
+var blackPixel = [0, 0, 0, 255];
+var transparentBlackPixel = [0, 0, 0, 0];
+
+var destCanvas = document.getElementById('dest');
+var destCtx = destCanvas.getContext('2d');
+destCtx.imageSmoothingEnabled = false;
+
+function checkPixel(location, expected) {
+ var actual = destCtx.getImageData(location[0], location[1], 1, 1).data;
+ assert_array_equals(actual, expected);
+}
+
+function PreparePixelTests(blueCheck, blackCheck, redCheck, testDescription) {
+ var pixelTests = [];
+ for (var i = 0; i < blueCheck.length; i++) {
+ var message = testDescription + 'Pixel ' + blueCheck[i][0] + ',' + blueCheck[i][1] + ' should be blue.';
+ pixelTests.push([message, blueCheck[i], bluePixel]);
+ }
+ for (var i = 0; i < blackCheck.length; i++) {
+ var message = testDescription + 'Pixel ' + blackCheck[i][0] + ',' + blackCheck[i][1] + ' should be black.';
+ pixelTests.push([message, blackCheck[i], blackPixel]);
+ }
+ for (var i = 0; i < redCheck.length; i++) {
+ var message = testDescription + 'Pixel ' + redCheck[i][0] + ',' + redCheck[i][1] + ' should be red.';
+ pixelTests.push([message, redCheck[i], redPixel]);
+ }
+ pixelTests.push([testDescription + 'Pixel outside canvas should be transparent black.\n', [100, 100], transparentBlackPixel]);
+ return pixelTests;
+}
+
+function drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription) {
+ destCtx.fillStyle = 'red';
+ destCtx.fillRect(0, 0, destCanvasWidth, destCanvasHeight);
+
+ var sourceCanvas = document.createElement('canvas');
+ sourceCanvas.width = sourceCanvasWidth;
+ sourceCanvas.height = sourceCanvasHeight;
+ var sourceCtx = sourceCanvas.getContext('2d');
+ sourceCtx.fillStyle = 'blue';
+ sourceCtx.fillRect(blueRect.x, blueRect.y, blueRect.w, blueRect.h);
+ sourceCtx.fillStyle = 'black';
+ sourceCtx.fillRect(blackRect.x, blackRect.y, blackRect.w, blackRect.h);
+ if (typeof sourceRect.x !== 'undefined')
+ destCtx.drawImage(sourceCanvas, sourceRect.x, sourceRect.y, sourceRect.w, sourceRect.h,
+ destRect.x, destRect.y, destRect.w, destRect.h);
+ else if (typeof destRect.w !== 'undefined')
+ destCtx.drawImage(sourceCanvas, destRect.x, destRect.y, destRect.w, destRect.h);
+ else
+ destCtx.drawImage(sourceCanvas, destRect.x, destRect.y);
+ var pixelTests = PreparePixelTests(blueCheck, blackCheck, redCheck, testDescription);
+ generate_tests(checkPixel, pixelTests);
+}
+
+var testDescription;
+var sourceRect = {}, destRect = {};
+var blueCheck, blackCheck, redCheck;
+
+// 2 arguments, the dest origin is 0,0
+// The source canvas will be copied to the 0,0 position of the destination canvas
+testDescription = 'Test scenario 1: dx = 0, dy = 0 --- ';
+destRect = {x: 0, y: 0};
+blueCheck = [[0,0], [0,49], [49,0], [49,49]];
+blackCheck = [[5,5], [5,44], [44,5], [44,44]];
+redCheck = [[50,0], [0,50], [50,50], [99,99]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// 2 arguments, the dest origin is not 0,0
+// The source canvas will copied to the 25, 25 position of the destination canvas
+testDescription = 'Test scenario 2: dx = 25, dy = 25 --- ';
+destRect = {x: 25, y: 25};
+blueCheck = [[25,25], [25,74], [74,25], [74,74]];
+blackCheck = [[30,30], [30,69], [69,30], [69,69]];
+redCheck = [[24,24], [24,75], [75,24], [75,75]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// 4 arguments, the source origin is not 0,0, the dest size is provided
+// The source canvas will copied to the 50, 50 position of the destination canvas and
+// on an area of 50x50 pixels
+testDescription = 'Test scenario 3: dx = 50, dy = 50, dw = 50, dh = 50 --- ';
+destRect = {x: 50, y: 50, w: 50, h: 50};
+blueCheck = [[50,50], [50,99], [99,50], [99,99]];
+blackCheck = [[55,55], [55,94], [94,55], [94,94]];
+redCheck = [[0,0], [49,49], [49,99], [99,49]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// 4 arguments, the dest origin is not 0,0 and the dest size is provided but
+// does not match the size of the source. The image will be distorted
+// The source canvas will copied to the 50,50 position of the destination canvas
+// and it will be shrunk to a and area of 20x20
+testDescription = 'Test scenario 4: dx = 50, dy = 50, dw = 20, dh = 20 --- ';
+destRect = {x: 50, y: 50, w: 20, h: 20};
+blueCheck = [[50,50], [50,69], [69,50], [69,69]];
+blackCheck = [[52,52], [52,67], [67,52], [67,67]];
+redCheck = [[49,49], [49,70], [70,49], [70,70]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// The source canvas will copied to the 50,50 position of the destination canvas
+// over an area of 50x25 pixels
+// The copied image will be distorted along the x axis
+testDescription = 'Test scenario 5: dx = 50, dy = 50, dw = 50, dh = 20 --- ';
+destRect = {x: 50, y: 50, w: 50, h: 20};
+blueCheck = [[50,50], [50,69], [99,50], [99,69]];
+blackCheck = [[55,52], [55,67], [94,52], [94,67]];
+redCheck = [[49,49], [49, 69], [99,49], [99,70]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// 8 arguments, both destination and source origins are 0, 0
+// An area of 25x25 pixels of the source image will be copied to
+// an area of 25x25 pixels of the destination canvas
+// destCtx.drawImage(sourceCanvas, 0, 0, 25, 25, 0, 0, 25, 25);
+testDescription = 'Test scenario 6: sx = 0, sy = 0, sw = 25, sh = 25, dx = 0, dy = 0, dw = 25, dh = 25 --- ';
+sourceRect = {x: 0, y: 0, w: 25, h: 25};
+destRect = {x: 0, y: 0, w: 25, h: 25};
+blueCheck = [[0,0], [4,4], [0,24], [24,0]];
+blackCheck = [[5,5], [5,24], [24,5], [24,24]];
+redCheck = [[25,25], [25, 99], [99,25], [99,99]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// 8 arguments the destination origin is not 0,0
+// An area of 25x25 pixels of the source image will be copied to
+// an area of 25x25 pixels of the destination canvas in the position 25,25
+testDescription = 'Test scenario 7: sx = 0, sy = 0, sw = 25, sh = 25, dx = 25, dy = 25, dw = 25, dh = 25 --- ';
+sourceRect = {x: 0, y: 0, w: 25, h: 25};
+destRect = {x: 25, y: 25, w: 25, h: 25};
+blueCheck = [[25,25], [25,49], [49,25], [29,29]];
+blackCheck = [[30,30], [30,49], [49,30], [49,49]];
+redCheck = [[24,24], [24, 50], [50,24], [50,50]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// The source rectangle overflows the source image
+// The source area is clipped to fit the source image
+// and the destination are is clipped in the same proportion
+testDescription = 'Test scenario 8: sx = 25, sy = 25, sw = 50, sh = 50, dx = 0, dy = 0, dw = 50, dh = 50 --- ';
+sourceRect = {x: 25, y: 25, w: 50, h: 50};
+destRect = {x: 0, y: 0, w: 50, h: 50};
+blueCheck = [[0,20], [20,0], [20,20], [24,24]];
+blackCheck = [[0,0], [0,19], [19,0], [19,19]];
+redCheck = [[0,25], [25, 0], [25,25], [99,99]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// The destination rectangle has negative width and height. When the source
+// rectangle is outside the source image, the source rectangle must be clipped
+// to the source image and the destination rectangle must be clipped in the same
+// proportion.
+testDescription = 'Test scenario 9: sx = 0, sy = 0, sw = 50, sh = 50, dx = 100, dy = 100, dw = -50, dh = -50 --- ';
+sourceRect = {x: 0, y: 0, w: 50, h: 50};
+destRect = {x: 100, y: 100, w: -50, h: -50};
+blueCheck = [[50,50], [50,99], [99,50], [99,99]];
+blackCheck = [[55,55], [55,94], [94,55], [94,94]];
+redCheck = [[0,0], [49,49], [0,99], [99,0]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// The destination rectangle is larger than the destination canvas
+// When the destination rectangle is outside the destination image (the scratch bitmap),
+// the pixels that land outside the scratch bitmap are discarded,
+// as if the destination was an infinite canvas whose rendering was
+// clipped to the dimensions of the scratch bitmap.
+testDescription = 'Test scenario 10: sx = 0, sy = 0, sw = 50, sh = 50, dx = 0, dy = 0, dw = 200, dh = 200 --- ';
+sourceRect = {x: 0, y: 0, w: 50, h: 50};
+destRect = {x: 0, y: 0, w: 200, h: 200};
+blueCheck = [[0,0], [0,99], [99,0], [19,19]];
+blackCheck = [[20,20], [20,99], [99,20], [99,99]];
+redCheck = [];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// The source rectangle is larger than the source canvas
+// The source area is clipped to fit the source image
+// and the destination are is clipped in the same proportion
+testDescription = 'Test scenario 11: sx = 0, sy = 0, sw = 100, sh = 100, dx = 0, dy = 0, dw = 50, dh = 50 --- ';
+sourceRect = {x: 0, y: 0, w: 100, h: 100};
+destRect = {x: 0, y: 0, w: 50, h: 50};
+blueCheck = [[0,0], [1,1], [23,23], [24,24]];
+blackCheck = [[3,3], [3,21], [21,3], [21,21]];
+redCheck = [[0,25], [25, 0], [25,25], [99,99]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+// Negative coordinates of the source rectangle.
+// The source area is clipped to fit the source image and the destination area
+// is clipped in the same proportion. In this specific test:
+// - source is clipped by 20 from top and left.
+// - destination will get proportionally clipped by 50 from top and left as we
+// are scaling the source image 2.5 times.
+// - the rect will be drawn from 70,70 to 100,100.
+testDescription = 'Test scenario 12: sx = -20, sy = -20, sw = 50, sh = 50, dx = 20, dy = 20, dw = 125, dh = 125 --- ';
+sourceRect = {x: -20, y: -20, w: 50, h: 50};
+destRect = {x: 20, y: 20, w: 125, h: 125};
+blueCheck = [[70,70], [70,99], [99,70], [82,82]];
+blackCheck = [[84,84], [84,99], [99,84], [99,99]];
+redCheck = [[0,69], [69, 0], [69,69]];
+drawCanvasOnCanvasUsingDrawImage(sourceRect, destRect, blueCheck, blackCheck, redCheck, testDescription);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self.html
new file mode 100644
index 0000000000..83cf53583c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self.html
@@ -0,0 +1,17 @@
+<link rel="match" href="drawimage_canvas_self_ref.html">
+<canvas id="dest" height="100" width="100"></canvas>
+<script>
+var canvasWidth = canvasHeight = 100;
+var destWidth = canvasWidth / 4;
+var destHeight = canvasHeight / 4;
+var destCanvas = document.getElementById('dest');
+var destCtx = destCanvas.getContext('2d');
+
+destCtx.fillStyle = 'red';
+destCtx.fillRect(0, 0, canvasWidth, canvasHeight);
+destCtx.fillStyle = 'green';
+destCtx.fillRect(0, 0, canvasWidth / 2, canvasHeight / 2);
+destCtx.drawImage(destCanvas,
+ 0, 0, destWidth, destHeight,
+ canvasWidth / 2, canvasHeight / 2, destWidth, destHeight);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html
new file mode 100644
index 0000000000..9f297cacdc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_canvas_self_ref.html
@@ -0,0 +1,11 @@
+<canvas id="dest" height="100" width="100"></canvas>
+<script>
+var canvasWidth = canvasHeight = 100;
+var destCanvas = document.getElementById('dest');
+var destCtx = destCanvas.getContext('2d');
+destCtx.fillStyle = 'red';
+destCtx.fillRect(0, 0, canvasWidth, canvasHeight);
+destCtx.fillStyle = 'green';
+destCtx.fillRect(0, 0, canvasWidth / 2, canvasHeight / 2);
+destCtx.fillRect(canvasWidth / 2, canvasHeight / 2, canvasWidth / 4, canvasHeight / 4);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_crossorigin.sub.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_crossorigin.sub.html
new file mode 100644
index 0000000000..3d57d9f064
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_crossorigin.sub.html
@@ -0,0 +1,61 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ function draw_and_read_image(img, should_throw) {
+ let c = document.createElement('canvas');
+ document.body.appendChild(c);
+ let ctx = c.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+
+ function get_image_data() {
+ ctx.getImageData(0, 0, 4, 4);
+ }
+
+ if (should_throw) {
+ assert_throws_dom('SecurityError', get_image_data);
+ } else {
+ get_image_data();
+ }
+
+ document.body.removeChild(c);
+ }
+
+ async_test(t => {
+ let img = new Image();
+ img.src = "/images/green.png";
+ img.crossOrigin = "anonymous";
+ img.onload = t.step_func_done(() => {
+ draw_and_read_image(img, false);
+ });
+ img.onerror = t.unreached_func();
+ }, "Can get pixels of canvas with same origin image drawn");
+
+ async_test(t => {
+ let img = new Image();
+ img.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/images/green.png?pipe=header(Access-Control-Allow-Origin,*)";
+ img.crossOrigin = "anonymous";
+ img.onload = t.step_func_done(() => {
+ draw_and_read_image(img, false);
+ });
+ img.onerror = t.unreached_func();
+ }, "Can get pixels of canvas with CORS enabled cross origin image drawn");
+
+ async_test(t => {
+ let img = new Image();
+ img.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/images/green.png?pipe=header(Access-Control-Allow-Origin,*)";
+ img.onload = t.step_func_done(() => {
+ draw_and_read_image(img, true);
+ });
+ img.onerror = t.unreached_func();
+ }, "Can't get pixels of canvas with CORS enabled cross origin image drawn from non-CORS element");
+
+ async_test(t => {
+ let img = new Image();
+ img.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/images/green.png";
+
+ img.onload = t.step_func_done(() => {
+ draw_and_read_image(img, true);
+ });
+ img.onerror = t.unreached_func();
+ }, "Can't get pixels of canvas with non-CORS enabled cross origin image drawn");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_html_image.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_html_image.html
new file mode 100644
index 0000000000..59a7d64465
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_html_image.html
@@ -0,0 +1,268 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<canvas id="dest" height="100" width="100"></canvas>
+
+<script>
+var sourceWidth = sourceHeight = 100;
+var destCanvasWidth = destCanvasHeight = 100;
+var redPixel = [255, 0, 0, 255];
+var lightPixel = [253, 140, 245, 255];
+var grayPixel = [41, 122, 115, 255];
+var transparentBlackPixel = [0, 0, 0, 0];
+
+var destCanvas = document.getElementById('dest');
+var sourceImg = document.createElement('img');
+sourceImg.src = '/html/canvas/resources/2x2.png';
+sourceImg.width = sourceWidth;
+sourceImg.height = sourceHeight;
+var destCtx = destCanvas.getContext('2d');
+destCtx.imageSmoothingEnabled = false;
+
+function checkPixel(location, expected) {
+ var actual = destCtx.getImageData(location[0], location[1], 1, 1).data;
+ assert_array_equals(actual, expected);
+}
+
+function PreparePixelTests(lightPixelCheck, grayPixelCheck, redCheck, testDescription) {
+ var pixelTests = [];
+ for (var i = 0; i < lightPixelCheck.length; i++) {
+ var message = testDescription + 'Pixel ' + lightPixelCheck[i][0] + ',' + lightPixelCheck[i][1] + ' should be light purple.';
+ pixelTests.push([message, lightPixelCheck[i], lightPixel]);
+ }
+ for (var i = 0; i < grayPixelCheck.length; i++) {
+ var message = testDescription + 'Pixel ' + grayPixelCheck[i][0] + ',' + grayPixelCheck[i][1] + ' should be gray.';
+ pixelTests.push([message, grayPixelCheck[i], grayPixel]);
+ }
+ for (var i = 0; i < redCheck.length; i++) {
+ var message = testDescription + 'Pixel ' + redCheck[i][0] + ',' + redCheck[i][1] + ' should be red.';
+ pixelTests.push([message, redCheck[i], redPixel]);
+ }
+ pixelTests.push([testDescription + 'Pixel outside canvas should be transparent black.\n', [100, 100], transparentBlackPixel]);
+ return pixelTests;
+}
+
+function drawCustomImageOnCanvas(sourceImage, sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription) {
+ destCtx.fillStyle = 'red';
+ destCtx.fillRect(0, 0, destCanvasWidth, destCanvasHeight);
+ if (typeof sourceRect.x !== 'undefined')
+ destCtx.drawImage(sourceImage, sourceRect.x, sourceRect.y, sourceRect.w, sourceRect.h,
+ destRect.x, destRect.y, destRect.w, destRect.h);
+ else if (typeof destRect.w !== 'undefined')
+ destCtx.drawImage(sourceImage, destRect.x, destRect.y, destRect.w, destRect.h);
+ else
+ destCtx.drawImage(sourceImage, destRect.x, destRect.y);
+ var pixelTests = PreparePixelTests(lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+ generate_tests(checkPixel, pixelTests);
+}
+
+function drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription) {
+ drawCustomImageOnCanvas(sourceImg, sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+var testDescription;
+var sourceRect = {}, destRect = {};
+var lightPixelCheck, grayPixelCheck, redCheck;
+
+// 2 arguments, the dest origin is 0,0
+// The source image will copied to the 0,0 position of the destination canvas
+function runDrawImageTest_dX0_dY0() {
+ testDescription = 'Test scenario 1: dx = 0, dy = 0 --- ';
+ destRect = {x: 0, y: 0};
+ lightPixelCheck = [[0,0], [0,99], [99,0], [99,99]];
+ grayPixelCheck = [];
+ redCheck = [];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// 2 arguments, the dest origin is not 0,0
+// The source canvas will copied to the 25,25 position of the destination canvas
+function runDrawImageTest_dX25_dY25() {
+ testDescription = 'Test scenario 2: dx = 25, dy = 25 --- ';
+ destRect = {x: 25, y: 25};
+ lightPixelCheck = [[25,25], [25,99], [99,25], [99,99]];
+ grayPixelCheck = [];
+ redCheck = [[0,0], [24,24], [0,25], [25,0], [0,99], [99,0]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// 4 arguments, the source origin is not 0,0, the dest size is provided
+// The source canvas will copied to the 50, 50 position of the destination canvas and
+// on an area of 50x50 pixels
+function runDrawImageTest_dX50_dY50_dW50_dH50() {
+ testDescription = 'Test scenario 3: dx = 50, dy = 50, dw = 50, dh = 50 --- ';
+ destRect = {x: 50, y: 50, w: 50, h: 50};
+ lightPixelCheck = [[50,50], [99,99]];
+ grayPixelCheck = [[50,99], [99,50]];
+ redCheck = [[0,0], [49,49], [0,50], [50,0], [0,99], [99,0]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// 4 arguments, the dest origin is not 0,0 and the dest size is provided but
+// does not match the size of the source. The image will be distorted
+// The source canvas will copied to the 50,50 position of the destination canvas
+// and it will be shrunk to a and area of 16x16
+function runDrawImageTest_dX50_dY50_dW16_dH16() {
+ testDescription = 'Test scenario 4: dx = 50, dy = 50, dw = 16, dh = 16 --- ';
+ destRect = {x: 50, y: 50, w: 16, h: 16};
+ lightPixelCheck = [[50,50], [65,65]];
+ grayPixelCheck = [[50,65], [65,50]];
+ redCheck = [[0,0], [49,49], [49,66], [66,49], [66,66], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// The source canvas will copied to the 50,50 position of the destination canvas
+// over an area of 64x32 pixels
+// The copied image will be distorted along the x axis
+function runDrawImageTest_dX50_dY50_dW64_dH32() {
+ testDescription = 'Test scenario 5: dx = 50, dy = 50, dw = 64, dh = 32 --- ';
+ destRect = {x: 50, y: 50, w: 64, h: 32};
+ lightPixelCheck = [[50,50], [99,81]];
+ grayPixelCheck = [[50,81], [99,50]];
+ redCheck = [[0,0], [49,49], [49,82], [99,49], [99,82], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// 8 arguments, both destination and source origins are 0, 0
+// An area of 32x32 pixels of the source image will be copied to
+// an area of 32x32 pixels of the destination canvas
+function runDrawImageTest_sX0_sY0_sW32_sH32_dX0_dY0_dW32_dH32() {
+ testDescription = 'Test scenario 6: sx = 0, sy = 0, sw = 32, sh = 32, dx = 0, dy = 0, dw = 32, dh = 32 --- ';
+ sourceRect = {x: 0, y: 0, w: 32, h: 32};
+ destRect = {x: 0, y: 0, w: 32, h: 32};
+ lightPixelCheck = [[0,0], [0,31], [31,0], [31,31]];
+ grayPixelCheck = [];
+ redCheck = [[0,32], [32,0], [32,32], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// 8 arguments the destination origin is not 0,0
+// An area of 32x32 pixels of the source image will be copied to
+// an area of 32x32 pixels of the destination canvas in the position 32,32
+function runDrawImageTest_sX0_sY0_sW32_sH32_dX32_dY32_dW32_dH32() {
+ testDescription = 'Test scenario 7: sx = 0, sy = 0, sw = 32, sh = 32, dx = 32, dy = 32, dw = 32, dh = 32 --- ';
+ sourceRect = {x: 0, y: 0, w: 32, h: 32};
+ destRect = {x: 32, y: 32, w: 32, h: 32};
+ lightPixelCheck = [[32,32], [32,63], [63,32], [63,63]];
+ grayPixelCheck = [];
+ redCheck = [[0,0], [31,31], [31,64], [64,31], [64,64], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// The source rectangle overflows the source image
+// The source area is clipped to fit the source image
+// and the destination are is clipped in the same proportion
+function runDrawImageTest_sX32_sY32_sW32_sH32_dX0_dY0_dW32_dH32() {
+ testDescription = 'Test scenario 8: sx = 32, sy = 32, sw = 32, sh = 32, dx = 0, dy = 0, dw = 32, dh = 32 --- ';
+ sourceRect = {x: 32, y: 32, w: 32, h: 32};
+ destRect = {x: 0, y: 0, w: 32, h: 32};
+ lightPixelCheck = [[0,0], [0,31], [31,0], [31,31]];
+ grayPixelCheck = [];
+ redCheck = [[0,32], [32,0], [32,32], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// The destination rectangle has negative width and height. When the source
+// rectangle is outside the source image, the source rectangle must be clipped
+// to the source image and the destination rectangle must be clipped in the same
+// proportion.
+function runDrawImageTest_sX0_sY0_sW32_sH32_dX32_dY32_dWm32_dHm32() {
+ testDescription = 'Test scenario 9: sx = 32, sy = 32, sw = 32, sh = 32, dx = 32, dy = 32, dw = -32, dh = -32 --- ';
+ sourceRect = {x: 32, y: 32, w: 32, h: 32};
+ destRect = {x: 0, y: 0, w: 32, h: 32};
+ lightPixelCheck = [[0,0], [0,31], [31,0], [31,31]];
+ grayPixelCheck = [];
+ redCheck = [[0,32], [32,0], [32,32], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// The destination rectangle is larger than the destination canvas.
+// When the destination rectangle is outside the destination image (the scratch bitmap),
+// the pixels that land outside the scratch bitmap are discarded,
+// as if the destination was an infinite canvas
+// whose rendering was clipped to the dimensions of the scratch bitmap.
+function runDrawImageTest_sX0_sY0_sW512_sH512_dX0_dY0_dW256_dH256() {
+ testDescription = 'Test scenario 10: sx = 0, sy = 0, sw = 512, sh = 512, dx = 0, dy = 0, dw = 256, dh = 256 --- ';
+ sourceRect = {x: 0, y: 0, w: 512, h: 512};
+ destRect = {x: 0, y: 0, w: 256, h: 256};
+ lightPixelCheck = [[0,0], [0,99], [99,0], [99,99]];
+ grayPixelCheck = [];
+ redCheck = [];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// The source rectangle is larger than the source canvas
+// The source area is clipped to fit the source image
+// and the destination area is clipped in the same proportion
+function runDrawImageTest_sX0_sY0_sW2048_sH2048_dX0_dY0_dW800_dH800() {
+ testDescription = 'Test scenario 11: sx = 0, sy = 0, sw = 2048, sh = 2048, dx = 0, dy = 0, dw = 800, dh = 800 --- ';
+ sourceRect = {x: 0, y: 0, w: 2048, h: 2048};
+ destRect = {x: 0, y: 0, w: 800, h: 800};
+ lightPixelCheck = [[0,0], [0,99], [99,0], [99,99]];
+ grayPixelCheck = [];
+ redCheck = [];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// Negative coordinates of the source rectangle
+// The source area is clipped to fit the source image
+// and the destination area is clipped in the same proportion
+function runDrawImageTest_sXm20_sYm20_sW50_sH50_dX20_dY20_dW125_dH125() {
+ testDescription = 'Test scenario 12: sx = -20, sy = -20, sw = 50, sh = 50, dx = 20, dy = 20, dw = 125, dh = 125 --- ';
+ sourceRect = {x: -20, y: -20, w: 50, h: 50};
+ destRect = {x: 20, y: 20, w: 125, h: 125};
+ lightPixelCheck = [[70,70], [70,99], [99,70], [99,99]];
+ grayPixelCheck = [];
+ redCheck = [[0,0], [0,99], [99,0], [69,69], [69, 99], [99,69]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// The source Image doesn't have a src url defined.
+// No exception is thrown and nothing is drawn.
+function runDrawImageTestImageWithuotSource() {
+ testDescription = 'Test scenario 13: draw an image element that does not have a source --- ';
+ var sourceImage = document.createElement('img');
+ sourceRect = {x: 0, y: 0, w: 50, h: 50};
+ destRect = {x: 0, y: 0, w: 100, h: 100};
+ lightPixelCheck = [];
+ grayPixelCheck = [];
+ redCheck = [[0,0], [0,99], [99,0], [99,69]];
+ drawCustomImageOnCanvas(sourceImage, sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+// Clipping the source and down scaling to the destination
+function runDrawImageTest_sX64_sY64_sW384_sH384_dX0_dY0_dW32_dH64() {
+ testDescription = 'Test scenario 14: sx = 64, sy = 64, sw = 384, sh = 384, dx = 0, dy = 0, dw = 32, dh = 64 --- ';
+ sourceRect = {x: 64, y: 64, w: 384, h: 384};
+ destRect = {x: 0, y: 0, w: 32, h: 64};
+ lightPixelCheck = [[0,0], [15,31], [17,33], [31,63]];
+ grayPixelCheck = [[16,0], [31,31], [0, 33], [15,63]];
+ redCheck = [[0,64], [32,0], [32,64], [99,99]];
+ drawImageOnCanvas(sourceRect, destRect, lightPixelCheck, grayPixelCheck, redCheck, testDescription);
+}
+
+
+function runDrawImageTests() {
+ runDrawImageTest_dX0_dY0();
+ runDrawImageTest_dX25_dY25();
+ runDrawImageTest_dX50_dY50_dW50_dH50();
+ runDrawImageTest_dX50_dY50_dW16_dH16();
+ runDrawImageTest_dX50_dY50_dW64_dH32();
+ runDrawImageTest_sX0_sY0_sW32_sH32_dX0_dY0_dW32_dH32();
+ runDrawImageTest_sX0_sY0_sW32_sH32_dX32_dY32_dW32_dH32();
+ runDrawImageTest_sX32_sY32_sW32_sH32_dX0_dY0_dW32_dH32();
+ runDrawImageTest_sX0_sY0_sW32_sH32_dX32_dY32_dWm32_dHm32();
+ runDrawImageTest_sX0_sY0_sW512_sH512_dX0_dY0_dW256_dH256();
+ runDrawImageTest_sX0_sY0_sW2048_sH2048_dX0_dY0_dW800_dH800();
+ runDrawImageTest_sXm20_sYm20_sW50_sH50_dX20_dY20_dW125_dH125();
+ runDrawImageTestImageWithuotSource();
+ runDrawImageTest_sX64_sY64_sW384_sH384_dX0_dY0_dW32_dH64();
+}
+
+async_test(t => {
+ window.onload = function() {
+ t.step(runDrawImageTests);
+ t.done();
+ }
+}, 'Draw 100x100 image to 100x100 canvas at 0,0.');
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_1.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_1.html
new file mode 100644
index 0000000000..ea3300bef2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_1.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Load a 100x100 image to a SVG image and draw it to a 100x100 canvas.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<div id="log"></div>
+<canvas id="dest" height="100" width="100"></canvas>
+<script>
+async_test(t => {
+ var sourceImg = document.createElementNS('http://www.w3.org/2000/svg', 'image');
+ sourceImg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/html/canvas/resources/2x2.png');
+ sourceImg.width = 100;
+ sourceImg.height = 100;
+
+ window.onload = t.step_func_done(() => {
+ var destCanvas = document.getElementById('dest');
+ var destCtx = destCanvas.getContext('2d');
+ destCtx.fillStyle = "#FF0000";
+ destCtx.fillRect(0, 0, destCanvas.width, destCanvas.height);
+ destCtx.imageSmoothingEnabled = false;
+ // 2 arguments, the dest origin is 0,0
+ // The source canvas will copied to the 0,0 position of the destination canvas
+ destCtx.drawImage(sourceImg, 0, 0);
+ _assertPixel(destCanvas, 0, 0, 253, 140, 245, 255);
+ _assertPixel(destCanvas, 0, 99, 253, 140, 245, 255);
+ _assertPixel(destCanvas, 99, 0, 253, 140, 245, 255);
+ _assertPixel(destCanvas, 99, 99, 253, 140, 245, 255);
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_with_foreign_object_does_not_taint.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_with_foreign_object_does_not_taint.html
new file mode 100644
index 0000000000..f29b2bf5a8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/drawimage_svg_image_with_foreign_object_does_not_taint.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Draw an SVG image with a foreignObject to a canvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function loadImage(url) {
+ return new Promise(resolve => {
+ const image = new window.Image();
+ image.onload = () => {
+ resolve(image);
+ };
+ image.src = url;
+ });
+}
+
+promise_test(async (t) => {
+ // Load a data URL for an SVG image with a foreign object.
+ const url = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject></foreignObject></svg>';
+ const image = await loadImage(url);
+
+ // Draw the image to a canvas.
+ const canvas = document.createElement('canvas');
+ const context = canvas.getContext('2d');
+ canvas.width = image.width;
+ canvas.height = image.height;
+ context.drawImage(image, 0, 0);
+
+ // The canvas should not be tainted, so the following shouldn't throw.
+ assert_true(canvas.toDataURL().length > 0);
+}, 'Canvas should not be tainted after drawing SVG including <foreignObject>');
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none-ref.html
new file mode 100644
index 0000000000..320a9b8108
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage from a createImageBitmap source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <img id="img-element" style="image-orientation: none;" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none.tentative.html
new file mode 100644
index 0000000000..39ed4a25dc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-orientation-none.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-bitmap-orientation-none-ref.html">
+ <script>
+ image = new Image();
+ image.src = "/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg";
+
+ let imageLoadPromise = new Promise(resolve => {
+ image.onload = resolve;
+ });
+ let contentLoadedPromise = new Promise(resolve => {
+ window.addEventListener('DOMContentLoaded', resolve);
+ });
+ Promise.all([imageLoadPromise, contentLoadedPromise]).then( function() {
+ const can = document.getElementById('bitmap-canvas');
+ can.height = 50;
+ can.width = 100;
+ can.getContext('2d').drawImage(image, 0, 0);
+ })
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <canvas id="bitmap-canvas" style="image-orientation: none;"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-ref.html
new file mode 100644
index 0000000000..261d6a0b7c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage from a createImageBitmap source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none-ref.html
new file mode 100644
index 0000000000..3a78aad068
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage from a createImageBitmap source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <img id="img-element" style="image-orientation: none;" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none.tentative.html
new file mode 100644
index 0000000000..3b16241c97
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-orientation-none.tentative.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-bitmap-swap-width-height-orientation-none-ref.html">
+ <script>
+ image = new Image();
+ image.src = "/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg";
+
+ let imageLoadPromise = new Promise(resolve => {
+ image.onload = resolve;
+ });
+ let contentLoadedPromise = new Promise(resolve => {
+ window.addEventListener('DOMContentLoaded', resolve);
+ });
+ Promise.all([imageLoadPromise, contentLoadedPromise]).then( async function() {
+ const bitmap = await createImageBitmap(image);
+ const can = document.getElementById('bitmap-canvas');
+ can.height = 50;
+ can.width = 100;
+ can.getContext('2d').drawImage(bitmap, 0, 0);
+ })
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <canvas id="bitmap-canvas" style="image-orientation: none;"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-ref.html
new file mode 100644
index 0000000000..247d7f4049
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage from a createImageBitmap source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height.tentative.html
new file mode 100644
index 0000000000..744ca54f47
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap-swap-width-height.tentative.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-bitmap-swap-width-height-ref.html">
+ <script>
+ image = new Image();
+ image.src = "/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg";
+
+ let imageLoadPromise = new Promise(resolve => {
+ image.onload = resolve;
+ });
+ let contentLoadedPromise = new Promise(resolve => {
+ window.addEventListener('DOMContentLoaded', resolve);
+ });
+ Promise.all([imageLoadPromise, contentLoadedPromise]).then( async function() {
+ const bitmap = await createImageBitmap(image);
+ const can = document.getElementById('bitmap-canvas');
+ can.height = 100;
+ can.width = 50;
+ can.getContext('2d').drawImage(bitmap, 0, 0);
+ })
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <canvas id="bitmap-canvas"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap.tentative.html
new file mode 100644
index 0000000000..632a170b88
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-bitmap.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-bitmap-ref.html">
+ <script>
+ image = new Image();
+ image.src = "/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg";
+
+ let imageLoadPromise = new Promise(resolve => {
+ image.onload = resolve;
+ });
+ let contentLoadedPromise = new Promise(resolve => {
+ window.addEventListener('DOMContentLoaded', resolve);
+ });
+ Promise.all([imageLoadPromise, contentLoadedPromise]).then( function() {
+ const can = document.getElementById('bitmap-canvas');
+ can.height = 50;
+ can.width = 100;
+ can.getContext('2d').drawImage(image, 0, 0);
+ })
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <canvas id="bitmap-canvas"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob-ref.html
new file mode 100644
index 0000000000..2bd6037835
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from a blob with image orientation: from-image, reference</title>
+</head>
+<body>
+ <img id="img-element" style="width: 150px; height: 300px;" src="/css/css-images/image-orientation/support/exif-orientation-8-llo.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob.tentative.html
new file mode 100644
index 0000000000..330b3cbfe5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-blob.tentative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from a blob with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-blob-ref.html">
+ <script>
+ function makeBlob() {
+ return new Promise(function(resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", '/css/css-images/image-orientation/support/exif-orientation-8-llo.jpg');
+ xhr.responseType = 'blob';
+ xhr.send();
+ xhr.onload = function() {
+ resolve(xhr.response);
+ };
+ });
+ }
+
+ window.onload = function() {
+ var cfb = document.getElementById("canvasWithFileBitmap");
+ makeBlob().then(function(blob){createImageBitmap(blob).then(bitmap => {
+ cfb.getContext("2d").drawImage(bitmap, 0, 0, 150, 150 * bitmap.height / bitmap.width);
+ window.requestAnimationFrame(() => {
+ document.documentElement.removeAttribute("class");
+ });
+ });
+ });
+ }
+</script>
+</head>
+<body>
+ <canvas id="canvasWithFileBitmap" width="150" height="300"></canvas>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none-ref.html
new file mode 100644
index 0000000000..b847b9eb73
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage from an element source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <img id="img-element" style="image-orientation: none;" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none.tentative.html
new file mode 100644
index 0000000000..61563da738
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-orientation-none.tentative.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-element-orientation-none-ref.html">
+ <script>
+ window.onload = () => {
+ const img = document.getElementById('img-element');
+
+ const can = document.getElementById('bitmap-canvas');
+ can.height = img.height;
+ can.width = img.width;
+ can.getContext('2d').drawImage(img, 0, 0);
+ };
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <canvas id="bitmap-canvas" style="image-orientation: none;"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-ref.html
new file mode 100644
index 0000000000..3f4d1e5ff4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage from an element source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none-ref.html
new file mode 100644
index 0000000000..b26154b40a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference drawImage from an element source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <img id="img-element" style="image-orientation: none;" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none.tentative.html
new file mode 100644
index 0000000000..290d7acf3a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-orientation-none.tentative.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: none</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-element-swap-width-height-orientation-none-ref.html">
+ <script>
+ window.onload = () => {
+ const img = document.getElementById('img-element');
+
+ const can = document.getElementById('bitmap-canvas');
+ can.height = 50;
+ can.width = 100;
+ can.getContext('2d').drawImage(img, 0, 0);
+ };
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <canvas id="bitmap-canvas" style="image-orientation: none;"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-ref.html
new file mode 100644
index 0000000000..21f0f88b88
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference drawImage from an element source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height.tentative.html
new file mode 100644
index 0000000000..20d59358b4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element-swap-width-height.tentative.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-element-swap-width-height-ref.html">
+ <script>
+ window.onload = () => {
+ const img = document.getElementById('img-element');
+
+ const can = document.getElementById('bitmap-canvas');
+ can.height = 100;
+ can.width = 50;
+ can.getContext('2d').drawImage(img, 0, 0);
+ };
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-7-rl.jpg">
+ <canvas id="bitmap-canvas"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element.tentative.html
new file mode 100644
index 0000000000..62cdf20c79
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-from-element.tentative.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>createImageBitmap and drawImage from an element source with image orientation: from-image</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-from-element-ref.html">
+ <script>
+ window.onload = () => {
+ const img = document.getElementById('img-element');
+
+ const can = document.getElementById('bitmap-canvas');
+ can.height = img.height;
+ can.width = img.width;
+ can.getContext('2d').drawImage(img, 0, 0);
+ };
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <canvas id="bitmap-canvas"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect-ref.html
new file mode 100644
index 0000000000..19ffcc39c9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>reference for drawImage with image orientation: from-image and a sub-image source rect</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+ <script>
+ window.onload = () => {
+ const img = document.getElementById('img-element');
+
+ const can = document.getElementById('bitmap-canvas');
+ can.height = img.height;
+ can.width = img.width;
+ can.getContext('2d').drawImage(img, 40, 20, 50, 25, 0, 0, can.width, can.height);
+ };
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr-pre-rotated.jpg">
+ <canvas id="bitmap-canvas"></canvas>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect.tentative.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect.tentative.html
new file mode 100644
index 0000000000..d889e39302
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-images-to-the-canvas/image-orientation/drawImage-with-src-rect.tentative.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>drawImage with image orientation: from-image and a sub-image source rect</title>
+<link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
+<link rel="match" href="drawImage-with-src-rect-ref.html">
+<meta name=fuzzy content="0-3;0-200">
+ <script>
+ window.onload = () => {
+ const img = document.getElementById('img-element');
+
+ const can = document.getElementById('bitmap-canvas');
+ can.height = img.height;
+ can.width = img.width;
+ can.getContext('2d').drawImage(img, 40, 20, 50, 25, 0, 0, can.width, can.height);
+ };
+ </script>
+</head>
+<body>
+ <img id="img-element" src="/css/css-images/image-orientation/support/exif-orientation-3-lr.jpg">
+ <canvas id="bitmap-canvas"></canvas>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm
new file mode 100644
index 0000000000..18c3c9afb9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm
@@ -0,0 +1,31 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: isPointInPath() unaffected by the current transformation matrix</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath" />
+ <meta name="assert" content="isPointInPath must check the point (x, y) as coordinates unaffected by the current transformation matrix." />
+ <script type="text/javascript">
+ async_test(function(t) {
+ window.addEventListener("load", t.step_func_done(function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Create a path that is transformed by a translation transformation matrix.
+ ctx.translate(100, 50);
+ ctx.rect(0, 0, 100, 50);
+
+ // Ensure that the coordinates passed to isPointInPath are unaffected by the current transformation matrix.
+ assert_true(ctx.isPointInPath(125, 75), "isPointInPath(125, 75)");
+ assert_false(ctx.isPointInPath(25, 25), "!isPointInPath(25, 25)");
+ }));
+ }, "isPointInPath unaffected by transformation matrix");
+ </script>
+ </head>
+ <body>
+ <p>Description: isPointInPath must check the point (x, y) as coordinates unaffected by the current transformation matrix.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html
new file mode 100644
index 0000000000..bf38fa68b7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html
@@ -0,0 +1,50 @@
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>drawFocusIfNeeded() - AAPI test</title>
+ <link rel="author" title="Mark Sadecki" href="mark@w3.org">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This manual test can be used to verify that drawFocusIfNeeded actually updates the accessible location information (i.e. UIAutomation's CurrentBoundingRectangle) in the Accessibility API. To perform this test, you will need an <a href="http://www.w3.org/WAI/PF/wiki/ARIA_Test_Plan#Test_tools">accessibility API inspector</a>. To perform this test, use the <code>tab</code> key to move from the first focusable element to through to the fourth. This test passes if the first parameter of the bounding rectangle increases by 100 when focus is moved from the gray square to the orange square.</p>
+ <p><a href="http://www.w3.org">First focusable element</a></p>
+ <canvas height=100 width=200 id=canvas>
+ <a href='http://www.w3.org' id='button1'>Second focusable element</a>
+ <a href='http://www.w3.org' id='button2'>Third focusable element</a>
+ </canvas>
+ <p><a href="http://www.w3.org">Fourth focusable element</a></p>
+
+ <script>
+ var button1 = document.getElementById('button1');
+ var button2 = document.getElementById('button2');
+ var canvas = document.getElementById('canvas');
+ var buttons = canvas.getElementsByTagName('a');
+
+ for (var i = 0; i < buttons.length; i++) {
+ buttons[i].addEventListener('focus', drawCanvas, false);
+ buttons[i].addEventListener('blur', drawCanvas, false);
+ }
+
+ function drawRect(context, color, element) {
+ context.beginPath();
+ context.rect(10, 10, 80, 80);
+ context.fillStyle = color;
+ context.fill();
+ context.drawFocusIfNeeded(element);
+ }
+
+ function drawCanvas() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ context.clearRect (0, 0, 200, 100);
+
+ drawRect(context, "gray", button1);
+ context.translate(100,0);
+ drawRect(context, "orange", button2);
+ }
+ drawCanvas();
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html
new file mode 100644
index 0000000000..6daf32a2af
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded to draw a focus ring in the canvas, then compare the ImageData before and after the invocation of the method to check that the focus ring was actually drawn.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(10, 10, 80, 80);
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+ context.rect(5, 5, 90, 90);
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_false(identical, "The focus ring must appear in the canvas");
+
+
+ }, 'drawFocusIfNeeded draws a focus ring.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html
new file mode 100644
index 0000000000..ec0a4ef427
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded does nothing if the element is not in focus but comparing ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(10, 10, 80, 80);
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.strokeStyle = 'blue';
+ context.rect(5, 5, 90, 90);
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_true(identical, "No focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does not draw a focus ring if the element is not in focus.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html
new file mode 100644
index 0000000000..b62c0641f5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded does nothing if the element is not a descendant but comparing ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(10, 10, 80, 80);
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.strokeStyle = 'blue';
+ context.rect(5, 5, 90, 90);
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_true(identical, "No focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does not draw a focus ring if the element is not a descendant of the context.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html
new file mode 100644
index 0000000000..326db0daa8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded to draw a complex path focus then compare ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+
+ context.moveTo(10, 40);
+ context.lineTo(50, 10);
+ context.lineTo(90, 40);
+ context.lineTo(70, 40);
+ context.lineTo(70, 90);
+ context.lineTo(30, 90);
+ context.lineTo(30, 40);
+ context.closePath();
+
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.beginPath();
+ context.moveTo(5, 40);
+ context.lineTo(50, 5);
+ context.lineTo(95, 40);
+ context.lineTo(95, 45);
+ context.lineTo(75, 45);
+ context.lineTo(75, 95);
+ context.lineTo(25, 95);
+ context.lineTo(25, 45);
+ context.lineTo(5, 45);
+ context.closePath();
+
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_false(identical, "A focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does draw a focus ring if the element is in focus.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html
new file mode 100644
index 0000000000..96a4e3fd5d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded to draw a complex path focus then compare ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <p id='element' tabindex='1'>This is text.</p>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+
+ context.moveTo(10, 40);
+ context.lineTo(50, 10);
+ context.lineTo(90, 40);
+ context.lineTo(70, 40);
+ context.lineTo(70, 90);
+ context.lineTo(30, 90);
+ context.lineTo(30, 40);
+ context.closePath();
+
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.beginPath();
+ context.moveTo(5, 40);
+ context.lineTo(50, 5);
+ context.lineTo(95, 40);
+ context.lineTo(95, 45);
+ context.lineTo(75, 45);
+ context.lineTo(75, 95);
+ context.lineTo(25, 95);
+ context.lineTo(25, 45);
+ context.lineTo(5, 45);
+ context.closePath();
+
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_false(identical, "A focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does draw a focus ring if the element is in focus and the user activated a particular focus ring.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math-ref.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math-ref.html
new file mode 100644
index 0000000000..6c5dab9f41
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>font-size: math treated as medium in disconnected canvas (reference)</title>
+<body>
+</body>
+<script>
+var d = new Document();
+var c = d.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+var ctx = c.getContext("2d");
+ctx.font = `medium serif`;
+ctx.fillText("Hello World!", 5, c.height / 2);
+c.toBlob((blob) => {
+ var img = document.createElement("img");
+ const url = URL.createObjectURL(blob);
+ img.src = url;
+ img.style.border = "3px solid cyan";
+ document.body.appendChild(img);
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html b/testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html
new file mode 100644
index 0000000000..2cecff68f1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>font-size: math treated as medium in disconnected canvas</title>
+<link rel="match" href="canvas.2d.disconnected-font-size-math-ref.html">
+<body>
+</body>
+<script>
+var d = new Document();
+var c = d.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+var ctx = c.getContext("2d");
+ctx.font = `math serif`;
+ctx.fillText("Hello World!", 5, c.height / 2);
+c.toBlob((blob) => {
+ var img = document.createElement("img");
+ const url = URL.createObjectURL(blob);
+ img.src = url;
+ img.style.border = "3px solid cyan";
+ document.body.appendChild(img);
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html
new file mode 100644
index 0000000000..37701bacee
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.fillStyle.parse.current.notrendered</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.current.basic</h1>
+<p class="desc">currentColor is computed from the canvas element</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("currentColor is computed from the canvas element even when element is not rendered");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('style', 'color: #0f0;');
+canvas.style.display = 'none';
+canvas.offsetTop;
+ctx.fillStyle = 'currentColor';
+canvas.style.display = 'inline';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255);
+
+
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm
new file mode 100644
index 0000000000..5b77c98de7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm
@@ -0,0 +1,59 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: createlinearGradient() with two points same</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-createlineargradient" />
+ <meta name="assert" content="If the two points in a linear gradient have identical x,y coordinates, the canvas must paint nothing." />
+ <script type="text/javascript">
+ async_test(function(t) {
+ window.addEventListener("load", t.step_func_done(function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+ var width = canvas.width;
+ var height = canvas.height;
+
+ // Start by drawing a left to right, green-to-blue linear gradient.
+ var lingrad = ctx.createLinearGradient(0, 50, 100, 50);
+ lingrad.addColorStop(0, "rgba(0, 255, 0, 1.0)");
+ lingrad.addColorStop(1, "rgba(0, 0, 255, 1.0)");
+ ctx.fillStyle = lingrad;
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Get the current state of the canvas
+ var initial = ctx.getImageData(0, 0, width, height);
+
+ // Nothing must be drawn if the two points in the linear gradient are the same.
+ lingrad = ctx.createLinearGradient(100, 100, 100, 100);
+ lingrad.addColorStop(0, "rgba(255, 0, 0, 1.0)");
+ lingrad.addColorStop(1, "rgba(255, 0, 0, 1.0)");
+ ctx.fillStyle = lingrad;
+ ctx.fillRect(0, 0, 300, 150);
+
+ // Check that nothing is drawn.
+ var after = ctx.getImageData(0, 0, width, height);
+
+ // Asserts
+ assert_equals(initial.width, after.width, "widths are equal");
+ assert_equals(initial.height, after.height, "heights are equal");
+ assert_array_equals(initial.data, after.data, "data are equal");
+
+ for (var i = 0; i < after.data.length; i += 4) {
+ var r = after.data[i];
+ var g = after.data[i+1];
+ var b = after.data[i+2];
+ var a = after.data[i+3];
+ assert_false(r == 0xFF && g == 0 && b == 0 && a == 0xFF, "no red");
+ }
+ }));
+ }, "linear gradient from point to self draws nothing");
+ </script>
+ </head>
+ <body>
+ <p>Description: If the two points in a linear gradient have identical x,y coordinates, the canvas must paint nothing.</p>
+ <p>Test passes if there is one left-to-right, green-to-blue linear gradient seen on the page and no red is seen on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-expected.html b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-expected.html
new file mode 100644
index 0000000000..f347abc9d3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-expected.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title></title>
+ <style type="text/css">
+ div {
+ width: 300px;
+ height: 150px;
+ background: conic-gradient(
+ from 90deg at 100px 50px,
+ red 0.2turn,
+ orange 0.2turn 0.4turn,
+ yellow 0.4turn 0.6turn,
+ green 0.6turn 0.8turn,
+ blue 0.8turn 1.0turn
+ );
+ </style>
+</head>
+<body>
+ <div id="output"></div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation-expected.html b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation-expected.html
new file mode 100644
index 0000000000..68d750f462
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation-expected.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title></title>
+ <style type="text/css">
+ div {
+ width: 300px;
+ height: 150px;
+ background: conic-gradient(
+ from 180deg at 100px 50px,
+ red 0.2turn,
+ orange 0.2turn 0.4turn,
+ yellow 0.4turn 0.6turn,
+ green 0.6turn 0.8turn,
+ blue 0.8turn 1.0turn
+ );
+ </style>
+</head>
+<body>
+ <div id="output"></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation.html b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation.html
new file mode 100644
index 0000000000..e8b213b3d8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient-rotation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Conic gradient</title>
+ <link rel="match" href="conic-gradient-rotation-expected.html"/>
+</head>
+<body>
+ <canvas id="c"></canvas>
+ <script type="text/javascript">
+ const canvas = document.getElementById('c');
+ const ctx = canvas.getContext('2d');
+
+ const grad = ctx.createConicGradient(2.5*Math.PI, 100, 50);
+
+ grad.addColorStop(0, "red");
+ grad.addColorStop(0.2, "red");
+ grad.addColorStop(0.2, "orange");
+ grad.addColorStop(0.4, "orange");
+ grad.addColorStop(0.4, "yellow");
+ grad.addColorStop(0.6, "yellow");
+ grad.addColorStop(0.6, "green");
+ grad.addColorStop(0.8, "green");
+ grad.addColorStop(0.8, "blue");
+
+ ctx.fillStyle = grad;
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ </script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient.html b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient.html
new file mode 100644
index 0000000000..73fcf6c23e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/fill-and-stroke-styles/conic-gradient.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Conic gradient</title>
+ <link rel="match" href="conic-gradient-expected.html"/>
+</head>
+<body>
+ <canvas id="c"></canvas>
+ <script type="text/javascript">
+ const canvas = document.getElementById('c');
+ const ctx = canvas.getContext('2d');
+
+ const grad = ctx.createConicGradient(0, 100, 50);
+
+ grad.addColorStop(0, "red");
+ grad.addColorStop(0.2, "red");
+ grad.addColorStop(0.2, "orange");
+ grad.addColorStop(0.4, "orange");
+ grad.addColorStop(0.4, "yellow");
+ grad.addColorStop(0.6, "yellow");
+ grad.addColorStop(0.6, "green");
+ grad.addColorStop(0.8, "green");
+ grad.addColorStop(0.8, "blue");
+
+ ctx.fillStyle = grad;
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ </script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-fillStyle-opacity.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-fillStyle-opacity.html
new file mode 100644
index 0000000000..b5f9d98b89
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-fillStyle-opacity.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-opacity-expected.html"/>
+<meta name="fuzzy" content="maxDifference=0-2; totalPixels=0-14000">
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'rgba(0, 128, 128, 0.75)';
+ ctx.fillRect(10, 10, 50, 50);
+ ctx.fillStyle = 'rgba(255, 0, 255, 0.5)';
+ ctx.fillRect(70, 10, 50, 50);
+ ctx.fillStyle = 'rgba(255, 165, 0, 0.25)';
+ ctx.fillRect(10, 70, 50, 50);
+ ctx.fillStyle = 'rgba(210, 105, 30, 0)';
+ ctx.fillRect(70, 70, 50, 50);
+
+ ctx.fillStyle = 'rgba(0, 255, 255, 0.8)';
+ ctx.fillRect(10, 150, 50, 50);
+ ctx.fillStyle = 'rgba(255, 0, 0, 0.6)';
+ ctx.fillRect(20, 150, 50, 50);
+ ctx.fillStyle = 'rgba(255, 255, 0, 0.4)';
+ ctx.fillRect(30, 150, 50, 50);
+ ctx.fillStyle = 'rgba(0, 128, 0, 0.2)';
+ ctx.fillRect(40, 150, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle-expected.html
new file mode 100644
index 0000000000..f87794f0b7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle-expected.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<body>
+ <div id="sq-1"></div>
+ <div id="sq-2"></div>
+ <div id="sq-3"></div>
+ <div id="sq-4"></div>
+</body>
+<style>
+ /*The expected behavior when setting the opacity through different methods
+ is that the opacity of the resulting drawn element is the product of the opacity
+ value set by each of the methods.*/
+ div{
+ width: 50px;
+ height: 50px;
+ position: absolute;
+ }
+ #sq-1{
+ background-color: black;
+ left: 18px;
+ top: 18px;
+ opacity: 0.125;
+ }
+ #sq-2{
+ background-color: black;
+ left: 78px;
+ top: 18px;
+ opacity: 0.03125;
+ }
+ #sq-3{
+ background-color: black;
+ left: 18px;
+ top: 78px;
+ opacity: 0.1875;
+ }
+ #sq-4{
+ background-color: black;
+ left: 78px;
+ top: 78px;
+ opacity: 0.016;
+ }
+</style>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle.html
new file mode 100644
index 0000000000..24c97d62ec
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity-alpha-and-fillStyle.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-filter-opacity-alpha-and-fillStyle-expected.html"/>
+<meta name="fuzzy" content="maxDifference=0-2; totalPixels=0-10000">
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The expected behavior when setting the opacity through different methods
+ is that the opacity of the resulting drawn element is the product of the opacity
+ value set by each of the methods.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+
+ ctx.globalAlpha = 0.5;
+ ctx.fillStyle = 'rgba(0,0,0,0.5)';
+ ctx.filter = 'opacity(50%)';
+ ctx.fillRect(10, 10, 50, 50);
+
+ ctx.globalAlpha = 0.5;
+ ctx.fillStyle = 'rgba(0,0,0,0.25)';
+ ctx.filter = 'opacity(25%)';
+ ctx.fillRect(70, 10, 50, 50);
+
+ ctx.globalAlpha = 0.75;
+ ctx.fillStyle = 'rgba(0,0,0,0.5)';
+ ctx.filter = 'opacity(50%)';
+ ctx.fillRect(10, 70, 50, 50);
+
+ ctx.globalAlpha = 0.8;
+ ctx.fillStyle = 'rgba(0,0,0,0.2)';
+ ctx.filter = 'opacity(10%)';
+ ctx.fillRect(70, 70, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity.html
new file mode 100644
index 0000000000..cb2fc018af
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-opacity.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-opacity-expected.html"/>
+<meta name="fuzzy" content="maxDifference=0-2; totalPixels=0-14000">
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.filter = 'opacity(75%)';
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(10, 10, 50, 50);
+ ctx.filter = 'opacity(50%)';
+ ctx.fillStyle = 'magenta';
+ ctx.fillRect(70, 10, 50, 50);
+ ctx.filter = 'opacity(25%)';
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(10, 70, 50, 50);
+ ctx.filter = 'opacity(0%)';
+ ctx.fillStyle = 'chocolate';
+ ctx.fillRect(70, 70, 50, 50);
+
+ ctx.filter = 'opacity(80%)';
+ ctx.fillStyle = 'cyan';
+ ctx.fillRect(10, 150, 50, 50);
+ ctx.filter = 'opacity(60%)';
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 150, 50, 50);
+ ctx.filter = 'opacity(40%)';
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(30, 150, 50, 50);
+ ctx.filter = 'opacity(20%)';
+ ctx.fillStyle = 'green';
+ ctx.fillRect(40, 150, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur-expected.html
new file mode 100644
index 0000000000..1f218b4bd2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The shadow and shadow blur effects should be the same regardless if they were
+ defined with filters or properties. The blur parameter is set as double when
+ using the shadowBlur property since its uses havlf of the value set as the
+ standard deviation for the gaussian blur (https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur-dev)
+ while the filter parameter is used directly as the standard deviation
+ (https://drafts.fxtf.org/filter-effects/#funcdef-filter-drop-shadow). The
+ fuzziness is defined with a maxDifference of 13 as to be the 5% of 256, since
+ the CSS spec defines the expected behavior in relation to an ideal Gaussian blur
+ with a tolerance of 5%. See: https://drafts.csswg.org/css-backgrounds-3/#shadow-blur.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.shadowOffsetX = 10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowBlur = 4;
+ ctx.shadowColor = 'red';
+ ctx.fillRect(20, 20, 50, 50);
+ ctx.shadowBlur = 8;
+ ctx.shadowColor = 'blue';
+ ctx.fillRect(100, 20, 50, 50);
+ ctx.shadowBlur = 20;
+ ctx.shadowColor = 'yellow';
+ ctx.fillRect(20, 100, 50, 50);
+ ctx.shadowBlur = 30;
+ ctx.shadowColor = 'cyan';
+ ctx.fillRect(100, 100, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur.html
new file mode 100644
index 0000000000..ab3699906d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-blur.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-filter-shadow-and-properties-blur-expected.html"/>
+<meta name="fuzzy" content="maxDifference=0-13; totalPixels=0-25600">
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The shadow and shadow blur effects should be the same regardless if they were
+ defined with filters or properties. The blur parameter is set as double when
+ using the shadowBlur property since its uses havlf of the value set as the
+ standard deviation for the gaussian blur (https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur-dev)
+ while the filter parameter is used directly as the standard deviation
+ (https://drafts.fxtf.org/filter-effects/#funcdef-filter-drop-shadow). The
+ fuzziness is defined with a maxDifference of 13 as to be the 5% of 256, since
+ the CSS spec defines the expected behavior in relation to an ideal Gaussian blur
+ with a tolerance of 5%. See: https://drafts.csswg.org/css-backgrounds-3/#shadow-blur.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.filter = 'drop-shadow(10px 10px 2px red)';
+ ctx.fillRect(20, 20, 50, 50);
+ ctx.filter = 'drop-shadow(10px 10px 4px blue)';
+ ctx.fillRect(100, 20, 50, 50);
+ ctx.filter = 'drop-shadow(10px 10px 10px yellow)';
+ ctx.fillRect(20, 100, 50, 50);
+ ctx.filter = 'drop-shadow(10px 10px 15px cyan)';
+ ctx.fillRect(100, 100, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-expected.html
new file mode 100644
index 0000000000..294a219b70
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The expected behavior when both shadow properties and filters are used at the
+ same time is that the filter is applied to the elements drawn and the shadow
+ properties create another shadow that includes even shadows of the
+ filter-generated shadows.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'cyan';
+ ctx.fillRect(40, 40, 50, 50);
+ ctx.fillRect(30, 30, 50, 50);
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 50, 50);
+ ctx.fillStyle = 'black';
+ ctx.fillRect(10, 10, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties.html
new file mode 100644
index 0000000000..2057b95c3e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-and-properties.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-filter-shadow-and-properties-expected.html"/>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The expected behavior when both shadow properties and filters are used at the
+ same time is that the filter is applied to the elements drawn and the shadow
+ properties create another shadow that includes even shadows of the
+ filter-generated shadows.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.shadowColor = 'cyan';
+ ctx.shadowOffsetX = 20;
+ ctx.shadowOffsetY = 20;
+ ctx.filter = 'drop-shadow(10px 10px 0 red)';
+ ctx.fillRect(10, 10, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-expected.html
new file mode 100644
index 0000000000..04bc6392cc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow-expected.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The expected behavior of filter-generated shadows is tested against
+ a drawing using only rectangles that draws the shadows manually.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 20, 50, 50);
+ ctx.fillStyle = 'black';
+ ctx.fillRect(10, 10, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow.html
new file mode 100644
index 0000000000..ddc6c89ee5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-filter-shadow.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-filter-shadow-expected.html"/>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ /*
+ The expected behavior of filter-generated shadows is tested against
+ a drawing using only rectangles that draws the shadows manually.
+ */
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.filter = 'drop-shadow(10px 10px 0 red)';
+ ctx.fillRect(10, 10, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-globalAlpha.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-globalAlpha.html
new file mode 100644
index 0000000000..6d7bbcd03d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-globalAlpha.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-opacity-expected.html"/>
+<meta name="fuzzy" content="maxDifference=0-2; totalPixels=0-14000">
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.globalAlpha = 0.75;
+ ctx.fillStyle = 'teal';
+ ctx.fillRect(10, 10, 50, 50);
+ ctx.globalAlpha = 0.5;
+ ctx.fillStyle = 'magenta';
+ ctx.fillRect(70, 10, 50, 50);
+ ctx.globalAlpha = 0.25;
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(10, 70, 50, 50);
+ ctx.globalAlpha = 0;
+ ctx.fillStyle = 'chocolate';
+ ctx.fillRect(70, 70, 50, 50);
+
+ ctx.globalAlpha = 0.8;
+ ctx.fillStyle = 'cyan';
+ ctx.fillRect(10, 150, 50, 50);
+ ctx.globalAlpha = 0.6;
+ ctx.fillStyle = 'red';
+ ctx.fillRect(20, 150, 50, 50);
+ ctx.globalAlpha = 0.4;
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(30, 150, 50, 50);
+ ctx.globalAlpha = 0.2;
+ ctx.fillStyle = 'green';
+ ctx.fillRect(40, 150, 50, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes-expected.html
new file mode 100644
index 0000000000..3eb7581981
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes-expected.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<body>
+</body>
+<script>
+ /*
+ Compare how the opacity is handled in different blend modes when setting its
+ value with filters or with properties.
+ */
+
+ function drawSquares(canvasId, x, y, compositeOperation) {
+ var canvas = document.getElementById(canvasId);
+ var ctx = canvas.getContext('2d');
+ canvas.style.position = 'absolute';
+ canvas.style.left = `${x}px`;
+ canvas.style.top = `${y}px`;
+
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.globalAlpha = 1.0;
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 200, 60);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.globalAlpha = 0.7;
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.globalCompositeOperation = compositeOperation;
+ ctx.globalAlpha = 0.5;
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(25, 25, 50, 50);
+ }
+
+ // Fomatted in the same matrix as the drawn elements.
+ var compositeOperations =
+ ['source-over', 'source-in', 'source-out', 'source-atop','destination-over',
+ 'destination-in', 'destination-out', 'destination-atop', 'lighter', 'copy',
+ 'xor', 'multiply', 'screen', 'overlay', 'darken',
+ 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light',
+ 'difference', 'exclusion', 'hue', 'saturation', 'color',
+ 'luminosity'];
+
+ for (var i = 0; i < compositeOperations.length; i++){
+ var canvas = document.createElement('canvas');
+ canvas.id = `canvas-${i}`;
+ document.body.appendChild(canvas);
+ drawSquares(canvas.id, (i%5)*300, Math.floor(i/5)*300,
+ compositeOperations[i]);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes.html
new file mode 100644
index 0000000000..a2d513eb62
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-blend-modes.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<link rel="match" href="canvas-opacity-blend-modes-expected.html"/>
+<meta name="fuzzy" content="maxDifference=0-2; totalPixels=0-390000">
+<body>
+</body>
+<script>
+ /*
+ Compare how the opacity is handled in different blend modes when setting its
+ value with filters or with properties.
+ */
+
+ function drawSquares(canvasId, x, y, compositeOperation) {
+ var canvas = document.getElementById(canvasId);
+ var ctx = canvas.getContext('2d');
+ canvas.style.position = 'absolute';
+ canvas.style.left = `${x}px`;
+ canvas.style.top = `${y}px`;
+
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.filter = 'opacity(100%)';
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, 200, 60);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.filter = 'opacity(70%)';
+ ctx.fillStyle = 'red';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.globalCompositeOperation = compositeOperation;
+ ctx.filter = 'opacity(50%)';
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(25, 25, 50, 50);
+ }
+
+ // Fomatted in the same matrix as the drawn elements.
+ var compositeOperations =
+ ['source-over', 'source-in', 'source-out', 'source-atop','destination-over',
+ 'destination-in', 'destination-out', 'destination-atop', 'lighter', 'copy',
+ 'xor', 'multiply', 'screen', 'overlay', 'darken',
+ 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light',
+ 'difference', 'exclusion', 'hue', 'saturation', 'color',
+ 'luminosity'];
+
+ for (var i = 0; i < compositeOperations.length; i++){
+ var canvas = document.createElement('canvas');
+ canvas.id = `canvas-${i}`;
+ document.body.appendChild(canvas);
+ drawSquares(canvas.id, (i%5)*300, Math.floor(i/5)*300,
+ compositeOperations[i]);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-expected.html
new file mode 100644
index 0000000000..caf6b53ce3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/canvas-opacity-expected.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<body>
+ <div id="sq-1"></div>
+ <div id="sq-2"></div>
+ <div id="sq-3"></div>
+ <div id="sq-4"></div>
+ <div id="sq-5"></div>
+ <div id="sq-6"></div>
+ <div id="sq-7"></div>
+ <div id="sq-8"></div>
+</body>
+<style>
+ div{
+ width: 50px;
+ height: 50px;
+ position: absolute;
+ }
+ #sq-1{
+ background-color: teal;
+ left: 18px;
+ top: 18px;
+ opacity: 0.75;
+ }
+ #sq-2{
+ background-color: magenta;
+ left: 78px;
+ top: 18px;
+ opacity: 0.5;
+ }
+ #sq-3{
+ background-color: orange;
+ left: 18px;
+ top: 78px;
+ opacity: 0.25;
+ }
+ #sq-4{
+ background-color: chocolate;
+ left: 78px;
+ top: 78px;
+ opacity: 0;
+ }
+ #sq-5{
+ background-color: cyan;
+ left: 18px;
+ top: 158px;
+ opacity: 0.8;
+ }
+ #sq-6{
+ background-color: red;
+ left: 28px;
+ top: 158px;
+ opacity: 0.6;
+ }
+ #sq-7{
+ background-color: yellow;
+ left: 38px;
+ top: 158px;
+ opacity: 0.4;
+ }
+ #sq-8{
+ background-color: green;
+ left: 48px;
+ top: 158px;
+ opacity: 0.2;
+ }
+</style>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-crash.html b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-crash.html
new file mode 100644
index 0000000000..f64379c792
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/svg-filter-crash.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<script>
+ document.addEventListener('DOMContentLoaded', async () => {
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
+ const filter = document.createElementNS('http://www.w3.org/2000/svg', 'filter')
+ filter.setAttribute('id', 'id_0')
+ svg.appendChild(filter)
+ document.documentElement.appendChild(svg)
+ const canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas')
+ const context = canvas.getContext('2d')
+ context.filter = 'url(#id_0) url(#id_0) sepia() url(#id_0)'
+ svg.setAttribute('style', 'display: inline-block;')
+ })
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur-expected.html
new file mode 100644
index 0000000000..ae8911b2de
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur-expected.html
@@ -0,0 +1,19 @@
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.filter = 'blur(2px)';
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(10,10,100,100);
+ ctx.filter = 'blur(5px)';
+ ctx.fillStyle = 'magenta';
+ ctx.fillRect(120, 10, 100, 100);
+ ctx.filter = 'blur(5px) blur(10px)';
+ ctx.fillStyle = 'cyan';
+ ctx.fillRect(10, 120, 100, 100);
+ ctx.filter = 'none';
+ ctx.fillStyle = 'black';
+ ctx.fillRect(120, 120, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur.html
new file mode 100644
index 0000000000..9fe7ef120c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-blur.html
@@ -0,0 +1,24 @@
+<head>
+ <link rel="match" href="canvas-filter-object-blur-expected.html">
+</head>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.filter = new CanvasFilter({name: "gaussianBlur", stdDeviation: 2});
+ ctx.fillStyle = 'yellow';
+ ctx.fillRect(10,10,100,100);
+ ctx.filter = new CanvasFilter({name: "gaussianBlur", stdDeviation: 5});
+ ctx.fillStyle = 'magenta';
+ ctx.fillRect(120, 10, 100, 100);
+ ctx.filter = new CanvasFilter([
+ {name: "gaussianBlur", stdDeviation: 5},
+ {name: "gaussianBlur", stdDeviation: 10}]);
+ ctx.fillStyle = 'cyan';
+ ctx.fillRect(10, 120, 100, 100);
+ ctx.filter = 'none';
+ ctx.fillStyle = 'black';
+ ctx.fillRect(120, 120, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer-expected.html
new file mode 100644
index 0000000000..a2351cbcf2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer-expected.html
@@ -0,0 +1,65 @@
+<body>
+ <canvas id="canvas" width="500" height="100"></canvas>
+ <svg width="0", height="0">
+ <defs>
+ <filter color-interpolation-filters='sRGB' id="Identity" filterUnits="objectBoundingBox"
+ x="0%" y="0%" width="100%" height="100%">
+ <feComponentTransfer>
+ <feFuncR type="identity"/>
+ <feFuncG type="identity"/>
+ <feFuncB type="identity"/>
+ <feFuncA type="identity"/>
+ </feComponentTransfer>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="Table">
+ <feComponentTransfer>
+ <feFuncR type="table" tableValues="0 2 0.5 1"/>
+ <feFuncG type="table" tableValues="1 -1 5 0"/>
+ <feFuncB type="table" tableValues="0 1 1 0"/>
+ </feComponentTransfer>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="Discrete">
+ <feComponentTransfer>
+ <feFuncR type="discrete" tableValues="0 2 0.5 1"/>
+ <feFuncG type="discrete" tableValues="1 -1 5 0"/>
+ <feFuncB type="discrete" tableValues="0 1 1 0"/>
+ </feComponentTransfer>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="Linear">
+ <feComponentTransfer>
+ <feFuncR type="linear" slope=".5" intercept=".25"/>
+ <feFuncG type="linear" slope="1.5" intercept="0"/>
+ <feFuncB type="linear" slope="-0.5" intercept=".5"/>
+ </feComponentTransfer>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="Gamma">
+ <feComponentTransfer>
+ <feFuncR type="gamma" amplitude="2" exponent="5" offset="-0.5"/>
+ <feFuncG type="gamma" amplitude="0.9" exponent="3" offset="0.3"/>
+ <feFuncB type="gamma" amplitude="1.1" exponent="1" offset="0.1"/>
+ </feComponentTransfer>
+ </filter>
+ </defs>
+ </svg>
+</body>
+<script type="text/javascript">
+ const ctx = document.getElementById("canvas").getContext("2d");
+
+ const grad = ctx.createLinearGradient(10, 0, 490, 0);
+ grad.addColorStop(0, "#f00");
+ grad.addColorStop(0.33, "#0f0");
+ grad.addColorStop(0.67, "#00f");
+ grad.addColorStop(1, "#000");
+ ctx.fillStyle = grad;
+
+ ctx.filter = "url('#Identity')";
+ ctx.fillRect(10, 10, 480, 10);
+ ctx.filter = "url('#Table')";
+ ctx.fillRect(10, 30, 480, 10);
+ ctx.filter = "url('#Discrete')";
+ ctx.fillRect(10, 50, 480, 10);
+ ctx.filter = "url('#Linear')";
+ ctx.fillRect(10, 70, 480, 10);
+ ctx.filter = "url('#Gamma')";
+ ctx.fillRect(10, 90, 480, 10);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer.html
new file mode 100644
index 0000000000..47889c0db2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-component-transfer.html
@@ -0,0 +1,62 @@
+<head>
+ <link rel="match" href="canvas-filter-object-component-transfer-expected.html">
+</head>
+<body>
+ <canvas id="canvas" width="500" height="100"></canvas>
+</body>
+<script>
+ const ctx = document.getElementById("canvas").getContext("2d");
+
+ const grad = ctx.createLinearGradient(10, 0, 490, 0);
+ grad.addColorStop(0, "#f00");
+ grad.addColorStop(0.33, "#0f0");
+ grad.addColorStop(0.67, "#00f");
+ grad.addColorStop(1, "#000");
+ ctx.fillStyle = grad;
+
+ const identityFilter = new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "identity"},
+ funcG: {type: "identity"},
+ funcB: {type: "identity"},
+ funcA: {type: "identity"},
+ });
+ ctx.filter = identityFilter;
+ ctx.fillRect(10, 10, 480, 10);
+
+ const tableFilter = new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "table", tableValues: [0, 2, 0.5, 1]},
+ funcG: {type: "table", tableValues: [1, -1, 5, 0]},
+ funcB: {type: "table", tableValues: [0, 1, 1, 0]},
+ });
+ ctx.filter = tableFilter;
+ ctx.fillRect(10, 30, 480, 10);
+
+ const discreteFilter = new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "discrete", tableValues: [0, 2, 0.5, 1]},
+ funcG: {type: "discrete", tableValues: [1, -1, 5, 0]},
+ funcB: {type: "discrete", tableValues: [0, 1, 1, 0]},
+ });
+ ctx.filter = discreteFilter;
+ ctx.fillRect(10, 50, 480, 10);
+
+ const linearFilter = new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "linear", slope: 0.5, intercept: 0.25},
+ funcG: {type: "linear", slope: 1.5, intercept: 0},
+ funcB: {type: "linear", slope: -0.5, intercept: 0.5},
+ });
+ ctx.filter = linearFilter;
+ ctx.fillRect(10, 70, 480, 10);
+
+ const gammaFilter = new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "gamma", amplitude: 2, exponent: 5, offset: -0.5},
+ funcG: {type: "gamma", amplitude: 0.9, exponent: 3, offset: 0.3},
+ funcB: {type: "gamma", amplitude: 1.1, exponent: 1, offset: 0.1},
+ });
+ ctx.filter = gammaFilter;
+ ctx.fillRect(10, 90, 480, 10);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix-expected.html
new file mode 100644
index 0000000000..896a93542e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix-expected.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<style type="text/css">
+ canvas {
+ margin: 5px;
+ }
+</style>
+<body>
+ <svg width="0" height="0">
+ <filter color-interpolation-filters='sRGB' id="justKernel">
+ <feConvolveMatrix
+ kernelMatrix="3 0 0 0 0 0 0 0 -3"/>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="preserveAlpha">
+ <feConvolveMatrix
+ kernelMatrix="3 0 0 0 0 0 0 0 -3"
+ preserveAlpha="true"/>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="target">
+ <feConvolveMatrix
+ kernelMatrix="3 0 0 0 0 0 0 0 -3"
+ targetX="2" targetY="2"/>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="divisor">
+ <feConvolveMatrix
+ kernelMatrix="3 0 0 0 0 0 0 0 -3"
+ divisor="3"/>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="bias">
+ <feConvolveMatrix
+ kernelMatrix="3 0 0 0 0 0 0 0 -3"
+ bias="0.5"/>
+ </filter>
+ <filter color-interpolation-filters='sRGB' id="edgeMode">
+ <feConvolveMatrix
+ kernelMatrix="3 0 0 0 0 0 0 0 -3"
+ edgeMode="wrap"/>
+ </filter>
+ </svg>
+</body>
+<script type="text/javascript">
+
+const filters = [
+ "url('#justKernel')",
+ "url('#preserveAlpha')",
+ "url('#target')",
+ "url('#divisor')",
+ "url('#bias')",
+ "url('#edgeMode')",
+];
+
+function draw(ctx) {
+ ctx.fillRect(0, 20, 120, 100);
+
+ ctx.beginPath();
+ ctx.arc(150, 70, 50, 0, 2*Math.PI);
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.moveTo(220, 20);
+ ctx.lineTo(170, 120);
+ ctx.lineTo(270, 120);
+ ctx.lineTo(220, 20);
+ ctx.fill();
+}
+
+for (f of filters) {
+ const canvas = document.createElement("canvas");
+ document.body.prepend(canvas);
+ const ctx = canvas.getContext("2d");
+ ctx.filter = "blur(0px)";
+ ctx.fillStyle = "rgba(0,255,0,0.5)";
+ draw(ctx);
+ ctx.fillStyle = "rgba(255,0,255,0.5)";
+ ctx.filter = f;
+ draw(ctx);
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix.html
new file mode 100644
index 0000000000..1dfd602d13
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-convolve-matrix.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<head>
+ <link rel="match" href="canvas-filter-object-convolve-matrix-expected.html">
+ <style type="text/css">
+ canvas {
+ margin: 5px;
+ }
+ </style>
+</head>
+<body>
+</body>
+<script>
+function makeConvolveFilter(options) {
+ const KERNEL_MATRIX = [
+ [3, 0, 0],
+ [0, 0, 0],
+ [0, 0, -3],
+ ];
+
+ options = Object.assign(options, {
+ kernelMatrix: KERNEL_MATRIX, name: "convolveMatrix"});
+ return new CanvasFilter(options);
+}
+
+const test_cases = [
+ {},
+ {preserveAlpha: true},
+ {targetX: 2, targetY: 2},
+ {divisor: 3},
+ {bias: 0.5},
+ {edgeMode: "wrap"}
+];
+
+function draw(ctx) {
+ ctx.fillRect(0, 20, 120, 100);
+
+ ctx.beginPath();
+ ctx.arc(150, 70, 50, 0, 2*Math.PI);
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.moveTo(220, 20);
+ ctx.lineTo(170, 120);
+ ctx.lineTo(270, 120);
+ ctx.lineTo(220, 20);
+ ctx.fill();
+}
+
+for (tc of test_cases) {
+ const canvas = document.createElement("canvas");
+ document.body.prepend(canvas);
+ const ctx = canvas.getContext("2d");
+ ctx.filter = "blur(0px)";
+ ctx.fillStyle = "rgba(0,255,0,0.5)";
+ draw(ctx);
+ ctx.fillStyle = "rgba(255,0,255,0.5)";
+ ctx.filter = makeConvolveFilter(tc);
+ draw(ctx);
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
new file mode 100644
index 0000000000..ff0eebe2e0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence-expected.html
@@ -0,0 +1,37 @@
+<body>
+ <svg style="display:none">>
+ <filter id="base">
+ <feTurbulence baseFrequency="0.025"/>
+ </filter>
+ <filter id="base2d">
+ <feTurbulence baseFrequency="0.025, 0.1"/>
+ </filter>
+ <filter id="highFrequency">
+ <feTurbulence baseFrequency="0.05"/>
+ </filter>
+ <filter id="seed">
+ <feTurbulence baseFrequency="0.025" seed="100"/>
+ </filter>
+ <filter id="numOctaves">
+ <feTurbulence baseFrequency="0.025" numOctaves="2"/>
+ </filter>
+ <filter id="empty">
+ <feTurbulence/>
+ </filter>
+ <filter id="fractalNoise">
+ <feTurbulence baseFrequency="0.025" type="fractalNoise"/>
+ </filter>
+ <filter id="stitchTiles">
+ <feTurbulence baseFrequency="0.025" stitchTiles="noStitch"/>
+ </filter>
+</body>
+<script>
+ testCases = document.getElementsByTagName("filter");
+ for (tc of testCases) {
+ const canvas = document.createElement("canvas");
+ document.body.appendChild(canvas);
+ const ctx = canvas.getContext("2d");
+ ctx.filter = `url(#${tc.id})`;
+ ctx.fillRect(0, 0, 1, 1);
+ }
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
new file mode 100644
index 0000000000..b5b494825e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html
@@ -0,0 +1,26 @@
+<head>
+ <link rel="match" href="canvas-filter-object-blur-expected.html">
+</head>
+<body>
+</body>
+<script>
+ const testCases = [
+ {baseFrequency: 0.025},
+ {baseFrequency: [0.025, 0.1]},
+ {baseFrequency: 0.05},
+ {baseFrequency: 0.025, seed: 100},
+ {baseFrequency: 0.025, numOctaves: 2},
+ {},
+ {baseFrequency: 0.025, type: "fractalNoise"},
+ {baseFrequency: 0.025, stitchTiles: "stitch"},
+ ]
+
+ for (tc of testCases) {
+ const canvas = document.createElement("canvas");
+ document.body.appendChild(canvas);
+ const ctx = canvas.getContext("2d");
+ const filterOptions = {...{name: "turbulence"}, ...tc};
+ ctx.filter = new CanvasFilter(filterOptions);
+ ctx.fillRect(0, 0, 1, 1);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion-expected.html
new file mode 100644
index 0000000000..f043b0e762
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion-expected.html
@@ -0,0 +1,30 @@
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var ctx = document.getElementById('canvas').getContext('2d');
+
+ // preserveAlpha for convolveMatrix is the only boolean so far implemented
+ function drawWithConvolveFilter(x, y, preserveAlphaValue) {
+ ctx.filter = new CanvasFilter({
+ name: "convolveMatrix",
+ kernelMatrix: [[1, 0], [0, 1]],
+ preserveAlpha: preserveAlphaValue,
+ });
+ ctx.fillRect(x, y, 30, 30);
+ }
+
+ ctx.fillStyle = "rgba(255,0,255,0.5)";
+ let x = 10;
+ let y = 10;
+ for (var i = 0; i < 6; i++) {
+ drawWithConvolveFilter(x, y, true);
+ x += 40;
+ }
+ y = 50;
+ x = 10;
+ for (var i = 0; i < 5; i++) {
+ drawWithConvolveFilter(x, y, false);
+ x += 40;
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion.html
new file mode 100644
index 0000000000..97ade79f37
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion.html
@@ -0,0 +1,58 @@
+<head>
+ <link rel="match" href="canvas-filter-boolean-conversion-expected.html">
+</head>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ // Test the built-in ECMAScript types Undefined, Null, Boolean, String, Number, and Object
+ // as input to the CanvasFilter resolver when a bool is the intended result.
+ var ctx = document.getElementById('canvas').getContext('2d');
+
+ // preserveAlpha for convolveMatrix is the only boolean so far implemented
+ function drawWithConvolveFilter(x, y, preserveAlphaValue) {
+ ctx.filter = new CanvasFilter({
+ name: "convolveMatrix",
+ kernelMatrix: [[1, 0], [0, 1]],
+ preserveAlpha: preserveAlphaValue,
+ });
+ ctx.fillRect(x, y, 30, 30);
+ }
+
+ const trueTestCases = [
+ true,
+ { valueOf() { return false; }},
+ "foo",
+ 1,
+ {},
+ []
+ ];
+
+ const falseTestCases = [
+ false,
+ "",
+ 0,
+ null,
+ undefined,
+ ];
+
+ ctx.fillStyle = "rgba(255,0,255,0.5)";
+ let x = 10;
+ let y = 10;
+ for (tc of trueTestCases) {
+ drawWithConvolveFilter(x, y, tc);
+ x += 40;
+ }
+ y = 50;
+ x = 10;
+ for (tc of falseTestCases) {
+ drawWithConvolveFilter(x, y, tc);
+ x += 40;
+ }
+
+ ctx.filter = new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "discrete", tableValues: 0.5},
+ });
+ ctx.fillRect(10, 10, 100, 100);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion-expected.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion-expected.html
new file mode 100644
index 0000000000..8b4262ed04
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion-expected.html
@@ -0,0 +1,26 @@
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ var ctx = document.getElementById('canvas').getContext('2d');
+ // Null and False both evaluate to zero
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 0});
+ ctx.fillRect(10, 10, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 0});
+ ctx.fillRect(50, 10, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 0});
+ ctx.fillRect(90, 10, 30, 30);
+ // True evaluates to one
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 1});
+ ctx.fillRect(130, 10, 30, 30);
+ // String, Number and Object should all work
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+ ctx.fillRect(10, 50, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+ ctx.fillRect(50, 50, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+ ctx.fillRect(90, 50, 30, 30);
+ // Valid sequence
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+ ctx.fillRect(130, 50, 30, 30);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion.html
new file mode 100644
index 0000000000..c742633224
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-long-conversion.html
@@ -0,0 +1,35 @@
+<head>
+ <link rel="match" href="canvas-filter-long-conversion-expected.html">
+</head>
+<body>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+ // Test the built-in ECMAScript types Undefined, Null, Boolean, String, Number, and Object
+ // as input to the CanvasFilter resolver when a long is the intended result.
+ var ctx = document.getElementById('canvas').getContext('2d');
+
+ // Null, False and [] evaluate to zero
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: null});
+ ctx.fillRect(10, 10, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: false});
+ ctx.fillRect(50, 10, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: []});
+ ctx.fillRect(90, 10, 30, 30);
+ // True evaluates to one
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: true});
+ ctx.fillRect(130, 10, 30, 30);
+ // String, Number and Object should all work
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: "5"});
+ ctx.fillRect(10, 50, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: 5});
+ ctx.fillRect(50, 50, 30, 30);
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: { valueOf() { return 5; }}});
+ ctx.fillRect(90, 50, 30, 30);
+ // Valid sequence
+ ctx.filter = new CanvasFilter({filter: "gaussianBlur", stdDeviation: [5]});
+ ctx.fillRect(130, 50, 30, 30);
+
+ // Undefined and other inputs that throw exceptions are tested in:
+ // html/canvas/element/filters/2d.filter.canvasFilterObject.blur.exceptions.html
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-sequence-conversion.html b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-sequence-conversion.html
new file mode 100644
index 0000000000..d48627867e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-sequence-conversion.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>Canvas test: canvas-filter-sequence-conversion</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body class="show_output">
+
+<h1>canvas-filter-sequence-conversion</h1>
+<p class="desc">Test converting types into sequences</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Test pixels on CanvasFilter() various inputs to tableValues (which is a sequence)");
+_addTest(function(canvas, ctx) {
+
+ // Inputs to parameters that are expecting sequence<long>. Results are either the value of the
+ // red pixel drawing using the resultant filter or that we expect this input to throw an error.
+ const testCases = [
+ {input: [], result: 0},
+ {input: [0.5], result: 127},
+ {input: ["0.5"], result: 127},
+ {input: 1, result: "throws"},
+ {input: {}, result: "throws"},
+ {input: false, result: "throws"},
+ {input: true, result: "throws"},
+ {input: NaN, result: "throws"},
+ {input: { valueOf() { return [1]; }}, result: "throws"},
+ ];
+
+ // A simple filter that just overrides the red channel if successful.
+ function makeFilter(value) {
+ return new CanvasFilter({
+ name: "componentTransfer",
+ funcR: {type: "table", tableValues: value}
+ });
+ }
+
+ for (const tc of testCases) {
+ if (tc.result === "throws") {
+ assert_throws_js(TypeError, function(){ makeFilter(tc.input) });
+ } else {
+ ctx.reset();
+ ctx.filter = makeFilter(tc.input);
+ ctx.fillRect(0, 0, 100, 100);
+ _assertPixelApprox(canvas, 5, 5, tc.result,0,0,255, 2);
+ }
+ }
+ t.done();
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/image-smoothing/imagesmoothing.html b/testing/web-platform/tests/html/canvas/element/manual/image-smoothing/imagesmoothing.html
new file mode 100644
index 0000000000..1a86a8f201
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/image-smoothing/imagesmoothing.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext2D imageSmoothingEnabled test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#image-smoothing">
+<script>
+function createTestImage() {
+ var image = document.createElement('canvas');
+ var imgctx = image.getContext('2d');
+ imgctx.fillStyle = "#F00";
+ imgctx.fillRect(0, 0, 2, 2);
+ imgctx.fillStyle = "#0F0";
+ imgctx.fillRect(0, 0, 1, 1);
+ return image;
+}
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ assert_true(ctx.imageSmoothingEnabled);
+}, "When the canvas context is created, imageSmoothingEnabled must be set to true.");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ ctx.imageSmoothingEnabled = false;
+ assert_false(ctx.imageSmoothingEnabled);
+}, "On getting imageSmoothingEnabled, the user agent must return the last value it was set to.");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ var image = createTestImage();
+ ctx.scale(10, 10);
+ ctx.drawImage(image, 0, 0);
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_not_equals(pixels[0], 0);
+ assert_not_equals(pixels[1], 255);
+}, "Test that image smoothing is actually on by default and just the attribute value.");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ ctx.imageSmoothingEnabled = true;
+ var image = createTestImage();
+ ctx.scale(10, 10);
+ ctx.drawImage(image, 0, 0);
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_not_equals(pixels[0], 0);
+ assert_not_equals(pixels[1], 255);
+}, "Test that image smoothing works when imageSmoothingEnabled is set to true");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ var image = createTestImage();
+ ctx.imageSmoothingEnabled = false;
+ ctx.scale(10, 10);
+ ctx.drawImage(image, 0, 0);
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_array_equals(pixels, [0, 255, 0, 255]);
+}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with drawImage().");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ var image = createTestImage();
+ ctx.imageSmoothingEnabled = false;
+ ctx.scale(10, 10);
+ ctx.fillStyle = ctx.createPattern(image, 'repeat');
+ ctx.fillRect(0, 0, 10, 10);
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_array_equals(pixels, [0, 255, 0, 255]);
+}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with fillRect and createPattern().");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ var image = createTestImage();
+ ctx.imageSmoothingEnabled = false;
+ ctx.fillStyle = ctx.createPattern(image, 'repeat');
+ ctx.scale(10, 10);
+ ctx.rect(0, 0, 10, 10);
+ ctx.fill();
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_array_equals(pixels, [0, 255, 0, 255]);
+}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with fill() and createPattern().");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ var image = createTestImage();
+ ctx.strokeStyle = ctx.createPattern(image, 'repeat');
+ ctx.lineWidth = 5;
+ ctx.imageSmoothingEnabled = false;
+ ctx.scale(10, 10);
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(10, 10);
+ ctx.stroke();
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_array_equals(pixels, [0, 255, 0, 255]);
+}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) works with stroke() and createPattern().");
+
+test(function() {
+ var repaints = 5;
+ var ctx = document.createElement('canvas').getContext('2d');
+
+ function draw() {
+ ctx.clearRect(0, 0, 10, 10);
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ var image = createTestImage();
+ ctx.imageSmoothingEnabled = false;
+ ctx.scale(10, 10);
+ ctx.drawImage(image, 0, 0);
+ var pixels = ctx.getImageData(9, 9, 1, 1).data;
+ assert_array_equals(pixels, [0, 255, 0, 255]);
+ }
+
+ while (repaints > 0) {
+ draw();
+ repaints = repaints - 1;
+ }
+
+}, "Test that imageSmoothingEnabled = false (nearest-neighbor interpolation) still works after repaints.");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-ImageBitmap-close.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-ImageBitmap-close.html
new file mode 100644
index 0000000000..fca8274528
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-ImageBitmap-close.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<body>
+ <p>Tests that the close method of ImageBitmap does dispose the image data.</p>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+promise_test(function(t) {
+ var worker = new Worker('worker-onmessage-noop.js');
+
+ var imgHeight = 10;
+ var imgWidth = 10;
+ var imageData = new ImageData(10, 10);
+ var bitmap;
+ var ctx;
+ return createImageBitmap(imageData).then(imageBitmap => {
+ bitmap = imageBitmap;
+ assert_equals(bitmap.width, imgWidth, "bitmap.width = 10");
+ assert_equals(bitmap.height, imgWidth, "bitmap.height = 10");
+
+ // Apply structured clone to the bitmap, nothing should be changed
+ worker.postMessage({data: bitmap});
+ assert_equals(bitmap.width, imgWidth, "bitmap.width = 10");
+ assert_equals(bitmap.height, imgWidth, "bitmap.height = 10");
+
+ // After calling close, the image data associated with the bitmap should no longer exist
+ bitmap.close();
+ assert_equals(bitmap.width, 0, "bitmap.width = 0");
+ assert_equals(bitmap.height, 0, "bitmap.height = 0");
+
+ var canvas = document.createElement("canvas");
+ canvas.width = imgWidth;
+ canvas.height = imgHeight;
+ ctx = canvas.getContext("2d");
+ assert_throws_dom("InvalidStateError", function() { ctx.drawImage(bitmap, 0, 0); });
+
+ // Try to apply structured clone to an already closed bitmap
+ try {
+ worker.postMessage({data: bitmap});
+ throw new Error("Apply clone to an closed bitmap should be rejected");
+ }
+ catch(ex) {
+ // Apply structured clone to an already closed bitmap is rejected as expected.
+ }
+
+ // Try to apply transferring to an already closed bitmap
+ try {
+ worker.postMessage({data: bitmap}, [bitmap]);
+ throw new Error("Apply transferring to an closed bitmap should be rejected");
+ } catch(ex) {
+ // Apply structured clone to an already closed bitmap is rejected as expected.
+ }
+
+ // Calling createImageBitmap from a closed bitmap should be rejected
+ return createImageBitmap(bitmap).then(function() {
+ throw new Error("createImageBitmap from a closed bitmap should be rejected");
+ }, ex => {
+ // Calling createImageBitmap from a closed ImageBitmap is rejected as expected.
+ });
+ }).then(() => {
+ // Call close to a already closed bitmap should be noop.
+ bitmap.close();
+ assert_equals(bitmap.width, 0, "bitmap.height = 0");
+ assert_equals(bitmap.height, 0, "bitmap.height = 0");
+
+ return createImageBitmap(imageData).then(imageBitmap => {
+ bitmap = imageBitmap;
+ assert_equals(bitmap.width, imgWidth, "bitmap.width = 10");
+ assert_equals(bitmap.height, imgWidth, "bitmap.height = 10");
+
+ // Transfer the bitmap to a worker
+ worker.postMessage({data: bitmap}, [bitmap]);
+
+ // After transferring, the bitmap is neutered.
+ assert_equals(bitmap.width, 0, "bitmap.height = 0");
+ assert_equals(bitmap.height, 0, "bitmap.height = 0");
+
+ // Calling close to a neutered bitmap should be noop.
+ bitmap.close();
+ assert_equals(bitmap.width, 0, "bitmap.height = 0");
+ assert_equals(bitmap.height, 0, "bitmap.height = 0");
+
+ });
+ }).catch(function(ex) {
+ throw new Error("No exception should be thrown.");
+ })
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-resize.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-resize.html
new file mode 100644
index 0000000000..782c7e130c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-resize.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function checkNoCrop(imageBitmap)
+{
+ var canvas = document.createElement("canvas");
+ canvas.width = 50;
+ canvas.height = 50;
+ var ctx = canvas.getContext("2d");
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.drawImage(imageBitmap, 0, 0);
+ var d = ctx.getImageData(0, 0, 1, 1).data;
+ assert_array_equals(d, [255, 0, 0, 255], "This pixel should be red.");
+ d = ctx.getImageData(39, 0, 1, 1).data;
+ assert_array_equals(d, [0, 255, 0, 255], "This pixel should be green.");
+ d = ctx.getImageData(0, 39, 1, 1).data;
+ assert_array_equals(d, [0, 0, 255, 255], "This pixel should be blue.");
+ d = ctx.getImageData(39, 39, 1, 1).data;
+ assert_array_equals(d, [0, 0, 0, 255], "This pixel should be black.");
+ d = ctx.getImageData(41, 41, 1, 1).data;
+ assert_array_equals(d, [0, 0, 0, 0], "This pixel should be transparent black.");
+}
+
+function checkCrop(imageBitmap)
+{
+ var canvas = document.createElement("canvas");
+ canvas.width = 50;
+ canvas.height = 50;
+ var ctx = canvas.getContext("2d");
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.drawImage(imageBitmap, 0, 0);
+ var d = ctx.getImageData(0, 0, 1, 1).data;
+ assert_array_equals(d, [255, 0, 0, 255], "This pixel should be red.");
+ d = ctx.getImageData(19, 0, 1, 1).data;
+ assert_array_equals(d, [0, 255, 0, 255], "This pixel should be green.");
+ d = ctx.getImageData(0, 19, 1, 1).data;
+ assert_array_equals(d, [0, 0, 255, 255], "This pixel should be blue.");
+ d = ctx.getImageData(19, 19, 1, 1).data;
+ assert_array_equals(d, [0, 0, 0, 255], "This pixel should be black.");
+ d = ctx.getImageData(21, 21, 1, 1).data;
+ assert_array_equals(d, [0, 0, 0, 0], "This pixel should be transparent black.");
+}
+
+function compareBitmaps(bitmap1, bitmap2)
+{
+ var canvas1 = document.createElement("canvas");
+ var canvas2 = document.createElement("canvas");
+ canvas1.width = 50;
+ canvas1.height = 50;
+ canvas2.width = 50;
+ canvas2.height = 50;
+ var ctx1 = canvas1.getContext("2d");
+ var ctx2 = canvas2.getContext("2d");
+ ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
+ ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
+ ctx1.drawImage(bitmap1, 0, 0);
+ ctx2.drawImage(bitmap2, 0, 0);
+ var data1 = ctx1.getImageData(0, 0, 50, 50).data;
+ var data2 = ctx2.getImageData(0, 0, 50, 50).data;
+ var dataMatched = true;
+ for (var i = 0; i < data1.length; i++) {
+ if (data1[i] != data2[i]) {
+ dataMatched = false;
+ break;
+ }
+ }
+ assert_false(dataMatched);
+}
+
+function testImageBitmap(source)
+{
+ return Promise.all([
+ createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "high"}),
+ createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "medium"}),
+ createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "low"}),
+ createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "pixelated"}),
+ createImageBitmap(source, 5, 5, 10, 10, {resizeWidth: 20, resizeHeight: 20, resizeQuality: "high"}),
+ createImageBitmap(source, 5, 5, 10, 10, {resizeWidth: 20, resizeHeight: 20, resizeQuality: "medium"}),
+ createImageBitmap(source, 5, 5, 10, 10, {resizeWidth: 20, resizeHeight: 20, resizeQuality: "low"}),
+ createImageBitmap(source, 5, 5, 10, 10, {resizeWidth: 20, resizeHeight: 20, resizeQuality: "pixelated"}),
+ ]).then(([noCropHigh, noCropMedium, noCropLow, noCropPixelated, cropHigh, cropMedium, cropLow, cropPixelated]) => {
+ checkNoCrop(noCropHigh);
+ checkNoCrop(noCropMedium);
+ checkNoCrop(noCropLow);
+ checkNoCrop(noCropPixelated);
+ checkCrop(cropHigh);
+ checkCrop(cropMedium);
+ checkCrop(cropLow);
+ checkCrop(cropPixelated);
+ // Brute-force comparison among all bitmaps is too expensive
+ compareBitmaps(noCropHigh, noCropMedium);
+ compareBitmaps(noCropLow, noCropPixelated);
+ compareBitmaps(cropHigh, cropMedium);
+ compareBitmaps(cropLow, cropPixelated);
+ });
+}
+
+function initializeTestCanvas()
+{
+ var testCanvas = document.createElement("canvas");
+ testCanvas.width = 20;
+ testCanvas.height = 20;
+ var testCtx = testCanvas.getContext("2d");
+ testCtx.fillStyle = "rgb(255, 0, 0)";
+ testCtx.fillRect(0, 0, 10, 10);
+ testCtx.fillStyle = "rgb(0, 255, 0)";
+ testCtx.fillRect(10, 0, 10, 10);
+ testCtx.fillStyle = "rgb(0, 0, 255)";
+ testCtx.fillRect(0, 10, 10, 10);
+ testCtx.fillStyle = "rgb(0, 0, 0)";
+ testCtx.fillRect(10, 10, 10, 10);
+ return testCanvas;
+}
+
+// Blob
+promise_test(function() {
+ return new Promise((resolve, reject) => {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", '/images/pattern.png');
+ xhr.responseType = 'blob';
+ xhr.send();
+ xhr.onload = function() {
+ resolve(xhr.response);
+ };
+ }).then(testImageBitmap);
+}, 'createImageBitmap from a Blob with resize option.');
+
+// HTMLCanvasElement
+promise_test(function() {
+ var testCanvas = initializeTestCanvas();
+ return testImageBitmap(testCanvas);
+}, 'createImageBitmap from a HTMLCanvasElement with resize option.');
+
+// HTMLImageElement
+promise_test(function() {
+ return new Promise((resolve, reject) => {
+ var image = new Image();
+ image.onload = function() {
+ resolve(image);
+ }
+ image.src = '/images/pattern.png'
+ }).then(testImageBitmap);
+}, 'createImageBitmap from a HTMLImageElement with resize option.');
+
+// HTMLImageElement of svg with no specified size
+promise_test(function() {
+ return new Promise((resolve, reject) => {
+ var image = new Image();
+ image.onload = function() {
+ resolve(image);
+ }
+ image.src = '/images/pattern-nosize.svg'
+ }).then(testImageBitmap);
+}, 'createImageBitmap from a HTMLImageElement of svg with no specified size with resize option.');
+
+// ImageBitmap
+promise_test(function() {
+ var testCanvas = initializeTestCanvas();
+ return createImageBitmap(testCanvas).then(testImageBitmap);
+}, 'createImageBitmap from an ImageBitmap with resize option.');
+
+// ImageData
+promise_test(function() {
+ var canvas = initializeTestCanvas();
+ var ctx = canvas.getContext("2d");
+ var data = ctx.getImageData(0, 0, 20, 20);
+ return testImageBitmap(data);
+}, 'createImageBitmap from an ImageData with resize option.');
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-video-resize.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-video-resize.html
new file mode 100644
index 0000000000..d48d9e80ca
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/canvas-createImageBitmap-video-resize.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<script>
+function createNewCanvas(width, height)
+{
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ var ctx = canvas.getContext("2d");
+ ctx.clearRect(0, 0, width, height);
+ return ctx;
+}
+
+function checkLowResult(imageBitmap, bw, bh, video, sx, sy, sw, sh)
+{
+ var ctx1 = createNewCanvas(bw, bh);
+ var ctx2 = createNewCanvas(bw, bh);
+ ctx1.drawImage(imageBitmap, 0, 0);
+ ctx2.drawImage(video, sx, sy, sw, sh, 0, 0, bw, bh);
+ var data1 = ctx1.getImageData(0, 0, bw, bh).data;
+ var data2 = ctx2.getImageData(0, 0, bw, bh).data;
+ var dataMatched = true;
+ for (var i = 0; i < data1.length; i++) {
+ // data1[i] is strictly the same as data2[i] on software rendering.
+ // But on GPU, the difference could be quite significant.
+ if (Math.abs(data1[i] - data2[i]) > 33) {
+ dataMatched = false;
+ break;
+ }
+ }
+ assert_true(dataMatched);
+}
+
+function generateTest()
+{
+ bitmapWidth = video.videoWidth/2;
+ bitmapHeight = video.videoHeight/2;
+ return Promise.all([
+ createImageBitmap(video, {resizeWidth: bitmapWidth, resizeHeight: bitmapHeight, resizeQuality: "low"}),
+ createImageBitmap(video, 10, 10, bitmapWidth, bitmapHeight, {resizeWidth: bitmapWidth, resizeHeight: bitmapHeight, resizeQuality: "low"}),
+ ]).then(t.step_func_done(([noCropLow, cropLow]) => {
+ checkLowResult(noCropLow, bitmapWidth, bitmapHeight, video, 0, 0, video.videoWidth, video.videoHeight);
+ checkLowResult(cropLow, bitmapWidth, bitmapHeight, video, 10, 10, bitmapWidth, bitmapHeight);
+ }), t.step_func_done(function() {
+ assert_true(false, 'Promise rejected');
+ }));
+}
+
+var t = async_test('createImageBitmap(HTMLVideoElement) with resize option');
+
+// HTMLVideoElement
+var video = document.createElement("video");
+video.preload = "auto";
+if (video.requestVideoFrameCallback) {
+ video.requestVideoFrameCallback(t.step_func(() => generateTest()));
+} else {
+ video.oncanplaythrough = t.step_func(() => generateTest());
+}
+video.src = getVideoURI("/media/counting");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/common.sub.js b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/common.sub.js
new file mode 100644
index 0000000000..1889035202
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/common.sub.js
@@ -0,0 +1,168 @@
+function makeCanvas() {
+ return new Promise(resolve => {
+ var testCanvas = document.createElement("canvas");
+ testCanvas.width = 20;
+ testCanvas.height = 20;
+ var testCtx = testCanvas.getContext("2d");
+ testCtx.fillStyle = "rgb(255, 0, 0)";
+ testCtx.fillRect(0, 0, 10, 10);
+ testCtx.fillStyle = "rgb(0, 255, 0)";
+ testCtx.fillRect(10, 0, 10, 10);
+ testCtx.fillStyle = "rgb(0, 0, 255)";
+ testCtx.fillRect(0, 10, 10, 10);
+ testCtx.fillStyle = "rgb(0, 0, 0)";
+ testCtx.fillRect(10, 10, 10, 10);
+ resolve(testCanvas);
+ });
+}
+
+function makeOffscreenCanvas() {
+ return new Promise(resolve => {
+ let canvas = new OffscreenCanvas(20, 20);
+ var testCtx = canvas.getContext("2d");
+ testCtx.fillStyle = "rgb(255, 0, 0)";
+ testCtx.fillRect(0, 0, 10, 10);
+ testCtx.fillStyle = "rgb(0, 255, 0)";
+ testCtx.fillRect(10, 0, 10, 10);
+ testCtx.fillStyle = "rgb(0, 0, 255)";
+ testCtx.fillRect(0, 10, 10, 10);
+ testCtx.fillStyle = "rgb(0, 0, 0)";
+ testCtx.fillRect(10, 10, 10, 10);
+ resolve(canvas);
+ });
+}
+
+var imageBitmapVideoPromise = new Promise(function(resolve, reject) {
+ var video = document.createElement("video");
+ video.oncanplaythrough = function() {
+ resolve(video);
+ };
+ video.onerror = reject;
+
+ // preload=auto is required to ensure a frame is available once
+ // canplaythrough is fired. The default of preload=metadata does not
+ // gaurantee this.
+ video.preload = "auto";
+ video.src = getVideoURI("/images/pattern");
+
+ // Prevent WebKit from garbage collecting event handlers.
+ window._video = video;
+});
+
+function makeVideo() {
+ return imageBitmapVideoPromise;
+}
+
+var imageBitmapDataUrlVideoPromise = fetch(getVideoURI("/images/pattern"))
+ .then(response => Promise.all([response.headers.get("Content-Type"), response.arrayBuffer()]))
+ .then(([type, data]) => {
+ return new Promise(function(resolve, reject) {
+ var video = document.createElement("video");
+ video.oncanplaythrough = function() {
+ resolve(video);
+ };
+ video.onerror = reject;
+
+ var encoded = btoa(String.fromCodePoint(...new Uint8Array(data)));
+ var dataUrl = `data:${type};base64,${encoded}`;
+
+ // preload=auto is required to ensure a frame is available once
+ // canplaythrough is fired. The default of preload=metadata does not
+ // gaurantee this.
+ video.preload = "auto";
+ video.src = dataUrl;
+
+ // Prevent WebKit from garbage collecting event handlers.
+ window._dataVideo = video;
+ });
+ });
+
+function makeDataUrlVideo() {
+ return imageBitmapDataUrlVideoPromise;
+}
+
+function makeMakeHTMLImage(src) {
+ return function() {
+ return new Promise((resolve, reject) => {
+ var img = new Image();
+ img.onload = function() {
+ resolve(img);
+ };
+ img.onerror = reject;
+ img.src = src;
+ });
+ }
+}
+
+function makeMakeSVGImage(src) {
+ return function() {
+ return new Promise((resolve, reject) => {
+ var image = document.createElementNS("http://www.w3.org/2000/svg", "image");
+ image.onload = () => resolve(image);
+ image.onerror = reject;
+ image.setAttribute("externalResourcesRequired", "true");
+ image.setAttributeNS("http://www.w3.org/1999/xlink", 'xlink:href', src);
+ document.body.appendChild(image);
+ });
+ }
+}
+
+function makeImageData() {
+ return new Promise(function(resolve, reject) {
+ var width = 20, height = 20;
+ var imgData = new ImageData(width, height);
+ for (var i = 0; i < width * height * 4; i += 4) {
+ imgData.data[i] = 0;
+ imgData.data[i + 1] = 0;
+ imgData.data[i + 2] = 0;
+ imgData.data[i + 3] = 255; //alpha channel: 255
+ }
+ var halfWidth = width / 2;
+ var halfHeight = height / 2;
+ // initialize to R, G, B, Black, with each one 10*10 pixels
+ for (var i = 0; i < halfHeight; i++)
+ for (var j = 0; j < halfWidth; j++)
+ imgData.data[i * width * 4 + j * 4] = 255;
+ for (var i = 0; i < halfHeight; i++)
+ for (var j = halfWidth; j < width; j++)
+ imgData.data[i * width * 4 + j * 4 + 1] = 255;
+ for (var i = halfHeight; i < height; i++)
+ for (var j = 0; j < halfWidth; j++)
+ imgData.data[i * width * 4 + j * 4 + 2] = 255;
+ resolve(imgData);
+ });
+}
+
+function makeImageBitmap() {
+ return makeCanvas().then(canvas => {
+ return createImageBitmap(canvas);
+ });
+}
+
+function makeBlob(src) {
+ return function () {
+ return new Promise(function(resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", src);
+ xhr.responseType = 'blob';
+ xhr.send();
+ xhr.onload = function() {
+ resolve(xhr.response);
+ };
+ });
+ }
+}
+
+var imageSourceTypes = [
+ { name: 'an HTMLCanvasElement', factory: makeCanvas },
+ { name: 'an HTMLVideoElement', factory: makeVideo },
+ { name: 'an HTMLVideoElement from a data URL', factory: makeDataUrlVideo },
+ { name: 'a bitmap HTMLImageElement', factory: makeMakeHTMLImage("/images/pattern.png") },
+ { name: 'a vector HTMLImageElement', factory: makeMakeHTMLImage("/images/pattern.svg") },
+ { name: 'a bitmap SVGImageElement', factory: makeMakeSVGImage("/images/pattern.png") },
+ { name: 'a vector SVGImageElement', factory: makeMakeSVGImage("/images/pattern.svg") },
+ { name: 'an OffscreenCanvas', factory: makeOffscreenCanvas },
+ { name: 'an ImageData', factory: makeImageData },
+ { name: 'an ImageBitmap', factory: makeImageBitmap },
+ { name: 'a Blob', factory: makeBlob("/images/pattern.png") },
+];
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-blob-invalidtype.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-blob-invalidtype.html
new file mode 100644
index 0000000000..23af96408a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-blob-invalidtype.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap: blob with wrong mime type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<script>
+promise_test(t => {
+ // Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
+ const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
+ "ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
+
+ let bytes = new Array(IMAGE.length);
+ for (let i = 0; i < IMAGE.length; i++) {
+ bytes[i] = IMAGE.charCodeAt(i);
+ }
+
+ let blob = new Blob([new Uint8Array(bytes)], { type: "text/html"});
+
+ return window.createImageBitmap(blob)
+ .then(imageBitmap => {
+ assert_true(true, "Image created!");
+ assert_equals(imageBitmap.width, 1, "Image is 1x1");
+ assert_equals(imageBitmap.height, 1, "Image is 1x1");
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-bounds.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-bounds.html
new file mode 100644
index 0000000000..a2dcf0cc0b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-bounds.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap: clipping to the bitmap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<div id="results"></div>
+<script>
+const color = 204;
+function testClip( name, sx, sy, sw, sh, expectedColors, expectedWidth, expectedHeight ) {
+ promise_test(function(t) {
+ return new Promise(function(resolve, reject) {
+ const image = new Image();
+ image.onload = function() { resolve(image); };
+ image.onerror = function() { reject(); };
+ image.src = "/images/green-16x16.png";
+ }).then(function(image) {
+ return createImageBitmap(image, sx, sy, sw, sh);
+ }).then(function(imageBitmap) {
+
+ assert_equals(imageBitmap.width, expectedWidth);
+ assert_equals(imageBitmap.height, expectedHeight);
+
+ const canvas = document.createElement("canvas");
+ canvas.width = 16;
+ canvas.height = 16;
+
+ // debug
+ document.getElementById("results").append(canvas);
+ canvas.setAttribute("style", "width: 100px; height: 100px;");
+
+ const ctx = canvas.getContext("2d");
+ ctx.fillStyle = `rgb(${color}, ${color}, ${color})`;
+ ctx.fillRect(0, 0, 20, 20);
+ ctx.drawImage(imageBitmap, 0, 0);
+
+ for (let [x, y, r, g, b, a] of expectedColors) {
+ _assertPixel(canvas, x,y, r,g,b,a);
+ }
+ });
+ }, name);
+}
+testClip( "simple clip inside",
+ 8, 8, 8, 8, [
+ [ 4, 4, 0,255,0,255], [12, 4, color,color,color,255],
+ [ 4, 12, color,color,color,255], [12, 12, color,color,color,255]
+ ], 8, 8
+);
+testClip( "clip outside negative",
+ -8, -8, 16, 16, [
+ [ 4, 4, color,color,color,255], [12, 4, color,color,color,255],
+ [ 4, 12, color,color,color,255], [12, 12, 0,255,0,255]
+ ], 16, 16
+);
+testClip( "clip outside positive",
+ 8, 8, 16, 16, [
+ [ 4, 4, 0,255,0,255], [12, 4, color,color,color,255],
+ [ 4, 12, color,color,color,255], [12, 12, color,color,color,255]
+ ], 16, 16
+);
+testClip( "clip inside using negative width and height",
+ 24, 24, -16, -16, [
+ [ 4, 4, 0,255,0,255], [12, 4, color,color,color,255],
+ [ 4, 12, color,color,color,255], [12, 12, color,color,color,255]
+ ], 16, 16
+);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-colorSpaceConversion.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-colorSpaceConversion.html
new file mode 100644
index 0000000000..2ddf3648f5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-colorSpaceConversion.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<title>Test colorSpaceConversion option for createImageBitmap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<script src="/common/media.js"></script>
+<script src="common.sub.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body>
+<script>
+function testCanvasDisplayingPattern(canvas, width, height)
+{
+ var tolerance = 10; // high tolerance for differing color management results
+ const check = (x, y, r, g, b, a) =>
+ _assertPixelApprox(canvas, x,y, r,g,b,a, tolerance);
+
+ check(1 * width / 4, 1 * height / 4, 124,0,27,255);
+ check(3 * width / 4, 1 * height / 4, 0,124,46,255);
+ check(1 * width / 4, 3 * height / 4, 60,0,123,255);
+ check(3 * width / 4, 3 * height / 4, 0,0,0,255);
+}
+
+function testDrawImageBitmap(source, options)
+{
+ var canvas = document.createElement("canvas");
+ canvas.width = 20;
+ canvas.height = 20;
+ var ctx = canvas.getContext("2d");
+ return createImageBitmap(source, options).then(imageBitmap => {
+ ctx.drawImage(imageBitmap, 0, 0);
+ testCanvasDisplayingPattern(canvas, 20, 20);
+ });
+}
+
+var wideGamutImageSourceTypes = [
+ {name: 'a bitmap HTMLImageElement', factory: makeMakeHTMLImage("/images/wide-gamut-pattern.png")},
+ {name: 'a Blob', factory: makeBlob("/images/wide-gamut-pattern.png")},
+];
+
+for (let { name, factory } of wideGamutImageSourceTypes) {
+ promise_test(function() {
+ return factory().then(function(img) {
+ return testDrawImageBitmap(img, {colorSpaceConversion: "none"});
+ });
+ }, `createImageBitmap from ${name}, and drawImage on the created ImageBitmap with colorSpaceConversion: none`);
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage-closed.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage-closed.html
new file mode 100644
index 0000000000..3b8644cff5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage-closed.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>attempt to draw a closed ImageBitmap to a 2d canvas throws INVALID_STATE_ERR</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<script>
+promise_test(function(t) {
+ return new Promise(function(resolve, reject) {
+ const image = new Image();
+ image.onload = function() { resolve(image); };
+ image.onerror = function() { reject(); };
+ image.src = "/images/green-16x16.png";
+ }).then(function(image) {
+ return createImageBitmap(image, 0, 0, 16, 16);
+ }).then(function(imageBitmap) {
+ imageBitmap.close();
+
+ const canvas = document.createElement("canvas");
+ canvas.width = 16;
+ canvas.height = 16;
+
+ const ctx = canvas.getContext("2d");
+ assert_throws_dom("InvalidStateError", function() { ctx.drawImage(imageBitmap, 0, 0); });
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage.html
new file mode 100644
index 0000000000..5b5698813a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-drawImage.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap + drawImage test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<script src="/common/media.js"></script>
+<script src="common.sub.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body>
+<script>
+function testCanvasDisplayingPattern(canvas, width, height, sourceIsVideo)
+{
+ var tolerance = 3;
+ let topLeft = [255, 0, 0, 255];
+ let topRight = [0, 255, 0, 255];
+ let bottomLeft = [0, 0, 255, 255];
+ let bottomRight = [0, 0, 0, 255];
+ if (sourceIsVideo) {
+ // The source video uses colors in the Rec.601 color space whose
+ // values are close to full red, full green, full blue, and black,
+ // but when converted to sRGB, are somewhat different.
+ topLeft = [247, 37, 0, 255];
+ topRight = [63, 251, 0, 255];
+ bottomLeft = [28, 35, 255, 255];
+ bottomRight = [5, 0, 2, 255];
+ }
+ const check = (x, y, [r, g, b, a]) =>
+ _assertPixelApprox(canvas, x,y, r,g,b,a, tolerance);
+ check(1 * width / 4, 1 * height / 4, topLeft);
+ check(3 * width / 4, 1 * height / 4, topRight);
+ check(1 * width / 4, 3 * height / 4, bottomLeft);
+ check(3 * width / 4, 3 * height / 4, bottomRight);
+}
+
+function testDrawImageBitmap(source, args = [], { resizeWidth = 20, resizeHeight = 20 } = {})
+{
+ let sourceIsVideo = source instanceof HTMLVideoElement;
+ var canvas = document.createElement("canvas");
+ canvas.width = resizeWidth;
+ canvas.height = resizeHeight;
+ var ctx = canvas.getContext("2d");
+ return createImageBitmap(source, ...args).then(imageBitmap => {
+ assert_equals(imageBitmap.width, resizeWidth);
+ assert_equals(imageBitmap.height, resizeHeight);
+ ctx.drawImage(imageBitmap, 0, 0);
+ testCanvasDisplayingPattern(canvas, resizeWidth, resizeHeight, sourceIsVideo);
+ });
+}
+
+for (let { name, factory } of imageSourceTypes) {
+ promise_test(function() {
+ return factory().then(function(img) {
+ return testDrawImageBitmap(img);
+ });
+ }, `createImageBitmap from ${name}, and drawImage on the created ImageBitmap`);
+
+ promise_test(function() {
+ return factory().then(function(img) {
+ const options = { resizeWidth: 10, resizeHeight: 10 };
+ return testDrawImageBitmap(img, [options], options);
+ });
+ }, `createImageBitmap from ${name} scaled down, and drawImage on the created ImageBitmap`);
+
+ promise_test(function() {
+ return factory().then(function(img) {
+ const options = { resizeWidth: 40, resizeHeight: 40 };
+ return testDrawImageBitmap(img, [options], options);
+ });
+ }, `createImageBitmap from ${name} scaled up, and drawImage on the created ImageBitmap`);
+
+ promise_test(function() {
+ return factory().then(function(img) {
+ const options = { resizeWidth: 10, resizeHeight: 40 };
+ return testDrawImageBitmap(img, [options], options);
+ });
+ }, `createImageBitmap from ${name} resized, and drawImage on the created ImageBitmap`);
+
+ promise_test(function() {
+ return factory().then(function(img) {
+ return testDrawImageBitmap(img, [20, 20, -20, -20]);
+ });
+ }, `createImageBitmap from ${name} with negative sw/sh, and drawImage on the created ImageBitmap`);
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation.html
new file mode 100644
index 0000000000..8b2a33e85b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<title>Test that createImageBitmap honors EXIF orientation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>canvas { outline: 1px solid black; margin-right: 1em; }</style>
+<body>
+<script>
+function loadImage(src) {
+ return new Promise(function(resolve) {
+ const image = new Image();
+ image.addEventListener("load", () => resolve(image), { once: true });
+ image.src = src;
+ });
+}
+
+function checkColors(ctx, w, h, expectedColors) {
+ let data = ctx.getImageData(0, 0, w, h).data;
+ for (let [row, col, r, g, b, a] of expectedColors) {
+ let x = col * 80 + 40;
+ let y = row * 80 + 40;
+ let i = (x + y * w) * 4;
+
+ let expected = [r, g, b, a];
+ let actual = [data[i], data[i + 1], data[i + 2], data[i + 3]];
+
+ assert_array_approx_equals(actual, expected, 1, `Pixel value at (${x},${y}) ${expected} =~ ${actual}.`);
+ }
+}
+
+async_test(function(t) {
+ const canvas = document.createElement("canvas");
+ canvas.width = 320;
+ canvas.height = 160;
+ document.body.append(canvas);
+
+ const ctx = canvas.getContext("2d");
+ loadImage("resources/squares_6.jpg")
+ .then((image) => createImageBitmap(image))
+ .then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0);
+ checkColors(ctx, canvas.width, canvas.height, [
+ // row, col, r, g, b, a
+ [0, 0, 255, 0, 0, 255],
+ [0, 1, 0, 255, 0, 255],
+ [0, 2, 0, 0, 255, 255],
+ [0, 3, 0, 0, 0, 255],
+ [1, 0, 255, 128, 128, 255],
+ [1, 1, 128, 255, 128, 255],
+ [1, 2, 128, 128, 255, 255],
+ [1, 3, 128, 128, 128, 255],
+ ]);
+ }));
+}, "createImageBitmap with EXIF rotation, imageOrientation from-image, and no cropping");
+
+async_test(function(t) {
+ const canvas = document.createElement("canvas");
+ canvas.width = 320;
+ canvas.height = 160;
+ document.body.append(canvas);
+
+ const ctx = canvas.getContext("2d");
+ loadImage("resources/squares_6.jpg")
+ .then((image) => createImageBitmap(image, { imageOrientation: "flipY" }))
+ .then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0);
+ checkColors(ctx, canvas.width, canvas.height, [
+ // row, col, r, g, b, a
+ [0, 0, 255, 128, 128, 255],
+ [0, 1, 128, 255, 128, 255],
+ [0, 2, 128, 128, 255, 255],
+ [0, 3, 128, 128, 128, 255],
+ [1, 0, 255, 0, 0, 255],
+ [1, 1, 0, 255, 0, 255],
+ [1, 2, 0, 0, 255, 255],
+ [1, 3, 0, 0, 0, 255],
+ ]);
+ }));
+}, "createImageBitmap with EXIF rotation, imageOrientation flipY, and no cropping");
+
+async_test(function(t) {
+ const canvas = document.createElement("canvas");
+ canvas.width = 160;
+ canvas.height = 160;
+ document.body.append(canvas);
+
+ const ctx = canvas.getContext("2d");
+ loadImage("resources/squares_6.jpg")
+ .then(image => createImageBitmap(image, 80, 0, 160, 160))
+ .then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0);
+ checkColors(ctx, canvas.width, canvas.height, [
+ // row, col, r, g, b, a
+ [0, 0, 0, 255, 0, 255],
+ [0, 1, 0, 0, 255, 255],
+ [1, 0, 128, 255, 128, 255],
+ [1, 1, 128, 128, 255, 255],
+ ]);
+ }));
+}, "createImageBitmap with EXIF rotation, imageOrientation from-image, and cropping");
+
+async_test(function(t) {
+ const canvas = document.createElement("canvas");
+ canvas.width = 160;
+ canvas.height = 160;
+ document.body.append(canvas);
+
+ const ctx = canvas.getContext("2d");
+ loadImage("resources/squares_6.jpg")
+ .then(image => createImageBitmap(image, 80, 0, 160, 160, { imageOrientation: "flipY" }))
+ .then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0);
+ checkColors(ctx, canvas.width, canvas.height, [
+ // row, col, r, g, b, a
+ [0, 0, 128, 255, 128, 255],
+ [0, 1, 128, 128, 255, 255],
+ [1, 0, 0, 255, 0, 255],
+ [1, 1, 0, 0, 255, 255],
+ ]);
+ }));
+}, "createImageBitmap with EXIF rotation, imageOrientation flipY, and cropping");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation_none.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation_none.html
new file mode 100644
index 0000000000..807925b88a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-exif-orientation_none.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>Test that createImageBitmap honors EXIF orientation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>canvas { outline: 1px solid black; margin-right: 1em; }</style>
+<body>
+<script>
+function loadImage(src) {
+ return new Promise(function(resolve) {
+ const image = new Image();
+ image.addEventListener("load", () => resolve(image), { once: true });
+ image.src = src;
+ });
+}
+
+function checkColors(ctx, w, h, is_verticle, expectedColors) {
+ let data = ctx.getImageData(0, 0, w, h).data;
+ row_width = 80;
+ col_width = 80;
+
+ for (let [row, col, r, g, b, a] of expectedColors) {
+ let x = col * row_width + 10;
+ let y = row * col_width + 10;
+ let i = (x + y * w) * 4;
+
+ let expected = [r, g, b, a];
+ let actual = [data[i], data[i + 1], data[i + 2], data[i + 3]];
+
+ assert_array_approx_equals(actual, expected, 1, `Pixel value at (${x},${y}) ${expected} =~ ${actual}.`);
+ }
+}
+
+for (let orientation of [1, 2, 3, 4, 5, 6, 7, 8]) {
+ async_test(function(t) {
+ const canvas = document.createElement("canvas");
+ canvas.width = 160;
+ canvas.height = 320;
+ document.body.append(canvas);
+
+ const ctx = canvas.getContext("2d");
+ loadImage(`resources/squares_${orientation}.jpg`)
+ .then((image) => createImageBitmap(image, { imageOrientation: "none" }))
+ .then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0, 160, 320);
+
+ checkColors(ctx, canvas.width, canvas.height, false, [
+ // row, col, r, g, b, a
+ [0, 0, 0, 0, 0, 255],
+ [0, 1, 128, 128, 128, 255],
+ [1, 0, 0, 0, 255, 255],
+ [1, 1, 128, 128, 255, 255],
+ [2, 0, 0, 255, 0, 255],
+ [2, 1, 128, 255, 128, 255],
+ [3, 0, 255, 0, 0, 255],
+ [3, 1, 255, 128, 128, 255],
+ ]);
+ }));
+ }, `createImageBitmap with Orientation ${orientation}`);
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-flipY.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-flipY.html
new file mode 100644
index 0000000000..9b0d2dfb79
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-flipY.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap + drawImage test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<script src="/common/media.js"></script>
+<script src="common.sub.js"></script>
+<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">
+<body>
+<script>
+function testCanvasDisplayingPattern(canvas, width, height, sourceIsVideo, flipped)
+{
+ var tolerance = 3;
+ let topLeft = [255, 0, 0, 255];
+ let topRight = [0, 255, 0, 255];
+ let bottomLeft = [0, 0, 255, 255];
+ let bottomRight = [0, 0, 0, 255];
+ if (sourceIsVideo) {
+ // The source video uses colors in the Rec.601 color space whose
+ // values are close to full red, full green, full blue, and black,
+ // but when converted to sRGB, are somewhat different.
+ topLeft = [247, 37, 0, 255];
+ topRight = [63, 251, 0, 255];
+ bottomLeft = [28, 35, 255, 255];
+ bottomRight = [5, 0, 2, 255];
+ }
+ if (flipped) {
+ [topLeft, bottomLeft] = [bottomLeft, topLeft];
+ [topRight, bottomRight] = [bottomRight, topRight];
+ }
+ const check = (x, y, [r, g, b, a]) =>
+ _assertPixelApprox(canvas, x,y, r,g,b,a, tolerance);
+ check(1 * width / 4, 1 * height / 4, topLeft);
+ check(3 * width / 4, 1 * height / 4, topRight);
+ check(1 * width / 4, 3 * height / 4, bottomLeft);
+ check(3 * width / 4, 3 * height / 4, bottomRight);
+}
+
+function testDrawImageBitmap(source, args = [], flipped, { resizeWidth = 20, resizeHeight = 20 } = {})
+{
+ let sourceIsVideo = source instanceof HTMLVideoElement;
+ var canvas = document.createElement("canvas");
+ canvas.width = resizeWidth;
+ canvas.height = resizeHeight;
+ var ctx = canvas.getContext("2d");
+ return createImageBitmap(source, ...args).then(imageBitmap => {
+ assert_equals(imageBitmap.width, resizeWidth);
+ assert_equals(imageBitmap.height, resizeHeight);
+ ctx.drawImage(imageBitmap, 0, 0);
+ testCanvasDisplayingPattern(canvas, resizeWidth, resizeHeight, sourceIsVideo, flipped);
+ });
+}
+
+for (let { name, factory } of imageSourceTypes) {
+ promise_test(function() {
+ return factory().then(function(img) {
+ const options = { imageOrientation: 'from-image' };
+ return testDrawImageBitmap(img, [options], false);
+ });
+ }, `createImageBitmap from ${name} imageOrientation: "from-image", and drawImage on the created ImageBitmap`);
+
+ promise_test(function() {
+ return factory().then(function(img) {
+ const options = { imageOrientation: 'flipY' };
+ return testDrawImageBitmap(img, [options], true);
+ });
+ }, `createImageBitmap from ${name} imageOrientation: "flipY", and drawImage on the created ImageBitmap`);
+
+}
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-in-worker-transfer.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-in-worker-transfer.html
new file mode 100644
index 0000000000..727a8a4978
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-in-worker-transfer.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createImageBitmap in worker and transfer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+promise_test(function(t) {
+ return new Promise(function(resolve, reject) {
+ var worker = new Worker("createImageBitmap-worker.js");
+ worker.addEventListener("message", function(evt) {
+ var bitmap = evt.data;
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+ resolve();
+ });
+ worker.postMessage('test');
+ });
+}, 'Transfer ImageBitmap created in worker');
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-invalid-args.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-invalid-args.html
new file mode 100644
index 0000000000..3cae3523ef
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-invalid-args.html
@@ -0,0 +1,239 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<script src="common.sub.js"></script>
+<script>
+
+function makeOversizedCanvas() {
+
+ return new Promise(resolve => {
+ let canvas = document.createElement('canvas');
+ canvas.setAttribute('width', '100000000');
+ canvas.setAttribute('height', '100000000');
+ resolve(canvas);
+ });
+}
+
+function makeOversizedOffscreenCanvas() {
+ return new Promise(resolve =>{
+ let canvas = new OffscreenCanvas(100000000, 100000000);
+ resolve(canvas);
+ });
+}
+
+function makeInvalidBlob() {
+ return new Promise(resolve => {
+ resolve(new Blob()); // Blob with no data cannot be decoded.
+ });
+}
+
+function makeBrokenImage() {
+ return new Promise((resolve, reject) => {
+ const image = new Image();
+ image.src = "data:,x";
+ image.onload = reject;
+ image.onerror = () => resolve(image);
+ });
+}
+
+function makeAvailableButBrokenImage(path) {
+ return new Promise((resolve, reject) => {
+ const image = new Image();
+ image.src = path;
+ image.onload = () => resolve(image);
+ image.onerror = reject;
+ });
+}
+
+testCases = [
+ {
+ description: 'createImageBitmap with <sourceType> source and sw set to 0',
+ promiseTestFunction:
+ (source, t) => {
+ return promise_rejects_js(t, RangeError,
+ createImageBitmap(source, 0, 0, 0, 10));
+ }
+ },
+ {
+ description: 'createImageBitmap with <sourceType> source and sh set to 0',
+ promiseTestFunction:
+ (source, t) => {
+ return promise_rejects_js(t, RangeError,
+ createImageBitmap(source, 0, 0, 10, 0));
+ }
+ },
+ {
+ description: 'createImageBitmap with <sourceType> source and oversized ' +
+ '(unallocatable) crop region',
+ promiseTestFunction:
+ (source, t) => {
+ return createImageBitmap(source, 0, 0, 100000000, 100000000)
+ .then(i => {
+ assert_equals(i.width, 100000000);
+ assert_equals(i.height, 100000000);
+ })
+ .catch(e => {
+ // This case is not explicitly documented in the specification for
+ // createImageBitmap, but it is expected that internal failures
+ // cause InvalidStateError.
+ //
+ // Note: https://bugs.chromium.org/p/chromium/issues/detail?id=799025
+ assert_throws_dom("InvalidStateError", () => { throw e });
+ });
+ }
+ },
+ {
+ description: 'createImageBitmap with <sourceType> source and ' +
+ 'a value of 0 int resizeWidth',
+ promiseTestFunction:
+ (source, t) => {
+ return createImageBitmap(source, {resizeWidth:0, resizeHeight:10})
+ .catch(e => {
+ assert_throws_dom("InvalidStateError", () => { throw e });
+ });
+ }
+ },
+ {
+ description: 'createImageBitmap with <sourceType> source and ' +
+ 'a value of 0 in resizeHeight',
+ promiseTestFunction:
+ (source, t) => {
+ return createImageBitmap(source, {resizeWidth:10, resizeHeight:0})
+ .catch(e => {
+ assert_throws_dom("InvalidStateError", () => { throw e });
+ });
+ }
+ },
+ {
+ description: 'createImageBitmap with <sourceType> source and ' +
+ 'a value between 0 and 1 in resizeWidth',
+ promiseTestFunction:
+ (source, t) => {
+ return createImageBitmap(source, {resizeWidth:0.5, resizeHeight:10})
+ .catch(e => {
+ assert_throws_dom("InvalidStateError", () => { throw e });
+ });
+ }
+ },
+ {
+ description: 'createImageBitmap with <sourceType> source and ' +
+ 'a value between 0 and 1 in resizeHeight',
+ promiseTestFunction:
+ (source, t) => {
+ return createImageBitmap(source, {resizeWidth:10, resizeHeight:0.5})
+ .catch(e => {
+ assert_throws_dom("InvalidStateError", () => { throw e });
+ });
+ }
+ },
+];
+
+// Generate the test matrix for each sourceType + testCase combo.
+imageSourceTypes.forEach(imageSourceType => {
+ testCases.forEach(testCase => {
+ let description = testCase.description.replace('<sourceType>',
+ imageSourceType.name);
+ promise_test( t => {
+ return imageSourceType.factory().then(source => {
+ return testCase.promiseTestFunction(source, t);
+ });
+ }, description);
+ });
+});
+
+promise_test( t => {
+ return promise_rejects_js(t, TypeError, createImageBitmap(undefined));
+}, "createImageBitmap with undefined image source.");
+
+promise_test( t => {
+ return promise_rejects_js(t, TypeError, createImageBitmap(null));
+}, "createImageBitmap with null image source.");
+
+promise_test( t => {
+ var context = document.createElement("canvas").getContext("2d");
+ return promise_rejects_js(t, TypeError, createImageBitmap(context));
+}, "createImageBitmap with CanvasRenderingContext2D image source.");
+
+promise_test( t => {
+ var context = document.createElement("canvas").getContext("webgl");
+ return promise_rejects_js(t, TypeError, createImageBitmap(context));
+}, "createImageBitmap with WebGLRenderingContext image source.");
+
+promise_test( t => {
+ var buffer = new Uint8Array();
+ return promise_rejects_js(t, TypeError, createImageBitmap(buffer));
+}, "createImageBitmap with Uint8Array image source.");
+
+promise_test( t => {
+ var buffer = new ArrayBuffer(8);
+ return promise_rejects_js(t, TypeError, createImageBitmap(buffer));
+}, "createImageBitmap with ArrayBuffer image source.");
+
+promise_test( t => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(new Image()));
+}, "createImageBitmap with empty image source.");
+
+promise_test( t => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(document.createElement('video')));
+}, "createImageBitmap with empty video source.");
+
+promise_test( t => {
+ return makeOversizedCanvas().then(canvas => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(canvas));
+ });
+}, "createImageBitmap with an oversized canvas source.");
+
+promise_test( t => {
+ return makeOversizedOffscreenCanvas().then(offscreenCanvas => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(offscreenCanvas));
+ });
+}, "createImageBitmap with an invalid OffscreenCanvas source.");
+
+promise_test( t => {
+ return makeInvalidBlob().then(blob => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(blob));
+ });
+}, "createImageBitmap with an undecodable blob source.");
+
+promise_test( t => {
+ return makeBrokenImage().then(image => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(image));
+ });
+}, "createImageBitmap with a broken image source.");
+
+promise_test( t => {
+ return makeAvailableButBrokenImage("/images/undecodable.png").then(image => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(image));
+ });
+}, "createImageBitmap with an available but undecodable image source.");
+
+promise_test( t => {
+ return makeAvailableButBrokenImage("/images/red-zeroheight.svg").then(image => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(image));
+ });
+}, "createImageBitmap with an available but zero height image source.");
+
+promise_test( t => {
+ return makeAvailableButBrokenImage("/images/red-zerowidth.svg").then(image => {
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(image));
+ });
+}, "createImageBitmap with an available but zero width image source.");
+
+promise_test( t => {
+ return makeImageBitmap().then(bitmap => {
+ bitmap.close()
+ return promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(bitmap));
+ });
+}, "createImageBitmap with a closed ImageBitmap.");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-origin.sub.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-origin.sub.html
new file mode 100644
index 0000000000..ae3d23cfbc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-origin.sub.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createImageBitmap: origin-clean flag</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/common/media.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<div id=log></div>
+<script>
+
+function assert_origin_unclean_getImageData(bitmap) {
+ const context = document.createElement("canvas").getContext("2d");
+ context.drawImage(bitmap, 0, 0);
+ assert_throws_dom("SecurityError", () => {
+ context.getImageData(0, 0, 1, 1);
+ });
+}
+
+function assert_origin_unclean_drawImage(bitmap) {
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+ ctx.drawImage(bitmap, 0, 0);
+ assert_throws_dom('SecurityError', () => canvas.toDataURL());
+}
+
+function assert_origin_unclean_transferFromImageBitmap(bitmap) {
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext('bitmaprenderer');
+ ctx.transferFromImageBitmap(bitmap);
+ assert_throws_dom('SecurityError', () => canvas.toDataURL());
+}
+
+forEachCanvasSource(get_host_info().HTTP_REMOTE_ORIGIN,
+ get_host_info().HTTP_ORIGIN,
+ (name, factory) => {
+ promise_test(function() {
+ return factory().then(createImageBitmap).then(assert_origin_unclean_getImageData);
+ }, `${name}: origin unclear getImageData`);
+ promise_test(function() {
+ return factory().then(createImageBitmap).then(assert_origin_unclean_drawImage);
+ }, `${name}: origin unclear 2dContext.drawImage`);
+ promise_test(function() {
+ return factory().then(createImageBitmap).then(assert_origin_unclean_transferFromImageBitmap);
+ }, `${name}: origin unclear bitmaprenderer.transferFromImageBitmap`);
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-serializable.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-serializable.html
new file mode 100644
index 0000000000..c185cd9cbd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-serializable.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createImageBitmap serialize test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/namespaces.js"></script>
+<script src="/common/media.js"></script>
+<script src="common.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<div id=log></div>
+<script>
+let worker, continuations = {};
+setup(function() {
+ worker = new Worker("transfer-worker.js");
+ worker.addEventListener("message", function(event) {
+ let { name, bitmap } = event.data;
+ if (continuations.hasOwnProperty(name)) {
+ continuations[name](bitmap);
+ }
+ });
+});
+
+for (let { name, factory } of imageSourceTypes) {
+ promise_test(function(t) {
+ return factory().then(createImageBitmap).then(function(bitmap) {
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+
+ worker.postMessage({ name: t.name, bitmap: bitmap });
+
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+
+ return new Promise(function(resolve) {
+ continuations[t.name] = resolve;
+ });
+ }).then(function(bitmap) {
+ assert_class_string(bitmap, "ImageBitmap");
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+ });
+ }, `Serialize ImageBitmap created from ${name}`);
+}
+
+promise_test(async (t) => {
+ const url = get_host_info().REMOTE_ORIGIN + '/images/pattern.png';
+ const image = await makeMakeHTMLImage(url)();
+ const bitmap = await createImageBitmap(image);
+
+ assert_throws_dom('DataCloneError', () => worker.postMessage(bitmap));
+}, 'Serializing a non-origin-clean ImageBitmap throws.');
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-sizeOverflow.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-sizeOverflow.html
new file mode 100644
index 0000000000..25c1fb6885
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-sizeOverflow.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap with size overflow</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+promise_test(function() {
+ var imgData = new ImageData(20, 20);
+ return createImageBitmap(imgData, 4294967400, 10, 10, 10);
+}, "createImageBitmap does not crash or reject the promise when passing very large sx");
+
+promise_test(function() {
+ var imgData = new ImageData(20, 20);
+ return createImageBitmap(imgData, 10, 4294967400, 10, 10);
+}, "createImageBitmap does not crash or reject the promise when passing very large sy");
+
+promise_test(function() {
+ var imgData = new ImageData(20, 20);
+ return createImageBitmap(imgData, 10, 10, 4294967400, 10);
+}, "createImageBitmap does not crash or reject the promise when passing very large sw");
+
+promise_test(function() {
+ var imgData = new ImageData(20, 20);
+ return createImageBitmap(imgData, 10, 10, 10, 4294967400);
+}, "createImageBitmap does not crash or reject the promise when passing very large sh");
+
+promise_test(function() {
+ var imgData = new ImageData(20, 20);
+ return createImageBitmap(imgData, 4294967400, 4294967400, 4294967400, 4294967400);
+}, "createImageBitmap does not crash or reject the promise when passing very large sx, sy, sw and sh");
+
+promise_test(function(t) {
+ var imgData = new ImageData(20, 20);
+ var imageBitmapOptions = {imageOrientation:'from-image', premultiplyAlpha:'default',
+ colorSpaceConversion:'none', resizeHeight:2122252543, resizeQuality:'high'};
+ return createImageBitmap(imgData, 0, 0, 4294967295, 64)
+ .then(imageBitmap => promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(imageBitmap, imageBitmapOptions)));
+}, "createImageBitmap throws an InvalidStateError error with big imageBitmap scaled up in big height");
+
+promise_test(function(t) {
+ var imgData = new ImageData(20, 20);
+ var imageBitmapOptions = {imageOrientation:'from-image', premultiplyAlpha:'default',
+ colorSpaceConversion:'none', resizeWidth:2122252543, resizeQuality:'high'};
+ return createImageBitmap(imgData, 0, 0, 4294967295, 64)
+ .then(imageBitmap => promise_rejects_dom(t, "InvalidStateError",
+ createImageBitmap(imageBitmap, imageBitmapOptions)));
+}, "createImageBitmap throws an InvalidStateError error with big imageBitmap scaled up in big width");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-transfer.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-transfer.html
new file mode 100644
index 0000000000..3ec02fcbf4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-transfer.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createImageBitmap transferring test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<script src="common.sub.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<div id=log></div>
+<script>
+let worker, continuations = {};
+setup(function() {
+ worker = new Worker("transfer-worker.js");
+ worker.addEventListener("message", function(event) {
+ let { name, bitmap } = event.data;
+ if (continuations.hasOwnProperty(name)) {
+ continuations[name](bitmap);
+ }
+ });
+});
+
+for (let { name, factory } of imageSourceTypes) {
+ promise_test(function(t) {
+ return factory().then(createImageBitmap).then(function(bitmap) {
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+
+ worker.postMessage({ name: t.name, bitmap: bitmap }, [bitmap]);
+
+ assert_equals(bitmap.width, 0);
+ assert_equals(bitmap.height, 0);
+
+ return new Promise(function(resolve) {
+ continuations[t.name] = resolve;
+ });
+ }).then(function(bitmap) {
+ assert_class_string(bitmap, "ImageBitmap");
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+ });
+ }, `Transfer ImageBitmap created from ${name}`);
+}
+
+promise_test(async (t) => {
+ const url = get_host_info().REMOTE_ORIGIN + '/images/pattern.png';
+ const image = await makeMakeHTMLImage(url)();
+ const bitmap = await createImageBitmap(image);
+
+ assert_throws_dom('DataCloneError',
+ () => worker.postMessage(bitmap, [bitmap]));
+}, 'Transferring a non-origin-clean ImageBitmap throws.');
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-worker.js b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-worker.js
new file mode 100644
index 0000000000..67a0904e47
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/createImageBitmap-worker.js
@@ -0,0 +1,17 @@
+function makeBlob() {
+ return new Promise(function(resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", '/images/pattern.png');
+ xhr.responseType = 'blob';
+ xhr.send();
+ xhr.onload = function() {
+ resolve(xhr.response);
+ };
+ });
+}
+
+addEventListener("message", () => {
+ makeBlob().then(createImageBitmap).then(bitmap => {
+ postMessage(bitmap, [bitmap]);
+ });
+});
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation-expected.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation-expected.html
new file mode 100644
index 0000000000..64b1791afe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation-expected.html
@@ -0,0 +1,18 @@
+<html>
+<body>
+ <canvas id="myCanvas" width="400" height="400"></canvas>
+</body>>
+<script>
+var canvas = document.getElementById('myCanvas');
+ctx = canvas.getContext('2d');
+image = document.createElement("img");
+image.src = "../../../resources/black_white.png"
+image.onload = function() {
+ Promise.all([
+ createImageBitmap(image, { imageOrientation: 'flipY' }),
+ ]).then(function(sprites) {
+ // Draw image onto the canvas
+ ctx.drawImage(sprites[0], 0, 0);
+});
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation.html
new file mode 100644
index 0000000000..e93c17c8e8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmap-from-imageData-no-image-rotation.html
@@ -0,0 +1,26 @@
+<html>
+ <link rel="match" href="imageBitmap-from-imageData-no-image-rotation-expected.html" />
+ <style type="text/css">
+ canvas {
+ image-orientation: none;
+ }
+ </style>
+<body>
+ <canvas id="myCanvas" width="400" height="400"></canvas>
+</body>>
+<script>
+var canvas = document.getElementById('myCanvas');
+ctx = canvas.getContext('2d');
+image = document.createElement("img");
+image.src = "../../../resources/black_white.png"
+image.onload = function() {
+ Promise.all([
+ // The image should be flipped and ignoring "image-orientation" setting
+ // in css style.
+ createImageBitmap(image, { imageOrientation: 'flipY' }),
+ ]).then(function(sprites) {
+ // Draw image onto the canvas
+ ctx.drawImage(sprites[0], 0, 0);
+});
+}
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-expected.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-expected.html
new file mode 100644
index 0000000000..bababda44c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+ <p>Test whether the imageOrientation "from-image" works when creating an ImageBitmap from the ImageData of a canvas, and then transfered to an ImageBitmapRenderingContext.</p>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+
+function drawSquares(ctx) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0,0,150,150);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(150,0,300,150);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0,150,150,300);
+}
+
+async function runTest() {
+ const canvas = document.getElementById('canvas');
+ canvas.width = 300;
+ canvas.height = 300;
+ const ctx = canvas.getContext('2d');
+ drawSquares(ctx);
+}
+
+runTest();
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped-expected.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped-expected.html
new file mode 100644
index 0000000000..5e21671973
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped-expected.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+ <p>Test whether the imageOrientation "flipY" works when creating an ImageBitmap from the ImageData of a canvas, and then transfered to an ImageBitmapRenderingContext.</p>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+
+function drawSquares(ctx) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0,150,150,150);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(150,150,300,150);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0,0,150,150);
+}
+
+async function runTest() {
+ const canvas = document.getElementById('canvas');
+ canvas.width = 300;
+ canvas.height = 300;
+ const ctx = canvas.getContext('2d');
+ drawSquares(ctx);
+}
+
+runTest();
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped.html
new file mode 100644
index 0000000000..02e0690876
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-flipped.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<link rel="match" href="imageBitmapRendering-transferFromImageBitmap-flipped-expected.html" />
+<body>
+ <p>Test whether the imageOrientation "flipY" works when creating an ImageBitmap from the ImageData of a canvas, and then transfered to an ImageBitmapRenderingContext.</p>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+
+function drawSquares(ctx) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0,0,150,150);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(150,0,300,150);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0,150,150,300);
+}
+
+async function runTest() {
+ const canvas_temp = document.createElement('canvas');
+ canvas_temp.width = 300;
+ canvas_temp.height = 300;
+ const ctx_temp = canvas_temp.getContext('2d');
+ drawSquares(ctx_temp);
+ const imageSource = ctx_temp.getImageData(0, 0, 300, 300);
+ const imageOrientation = 'flipY';
+ imageIDFlipped = await createImageBitmap(imageSource, 0, 0, 300, 300, { imageOrientation });
+ const canvas = document.getElementById('canvas');
+ const ctx = canvas.getContext('bitmaprenderer');
+ ctx.transferFromImageBitmap(imageIDFlipped);
+}
+
+runTest();
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl-expected.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl-expected.html
new file mode 100644
index 0000000000..4f155316f0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+
+<body>
+ <p>
+ Test creating an ImageBitmap from the transferToImageBitmap of a webgl OffscreenCanvas, and then
+ transferred to an ImageBitmapRenderingContext.
+ </p>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+
+ function drawSquares(ctx) {
+ ctx.enable(ctx.SCISSOR_TEST);
+ ctx.scissor(0, 150, 150, 150);
+ ctx.clearColor(1, 0, 0, 1);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(150, 150, 300, 150);
+ ctx.clearColor(0, 1, 0, 1);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(0, 0, 150, 150);
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ }
+
+ async function runTest() {
+ const canvas = document.getElementById('canvas');
+ canvas.width = 300;
+ canvas.height = 300;
+ const ctx = canvas.getContext('webgl');
+ drawSquares(ctx);
+ }
+
+ runTest();
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl.html
new file mode 100644
index 0000000000..049a3822cd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap-webgl.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<link rel="match" href="imageBitmapRendering-transferFromImageBitmap-webgl-expected.html" />
+
+<body>
+ <p>
+ Test creating an ImageBitmap from the transferToImageBitmap of a webgl OffscreenCanvas, and then
+ transferred to an ImageBitmapRenderingContext.
+ </p>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+
+ function drawSquares(ctx) {
+ ctx.enable(ctx.SCISSOR_TEST);
+ ctx.scissor(0, 150, 150, 150);
+ ctx.clearColor(1, 0, 0, 1);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(150, 150, 300, 150);
+ ctx.clearColor(0, 1, 0, 1);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ ctx.scissor(0, 0, 150, 150);
+ ctx.clearColor(0, 0, 1, 1);
+ ctx.clear(ctx.COLOR_BUFFER_BIT);
+ }
+
+ async function runTest() {
+ const offscreen = new OffscreenCanvas(300, 300);
+ const ctxOffscreen = offscreen.getContext('webgl');
+ drawSquares(ctxOffscreen);
+ const image = offscreen.transferToImageBitmap();
+ const canvas = document.getElementById('canvas');
+ const ctx = canvas.getContext('bitmaprenderer');
+ ctx.transferFromImageBitmap(image);
+ }
+
+ runTest();
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap.html
new file mode 100644
index 0000000000..6d3d886759
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imageBitmapRendering-transferFromImageBitmap.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<link rel="match" href="imageBitmapRendering-transferFromImageBitmap-expected.html" />
+<body>
+ <p>Test whether the imageOrientation "from-image" works when creating an ImageBitmap from the ImageData of a canvas, and then transfered to an ImageBitmapRenderingContext.</p>
+ <canvas id="canvas" width="300" height="300"></canvas>
+</body>
+<script>
+
+function drawSquares(ctx) {
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0,0,150,150);
+ ctx.fillStyle = 'green';
+ ctx.fillRect(150,0,300,150);
+ ctx.fillStyle = 'blue';
+ ctx.fillRect(0,150,150,300);
+}
+
+async function runTest() {
+ const canvas_temp = document.createElement('canvas');
+ canvas_temp.width = 300;
+ canvas_temp.height = 300;
+ const ctx_temp = canvas_temp.getContext('2d');
+ drawSquares(ctx_temp);
+ const imageSource = ctx_temp.getImageData(0, 0, 300, 300);
+ const imageOrientation = 'from-image';
+ imageIDFlipped = await createImageBitmap(imageSource, 0, 0, 300, 300, { imageOrientation });
+ const canvas = document.getElementById('canvas');
+ const ctx = canvas.getContext('bitmaprenderer');
+ ctx.transferFromImageBitmap(imageIDFlipped);
+}
+
+runTest();
+
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imagebitmap-replication-exif-orientation.html b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imagebitmap-replication-exif-orientation.html
new file mode 100644
index 0000000000..ab4331adef
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/imagebitmap-replication-exif-orientation.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify that image orientation is propagated when ImageBitmap objects are replicated.</title>
+<link rel="author" title="Justin Novosad" href="mailto:junov@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+<script>
+// This test is most relevant for browser implementations that apply EXIF image
+// orientation lazily. That is to say that the transform is applied at rasterization
+// time rather than at image decode time. This implies that image orientation metadata
+// is stored internally in the decoded image's data structure. This test ensures
+// that the orientation metadata is correctly carried over when ImageBitmap objects
+// are replicated (serialized/deserialized, copied or transferred).
+
+function checkImageBitmapRotated(bitmap) {
+ assert_equals(bitmap.width, 320, 'Bitmap width');
+ assert_equals(bitmap.height, 160, 'Bitmap height');
+
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+
+ const expected_colors = [
+ // row, col, r, g, b, a
+ [0, 0, 255, 0, 0, 255],
+ [0, 1, 0, 255, 0, 255],
+ [0, 2, 0, 0, 255, 255],
+ [0, 3, 0, 0, 0, 255],
+ [1, 0, 255, 128, 128, 255],
+ [1, 1, 128, 255, 128, 255],
+ [1, 2, 128, 128, 255, 255],
+ [1, 3, 128, 128, 128, 255],
+ ];
+
+ canvas.width = bitmap.width;
+ canvas.height = bitmap.height;
+ ctx.drawImage(bitmap, 0, 0);
+
+ let data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
+ for (let [row, col, r, g, b, a] of expected_colors) {
+ let x = col * 80 + 40;
+ let y = row * 80 + 40;
+ let i = (x + y * canvas.width) * 4;
+ let expected = [r, g, b, a];
+ let actual = [data[i], data[i + 1], data[i + 2], data[i + 3]];
+ assert_array_approx_equals(actual, expected, 1, `Pixel value at (${x},${y}) ${expected} =~ ${actual}.`);
+ }
+}
+
+promise_test(async t => {
+ const response = await fetch("resources/squares_6.jpg");
+ const blob = await response.blob();
+ const image = await createImageBitmap(blob)
+ const image_copy = structuredClone(image);
+ checkImageBitmapRotated(image_copy);
+}, "ImageBitmap from file with EXIF rotation, duplicated via structuredClone");
+
+promise_test(async t => {
+ const image = new Image();
+ image.src = "resources/squares_6.jpg"
+ await new Promise(resolve => image.onload = resolve);
+ const image_copy = await createImageBitmap(image);
+ checkImageBitmapRotated(image_copy);
+}, "ImageBitmap from file with EXIF rotation, loaded via <img>");
+
+promise_test(async t => {
+ const image = new Image();
+ image.src = "resources/squares_6.jpg"
+ // The following has no effect because the image's style is not
+ // processed unless the element is connected to the DOM.
+ image.style.imageOrientation = "none";
+ await new Promise(resolve => image.onload = resolve);
+ const image_copy = await createImageBitmap(image);
+ checkImageBitmapRotated(image_copy);
+}, "ImageBitmap from file with EXIF rotation, loaded via <img> not in DOM, imageOrientation = none");
+
+promise_test(async t => {
+ const image = new Image();
+ document.body.appendChild(image);
+ image.src = "resources/squares_6.jpg"
+ // The style is being processed in this case, but the imageOrientation
+ // CSS property must still have no effect because createImageBitmap
+ // accesses the element's underlying media directly, without being
+ // affected by the image's style (unlike drawImage).
+ image.style.imageOrientation = "none";
+ await new Promise(resolve => image.onload = resolve);
+ const image_copy = await createImageBitmap(image);
+ checkImageBitmapRotated(image_copy);
+}, "ImageBitmap from file with EXIF rotation, loaded via <img> in DOM, imageOrientation = none");
+
+
+promise_test(async t => {
+ const response = await fetch("resources/squares_6.jpg");
+ const blob = await response.blob();
+ const image = await createImageBitmap(blob);
+ const image_copy = await createImageBitmap(image);
+ checkImageBitmapRotated(image_copy);
+}, "ImageBitmap from file with EXIF rotation, duplicated via createImageBitmap");
+
+promise_test(async t => {
+ const worker = new Worker("serialize-worker.js");
+ const response = await fetch("resources/squares_6.jpg");
+ const blob = await response.blob()
+ const image = await createImageBitmap(blob);
+ worker.postMessage({bitmap: image});
+ const bitmap = (await new Promise(resolve => {worker.addEventListener("message", resolve)})).data.bitmap;
+ checkImageBitmapRotated(bitmap);
+}, "ImageBitmap from file with EXIF rotation, duplicated via worker serialization round-trip");
+
+promise_test(async t => {
+ const worker = new Worker("transfer-worker.js");
+ let response = await fetch("resources/squares_6.jpg");
+ let blob = await response.blob();
+ let image = await createImageBitmap(blob);
+ worker.postMessage({bitmap: image}, [image]);
+ const bitmap = (await new Promise(resolve => {worker.addEventListener("message", resolve)})).data.bitmap;
+ checkImageBitmapRotated(bitmap);
+}, "ImageBitmap from file with EXIF rotation, duplicated via worker transfer round-trip");
+
+promise_test(async t => {
+ // This test variant ensures additional code coverage.
+ // By creating a canvas pattern, a reference to the ImageBitmap's
+ // underlying pixel data is held in the source realm. This forces
+ // implementations that do lazy copying to duplicate the pixel
+ // data at transfer time. This test verifies that the lazy
+ // duplication code path (if applicable) carries over the image
+ // orientation metadata.
+ const worker = new Worker("transfer-worker.js");
+ let response = await fetch("resources/squares_6.jpg");
+ let blob = await response.blob();
+ let image = await createImageBitmap(blob);
+ const canvas = document.createElement('canvas');
+ const ctx = canvas.getContext('2d');
+ const pattern = ctx.createPattern(image, 'repeat');
+ worker.postMessage({bitmap: image}, [image]);
+ const bitmap = (await new Promise(resolve => {worker.addEventListener("message", resolve)})).data.bitmap;
+ checkImageBitmapRotated(bitmap);
+}, "ImageBitmap from file with EXIF rotation, duplicated via worker transfer round-trip, while referenced by a CanvasPattern");
+
+
+</script>
+</body> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_1.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_1.jpg
new file mode 100644
index 0000000000..0f0e8866b4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_1.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_2.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_2.jpg
new file mode 100644
index 0000000000..526f7a6c82
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_2.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_3.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_3.jpg
new file mode 100644
index 0000000000..a21e521c2d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_3.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_4.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_4.jpg
new file mode 100644
index 0000000000..c4380b1e67
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_4.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_5.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_5.jpg
new file mode 100644
index 0000000000..0bdd89aa1b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_5.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_6.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_6.jpg
new file mode 100644
index 0000000000..f197760a11
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_6.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_7.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_7.jpg
new file mode 100644
index 0000000000..9b1a346888
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_7.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_8.jpg b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_8.jpg
new file mode 100644
index 0000000000..41d2fbe7f0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/resources/squares_8.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/serialize-worker.js b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/serialize-worker.js
new file mode 100644
index 0000000000..a76537cc9e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/serialize-worker.js
@@ -0,0 +1,3 @@
+addEventListener('message', evt => {
+ postMessage(evt.data);
+});
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/transfer-worker.js b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/transfer-worker.js
new file mode 100644
index 0000000000..55465a899c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/transfer-worker.js
@@ -0,0 +1,3 @@
+addEventListener('message', evt => {
+ postMessage(evt.data, [evt.data.bitmap]);
+});
diff --git a/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/worker-onmessage-noop.js b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/worker-onmessage-noop.js
new file mode 100644
index 0000000000..c0a352b4d9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/imagebitmap/worker-onmessage-noop.js
@@ -0,0 +1,3 @@
+self.onmessage = function(e) {
+};
+
diff --git a/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers-expected.html b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers-expected.html
new file mode 100644
index 0000000000..873869ea72
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers-expected.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Canvas test: unclosed-layers</title>
+<h1>unclosed-layers</h1>
+<p class="desc">Check that unclosed layers aren't rendered.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers.html b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers.html
new file mode 100644
index 0000000000..afb53cfbeb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-layers.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<link rel="match" href="unclosed-layers-expected.html">
+<title>Canvas test: unclosed-layers</title>
+<h1>unclosed-layers</h1>
+<p class="desc">Check that unclosed layers aren't rendered.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.beginLayer({filter: {name: 'dropShadow', dx: -2, dy: 2}});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers-expected.html b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers-expected.html
new file mode 100644
index 0000000000..8557441f7e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers-expected.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Canvas test: unclosed-nested-layers</title>
+<h1>unclosed-nested-layers</h1>
+<p class="desc">Check that unclosed nested layers aren't rendered.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0,0,255,1)';
+ ctx.fillRect(60,60,75,50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers.html b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers.html
new file mode 100644
index 0000000000..ada874a51a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/layers/unclosed-nested-layers.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<link rel="match" href="unclosed-nested-layers-expected.html">
+<title>Canvas test: unclosed-nested-layers</title>
+<h1>unclosed-nested-layers</h1>
+<p class="desc">Check that unclosed nested layers aren't rendered.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+ // Missing ctx.endLayer() here.
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001-ref.htm
new file mode 100644
index 0000000000..f85af9aab2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: "square" lineCap</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: The square value of lineCap means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, must be added at the end of each line.</p>
+ <div><img src='/images/black-rectangle.png' alt='black rect' /></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001.htm b/testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001.htm
new file mode 100644
index 0000000000..583dbc9d13
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/line-styles/canvas_linestyles_linecap_001.htm
@@ -0,0 +1,37 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: "square" lineCap</title>
+ <link rel="match" href="canvas_linestyles_linecap_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-linecap" />
+ <meta name="assert" content="The square value of lineCap means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, must be added at the end of each line." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw the first red rectangle.
+ ctx.fillStyle ="rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(75, 0, 25, 50);
+
+ // Draw second red rectangle.
+ ctx.fillRect(0, 0, 25, 50);
+
+ // Draw a line with square lineCap.
+ ctx.strokeStyle = "rgba(0, 0, 0, 1.0)";
+ ctx.lineWidth = 50;
+ ctx.lineCap = "square";
+ ctx.beginPath();
+ ctx.moveTo(25, 25);
+ ctx.lineTo(75, 25);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: The square value of lineCap means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, must be added at the end of each line.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_a.html b/testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_a.html
new file mode 100644
index 0000000000..7e692f937d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_a.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel=match href=lineto_ref.html>
+<style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ }
+</style>
+<canvas id="c" width="150" height="150" >
+Your browser does not support the HTML5 canvas tag.</canvas>
+
+<script>
+var c = document.getElementById("c");
+var ctx = c.getContext("2d");
+
+ctx.beginPath();
+ctx.moveTo(20, 20);
+ctx.lineTo(20, 130);
+ctx.lineTo(130, 130);
+ctx.lineTo(130, 20);
+ctx.closePath();
+
+ctx.fillStyle = '#90EE90';
+ctx.fill();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_ref.html b/testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_ref.html
new file mode 100644
index 0000000000..3dc78ff804
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/line-styles/lineto_ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ }
+ div {
+ background: #90EE90;
+ width: 110px;
+ height: 110px;
+ margin: 20px;
+ }
+</style>
+<div></div>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/line-styles/setLineDash.html b/testing/web-platform/tests/html/canvas/element/manual/line-styles/setLineDash.html
new file mode 100644
index 0000000000..6b8d131da4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/line-styles/setLineDash.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>setLineDash</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/canvas/resources/canvas-tests.js"></script>
+<canvas id="canvas"></canvas>
+<script>
+test(function() {
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+
+ var initial = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+ ctx.setLineDash(initial);
+ assert_array_equals(ctx.getLineDash(), initial, "line dash sanity");
+
+ ctx.setLineDash([Infinity]);
+ assert_array_equals(ctx.getLineDash(), initial, "Inf doesn't reset line dash");
+
+ ctx.setLineDash([NaN]);
+ assert_array_equals(ctx.getLineDash(), initial, "NaN doesn't reset line dash");
+
+ ctx.setLineDash([-1]);
+ assert_array_equals(ctx.getLineDash(), initial, "Negative doesn't reset line dash");
+}, "Invalid arguments to setLineDash()");
+
+test(function() {
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ assert_equals(ctx.lineDashOffset, 0);
+
+ ctx.setLineDash([15, 10]);
+ ctx.lineDashOffset = 5;
+ ctx.strokeRect(10,10,100,100);
+
+ var lineDash = ctx.getLineDash();
+ assert_array_equals(lineDash, [15, 10]);
+ assert_equals(ctx.lineDashOffset, 5);
+
+ ctx.setLineDash([5, 10, 15]);
+ ctx.strokeRect(20, 20, 120, 120);
+ lineDash = ctx.getLineDash();
+ assert_array_equals(lineDash, [5, 10, 15, 5, 10, 15]);
+
+ ctx.setLineDash(["1", 2]);
+ lineDash = ctx.getLineDash();
+ assert_array_equals(lineDash, [1, 2]);
+
+ ctx.clearRect(0, 0, 700, 700);
+ assert_equals(ctx.lineDashOffset, 5);
+
+ ctx.setLineDash([20, 10]);
+ ctx.lineDashOffset = 0;
+ // Make the test immune to plaform anti-aliasing discrepancies.
+ ctx.lineWidth = 4;
+ ctx.strokeStyle = '#00FF00';
+ ctx.strokeRect(10.5, 10.5, 30, 30);
+
+ _assertPixel(canvas, 25, 10, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 35, 10, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 40, 25, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 40, 35, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 25, 40, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 15, 40, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 10, 25, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 10, 15, 0, 0, 0, 0, 0);
+
+ // Verify that lineDashOffset works as expected.
+ ctx.lineDashOffset = 20;
+ ctx.strokeRect(50.5, 10.5, 30, 30);
+ _assertPixel(canvas, 55, 10, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 65, 10, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 80, 15, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 80, 25, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 75, 40, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 65, 40, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 50, 35, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 50, 25, 0, 255, 0, 255, 0);
+
+ // Verify negative lineDashOffset.
+ ctx.lineDashOffset = -10;
+ ctx.strokeRect(90.5, 10.5, 30, 30);
+ _assertPixel(canvas, 95, 10, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 105, 10, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 120, 15, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 120, 25, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 115, 40, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 105, 40, 0, 255, 0, 255, 0);
+ _assertPixel(canvas, 90, 35, 0, 0, 0, 0, 0);
+ _assertPixel(canvas, 90, 25, 0, 255, 0, 255, 0);
+
+ // Ensure that all zeros or negative pattern does not cause error state in
+ // context.
+ ctx.setLineDash([0, 0]);
+ ctx.strokeRect(130.5, 10.5, 10, 10);
+ ctx.setLineDash([-1]);
+ ctx.strokeRect(130.5, 10.5, 10, 10);
+ _assertPixel(canvas, 135, 15, 0, 0, 0, 0, 0);
+ ctx.fillStyle = '#00FF00';
+ ctx.fillRect(130, 10, 10, 10);
+ _assertPixel(canvas, 135, 15, 0, 255, 0, 255, 0);
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm
new file mode 100644
index 0000000000..1763950d61
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_001.htm
@@ -0,0 +1,60 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Shadows for linear gradients</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" />
+ <meta name="assert" content="Shadows must be drawn for linear gradients." />
+ <script type="text/javascript">
+ async_test(function(t) {
+ window.addEventListener("load", t.step_func_done(function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a red rectangle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(150, 0, 100, 50);
+
+ // Set shadow styles to draw a black shadow to overlap the red rectangle.
+ ctx.shadowOffsetX = 150;
+ ctx.shadowColor = "rgba(0, 0, 0, 1.0)";
+
+ // Draw a left to right, green-to-blue linear gradient.
+ var lingrad = ctx.createLinearGradient(0, 50, 100, 50);
+ lingrad.addColorStop(0, "rgba(0, 255, 0, 1.0)");
+ lingrad.addColorStop(1, "rgba(0, 0, 255, 1.0)");
+ ctx.fillStyle = lingrad;
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Check the red is gone
+ var data = ctx.getImageData(150, 0, 100, 50);
+ for (var i = 0; i < data.data.length; i += 4) {
+ var r = data.data[i];
+ var g = data.data[i+1];
+ var b = data.data[i+2];
+ var a = data.data[i+3];
+ assert_equals(r, 0, "r channel");
+ assert_equals(g, 0, "g channel");
+ assert_equals(b, 0, "b channel");
+ assert_equals(a, 0xFF, "a channel");
+ }
+
+ for (var j = 0; j < data.data.length; j += 4) {
+ var r2 = data.data[j];
+ var g2 = data.data[j+1];
+ var b2 = data.data[j+2];
+ var a2 = data.data[j+3];
+ assert_false(r2 == 0xFF && g2 == 0 && b2 == 0 && a2 == 0xFF, "no red");
+ }
+ }));
+ }, "linear gradient fillRect draws shadow (black rectange)");
+ </script>
+ </head>
+ <body>
+ <p>Description: Shadows must be drawn for linear gradients.</p>
+ <p>Test passes if there is one gradient filled rectangle and one black rectangle, and no red seen on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm
new file mode 100644
index 0000000000..0658be808e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002-ref.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Shadows for images</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" />
+ <meta name="assert" content="Shadows must be drawn for images." />
+ <script type="text/javascript">
+ function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a black rectangle image on the canvas.
+ var img = document.getElementById("imgBlackRect");
+ ctx.drawImage(img, 0, 0);
+ ctx.drawImage(img, 150, 0);
+ }
+ </script>
+
+ </head>
+ <body onload="runTest()">
+ <p>Description: Shadows must be drawn for images.</p>
+ <p>Test passes if two black rectangles are shown and there is no red visible on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ <img id="imgBlackRect" style="display:none;" width="100" height="50" src="/images/black-rectangle.png">
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm
new file mode 100644
index 0000000000..908fffea13
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_002.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Shadows for images</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" />
+ <link rel="match" href="canvas_shadows_002-ref.htm" />
+ <meta name="assert" content="Shadows must be drawn for images." />
+ <script type="text/javascript">
+ function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a red rectangle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(150, 0, 100, 50);
+
+ // Set shadow styles to draw a black shadow to overlap the red rectangle.
+ ctx.shadowOffsetX = 150;
+ ctx.shadowColor = "rgba(0, 0, 0, 1.0)";
+
+ // Draw a black rectangle image on the canvas.
+ var img = document.getElementById("imgBlackRect");
+ ctx.drawImage(img, 0, 0);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: Shadows must be drawn for images.</p>
+ <p>Test passes if two black rectangles are shown and there is no red visible on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ <img id="imgBlackRect" style="display:none" width="100" height="50" src="/images/black-rectangle.png">
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html
new file mode 100644
index 0000000000..e568aa9a5c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors-expected.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>System Colors work for Canvas Drop-Shadow Filters</title>
+</head>
+<body>
+<div style="width: 100px; height: 100px; background-color: black"></div>
+<div style="width: 100px; height: 100px; background-color: GrayText"></div>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html
new file mode 100644
index 0000000000..42978fb18f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/canvas_shadows_system_colors.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>System Colors work for Canvas Drop-Shadow Filters</title>
+ <link rel="match" href="canvas_shadows_system_colors-expected.html">
+</head>
+<body>
+<canvas id='c' width="100" height="200">
+<script>
+// See crbug.com/1226282 and crbug.com/1081945
+// A reference test is necessary because system colors do not have defined
+// numeric values. Here we're comparing 'GrayText' to css 'GrayText'.
+var ctx = document.getElementById('c').getContext('2d');
+ctx.filter = 'drop-shadow(0px 100px 0 GrayText)';
+ctx.fillRect(0,0,100,100);
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html b/testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html
new file mode 100644
index 0000000000..eec27bf108
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/shadows/shadowBlur_gaussian_tolerance.1.html
@@ -0,0 +1,191 @@
+<!DOCTYPE HTML>
+<title>Test of canvas shadowBlur Gaussian blur pixel values</title>
+<meta charset=UTF-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<h1>Test of canvas shadowBlur Gaussian blur pixel values</h1>
+<script>
+
+/**
+ * See https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions
+ */
+function erf(x) {
+ if (x < 0) {
+ return -erf(-x);
+ }
+ var p = 0.3275911, a1 = 0.254829592, a2 = -0.284496736, a3 = 1.421413741, a4 = -1.453152027, a5 = 1.061405429;
+ var t = 1 / (1 + p * x);
+ return 1 - Math.exp(-x * x) * t * (a1 + t * (a2 + t * (a3 + t * (a4 + t * a5))));
+}
+
+/**
+ * See https://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_function
+ * and https://en.wikipedia.org/wiki/Normal_distribution#Numerical_approximations_for_the_normal_CDF
+ */
+function standard_normal_distribution_cumulative(x) {
+ return 0.5 * (1 + erf(x / Math.SQRT2));
+}
+
+/**
+ * Verify a single pixel; helper for run_blur_test.
+ * params - same as run_blur_test
+ * row & col - relative to the corner of the rectangle being blurred
+ * actual - actual color found there on the canvas
+ */
+function test_pixel(params, row, col, shadowOffset, actual) {
+ var expected_gaussian;
+ if (params.expected_sigma > 0) {
+ // Compute positions within a standard normal distribution (i.e.,
+ // where mean (μ) is and standard deviation (σ) is 1) in both
+ // dimensions.
+ // Add 0.5 because we want the middle of the pixel rather than the edge.
+ var pos_x = (col - shadowOffset + 0.5) / params.expected_sigma;
+ var pos_y = (row - shadowOffset + 0.5) / params.expected_sigma;
+
+ // Find the expected color value based on a Gaussian blur function.
+ // Since we're blurring the corner of a "very large" rectangle, we
+ // can, instead of sampling all of the pixels, use the cumulative
+ // form of the normal (Gaussian) distribution and pass it the
+ // position of the color transition (the edges of the rectangle),
+ // since we know everything above and to the left of that position
+ // is one color, and everything that is either below or to the right
+ // of that position is another color.
+ //
+ // NOTE: This assumes color-interpolation happens in sRGB rather
+ // than linearRGB. The canvas spec doesn't appear to be clear on
+ // this point. If it were linearRGB, we'd need to apply the
+ // correction after doing this calculation. (No correction to the
+ // input is needed since the input is all 0 or 1.)
+ expected_gaussian = standard_normal_distribution_cumulative(-pos_x) *
+ standard_normal_distribution_cumulative(-pos_y);
+ } else {
+ if (col >= shadowOffset || row >= shadowOffset) {
+ expected_gaussian = 0;
+ } else {
+ expected_gaussian = 1;
+ }
+ }
+ // TODO: maybe also compute expected value by triple box blur?
+
+ /*
+ * https://html.spec.whatwg.org/multipage/canvas.html#when-shadows-are-drawn
+ * describes how to draw shadows in canvas. It says, among other things:
+ *
+ * Perform a 2D Gaussian Blur on B, using σ as the standard deviation.
+ *
+ * without giving *any* allowance for error.
+ *
+ * However, other specifications that require Gaussian blurs allow some
+ * error; https://www.w3.org/TR/css-backgrounds-3/#shadow-blur allows up to
+ * 5%, and https://drafts.fxtf.org/filter-effects/#feGaussianBlurElement
+ * allows use of a triple box blur which is within 3%.
+ *
+ * Since expecting zero error is unreasonable, this test tests for the least
+ * restrictive of these bounds, the 5% error.
+ *
+ * Note that this allows 5% error in the color component, but there's no
+ * tolerance for error in the position; see comment below about sizes.
+ */
+
+ // Allow any rounding direction.
+ var min_b = Math.max( 0, Math.floor((expected_gaussian - 0.05) * 255));
+ var max_b = Math.min(255, Math.ceil ((expected_gaussian + 0.05) * 255));
+ var min_r = 255 - max_b;
+ var max_r = 255 - min_b;
+
+ var pos = "at row " + row + " col " + col + " ";
+
+ assert_true(min_r <= actual.r && actual.r <= max_r,
+ pos + "red component " + actual.r + " should be between " +
+ min_r + " and " + max_r + " (inclusive).");
+ assert_true(min_b <= actual.b && actual.b <= max_b,
+ pos + "blue component " + actual.b + " should be between " +
+ min_b + " and " + max_b + " (inclusive).");
+ assert_equals(actual.g, 0, pos + "green component should be 0");
+ assert_equals(actual.a, 255, pos + "alpha component should be 255");
+}
+
+/**
+ * Run a test of a single shadowBlur drawing operation. Expects a
+ * parameters object containing:
+ * name - name of test
+ * canvas_width - width of canvas to create
+ * canvas_height - height of canvas to create
+ * shadowBlur - shadowBlur to use for the test drawing operation
+ * expected_sigma - the standard deviation of the gaussian function
+ * that shadowBlur is expected to produce
+ * pixel_skip - how many pixels to skip when sampling results. Should
+ * be relatively prime with canvas_width.
+ */
+function run_blur_test(params) {
+ test(function() {
+ var canvas = document.createElement("canvas");
+ canvas.setAttribute("width", params.canvas_width);
+ canvas.setAttribute("height", params.canvas_height);
+ document.body.appendChild(canvas);
+ var cx = canvas.getContext("2d");
+
+ cx.fillStyle = "red";
+ cx.fillRect(0, 0, params.canvas_width, params.canvas_height);
+
+ // Fill a huge rect just to the top and left of the canvas, with its shadow
+ // blur centered at the middle of the canvas.
+ let edge = Math.floor(params.canvas_width / 2); // position of vertical
+ let big = Math.max(Math.ceil(params.expected_sigma * 1000),
+ params.canvas_width,
+ params.canvas_height);
+ cx.shadowBlur = params.shadowBlur;
+ cx.fillStyle = "green";
+ cx.shadowColor = "blue";
+ cx.shadowOffsetX = edge;
+ cx.shadowOffsetY = edge;
+ cx.fillRect(-big, -big, big, big);
+
+ var imageData =
+ cx.getImageData(0, 0, params.canvas_width, params.canvas_height);
+ for (var i = 0, i_max = params.canvas_width * params.canvas_height;
+ i < i_max;
+ i += params.pixel_skip) {
+ var row = Math.floor(i / params.canvas_width);
+ var col = i - row * params.canvas_width;
+
+ var actual = { r: imageData.data[i * 4],
+ g: imageData.data[i * 4 + 1],
+ b: imageData.data[i * 4 + 2],
+ a: imageData.data[i * 4 + 3] };
+
+ test_pixel(params, row, col, edge, actual);
+ }
+ }, "shadowBlur Gaussian pixel values for " + params.name);
+}
+
+run_blur_test({
+ name: "no blur",
+ canvas_width: 4,
+ canvas_height: 4,
+ shadowBlur: 0,
+ expected_sigma: 0,
+ pixel_skip: 1
+});
+run_blur_test({
+ name: "small blur",
+ canvas_width: 20,
+ canvas_height: 20,
+ // Try to test something smaller than 8 due to historic change in
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=10647 , but not too
+ // small, to avoid the error from rounding to individual pixels worth
+ // of box blur.
+ shadowBlur: 6,
+ expected_sigma: 3,
+ pixel_skip: 3
+});
+run_blur_test({
+ name: "large blur",
+ canvas_width: 100,
+ canvas_height: 100,
+ shadowBlur: 30,
+ expected_sigma: 15,
+ pixel_skip: 13
+});
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected-ref.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected-ref.html
new file mode 100644
index 0000000000..b36d29b97f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>HTML Canvas reference</title>
+<body>
+<canvas id=c>
+</body>
+<script>
+var c = document.getElementById("c");
+var ctx = c.getContext("2d");
+ctx.font = "50px monospace";
+ctx.fillText("Hello", 50, 75);
+ctx.font = "25px serif";
+ctx.fillText("World", 100, 100);
+c.style.border = "3px solid cyan";
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected.html
new file mode 100644
index 0000000000..a1715f6663
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.disconnected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>HTML Canvas testcase: canvas element not in document</title>
+<link rel=match href="canvas.2d.disconnected-ref.html">
+<meta name=fuzzy content="maxDifference=0-23;totalPixels=0-829">
+<body>
+</body>
+<script>
+var d = new Document();
+var c = d.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+var ctx = c.getContext("2d");
+ctx.font = "50px monospace";
+ctx.fillText("Hello", 50, 75);
+ctx.font = "25px serif";
+ctx.fillText("World", 100, 100);
+c.toBlob((blob) => {
+ var img = document.createElement("img");
+ const url = URL.createObjectURL(blob);
+ img.src = url;
+ img.style.border = "3px solid cyan";
+ document.body.appendChild(img);
+});
+</script>
+
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch-ref.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch-ref.html
new file mode 100644
index 0000000000..00ecdccad3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+function draw() {
+ ctx.font = '25px test';
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+document.fonts.add(f);
+
+f.load().then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.condensed.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.condensed.html
new file mode 100644
index 0000000000..72db41f007
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.condensed.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = condensed and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "condensed";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "condensed";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.expanded.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.expanded.html
new file mode 100644
index 0000000000..8a13ba13fc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.expanded.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = expanded and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "expanded";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "expanded";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-condensed.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-condensed.html
new file mode 100644
index 0000000000..afa910f62c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-condensed.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = extra-condensed and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "extra-condensed";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "extra-condensed";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-expanded.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-expanded.html
new file mode 100644
index 0000000000..d10d4d9312
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.extra-expanded.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = extra-expanded and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "extra-expanded";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "extra-expanded";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.normal.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.normal.html
new file mode 100644
index 0000000000..e8fd66acad
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.normal.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = normal and shows as fail for
+// fontStretch = expanded or condensed.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/fail.woff)');
+f.stretch = "expanded";
+document.fonts.add(f);
+
+var f1 = new FontFace('test', 'url(/fonts/pass.woff)');
+document.fonts.add(f1);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+f2.stretch = "condensed";
+document.fonts.add(f2);
+
+Promise.all([f.load(), f1.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-condensed.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-condensed.html
new file mode 100644
index 0000000000..2ac9719595
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-condensed.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = semi-condensed and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "semi-condensed";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "semi-condensed";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-expanded.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-expanded.html
new file mode 100644
index 0000000000..3c9fa27894
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.semi-expanded.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = semi-expanded and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "semi-expanded";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "semi-expanded";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-condensed.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-condensed.html
new file mode 100644
index 0000000000..2b0426e976
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-condensed.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = ultra-condensed and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "ultra-condensed";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "ultra-condensed";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-expanded.html b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-expanded.html
new file mode 100644
index 0000000000..5b4979de86
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas.2d.fontStretch.ultra-expanded.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.text.fontStretch</title>
+<link rel="match" href="canvas.2d.fontStretch-ref.html">
+<canvas id="c" class="output"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext('2d');
+
+// P shows as Pass for fontStretch = ultra-expanded and shows as fail for
+// fontStretch = fail.
+function draw() {
+ ctx.font = '25px test';
+ ctx.fontStretch = "ultra-expanded";
+ ctx.fillText("P", 10, 40);
+}
+
+var f = new FontFace('test', 'url(/fonts/pass.woff)');
+f.stretch = "ultra-expanded";
+document.fonts.add(f);
+
+var f2 = new FontFace('test', 'url(/fonts/fail.woff)');
+document.fonts.add(f2);
+
+Promise.all([f.load(), f2.load()]).then(draw);
+
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001-ref.htm
new file mode 100644
index 0000000000..1a19757e00
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001-ref.htm
@@ -0,0 +1,22 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Ignore property-independent style sheet syntax "inherit" in Text (reference)</title>
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ ctx.font = "40px Ahem";
+ ctx.fillText("Filler", 5, 50);
+ ctx.fillText("Filler", 5, 100);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: Ignore "inherit" property-independent style sheet syntax without assigning a new font value.</p>
+ <p>Test passes if there are two identical black boxes below.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001.htm b/testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001.htm
new file mode 100644
index 0000000000..923ce71c07
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/text/canvas_text_font_001.htm
@@ -0,0 +1,33 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Ignore property-independent style sheet syntax "inherit" in Text</title>
+ <link rel="match" href="canvas_text_font_001-ref.htm" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-font" />
+ <meta name="assert" content=": Ignore 'inherit' property-independent style sheet syntax without assigning a new font value." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Assign a valid font.
+ ctx.font = "40px Ahem";
+
+ // Assign property-independent style sheet syntax 'inherit' as font (this must be ignored).
+ ctx.font = "20px inherit";
+ ctx.fillText("Filler", 5, 50);
+
+ // Assign a valid font which was used earlier.
+ ctx.font = "40px Ahem";
+ ctx.fillText("Filler", 5, 100);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: Ignore "inherit" property-independent style sheet syntax without assigning a new font value.</p>
+ <p>Test passes if there are two identical black boxes below.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.state.saverestore.imageSmoothingEnabled.html b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.state.saverestore.imageSmoothingEnabled.html
new file mode 100644
index 0000000000..e99be83d5f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.state.saverestore.imageSmoothingEnabled.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CanvasRenderingContext2D imageSmoothingEnabled save/restore test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#image-smoothing">
+<script>
+function createTestImage() {
+ var image = document.createElement('canvas');
+ var imgctx = image.getContext('2d');
+ imgctx.fillStyle = "#F00";
+ imgctx.fillRect(0, 0, 2, 2);
+ imgctx.fillStyle = "#0F0";
+ imgctx.fillRect(0, 0, 1, 1);
+ return image;
+}
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ ctx.save();
+ ctx.imageSmoothingEnabled = false;
+ ctx.restore();
+ assert_equals(ctx.imageSmoothingEnabled, true);
+}, "Test that restore() undoes any modifications to imageSmoothingEnabled.");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ ctx.imageSmoothingEnabled = false;
+ var old = ctx.imageSmoothingEnabled;
+ ctx.save();
+ assert_equals(ctx.imageSmoothingEnabled, old);
+ ctx.restore();
+}, "Test that save() doesn't modify the values of imageSmoothingEnabled.");
+
+test(function() {
+ var ctx = document.createElement('canvas').getContext('2d');
+ ctx.imageSmoothingEnabled = false;
+ ctx.save();
+ ctx.imageSmoothingEnabled = true;
+ ctx.restore();
+ var image = createTestImage();
+ ctx.scale(10, 10);
+ ctx.drawImage(image, 0, 0);
+ var pixels = ctx.getImageData(0, 0, 1, 1).data;
+ assert_array_equals(pixels, [0, 255, 0, 255]);
+}, "Test that restoring actually changes smoothing and not just the attribute value.");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.zero.size.canvas.html b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.zero.size.canvas.html
new file mode 100644
index 0000000000..273e5c7484
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/2d.zero.size.canvas.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+</head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<canvas id="canvas" width="0" height="0"></canvas>
+<body>
+<script>
+test(function() {
+ var context = document.getElementById("canvas").getContext("2d");
+ context.fillStyle = "green";
+}, 'This test ensures that accessing the context of a zero sized canvas does not crash.');
+</script>
+</body>
+</html>
+
diff --git a/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001-ref.htm
new file mode 100644
index 0000000000..aee610d2ec
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: restore() pops top entry in drawing state stack</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: restore() pops the top entry in the drawing state stack.</p>
+ <div><img src='/images/threecolors.png' alt='3 colors'></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001.htm b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001.htm
new file mode 100644
index 0000000000..6d5a3cb20f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/the-canvas-state/canvas_state_restore_001.htm
@@ -0,0 +1,42 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: restore() pops top entry in drawing state stack</title>
+ <link rel="match" href="canvas_state_restore_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#the-canvas-state" />
+ <meta name="assert" content="restore() pops the top entry in the drawing state stack." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 99, 50);
+
+ // Save colors to the stack as separate drawing states.
+ ctx.fillStyle = "rgba(255, 255, 0, 1.0)";
+ ctx.save();
+ ctx.fillStyle = "rgba(0, 0, 255, 1.0)";
+ ctx.save();
+ ctx.fillStyle = "rgba(0, 255, 0, 1.0)";
+ ctx.save();
+
+ // Modify the current fillStyle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+
+ // Restore the drawing states previously saved and draw with them.
+ ctx.restore();
+ ctx.fillRect(66, 0, 33, 50);
+ ctx.restore();
+ ctx.fillRect(33, 0, 33, 50);
+ ctx.restore();
+ ctx.fillRect(0, 0, 33, 50);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: restore() pops the top entry in the drawing state stack.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/2d.transformation.getTransform.html b/testing/web-platform/tests/html/canvas/element/manual/transformations/2d.transformation.getTransform.html
new file mode 100644
index 0000000000..664efd50e6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/2d.transformation.getTransform.html
@@ -0,0 +1,39 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+// Ensure that context2d.getTransform works
+const epsilon = 1e-5;
+const canvas = document.createElement('canvas');
+const ctx = canvas.getContext('2d');
+
+test(function(t) {
+ assert_array_equals(ctx.getTransform().toFloat32Array(),
+ [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
+ "Assert that an untransformed matrix is identity");
+
+ ctx.scale(2, 3);
+ transform = ctx.getTransform();
+ assert_array_equals(ctx.getTransform().toFloat32Array(),
+ [2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
+ "Assert that context2d scaling works");
+
+ ctx.rotate(Math.PI/2);
+ transform = ctx.getTransform();
+ assert_array_approx_equals(ctx.getTransform().toFloat32Array(),
+ [0, 3, 0, 0, -2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], epsilon,
+ "Assert that context2d rotate works");
+
+ ctx.translate(1, -1);
+ transform = ctx.getTransform();
+ assert_array_approx_equals(ctx.getTransform().toFloat32Array(),
+ [0, 3, 0, 0, -2, 0, 0, 0, 0, 0, 1, 0, 2, 3, 0, 1], epsilon,
+ "Assert context2d translate works.");
+
+ ctx.resetTransform();
+ assert_array_equals(ctx.getTransform().toFloat32Array(),
+ [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
+ "Assert that a reset matrix is identity");
+}, 'This test ensures that getTransform works correctly.');
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001-ref.html b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001-ref.html
new file mode 100644
index 0000000000..caeea04cef
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<style>
+ html, body, div {
+ margin: 0;
+ padding: 0;
+ }
+ div {
+ width: 75px;
+ height: 75px;
+ float: left;
+ }
+</style>
+
+<div style="background-color:red"></div>
+<div style="clear:left"></div>
+<div style="background-color:blue"></div>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001.html b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001.html
new file mode 100644
index 0000000000..c12acbf6f3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_reset_001.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="match" href="canvas_transformations_reset_001-ref.html">
+<style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ }
+</style>
+<canvas id="c" width="150" height="150"></canvas>
+<script>
+var c = document.getElementById("c");
+var ctx = c.getContext("2d");
+
+ctx.translate(75, 75);
+ctx.fillStyle = 'blue';
+ctx.fillRect(0, 0, 75, 75);
+
+ctx.resetTransform();
+ctx.fillStyle = 'red';
+ctx.fillRect(0, 0, 75, 75);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001-ref.htm b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001-ref.htm
new file mode 100644
index 0000000000..1201bcca9f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: scale() transformation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: The scale(x, y) method must add the scaling transformation described by the arguments to the transformation matrix.</p>
+ <div><img alt='black rectangle' src="/images/black-rectangle.png"></div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001.htm b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001.htm
new file mode 100644
index 0000000000..73f71351ea
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/canvas_transformations_scale_001.htm
@@ -0,0 +1,31 @@
+<!doctype HTML>
+
+<html>
+ <head>
+ <title>HTML5 Canvas Test: scale() transformation</title>
+ <link rel="match" href="canvas_transformations_scale_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-scale" />
+ <meta name="assert" content="The scale(x, y) method must add the scaling transformation described by the arguments to the transformation matrix." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a red rectangle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Draw a black rectangle with scaling.
+ ctx.fillStyle = "rgba(0, 0, 0, 1.0)";
+ ctx.scale(2, 2);
+ ctx.fillRect(0, 0, 50, 25);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: The scale(x, y) method must add the scaling transformation described by the arguments to the transformation matrix.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/transform_a.html b/testing/web-platform/tests/html/canvas/element/manual/transformations/transform_a.html
new file mode 100644
index 0000000000..8c1f59efda
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/transform_a.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset=utf-8>
+<link rel=match href=transform_ref.html>
+<style>
+html, body {
+ margin: 0;
+}
+</style>
+<canvas id=c width=400 height=300></canvas>
+<script>
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+ctx.scale(3, 3);
+ctx.fillStyle = 'rgb(255, 0, 0)';
+ctx.beginPath();
+ctx.moveTo(10, 10);
+ctx.bezierCurveTo(10, 10, 20, 10, 20, 10);
+ctx.bezierCurveTo(20, 10, 20, 20, 20, 20);
+ctx.bezierCurveTo(20, 20, 10, 20, 10, 20);
+ctx.closePath();
+ctx.fill();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/transformations/transform_ref.html b/testing/web-platform/tests/html/canvas/element/manual/transformations/transform_ref.html
new file mode 100644
index 0000000000..2a166c36ce
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/transformations/transform_ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<style>
+html, body {
+ margin: 0;
+}
+section {
+ position: absolute;
+ background: rgb(255, 0, 0);
+ width: 30px;
+ height: 30px;
+ top: 30px;
+ left: 30px;
+}
+</style>
+<section></section>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm
new file mode 100644
index 0000000000..3272f32fb8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1-expected.htm
@@ -0,0 +1,10 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ </head>
+ <body>
+ <p>There should be no text below this, because the text is inside a canvas element.
+ The canvas is never closed, and the rest of the body ends up inside it.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1.htm
new file mode 100644
index 0000000000..5e0c914755
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-1.htm
@@ -0,0 +1,14 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ <link rel="match" href="unclosed-canvas-1-expected.htm">
+ <meta name="assert" content="Test what if canvas tag is unclosed in tag p" />
+ <script type="text/javascript"></script>
+ </head>
+ <body>
+ <p>There should be no text below this, because the text is inside a canvas element.
+ The canvas is never closed, and the rest of the body ends up inside it. </p>
+ <canvas>This text should NOT be visible if JavaScript is enabled.
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm
new file mode 100644
index 0000000000..fd48cd0db1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2-expected.htm
@@ -0,0 +1,14 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ </head>
+ <body>
+ <div><canvas></canvas></div>
+ <p>This text should be visible, even though it's preceded by an unclosed canvas tag,
+ because of the &lt;/div&gt; that closes an element opened before the canvas.
+ There's nothing special about div; we get the same results with other types of
+ elements.
+ </p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2.htm
new file mode 100644
index 0000000000..fb329e73d6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-2.htm
@@ -0,0 +1,15 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ <link rel="match" href="unclosed-canvas-2-expected.htm">
+ <meta name="assert" content="Test what if canvas tag is unclosed in tag div" />
+ <script type="text/javascript"></script>
+ </head>
+ <body>
+ <div><canvas></div>
+ <p>This text should be visible, even though it's preceded by an unclosed canvas tag,
+ because of the &lt;/div&gt; that closes an element opened before the canvas.
+ There's nothing special about div; we get the same results with other types of elements.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm
new file mode 100644
index 0000000000..efd239b4fb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3-expected.htm
@@ -0,0 +1,13 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ </head>
+ <body>
+ <p>There should be no text below this, because the text is inside a canvas element
+ and the &lt;/div&gt; that's also inside the canvas element does not close an open
+ element. The canvas is never closed, and the rest of the body ends up inside it.
+ There's nothing special about div; we get the same results with other types of
+ elements.</p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3.htm
new file mode 100644
index 0000000000..8ffaa0f9eb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-3.htm
@@ -0,0 +1,16 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ <link rel="match" href="unclosed-canvas-3-expected.htm">
+ <meta name="assert" content="Test what if canvas tag is unclosed in unclosed div" />
+ <script type="text/javascript"></script>
+ </head>
+ <body>
+ <p>There should be no text below this, because the text is inside a canvas element
+ and the &lt;/div&gt; that's also inside the canvas element does not close an open element.
+ The canvas is never closed, and the rest of the body ends up inside it.
+ There's nothing special about div; we get the same results with other types of elements.</p>
+ <canvas></div>This text should NOT be visible if JavaScript is enabled.
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm
new file mode 100644
index 0000000000..492449261e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4-expected.htm
@@ -0,0 +1,14 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ </head>
+ <body>
+ <p>There should be no text below this, because the text is inside a canvas element
+ and the &lt;/div&gt; that's also inside the canvas element does not close an open
+ element. The canvas is never closed, and the rest of the body ends up inside it.
+ There's nothing special about div; we get the same results with other types of
+ elements. The fact that the canvas tag uses XML self-closing syntax has no effect.
+ </p>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4.htm b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4.htm
new file mode 100644
index 0000000000..aa5fd14438
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/unclosed-canvas-4.htm
@@ -0,0 +1,17 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>unclosed canvas tag in body</title>
+ <link rel="match" href="unclosed-canvas-4-expected.htm">
+ <meta name="assert" content="Test what if canvas tag is unclosed in body" />
+ <script type="text/javascript"></script>
+ </head>
+ <body>
+ <p>There should be no text below this, because the text is inside a canvas element
+ and the &lt;/div&gt; that's also inside the canvas element does not close an open element.
+ The canvas is never closed, and the rest of the body ends up inside it.
+ There's nothing special about div; we get the same results with other types of elements.
+ The fact that the canvas tag uses XML self-closing syntax has no effect.</p>
+ <canvas/></div>This text should NOT be visible if JavaScript is enabled.
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/ImageData-fidelity.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/ImageData-fidelity.html
new file mode 100644
index 0000000000..c2d158f893
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/ImageData-fidelity.html
@@ -0,0 +1,126 @@
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var image = new Image();
+ // This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
+ // The image has no embedded color profile.
+ image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAx" +
+ "WXB3AAAAG0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAAElFTkSuQmCC";
+
+ image.onload = function() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 256;
+ canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(image, 0, 0);
+ var img = ctx.getImageData(0, 0, 256, 1);
+ t.step(function() {
+ for (var i = 0; i < 256; i++) {
+ assert_equals(img.data[4 * i], i, "red component");
+ assert_equals(img.data[4 * i + 1], i, "green component");
+ assert_equals(img.data[4 * i + 2], i, "blue component");
+ assert_equals(img.data[4 * i + 3], 255, "alpha component");
+ }
+ });
+ t.done();
+ }
+}, "Verify that drawImage->getImageData round trip preserves color values " +
+ "when image metadata has no color space and canvas uses the default " +
+ "color space.");
+
+async_test(function(t) {
+ var image = new Image();
+ // This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
+ // The image has an embedded sRGB color profile.
+ image.src =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAA" +
+ "G0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAo3pUWHRSYXcgcHJvZm" +
+ "lsZSB0eXBlIEFQUDEAAHicZU5bCsMwDPv3KXoEv/I6TrampTC20ft/LE7WETJBkK1YQrCX" +
+ "ZzmP+/I+X9vxKLAYyCGoC9En77FCV10ROWNHrM8hUW7cQZ00V/026tDZMRKbUQYDt4lJJr" +
+ "2FxeCTJc5BV4svNE4Nxl1Tn8N1LCgMIoKJ2sHvo25sHfK/odYT02luCWMP+AA5M0KbNr61" +
+ "PwAAAABJRU5ErkJggg==";
+
+ image.onload = function() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 256;
+ canvas.height = 1;
+ var ctx = canvas.getContext('2d', {colorSpace: 'srgb'});
+ ctx.drawImage(image, 0, 0);
+ var img = ctx.getImageData(0, 0, 256, 1);
+ t.step(function() {
+ for (var i = 0; i < 256; i++) {
+ assert_equals(img.data[4 * i], i, "red component");
+ assert_equals(img.data[4 * i + 1], i, "green component");
+ assert_equals(img.data[4 * i + 2], i, "blue component");
+ assert_equals(img.data[4 * i + 3], 255, "alpha component");
+ }
+ });
+ t.done();
+ }
+}, "Verify that drawImage->getImageData round trip preserves color values " +
+ "when image metadata has srgb color space and canvas uses the srgb " +
+ "color space.");
+
+async_test(function(t) {
+ var image = new Image();
+ // This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
+ // The image has no embedded color profile.
+ image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAx" +
+ "WXB3AAAAG0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAAElFTkSuQmCC";
+
+ image.onload = function() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 256;
+ canvas.height = 1;
+ var ctx = canvas.getContext('2d', {colorSpace: 'srgb'});
+ ctx.drawImage(image, 0, 0);
+ var img = ctx.getImageData(0, 0, 256, 1);
+ t.step(function() {
+ for (var i = 0; i < 256; i++) {
+ assert_equals(img.data[4 * i], i, "red component");
+ assert_equals(img.data[4 * i + 1], i, "green component");
+ assert_equals(img.data[4 * i + 2], i, "blue component");
+ assert_equals(img.data[4 * i + 3], 255, "alpha component");
+ }
+ });
+ t.done();
+ }
+}, "Verify that drawImage->getImageData round trip preserves color values " +
+ "when image metadata has no color space and canvas uses the srgb " +
+ "color space.");
+
+
+async_test(function(t) {
+ var image = new Image();
+ // This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
+ // The image has an embedded sRGB color profile.
+ image.src =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAA" +
+ "G0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAo3pUWHRSYXcgcHJvZm" +
+ "lsZSB0eXBlIEFQUDEAAHicZU5bCsMwDPv3KXoEv/I6TrampTC20ft/LE7WETJBkK1YQrCX" +
+ "ZzmP+/I+X9vxKLAYyCGoC9En77FCV10ROWNHrM8hUW7cQZ00V/026tDZMRKbUQYDt4lJJr" +
+ "2FxeCTJc5BV4svNE4Nxl1Tn8N1LCgMIoKJ2sHvo25sHfK/odYT02luCWMP+AA5M0KbNr61" +
+ "PwAAAABJRU5ErkJggg==";
+
+ image.onload = function() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 256;
+ canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(image, 0, 0);
+ var img = ctx.getImageData(0, 0, 256, 1);
+ t.step(function() {
+ for (var i = 0; i < 256; i++) {
+ assert_equals(img.data[4 * i], i, "red component");
+ assert_equals(img.data[4 * i + 1], i, "green component");
+ assert_equals(img.data[4 * i + 2], i, "blue component");
+ assert_equals(img.data[4 * i + 3], 255, "alpha component");
+ }
+ });
+ t.done();
+ }
+}, "Verify that drawImage->getImageData round trip preserves color values " +
+ "when image metadata has srgb color space and canvas uses the default " +
+ "color space.");
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-Blob.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-Blob.html
new file mode 100644
index 0000000000..9b96b1a6d2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-Blob.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that drawing ImageBitmaps with different image Blob source bit depths
+// and color profiles into sRGB and Display P3 canvases works, by reading pixels
+// with getImageData() as sRGB and Display P3 values.
+for (let [filename, expectedPixels] of Object.entries(imageTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let cropSource of [false, true]) {
+ async_test(function(t) {
+ fetch(`resources/${filename}`)
+ .then(t.step_func(response => response.blob()))
+ .then(t.step_func(blob => (cropSource ? createImageBitmap(blob, 1, 1, 1, 1) : createImageBitmap(blob))))
+ .then(t.step_func_done(function(imageBitmap) {
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+ ctx.drawImage(imageBitmap, 0, 0);
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+ }));
+ }, `${filename}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}, cropSource=${cropSource}`);
+ }
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageBitmap.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageBitmap.html
new file mode 100644
index 0000000000..0bd18e9beb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageBitmap.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that drawing ImageBitmaps created from other ImageBitamps with different
+// image source bit depths and color profiles into sRGB and Display P3
+// canvases works, by reading pixels with getImageData() as sRGB and Display P3
+// values.
+for (let [filename, expectedPixels] of Object.entries(imageTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let cropSource of [false, true]) {
+ async_test(function(t) {
+ let image = new Image();
+ image.onload = t.step_func_done(function() {
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+
+ createImageBitmap(image).then(t.step_func(function(sourceImageBitmap) {
+ let imageBitmapPromise;
+ if (cropSource)
+ imageBitmapPromise = createImageBitmap(sourceImageBitmap, 1, 1, 1, 1);
+ else
+ imageBitmapPromise = createImageBitmap(sourceImageBitmap);
+
+ imageBitmapPromise.then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0);
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+ }));
+ }));
+ });
+ image.src = `resources/${filename}`;
+ }, `${filename}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}, cropSource=${cropSource}`);
+ }
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageData.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageData.html
new file mode 100644
index 0000000000..2216b46dd8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-ImageData.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that ImageBitmaps created from ImageData sources with different color
+// spaces can be drawn into sRGB and Display P3 canvases, by reading pixels with
+// getImageData() as sRGB and Display P3 values.
+function runTest(sourceColorSpace, destinationColorSpace, colors) {
+ for (let [sourceColorString, expectedColor] of Object.entries(colors)) {
+ for (let cropSource of [false, true]) {
+ async_test(function(t) {
+ let sourceColor = sourceColorString.split(",").map(x => +x);
+
+ let sourceImageData = new ImageData(4, 4, { colorSpace: sourceColorSpace });
+ for (let i = 0; i < 4 * 4 * 4; i += 4) {
+ for (let c = 0; c < 4; ++c)
+ sourceImageData.data[i + c] = sourceColor[c];
+ }
+
+ let imageBitmapPromise;
+ if (cropSource)
+ imageBitmapPromise = createImageBitmap(sourceImageData, 2, 2, 2, 2);
+ else
+ imageBitmapPromise = createImageBitmap(sourceImageData);
+
+ imageBitmapPromise.then(t.step_func_done(function(imageBitmap) {
+ let destination = document.createElement("canvas");
+ destination.width = 2;
+ destination.height = 2;
+
+ let destinationContext = destination.getContext("2d", { colorSpace: destinationColorSpace });
+ destinationContext.drawImage(imageBitmap, 0, 0);
+
+ let destinationImageData = destinationContext.getImageData(1, 1, 1, 1);
+
+ assert_true(pixelsApproximatelyEqual(destinationImageData.data, expectedColor), `Actual pixel value ${[...destinationImageData.data]} is approximately equal to ${expectedColor}.`);
+ }));
+ }, `Source ${sourceColorSpace}, destination ${destinationColorSpace}, color ${sourceColorString}, cropSource=${cropSource}`);
+ }
+ }
+}
+
+runTest("srgb", "display-p3", fromSRGBToDisplayP3);
+runTest("display-p3", "srgb", fromDisplayP3ToSRGB);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-canvas.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-canvas.html
new file mode 100644
index 0000000000..f3156349ed
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-canvas.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that ImageBitmaps created from canvas sources with different color
+// spaces can be drawn into sRGB and Display P3 canvases, by reading pixels with
+// getImageData() as sRGB and Display P3 values.
+function runTest(sourceColorSpace, destinationColorSpace, colors) {
+ for (let [sourceColorString, expectedColor] of Object.entries(colors)) {
+ for (let cropSource of [false, true]) {
+ async_test(function(t) {
+ let source = document.createElement("canvas");
+ source.width = 4;
+ source.height = 4;
+
+ let sourceContext = source.getContext("2d", { colorSpace: sourceColorSpace });
+
+ let sourceColor = sourceColorString.split(",").map(x => +x);
+
+ let sourceImageData = new ImageData(4, 4, { colorSpace: sourceColorSpace });
+ for (let i = 0; i < 4 * 4 * 4; i += 4) {
+ for (let c = 0; c < 4; ++c)
+ sourceImageData.data[i + c] = sourceColor[c];
+ }
+ sourceContext.putImageData(sourceImageData, 0, 0);
+
+ let imageBitmapPromise;
+ if (cropSource)
+ imageBitmapPromise = createImageBitmap(source, 2, 2, 2, 2);
+ else
+ imageBitmapPromise = createImageBitmap(source);
+
+ imageBitmapPromise.then(t.step_func_done(function(imageBitmap) {
+ let destination = document.createElement("canvas");
+ destination.width = 2;
+ destination.height = 2;
+
+ let destinationContext = destination.getContext("2d", { colorSpace: destinationColorSpace });
+ destinationContext.drawImage(imageBitmap, 0, 0);
+
+ let destinationImageData = destinationContext.getImageData(1, 1, 1, 1);
+
+ assert_true(pixelsApproximatelyEqual(destinationImageData.data, expectedColor), `Actual pixel value ${[...destinationImageData.data]} is approximately equal to ${expectedColor}.`);
+ }));
+ }, `Source ${sourceColorSpace}, destination ${destinationColorSpace}, color ${sourceColorString}, cropSource=${cropSource}`);
+ }
+ }
+}
+
+runTest("srgb", "display-p3", fromSRGBToDisplayP3);
+runTest("display-p3", "srgb", fromDisplayP3ToSRGB);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-cloned.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-cloned.html
new file mode 100644
index 0000000000..cf4f38f8db
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-cloned.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that drawing structured cloned ImageBitmaps with different image source
+// bit depths and color profiles into sRGB and Display P3 canvases works, by
+// reading pixels with getImageData() as sRGB and Display P3 values.
+
+let nextTestID = 0;
+
+class Test {
+ constructor(testConfiguration) {
+ Object.assign(this, testConfiguration);
+ this.testID = nextTestID++;
+ }
+
+ run() {
+ let self = this;
+ async_test(function(t) {
+ self.t = t;
+ self.image = new Image();
+ self.image.onload = t.step_func(self.onImageLoaded.bind(self));
+ self.image.src = `resources/${self.filename}`;
+ }, `${this.filename}, Context ${this.contextColorSpace}, ImageData ${this.imageDataColorSpace}, cropSource=${this.cropSource}`);
+ }
+
+ onImageLoaded() {
+ let imageBitmapPromise;
+ if (this.cropSource)
+ imageBitmapPromise = createImageBitmap(this.image, 1, 1, 1, 1);
+ else
+ imageBitmapPromise = createImageBitmap(this.image);
+ imageBitmapPromise.then(this.t.step_func(this.onImageBitmapCreated.bind(this)));
+ }
+
+ onImageBitmapCreated(imageBitmap) {
+ window.addEventListener("message", this.t.step_func(this.onMessage.bind(this)));
+ window.postMessage({ imageBitmap, testID: this.testID });
+ }
+
+ onMessage(message) {
+ if (message.data.testID != this.testID)
+ return;
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: this.contextColorSpace });
+ ctx.drawImage(message.data.imageBitmap, 0, 0);
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: this.imageDataColorSpace });
+
+ let expected = this.expectedPixels[`${this.contextColorSpace} ${this.imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+
+ this.t.done();
+ }
+}
+
+for (let [filename, expectedPixels] of Object.entries(imageTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let cropSource of [false, true])
+ new Test({ filename, expectedPixels, contextColorSpace, imageDataColorSpace, cropSource }).run();
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-image.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-image.html
new file mode 100644
index 0000000000..e7e85c915d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-image.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that drawing ImageBitmaps with different image source bit depths and
+// color profiles into sRGB and Display P3 canvases works, by reading pixels
+// with getImageData() as sRGB and Display P3 values.
+for (let [filename, expectedPixels] of Object.entries(imageTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let cropSource of [false, true]) {
+ async_test(function(t) {
+ let image = new Image();
+ image.onload = t.step_func(function() {
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+
+ let imageBitmapPromise;
+ if (cropSource)
+ imageBitmapPromise = createImageBitmap(image, 1, 1, 1, 1);
+ else
+ imageBitmapPromise = createImageBitmap(image);
+
+ imageBitmapPromise.then(t.step_func_done(function(imageBitmap) {
+ ctx.drawImage(imageBitmap, 0, 0);
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+ }));
+ });
+ image.src = `resources/${filename}`;
+ }, `${filename}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}, cropSource=${cropSource}`);
+ }
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html
new file mode 100644
index 0000000000..3e86bb5596
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<body>
+<script>
+// Test that drawing ImageBitmaps with different video source color profiles
+// into sRGB and Display P3 canvases works, by reading pixels with
+// getImageData() as sRGB and Display P3 values.
+for (let [filenameBase, expectedPixels] of Object.entries(videoTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let cropSource of [false, true]) {
+ promise_test(async function(t) {
+
+ let video = document.createElement("video");
+ for (let format of ["mp4", "webm"]) {
+ let source = document.createElement("source");
+ source.src = `resources/${filenameBase}.${format}`;
+ source.type = `video/${format}`;
+ video.append(source);
+ }
+
+ let loadedData = new Promise(resolver => video.onloadeddata = resolver);
+
+ document.body.append(video);
+ await video.play();
+ await loadedData;
+ await new Promise(requestAnimationFrame);
+
+ let imageBitmap;
+ if (cropSource)
+ imageBitmap = await createImageBitmap(video, 1, 1, 1, 1);
+ else
+ imageBitmap = await createImageBitmap(video);
+
+ video.remove();
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+
+ ctx.drawImage(imageBitmap, 0, 0);
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+
+ }, `${filenameBase}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}, cropSource=${cropSource}`);
+ }
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html
new file mode 100644
index 0000000000..1b04cde779
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<body>
+<script>
+// Test that drawing videos with different color spaces into sRGB and Display P3
+// canvases works, by reading pixels with getImageData() as sRGB and Display P3
+// values.
+for (let [filenameBase, expectedPixels] of Object.entries(videoTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let scaleImage of [false, true]) {
+ promise_test(async function(t) {
+
+ let video = document.createElement("video");
+ for (let format of ["mp4", "webm"]) {
+ let source = document.createElement("source");
+ source.src = `resources/${filenameBase}.${format}`;
+ source.type = `video/${format}`;
+ video.append(source);
+ }
+
+ let loadedData = new Promise(resolver => video.onloadeddata = resolver);
+
+ document.body.append(video);
+ await video.play();
+ await loadedData;
+ await new Promise(requestAnimationFrame);
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+ if (scaleImage)
+ ctx.drawImage(video, 0, 0, 10, 10);
+ else
+ ctx.drawImage(video, 0, 0);
+ video.remove();
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+
+ }, `${filenameBase}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}, scaleImage=${scaleImage}`);
+ }
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage.https.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage.https.html
new file mode 100644
index 0000000000..35ee91343d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that drawing images with different bit depths and color profiles into
+// sRGB and Display P3 canvases works, by reading pixels with getImageData()
+// as sRGB and Display P3 values.
+for (let [filename, expectedPixels] of Object.entries({...imageTests, ...svgImageTests})) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ for (let scaleImage of [false, true]) {
+ async_test(function(t) {
+ let image = new Image();
+ image.onload = t.step_func_done(function() {
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 2;
+ canvas.height = 2;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+ if (scaleImage)
+ ctx.drawImage(image, 0, 0, 10, 10);
+ else
+ ctx.drawImage(image, 0, 0);
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+
+ t.done();
+
+ });
+ image.src = `resources/${filename}`;
+ }, `${filename}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}, scaleImage=${scaleImage}`);
+ }
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-canvas.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-canvas.html
new file mode 100644
index 0000000000..2b9fb9b8f4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-canvas.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that patterns created from canvas sources with different color spaces
+// can be drawn into sRGB and Display P3 canvases, by reading pixels with
+// getImageData() as sRGB and Display P3 values.
+function runTest(sourceColorSpace, destinationColorSpace, colors) {
+ for (let [sourceColorString, expectedColor] of Object.entries(colors)) {
+ test(function() {
+ let source = document.createElement("canvas");
+ source.width = 2;
+ source.height = 2;
+
+ let sourceContext = source.getContext("2d", { colorSpace: sourceColorSpace });
+
+ let sourceColor = sourceColorString.split(",").map(x => +x);
+
+ let sourceImageData = new ImageData(2, 2, { colorSpace: sourceColorSpace });
+ for (let i = 0; i < 2 * 2 * 4; i += 4) {
+ for (let c = 0; c < 4; ++c)
+ sourceImageData.data[i + c] = sourceColor[c];
+ }
+ sourceContext.putImageData(sourceImageData, 0, 0);
+
+ let destination = document.createElement("canvas");
+ destination.width = 4;
+ destination.height = 4;
+
+ let destinationContext = destination.getContext("2d", { colorSpace: destinationColorSpace });
+ destinationContext.fillStyle = destinationContext.createPattern(source, "repeat");
+ destinationContext.fillRect(0, 0, 4, 4);
+
+ let destinationImageData = destinationContext.getImageData(2, 2, 1, 1);
+
+ assert_true(pixelsApproximatelyEqual(destinationImageData.data, expectedColor), `Actual pixel value ${[...destinationImageData.data]} is approximately equal to ${expectedColor}.`);
+ }, `Source ${sourceColorSpace}, destination ${destinationColorSpace}, color ${sourceColorString}`);
+ }
+}
+
+runTest("srgb", "display-p3", fromSRGBToDisplayP3);
+runTest("display-p3", "srgb", fromDisplayP3ToSRGB);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-image.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-image.html
new file mode 100644
index 0000000000..75a8392c02
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-pattern-image.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="canvas-display-p3.js"></script>
+<script>
+// Test that patterns created from images with different bit depths and color
+// profiles into can be drawn into sRGB and Display P3 canvases, by reading
+// pixels with getImageData() as sRGB and Display P3 values.
+for (let [filename, expectedPixels] of Object.entries(imageTests)) {
+ for (let contextColorSpace of ["srgb", "display-p3"]) {
+ for (let imageDataColorSpace of ["srgb", "display-p3"]) {
+ async_test(function(t) {
+ let image = new Image();
+ image.onload = t.step_func_done(function() {
+
+ let canvas = document.createElement("canvas");
+ canvas.width = 4;
+ canvas.height = 4;
+
+ let ctx = canvas.getContext("2d", { colorSpace: contextColorSpace });
+ ctx.fillStyle = ctx.createPattern(image, "repeat");
+ ctx.fillRect(0, 0, 4, 4);
+
+ let imageData = ctx.getImageData(2, 2, 1, 1, { colorSpace: imageDataColorSpace });
+
+ let expected = expectedPixels[`${contextColorSpace} ${imageDataColorSpace}`];
+ assert_true(pixelsApproximatelyEqual(imageData.data, expected), `Actual pixel value ${[...imageData.data]} is approximately equal to ${expected}.`);
+
+ t.done();
+
+ });
+ image.src = `resources/${filename}`;
+ }, `${filename}, Context ${contextColorSpace}, ImageData ${imageDataColorSpace}`);
+ }
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-settings.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-settings.html
new file mode 100644
index 0000000000..2b1447437d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-settings.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+// Test that creating canvas contexts and ImageData objects respect the
+// requested color space.
+
+for (let contextColorSpace of [undefined, "srgb", "display-p3"]) {
+ for (let imageDataColorSpace of [undefined, "srgb", "display-p3"]) {
+ test(function() {
+ let contextSettings = { };
+ if (contextColorSpace)
+ contextSettings.colorSpace = contextColorSpace;
+ let resolvedContextColorSpace = contextColorSpace || "srgb";
+
+ let canvas = document.createElement("canvas");
+ let ctx = canvas.getContext("2d", contextSettings);
+ assert_equals(ctx.getContextAttributes().colorSpace, resolvedContextColorSpace, `CanvasRenderingContext2DSettings.colorSpace when set to ${contextColorSpace}`);
+
+ let imageDataSettings = { };
+ if (imageDataColorSpace)
+ imageDataSettings.colorSpace = imageDataColorSpace;
+ let resolvedImageDataColorSpace = imageDataColorSpace || resolvedContextColorSpace;
+
+ let imageData = ctx.getImageData(0, 0, 1, 1, imageDataSettings);
+ assert_equals(imageData.colorSpace, resolvedImageDataColorSpace, `getImageData() colorSpace when set to ${imageDataColorSpace}`);
+
+ imageData = ctx.createImageData(1, 1, imageDataSettings);
+ assert_equals(imageData.colorSpace, resolvedImageDataColorSpace, `createImageData() colorSpace when set to ${imageDataColorSpace}`);
+
+ imageData = ctx.createImageData(imageData);
+ assert_equals(imageData.colorSpace, resolvedImageDataColorSpace, `Cloned ImageData colorSpace when set to ${imageDataColorSpace}`);
+ }, `Context ${contextColorSpace}, ImageData ${imageDataColorSpace}`);
+ }
+}
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3.js b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3.js
new file mode 100644
index 0000000000..c6ee97b788
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3.js
@@ -0,0 +1,283 @@
+// Each PNG:
+// * is 2x2 and has a single color
+// * has a filename that indicates its contents:
+// <embedded-profile>-<8-or-16-bit-color-value>.png
+// * was generated using ImageMagick commands like:
+// convert -size 2x2 xc:'#BB0000FF' -profile Display-P3.icc Display-P3-BB0000FF.png
+// convert -size 2x2 xc:'#BBBC00000000FFFF' -profile Adobe-RGB.icc Adobe-RGB-BBBC00000000FFFF.png
+
+// Top level key is the image filename. Second level key is the pair of
+// CanvasRenderingContext2DSettings.colorSpace and ImageDataSettings.colorSpace.
+const imageTests = {
+ // 8 bit source images
+
+ "sRGB-FF0000FF.png": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [234, 51, 35, 255],
+ },
+ "sRGB-FF0000CC.png": {
+ "srgb srgb": [255, 0, 0, 204],
+ "srgb display-p3": [234, 51, 35, 204],
+ "display-p3 srgb": [255, 0, 0, 204],
+ "display-p3 display-p3": [234, 51, 35, 204],
+ },
+ "sRGB-BB0000FF.png": {
+ "srgb srgb": [187, 0, 0, 255],
+ "srgb display-p3": [171, 35, 23, 255],
+ "display-p3 srgb": [187, 1, 0, 255],
+ "display-p3 display-p3": [171, 35, 23, 255],
+ },
+ "sRGB-BB0000CC.png": {
+ "srgb srgb": [187, 0, 0, 204],
+ "srgb display-p3": [171, 35, 23, 204],
+ "display-p3 srgb": [187, 1, 0, 204],
+ "display-p3 display-p3": [171, 35, 23, 204],
+ },
+
+ "Display-P3-FF0000FF.png": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [255, 0, 0, 255],
+ },
+ "Display-P3-FF0000CC.png": {
+ "srgb srgb": [255, 0, 0, 204],
+ "srgb display-p3": [234, 51, 35, 204],
+ "display-p3 srgb": [255, 0, 0, 204],
+ "display-p3 display-p3": [255, 0, 0, 204],
+ },
+ "Display-P3-BB0000FF.png": {
+ "srgb srgb": [205, 0, 0, 255],
+ "srgb display-p3": [188, 39, 26, 255],
+ "display-p3 srgb": [205, 0, 0, 255],
+ "display-p3 display-p3": [187, 0, 0, 255],
+ },
+ "Display-P3-BB0000CC.png": {
+ "srgb srgb": [205, 0, 0, 204],
+ "srgb display-p3": [188, 39, 26, 204],
+ "display-p3 srgb": [205, 0, 0, 204],
+ "display-p3 display-p3": [187, 0, 0, 204],
+ },
+
+ "Adobe-RGB-FF0000FF.png": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 19, 11, 255],
+ "display-p3 display-p3": [255, 61, 43, 255],
+ },
+ "Adobe-RGB-FF0000CC.png": {
+ "srgb srgb": [255, 0, 0, 204],
+ "srgb display-p3": [234, 51, 35, 204],
+ "display-p3 srgb": [255, 19, 11, 204],
+ "display-p3 display-p3": [255, 61, 43, 204],
+ },
+ "Adobe-RGB-BB0000FF.png": {
+ "srgb srgb": [219, 0, 0, 255],
+ "srgb display-p3": [201, 42, 29, 255],
+ "display-p3 srgb": [219, 0, 1, 255],
+ "display-p3 display-p3": [201, 42, 29, 255],
+ },
+ "Adobe-RGB-BB0000CC.png": {
+ "srgb srgb": [219, 0, 0, 204],
+ "srgb display-p3": [201, 42, 29, 204],
+ "display-p3 srgb": [219, 0, 1, 204],
+ "display-p3 display-p3": [201, 42, 29, 204],
+ },
+
+ "Generic-CMYK-FF000000.jpg": {
+ "srgb srgb": [0, 163, 218, 255],
+ "srgb display-p3": [72, 161, 213, 255],
+ "display-p3 srgb": [0, 163, 218, 255],
+ "display-p3 display-p3": [0, 160, 213, 255],
+ },
+ "Generic-CMYK-BE000000.jpg": {
+ "srgb srgb": [0, 180, 223, 255],
+ "srgb display-p3": [80, 177, 219, 255],
+ "display-p3 srgb": [0, 180, 223, 255],
+ "display-p3 display-p3": [65, 177, 219, 255],
+ },
+
+ // 16 bit source images
+
+ "sRGB-FFFF00000000FFFF.png": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [234, 51, 35, 255],
+ },
+ "sRGB-FFFF00000000CCCC.png": {
+ "srgb srgb": [255, 0, 0, 204],
+ "srgb display-p3": [234, 51, 35, 204],
+ "display-p3 srgb": [255, 0, 0, 204],
+ "display-p3 display-p3": [234, 51, 35, 204],
+ },
+ "sRGB-BBBC00000000FFFF.png": {
+ "srgb srgb": [187, 0, 0, 255],
+ "srgb display-p3": [171, 35, 23, 255],
+ "display-p3 srgb": [187, 1, 0, 255],
+ "display-p3 display-p3": [171, 35, 23, 255],
+ },
+ "sRGB-BBBC00000000CCCC.png": {
+ "srgb srgb": [187, 0, 0, 204],
+ "srgb display-p3": [171, 35, 23, 204],
+ "display-p3 srgb": [187, 1, 0, 204],
+ "display-p3 display-p3": [171, 35, 23, 204],
+ },
+
+ "Display-P3-FFFF00000000FFFF.png": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [255, 0, 0, 255],
+ },
+ "Display-P3-FFFF00000000CCCC.png": {
+ "srgb srgb": [255, 0, 0, 204],
+ "srgb display-p3": [234, 51, 35, 204],
+ "display-p3 srgb": [255, 0, 0, 204],
+ "display-p3 display-p3": [255, 0, 0, 204],
+ },
+ "Display-P3-BBBC00000000FFFF.png": {
+ "srgb srgb": [205, 0, 0, 255],
+ "srgb display-p3": [188, 39, 26, 255],
+ "display-p3 srgb": [205, 0, 0, 255],
+ "display-p3 display-p3": [187, 0, 0, 255],
+ },
+ "Display-P3-BBBC00000000CCCC.png": {
+ "srgb srgb": [205, 0, 0, 204],
+ "srgb display-p3": [188, 39, 26, 204],
+ "display-p3 srgb": [205, 0, 0, 204],
+ "display-p3 display-p3": [187, 0, 0, 204],
+ },
+
+ "Adobe-RGB-FFFF00000000FFFF.png": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 19, 11, 255],
+ "display-p3 display-p3": [255, 61, 43, 255],
+ },
+ "Adobe-RGB-FFFF00000000CCCC.png": {
+ "srgb srgb": [255, 0, 0, 204],
+ "srgb display-p3": [234, 51, 35, 204],
+ "display-p3 srgb": [255, 19, 11, 204],
+ "display-p3 display-p3": [255, 61, 43, 204],
+ },
+ "Adobe-RGB-BBBC00000000FFFF.png": {
+ "srgb srgb": [219, 0, 0, 255],
+ "srgb display-p3": [201, 42, 29, 255],
+ "display-p3 srgb": [219, 0, 1, 255],
+ "display-p3 display-p3": [201, 42, 29, 255],
+ },
+ "Adobe-RGB-BBBC00000000CCCC.png": {
+ "srgb srgb": [219, 0, 0, 204],
+ "srgb display-p3": [201, 42, 29, 204],
+ "display-p3 srgb": [219, 0, 1, 204],
+ "display-p3 display-p3": [201, 42, 29, 204],
+ },
+};
+
+const svgImageTests = {
+ // SVG source images
+
+ "sRGB-FF0000.svg": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [234, 51, 35, 255],
+ },
+ "sRGB-BB0000.svg": {
+ "srgb srgb": [187, 0, 0, 255],
+ "srgb display-p3": [171, 35, 23, 255],
+ "display-p3 srgb": [187, 1, 0, 255],
+ "display-p3 display-p3": [171, 35, 23, 255],
+ },
+
+ "Display-P3-1-0-0.svg": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [255, 0, 0, 255],
+ },
+ "Display-P3-0.7333-0-0.svg": {
+ "srgb srgb": [205, 0, 0, 255],
+ "srgb display-p3": [188, 39, 26, 255],
+ "display-p3 srgb": [205, 0, 0, 255],
+ "display-p3 display-p3": [187, 0, 0, 255],
+ },
+};
+
+// Each video:
+// * is 300x200 and has a single color
+// * has a filename base that indicates its contents:
+//
+// <color-space>-<8-or-10-bit-color-value>
+//
+// * was generated using commands like:
+//
+// W=300 H=200 Y=3F Cb=66 Cr=F0 ; \
+// perl -e "print pack('c', 0x$Y) x ($W * $H), pack('c', 0x$Cb) x ($W * $H / 4), pack('c', 0x$Cr) x ($W * $H / 4)" | \
+// ffmpeg -f rawvideo -pix_fmt yuv420p -s:v ${W}x$H -r 25 -i - -pix_fmt yuv420p -colorspace bt709 -color_primaries bt709 -color_trc iec61966_2_1 sRGB-FF0100.webm
+//
+// W=300 H=200 Y=0BB Cb=1BD Cr=2EF ; \
+// perl -e "print pack('s', 0x$Y) x ($W * $H), pack('s', 0x$Cb) x ($W * $H / 4), pack('s', 0x$Cr) x ($W * $H / 4)" | \
+// ffmpeg -f rawvideo -pix_fmt yuv420p10le -s:v ${W}x$H -r 25 -i - -c:v libx265 -vtag hvc1 -pix_fmt yuv420p10le -colorspace bt2020nc -color_primaries bt2020 -color_trc bt2020-10 Rec2020-222000000.mp4
+//
+// W=300 H=200 Y=0BB Cb=1BD Cr=2EF ; \
+// perl -e "print pack('s', 0x$Y) x ($W * $H), pack('s', 0x$Cb) x ($W * $H / 4), pack('s', 0x$Cr) x ($W * $H / 4)" | \
+// ffmpeg -f rawvideo -pix_fmt yuv420p10le -s:v ${W}x$H -r 25 -i - -vcodec libvpx-vp9 -profile:v 2 -pix_fmt yuv420p10le -colorspace bt2020nc -color_primaries bt2020 -color_trc bt2020-10 Rec2020-222000000.webm
+//
+// where the Y'CbCr values were computed using https://jdashg.github.io/misc/colors/from-coeffs.html.
+const videoTests = {
+ // Rec.709 Y'CbCr (0x3F, 0x66, 0xF0) = sRGB (0xFF, 0x01, 0x00)
+ "sRGB-FF0100": {
+ "srgb srgb": [255, 1, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [234, 51, 35, 255],
+ },
+ // Rec.709 Y'CbCr (0x32, 0x6D, 0xD2) = sRGB (0xBB, 0x00, 0x00)
+ "sRGB-BB0000": {
+ "srgb srgb": [187, 0, 0, 255],
+ "srgb display-p3": [171, 35, 23, 255],
+ "display-p3 srgb": [187, 1, 0, 255],
+ "display-p3 display-p3": [171, 35, 23, 255],
+ },
+
+ // 10 bit Rec.2020 Y'CbCr (0x126, 0x183, 0x3C0) = Rec.2020 (0x3FF, 0x000, 0x000)
+ "Rec2020-3FF000000": {
+ "srgb srgb": [255, 0, 0, 255],
+ "srgb display-p3": [234, 51, 35, 255],
+ "display-p3 srgb": [255, 0, 0, 255],
+ "display-p3 display-p3": [255, 0, 9, 255],
+ },
+ // 10 bit Rec.2020 Y'CbCr (0x0BB, 0x1BD, 0x2EF) = Rec.2020 (0x222, 0x000, 0x000)
+ "Rec2020-222000000": {
+ "srgb srgb": [186, 0, 0, 255],
+ "srgb display-p3": [170, 34, 23, 255],
+ "display-p3 srgb": [186, 0, 0, 255],
+ "display-p3 display-p3": [169, 0, 3, 255],
+ },
+};
+
+const fromSRGBToDisplayP3 = {
+ "255,0,0,255": [234, 51, 35, 255],
+ "255,0,0,204": [234, 51, 35, 204],
+ "187,0,0,255": [171, 35, 23, 255],
+ "187,0,0,204": [171, 35, 23, 204],
+};
+
+const fromDisplayP3ToSRGB = {
+ "255,0,0,255": [255, 0, 0, 255],
+ "255,0,0,204": [255, 0, 0, 204],
+ "187,0,0,255": [205, 0, 0, 255],
+ "187,0,0,204": [205, 0, 0, 204],
+};
+
+function pixelsApproximatelyEqual(p1, p2) {
+ for (let i = 0; i < 4; ++i) {
+ if (Math.abs(p1[i] - p2[i]) > 3)
+ return false;
+ }
+ return true;
+}
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/imagedata-no-color-settings-crash.html b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/imagedata-no-color-settings-crash.html
new file mode 100644
index 0000000000..b21eaf72ab
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/imagedata-no-color-settings-crash.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext('2d',
+ {})
+ var dataFloat32 = new Float32Array(4);
+ var imageData = ctx.createImageData(dataFloat32, 1, 1,
+ {});
+ ctx.putImageData(imageData, 5, 5);
+ var data = ctx.getImageData(5,5,1,1).data;
+}, "Putting a float-32 ImageData with no color settings on a context 2D should not crash.");
+
+test(function() {
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext('2d',
+ {})
+ var dataUint16 = new Uint16Array(4);
+ var imageData = ctx.createImageData(dataUint16, 1, 1,
+ {});
+ ctx.putImageData(imageData, 5, 5);
+ var data = ctx.getImageData(5,5,1,1).data;
+}, "Putting a uint-16 ImageData with no color settings on a context 2D should not crash.");
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000CC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000CC.png
new file mode 100644
index 0000000000..9b3db7e22e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000CC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000FF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000FF.png
new file mode 100644
index 0000000000..78237d5a9d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BB0000FF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000CCCC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000CCCC.png
new file mode 100644
index 0000000000..3fbe7cadc0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000CCCC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000FFFF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000FFFF.png
new file mode 100644
index 0000000000..ab9b1bf5b7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-BBBC00000000FFFF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000CC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000CC.png
new file mode 100644
index 0000000000..a83344933d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000CC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000FF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000FF.png
new file mode 100644
index 0000000000..3222c5e26f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FF0000FF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000CCCC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000CCCC.png
new file mode 100644
index 0000000000..60f1239943
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000CCCC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000FFFF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000FFFF.png
new file mode 100644
index 0000000000..c558eb10b3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Adobe-RGB-FFFF00000000FFFF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-0.7333-0-0.svg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-0.7333-0-0.svg
new file mode 100644
index 0000000000..2737814877
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-0.7333-0-0.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2">
+ <rect width="2" height="2" style="fill: color(display-p3 0.7333 0 0);"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-1-0-0.svg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-1-0-0.svg
new file mode 100644
index 0000000000..5c1b07362a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-1-0-0.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2">
+ <rect width="2" height="2" style="fill: color(display-p3 1 0 0);"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000CC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000CC.png
new file mode 100644
index 0000000000..2036aeae25
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000CC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000FF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000FF.png
new file mode 100644
index 0000000000..35347a3055
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BB0000FF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000CCCC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000CCCC.png
new file mode 100644
index 0000000000..87f11b5d97
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000CCCC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000FFFF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000FFFF.png
new file mode 100644
index 0000000000..ea2f84caa1
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-BBBC00000000FFFF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000CC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000CC.png
new file mode 100644
index 0000000000..8a0abc74dd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000CC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000FF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000FF.png
new file mode 100644
index 0000000000..7b6d4a6150
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FF0000FF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000CCCC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000CCCC.png
new file mode 100644
index 0000000000..8a0abc74dd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000CCCC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000FFFF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000FFFF.png
new file mode 100644
index 0000000000..7b6d4a6150
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Display-P3-FFFF00000000FFFF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-BE000000.jpg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-BE000000.jpg
new file mode 100644
index 0000000000..21eecaa25e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-BE000000.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-FF000000.jpg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-FF000000.jpg
new file mode 100644
index 0000000000..32f3b691e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Generic-CMYK-FF000000.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.mp4 b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.mp4
new file mode 100644
index 0000000000..71ad32c5f0
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.mp4
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.webm b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.webm
new file mode 100644
index 0000000000..5e4eae49dc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-222000000.webm
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.mp4 b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.mp4
new file mode 100644
index 0000000000..0e2880a93a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.mp4
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.webm b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.webm
new file mode 100644
index 0000000000..4f28de8cea
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/Rec2020-3FF000000.webm
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-p3d65.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-p3d65.png
new file mode 100644
index 0000000000..5eb3f6a15f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-p3d65.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-rec2020.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-rec2020.png
new file mode 100644
index 0000000000..b64db07379
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-rec2020.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-srgb.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-srgb.png
new file mode 100644
index 0000000000..bfbba8b8e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-semitransparent-srgb.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.avif b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.avif
new file mode 100644
index 0000000000..c3890c5cf6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.avif
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.bmp b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.bmp
new file mode 100644
index 0000000000..9c9561c704
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.bmp
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.ico b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.ico
new file mode 100644
index 0000000000..87e8ff45de
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.ico
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.png
new file mode 100644
index 0000000000..bfbba8b8e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.webp b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.webp
new file mode 100644
index 0000000000..925646067a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb-transparent.webp
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.avif b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.avif
new file mode 100644
index 0000000000..c13b320ea8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.avif
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.bmp b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.bmp
new file mode 100644
index 0000000000..465d203d98
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.bmp
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.gif b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.gif
new file mode 100644
index 0000000000..25bcefb2bf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.gif
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.ico b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.ico
new file mode 100644
index 0000000000..e5375826ab
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.ico
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.jpg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.jpg
new file mode 100644
index 0000000000..c4579e8f06
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.jpg
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.png
new file mode 100644
index 0000000000..1b5876b5f3
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.svg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.svg
new file mode 100644
index 0000000000..0517130849
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.svg
@@ -0,0 +1,6 @@
+<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <rect x="0" y="0" width="10px" height="10px" fill="#9b1b1b"/>
+ <rect x="10" y="0" width="10px" height="10px" fill="#1b9b1b"/>
+ <rect x="0" y="10" width="10px" height="10px" fill="#1b1b9b"/>
+ <rect x="10" y="10" width="10px" height="10px" fill="#1b1b1b"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.webp b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.webp
new file mode 100644
index 0000000000..b7c0a421dc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/pattern-srgb.webp
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.png
new file mode 100644
index 0000000000..c4496db19b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.png
new file mode 100644
index 0000000000..3b4cfda52c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_AdobeRGB_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_opaque.png
new file mode 100644
index 0000000000..e7a142cd2e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_transparent.png
new file mode 100644
index 0000000000..0b035317c8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_DisplayP3_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_opaque.png
new file mode 100644
index 0000000000..a1dc7ddb0d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_transparent.png
new file mode 100644
index 0000000000..be2eb1208e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_ProPhoto_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_opaque.png
new file mode 100644
index 0000000000..e2a2d14451
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_transparent.png
new file mode 100644
index 0000000000..960d7d8e75
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_Rec2020_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.png
new file mode 100644
index 0000000000..80cf9785eb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.png
new file mode 100644
index 0000000000..3ec565f8c2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_AdobeRGB_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.png
new file mode 100644
index 0000000000..5f3134b79c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.png
new file mode 100644
index 0000000000..500a70eff8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_DisplayP3_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.png
new file mode 100644
index 0000000000..b5d0e07a7a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.png
new file mode 100644
index 0000000000..e4ec3e4454
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_ProPhoto_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.png
new file mode 100644
index 0000000000..c487d5846f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.png
new file mode 100644
index 0000000000..78fe202c0e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_Rec2020_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.png
new file mode 100644
index 0000000000..babf232a36
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.png
new file mode 100644
index 0000000000..3016404009
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_interlaced_sRGB_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_opaque.png
new file mode 100644
index 0000000000..8a665345e9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_transparent.png
new file mode 100644
index 0000000000..e51cda77c4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_16bit_sRGB_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.png
new file mode 100644
index 0000000000..8b787b5c87
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.png
new file mode 100644
index 0000000000..727028e765
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_AdobeRGB_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_opaque.png
new file mode 100644
index 0000000000..fe8bdd4963
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_transparent.png
new file mode 100644
index 0000000000..b836afebed
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_DisplayP3_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_opaque.png
new file mode 100644
index 0000000000..5ecd868606
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_transparent.png
new file mode 100644
index 0000000000..85a349dc1d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_ProPhoto_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_opaque.png
new file mode 100644
index 0000000000..599cd34040
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_transparent.png
new file mode 100644
index 0000000000..ecf65c3d46
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_Rec2020_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_opaque.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_opaque.png
new file mode 100644
index 0000000000..9cab6d12e6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_opaque.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_transparent.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_transparent.png
new file mode 100644
index 0000000000..5fa01e62c2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/png-16bit/2x2_8bit_sRGB_transparent.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.mp4 b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.mp4
new file mode 100644
index 0000000000..59572f5138
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.mp4
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.svg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.svg
new file mode 100644
index 0000000000..2b785f8cf4
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2">
+ <rect width="2" height="2" style="fill: #BB0000;"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.webm b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.webm
new file mode 100644
index 0000000000..23a6364bdb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000.webm
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000CC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000CC.png
new file mode 100644
index 0000000000..fe463486ef
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000CC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000FF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000FF.png
new file mode 100644
index 0000000000..be7009f613
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BB0000FF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000CCCC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000CCCC.png
new file mode 100644
index 0000000000..5220ccb7a9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000CCCC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000FFFF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000FFFF.png
new file mode 100644
index 0000000000..416ef12986
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-BBBC00000000FFFF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000.svg b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000.svg
new file mode 100644
index 0000000000..8798fdfc3a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2">
+ <rect width="2" height="2" style="fill: #FF0000;"/>
+</svg>
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000CC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000CC.png
new file mode 100644
index 0000000000..e86f64b71b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000CC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000FF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000FF.png
new file mode 100644
index 0000000000..22f33b14da
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0000FF.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.mp4 b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.mp4
new file mode 100644
index 0000000000..37a29f9f83
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.mp4
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.webm b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.webm
new file mode 100644
index 0000000000..31b69af924
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FF0100.webm
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000CCCC.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000CCCC.png
new file mode 100644
index 0000000000..e86f64b71b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000CCCC.png
Binary files differ
diff --git a/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000FFFF.png b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000FFFF.png
new file mode 100644
index 0000000000..22f33b14da
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/manual/wide-gamut-canvas/resources/sRGB-FFFF00000000FFFF.png
Binary files differ