diff --git a/components/canvas/backend.rs b/components/canvas/backend.rs index 5b1e50b02f3..966c8205c25 100644 --- a/components/canvas/backend.rs +++ b/components/canvas/backend.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use canvas_traits::canvas::{ - CompositionOptions, FillOrStrokeStyle, LineOptions, Path, ShadowOptions, + CompositionOptions, FillOrStrokeStyle, FillRule, LineOptions, Path, ShadowOptions, }; use compositing_traits::SerializableImageData; use euclid::default::{Point2D, Rect, Size2D, Transform2D}; @@ -47,6 +47,7 @@ pub(crate) trait GenericDrawTarget { fn fill( &mut self, path: &Path, + fill_rule: FillRule, style: FillOrStrokeStyle, composition_options: CompositionOptions, transform: Transform2D, @@ -68,7 +69,7 @@ pub(crate) trait GenericDrawTarget { ); fn get_size(&self) -> Size2D; fn pop_clip(&mut self); - fn push_clip(&mut self, path: &Path, transform: Transform2D); + fn push_clip(&mut self, path: &Path, fill_rule: FillRule, transform: Transform2D); fn push_clip_rect(&mut self, rect: &Rect); fn stroke( &mut self, diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 2379d09a3d0..7be42c97883 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -567,6 +567,7 @@ impl CanvasData { pub(crate) fn fill_path( &mut self, path: &Path, + fill_rule: FillRule, style: FillOrStrokeStyle, _shadow_options: ShadowOptions, composition_options: CompositionOptions, @@ -584,7 +585,7 @@ impl CanvasData { |self_, style| { self_ .drawtarget - .fill(path, style, composition_options, transform) + .fill(path, fill_rule, style, composition_options, transform) }, ) } @@ -615,8 +616,13 @@ impl CanvasData { ) } - pub(crate) fn clip_path(&mut self, path: &Path, transform: Transform2D) { - self.drawtarget.push_clip(path, transform); + pub(crate) fn clip_path( + &mut self, + path: &Path, + fill_rule: FillRule, + transform: Transform2D, + ) { + self.drawtarget.push_clip(path, fill_rule, transform); } /// diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index 810ef196b9d..09e34bd3ed7 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -173,9 +173,17 @@ impl CanvasPaintThread { Canvas2dMsg::ClearRect(ref rect, transform) => { self.canvas(canvas_id).clear_rect(rect, transform) }, - Canvas2dMsg::FillPath(style, path, shadow_options, composition_options, transform) => { + Canvas2dMsg::FillPath( + style, + path, + fill_rule, + shadow_options, + composition_options, + transform, + ) => { self.canvas(canvas_id).fill_path( &path, + fill_rule, style, shadow_options, composition_options, @@ -199,8 +207,9 @@ impl CanvasPaintThread { transform, ); }, - Canvas2dMsg::ClipPath(path, transform) => { - self.canvas(canvas_id).clip_path(&path, transform); + Canvas2dMsg::ClipPath(path, fill_rule, transform) => { + self.canvas(canvas_id) + .clip_path(&path, fill_rule, transform); }, Canvas2dMsg::DrawImage( snapshot, @@ -412,19 +421,30 @@ impl Canvas { fn fill_path( &mut self, path: &Path, + fill_rule: FillRule, style: FillOrStrokeStyle, shadow_options: ShadowOptions, composition_options: CompositionOptions, transform: Transform2D, ) { match self { - Canvas::Raqote(canvas_data) => { - canvas_data.fill_path(path, style, shadow_options, composition_options, transform) - }, + Canvas::Raqote(canvas_data) => canvas_data.fill_path( + path, + fill_rule, + style, + shadow_options, + composition_options, + transform, + ), #[cfg(feature = "vello")] - Canvas::Vello(canvas_data) => { - canvas_data.fill_path(path, style, shadow_options, composition_options, transform) - }, + Canvas::Vello(canvas_data) => canvas_data.fill_path( + path, + fill_rule, + style, + shadow_options, + composition_options, + transform, + ), } } @@ -515,11 +535,11 @@ impl Canvas { } } - fn clip_path(&mut self, path: &Path, transform: Transform2D) { + fn clip_path(&mut self, path: &Path, fill_rule: FillRule, transform: Transform2D) { match self { - Canvas::Raqote(canvas_data) => canvas_data.clip_path(path, transform), + Canvas::Raqote(canvas_data) => canvas_data.clip_path(path, fill_rule, transform), #[cfg(feature = "vello")] - Canvas::Vello(canvas_data) => canvas_data.clip_path(path, transform), + Canvas::Vello(canvas_data) => canvas_data.clip_path(path, fill_rule, transform), } } diff --git a/components/canvas/peniko_conversions.rs b/components/canvas/peniko_conversions.rs index 429f0be9e5a..61c94bd0adc 100644 --- a/components/canvas/peniko_conversions.rs +++ b/components/canvas/peniko_conversions.rs @@ -207,3 +207,12 @@ impl Convert for Filter { } } } + +impl Convert for FillRule { + fn convert(self) -> peniko::Fill { + match self { + FillRule::Nonzero => peniko::Fill::NonZero, + FillRule::Evenodd => peniko::Fill::EvenOdd, + } + } +} diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 875c6af1c8f..5c9507f7595 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -277,6 +277,7 @@ impl GenericDrawTarget for raqote::DrawTarget { fn fill( &mut self, path: &canvas_traits::canvas::Path, + fill_rule: FillRule, style: FillOrStrokeStyle, composition_options: CompositionOptions, transform: Transform2D, @@ -284,7 +285,11 @@ impl GenericDrawTarget for raqote::DrawTarget { self.set_transform(&transform); let draw_options = draw_options(composition_options); let pattern = style.to_raqote_pattern(); - let path = to_path(path); + let mut path = to_path(path); + path.winding = match fill_rule { + FillRule::Nonzero => raqote::Winding::NonZero, + FillRule::Evenodd => raqote::Winding::EvenOdd, + }; fill_draw_target(self, draw_options, &source(&pattern), path); } @@ -368,7 +373,14 @@ impl GenericDrawTarget for raqote::DrawTarget { rect.size.height, ); - ::fill(self, &pb, style, composition_options, transform); + ::fill( + self, + &pb, + FillRule::Nonzero, + style, + composition_options, + transform, + ); } fn get_size(&self) -> Size2D { Size2D::new(self.width(), self.height()) @@ -376,9 +388,19 @@ impl GenericDrawTarget for raqote::DrawTarget { fn pop_clip(&mut self) { self.pop_clip(); } - fn push_clip(&mut self, path: &canvas_traits::canvas::Path, transform: Transform2D) { + fn push_clip( + &mut self, + path: &canvas_traits::canvas::Path, + fill_rule: FillRule, + transform: Transform2D, + ) { self.set_transform(&transform); - self.push_clip(&to_path(path)); + let mut path = to_path(path); + path.winding = match fill_rule { + FillRule::Nonzero => raqote::Winding::NonZero, + FillRule::Evenodd => raqote::Winding::EvenOdd, + }; + self.push_clip(&path); } fn push_clip_rect(&mut self, rect: &Rect) { self.push_clip_rect(rect.to_box2d()); diff --git a/components/canvas/vello_backend.rs b/components/canvas/vello_backend.rs index ebbf25fea32..0ef6895abd8 100644 --- a/components/canvas/vello_backend.rs +++ b/components/canvas/vello_backend.rs @@ -17,7 +17,7 @@ use std::num::NonZeroUsize; use std::rc::Rc; use canvas_traits::canvas::{ - CompositionOptions, FillOrStrokeStyle, LineOptions, Path, ShadowOptions, + CompositionOptions, FillOrStrokeStyle, FillRule, LineOptions, Path, ShadowOptions, }; use compositing_traits::SerializableImageData; use euclid::default::{Point2D, Rect, Size2D, Transform2D}; @@ -311,13 +311,14 @@ impl GenericDrawTarget for VelloDrawTarget { fn fill( &mut self, path: &Path, + fill_rule: FillRule, style: FillOrStrokeStyle, composition_options: CompositionOptions, transform: Transform2D, ) { self.with_draw_options(&composition_options, |self_| { self_.scene.fill( - peniko::Fill::NonZero, + fill_rule.convert(), transform.cast().into(), &style .convert() @@ -418,7 +419,7 @@ impl GenericDrawTarget for VelloDrawTarget { self.scene.pop_layer(); } - fn push_clip(&mut self, path: &Path, transform: Transform2D) { + fn push_clip(&mut self, path: &Path, _fill_rule: FillRule, transform: Transform2D) { self.scene .push_layer(peniko::Mix::Clip, 1.0, transform.cast().into(), &path.0); } @@ -432,7 +433,7 @@ impl GenericDrawTarget for VelloDrawTarget { rect.size.width, rect.size.height, ); - self.push_clip(&path, Transform2D::identity()); + self.push_clip(&path, FillRule::Nonzero, Transform2D::identity()); } fn stroke( diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs index d170c6047d1..218526e15a4 100644 --- a/components/script/canvas_state.rs +++ b/components/script/canvas_state.rs @@ -38,6 +38,7 @@ use url::Url; use webrender_api::ImageKey; use crate::canvas_context::{CanvasContext, OffscreenRenderingContext, RenderingContext}; +use crate::conversions::Convert; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::{ CanvasDirection, CanvasFillRule, CanvasImageSource, CanvasLineCap, CanvasLineJoin, @@ -1927,12 +1928,12 @@ impl CanvasState { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill - pub(crate) fn fill_(&self, path: Path, _fill_rule: CanvasFillRule) { - // TODO: Process fill rule + pub(crate) fn fill_(&self, path: Path, fill_rule: CanvasFillRule) { let style = self.state.borrow().fill_style.to_fill_or_stroke_style(); self.send_canvas_2d_msg(Canvas2dMsg::FillPath( style, path, + fill_rule.convert(), self.state.borrow().shadow_options(), self.state.borrow().composition_options(), self.state.borrow().transform, @@ -1964,9 +1965,12 @@ impl CanvasState { } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip - pub(crate) fn clip_(&self, path: Path, _fill_rule: CanvasFillRule) { - // TODO: Process fill rule - self.send_canvas_2d_msg(Canvas2dMsg::ClipPath(path, self.state.borrow().transform)); + pub(crate) fn clip_(&self, path: Path, fill_rule: CanvasFillRule) { + self.send_canvas_2d_msg(Canvas2dMsg::ClipPath( + path, + fill_rule.convert(), + self.state.borrow().transform, + )); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath @@ -2332,3 +2336,12 @@ fn adjust_canvas_size(size: Size2D) -> Size2D { Size2D::zero() } } + +impl Convert for CanvasFillRule { + fn convert(self) -> FillRule { + match self { + CanvasFillRule::Nonzero => FillRule::Nonzero, + CanvasFillRule::Evenodd => FillRule::Evenodd, + } + } +} diff --git a/components/shared/canvas/canvas.rs b/components/shared/canvas/canvas.rs index 7ab12e8e242..2f503fcf51d 100644 --- a/components/shared/canvas/canvas.rs +++ b/components/shared/canvas/canvas.rs @@ -482,11 +482,12 @@ pub enum Canvas2dMsg { Transform2D, ), ClearRect(Rect, Transform2D), - ClipPath(Path, Transform2D), + ClipPath(Path, FillRule, Transform2D), PopClip, FillPath( FillOrStrokeStyle, Path, + FillRule, ShadowOptions, CompositionOptions, Transform2D, diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 42e1f741a8c..af8149bc296 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -479233,7 +479233,7 @@ [] ], "path-objects.yaml": [ - "cf218829598c1ee4275ceefd025974590fbe1cd8", + "ccb3d79b93a44d36fec6abebc9a95621c2913b6c", [] ], "pixel-manipulation.yaml": [ @@ -706232,6 +706232,20 @@ {} ] ], + "2d.path.clip.winding.evenodd.1.html": [ + "a1922011e4ac937605a42e0b14a0de63b05ded73", + [ + null, + {} + ] + ], + "2d.path.clip.winding.evenodd.2.html": [ + "e5aeba44b008e76000af1db74a756becf27ecadc", + [ + null, + {} + ] + ], "2d.path.closePath.empty.html": [ "837f5a76dc9701748f4d485c102cc93f6d410ce9", [ @@ -706295,6 +706309,20 @@ {} ] ], + "2d.path.fill.winding.evenodd.1.html": [ + "d030b93239c310a76a1423fe13c1adcf9fe399ce", + [ + null, + {} + ] + ], + "2d.path.fill.winding.evenodd.2.html": [ + "4553f29d1e4b245fe231eeeb75973b5eba69c15d", + [ + null, + {} + ] + ], "2d.path.fill.winding.subtract.1.html": [ "fa1232e8d0ff59c5d283dc01641b1075372f0a77", [ @@ -717826,6 +717854,34 @@ {} ] ], + "2d.path.clip.winding.evenodd.1.html": [ + "4cf680f62f2b6328d838929f64ebe50729b5b270", + [ + null, + {} + ] + ], + "2d.path.clip.winding.evenodd.1.worker.js": [ + "da772ea73d00beb9ae3332e4bf9d19fda68fdd70", + [ + "html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.worker.html", + {} + ] + ], + "2d.path.clip.winding.evenodd.2.html": [ + "6d47707e5ec00a8a9302c3a2caea1e9e8f25350b", + [ + null, + {} + ] + ], + "2d.path.clip.winding.evenodd.2.worker.js": [ + "23f626e7d7293c7559baa66793264685876e7c0d", + [ + "html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.worker.html", + {} + ] + ], "2d.path.closePath.empty.html": [ "a14a036b253d90462d5f4d1881a0d947b869c5dd", [ @@ -717952,6 +718008,34 @@ {} ] ], + "2d.path.fill.winding.evenodd.1.html": [ + "fc839c9f58b19a4be7a0e43fe661799902ee257e", + [ + null, + {} + ] + ], + "2d.path.fill.winding.evenodd.1.worker.js": [ + "64e1aa1099370dc955bf79e0f05642a53609b2c9", + [ + "html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.worker.html", + {} + ] + ], + "2d.path.fill.winding.evenodd.2.html": [ + "acb70538fd946bd7a6bbb561eae0e93724161b8b", + [ + null, + {} + ] + ], + "2d.path.fill.winding.evenodd.2.worker.js": [ + "1a69f4639d0c8b9a67d3e6b16fd764ea7e5f6683", + [ + "html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.worker.html", + {} + ] + ], "2d.path.fill.winding.subtract.1.html": [ "814f3c3a9e76b711e1fc2f3dac373afc0ab07f0a", [ diff --git a/tests/wpt/tests/html/canvas/element/path-objects/2d.path.clip.winding.evenodd.1.html b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.clip.winding.evenodd.1.html new file mode 100644 index 00000000000..a1922011e4a --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.clip.winding.evenodd.1.html @@ -0,0 +1,38 @@ + + + +Canvas test: 2d.path.clip.winding.evenodd.1 + + + + + + +

2d.path.clip.winding.evenodd.1

+

evenodd winding number rule works in clip

+ + +

Actual output:

+

FAIL (fallback content)

+ +
    + + diff --git a/tests/wpt/tests/html/canvas/element/path-objects/2d.path.clip.winding.evenodd.2.html b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.clip.winding.evenodd.2.html new file mode 100644 index 00000000000..e5aeba44b00 --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.clip.winding.evenodd.2.html @@ -0,0 +1,39 @@ + + + +Canvas test: 2d.path.clip.winding.evenodd.2 + + + + + + +

    2d.path.clip.winding.evenodd.2

    +

    evenodd winding number rule works in clip

    + + +

    Actual output:

    +

    FAIL (fallback content)

    + +
      + + diff --git a/tests/wpt/tests/html/canvas/element/path-objects/2d.path.fill.winding.evenodd.1.html b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.fill.winding.evenodd.1.html new file mode 100644 index 00000000000..d030b93239c --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.fill.winding.evenodd.1.html @@ -0,0 +1,37 @@ + + + +Canvas test: 2d.path.fill.winding.evenodd.1 + + + + + + +

      2d.path.fill.winding.evenodd.1

      +

      evenodd winding number rule works in fill

      + + +

      Actual output:

      +

      FAIL (fallback content)

      + +
        + + diff --git a/tests/wpt/tests/html/canvas/element/path-objects/2d.path.fill.winding.evenodd.2.html b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.fill.winding.evenodd.2.html new file mode 100644 index 00000000000..4553f29d1e4 --- /dev/null +++ b/tests/wpt/tests/html/canvas/element/path-objects/2d.path.fill.winding.evenodd.2.html @@ -0,0 +1,38 @@ + + + +Canvas test: 2d.path.fill.winding.evenodd.2 + + + + + + +

        2d.path.fill.winding.evenodd.2

        +

        evenodd winding number rule works in fill

        + + +

        Actual output:

        +

        FAIL (fallback content)

        + +
          + + diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.html b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.html new file mode 100644 index 00000000000..4cf680f62f2 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.html @@ -0,0 +1,39 @@ + + + +OffscreenCanvas test: 2d.path.clip.winding.evenodd.1 + + + + +

          2d.path.clip.winding.evenodd.1

          +

          evenodd winding number rule works in clip

          + + + diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.worker.js b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.worker.js new file mode 100644 index 00000000000..da772ea73d0 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.1.worker.js @@ -0,0 +1,33 @@ +// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. +// OffscreenCanvas test in a worker:2d.path.clip.winding.evenodd.1 +// Description:evenodd winding number rule works in clip +// Note: + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +var t = async_test("evenodd winding number rule works in clip"); +var t_pass = t.done.bind(t); +var t_fail = t.step_func(function(reason) { + throw reason; +}); +t.step(function() { + + var canvas = new OffscreenCanvas(100, 50); + var ctx = canvas.getContext('2d'); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.rect(0, 0, 100, 50); + + ctx.fillStyle = "#f00"; + ctx.clip("evenodd"); + ctx.fillRect(0, 0, 100, 50); + + _assertPixel(canvas, 50,25, 0,255,0,255); + t.done(); +}); +done(); diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.html b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.html new file mode 100644 index 00000000000..6d47707e5ec --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.html @@ -0,0 +1,40 @@ + + + +OffscreenCanvas test: 2d.path.clip.winding.evenodd.2 + + + + +

          2d.path.clip.winding.evenodd.2

          +

          evenodd winding number rule works in clip

          + + + diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.worker.js b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.worker.js new file mode 100644 index 00000000000..23f626e7d72 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.clip.winding.evenodd.2.worker.js @@ -0,0 +1,34 @@ +// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. +// OffscreenCanvas test in a worker:2d.path.clip.winding.evenodd.2 +// Description:evenodd winding number rule works in clip +// Note: + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +var t = async_test("evenodd winding number rule works in clip"); +var t_pass = t.done.bind(t); +var t_fail = t.step_func(function(reason) { + throw reason; +}); +t.step(function() { + + var canvas = new OffscreenCanvas(100, 50); + var ctx = canvas.getContext('2d'); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + let path = new Path2D(); + path.rect(0, 0, 100, 50); + path.rect(0, 0, 100, 50); + path.closePath(); + + ctx.fillStyle = "#f00"; + ctx.clip(path, "evenodd"); + ctx.fillRect(0, 0, 100, 50); + + _assertPixel(canvas, 50,25, 0,255,0,255); + t.done(); +}); +done(); diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.html b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.html new file mode 100644 index 00000000000..fc839c9f58b --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.html @@ -0,0 +1,38 @@ + + + +OffscreenCanvas test: 2d.path.fill.winding.evenodd.1 + + + + +

          2d.path.fill.winding.evenodd.1

          +

          evenodd winding number rule works in fill

          + + + diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.worker.js b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.worker.js new file mode 100644 index 00000000000..64e1aa10993 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.1.worker.js @@ -0,0 +1,32 @@ +// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. +// OffscreenCanvas test in a worker:2d.path.fill.winding.evenodd.1 +// Description:evenodd winding number rule works in fill +// Note: + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +var t = async_test("evenodd winding number rule works in fill"); +var t_pass = t.done.bind(t); +var t_fail = t.step_func(function(reason) { + throw reason; +}); +t.step(function() { + + var canvas = new OffscreenCanvas(100, 50); + var ctx = canvas.getContext('2d'); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.rect(0, 0, 100, 50); + + ctx.fillStyle = "#f00"; + ctx.fill("evenodd"); + + _assertPixel(canvas, 50,25, 0,255,0,255); + t.done(); +}); +done(); diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.html b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.html new file mode 100644 index 00000000000..acb70538fd9 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.html @@ -0,0 +1,39 @@ + + + +OffscreenCanvas test: 2d.path.fill.winding.evenodd.2 + + + + +

          2d.path.fill.winding.evenodd.2

          +

          evenodd winding number rule works in fill

          + + + diff --git a/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.worker.js b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.worker.js new file mode 100644 index 00000000000..1a69f4639d0 --- /dev/null +++ b/tests/wpt/tests/html/canvas/offscreen/path-objects/2d.path.fill.winding.evenodd.2.worker.js @@ -0,0 +1,33 @@ +// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. +// OffscreenCanvas test in a worker:2d.path.fill.winding.evenodd.2 +// Description:evenodd winding number rule works in fill +// Note: + +importScripts("/resources/testharness.js"); +importScripts("/html/canvas/resources/canvas-tests.js"); + +var t = async_test("evenodd winding number rule works in fill"); +var t_pass = t.done.bind(t); +var t_fail = t.step_func(function(reason) { + throw reason; +}); +t.step(function() { + + var canvas = new OffscreenCanvas(100, 50); + var ctx = canvas.getContext('2d'); + + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + let path = new Path2D(); + path.rect(0, 0, 100, 50); + path.rect(0, 0, 100, 50); + path.closePath(); + + ctx.fillStyle = "#f00"; + ctx.fill(path, "evenodd"); + + _assertPixel(canvas, 50,25, 0,255,0,255); + t.done(); +}); +done(); diff --git a/tests/wpt/tests/html/canvas/tools/yaml/path-objects.yaml b/tests/wpt/tests/html/canvas/tools/yaml/path-objects.yaml index cf218829598..ccb3d79b93a 100644 --- a/tests/wpt/tests/html/canvas/tools/yaml/path-objects.yaml +++ b/tests/wpt/tests/html/canvas/tools/yaml/path-objects.yaml @@ -2479,6 +2479,37 @@ cr.rectangle(0, 0, 100, 50) cr.fill() +- name: 2d.path.fill.winding.evenodd.1 + desc: evenodd winding number rule works in fill + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.rect(0, 0, 100, 50); + + ctx.fillStyle = "#f00"; + ctx.fill("evenodd"); + + @assert pixel 50,25 == 0,255,0,255; + +- name: 2d.path.fill.winding.evenodd.2 + desc: evenodd winding number rule works in fill + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + let path = new Path2D(); + path.rect(0, 0, 100, 50); + path.rect(0, 0, 100, 50); + path.closePath(); + + ctx.fillStyle = "#f00"; + ctx.fill(path, "evenodd"); + + @assert pixel 50,25 == 0,255,0,255; + - name: 2d.path.fill.winding.add code: | ctx.fillStyle = '#f00'; @@ -3046,6 +3077,39 @@ @assert pixel 50,25 == 0,255,0,255; expected: green +- name: 2d.path.clip.winding.evenodd.1 + desc: evenodd winding number rule works in clip + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + ctx.beginPath(); + ctx.rect(0, 0, 100, 50); + ctx.rect(0, 0, 100, 50); + + ctx.fillStyle = "#f00"; + ctx.clip("evenodd"); + ctx.fillRect(0, 0, 100, 50); + + @assert pixel 50,25 == 0,255,0,255; + +- name: 2d.path.clip.winding.evenodd.2 + desc: evenodd winding number rule works in clip + code: | + ctx.fillStyle = '#0f0'; + ctx.fillRect(0, 0, 100, 50); + + let path = new Path2D(); + path.rect(0, 0, 100, 50); + path.rect(0, 0, 100, 50); + path.closePath(); + + ctx.fillStyle = "#f00"; + ctx.clip(path, "evenodd"); + ctx.fillRect(0, 0, 100, 50); + + @assert pixel 50,25 == 0,255,0,255; + - name: 2d.path.clip.winding.1 code: | ctx.fillStyle = '#0f0';