diff --git a/components/canvas/canvas_paint_thread.rs b/components/canvas/canvas_paint_thread.rs index c6dca6a877c..633e09b5212 100644 --- a/components/canvas/canvas_paint_thread.rs +++ b/components/canvas/canvas_paint_thread.rs @@ -5,7 +5,7 @@ use std::borrow::ToOwned; use std::collections::HashMap; use std::sync::Arc; -use std::thread; +use std::{f32, thread}; use canvas_traits::ConstellationCanvasMsg; use canvas_traits::canvas::*; @@ -134,76 +134,149 @@ impl<'a> CanvasPaintThread<'a> { fn process_canvas_2d_message(&mut self, message: Canvas2dMsg, canvas_id: CanvasId) { match message { - Canvas2dMsg::FillText(text, x, y, max_width, style, is_rtl) => { - self.canvas(canvas_id).set_fill_style(style); - self.canvas(canvas_id) - .fill_text(text, x, y, max_width, is_rtl); + Canvas2dMsg::FillText( + text, + x, + y, + max_width, + style, + is_rtl, + text_options, + shadow_options, + composition_options, + transform, + ) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_fill_style(style); + canvas.set_text_options(text_options); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + canvas.fill_text(text, x, y, max_width, is_rtl); }, - Canvas2dMsg::FillRect(rect, style) => { - self.canvas(canvas_id).set_fill_style(style); - self.canvas(canvas_id).fill_rect(&rect); + Canvas2dMsg::FillRect(rect, style, shadow_options, composition_options, transform) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_fill_style(style); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + canvas.fill_rect(&rect); }, - Canvas2dMsg::StrokeRect(rect, style) => { - self.canvas(canvas_id).set_stroke_style(style); - self.canvas(canvas_id).stroke_rect(&rect); + Canvas2dMsg::StrokeRect( + rect, + style, + line_options, + shadow_options, + composition_options, + transform, + ) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_stroke_style(style); + canvas.set_line_options(line_options); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + canvas.stroke_rect(&rect); }, - Canvas2dMsg::ClearRect(ref rect) => self.canvas(canvas_id).clear_rect(rect), - Canvas2dMsg::FillPath(style, path) => { - self.canvas(canvas_id).set_fill_style(style); - self.canvas(canvas_id).fill_path(&path); + Canvas2dMsg::ClearRect(ref rect, transform) => { + self.canvas(canvas_id).set_transform(&transform); + self.canvas(canvas_id).clear_rect(rect) }, - Canvas2dMsg::StrokePath(style, path) => { - self.canvas(canvas_id).set_stroke_style(style); - self.canvas(canvas_id).stroke_path(&path); + Canvas2dMsg::FillPath(style, path, shadow_options, composition_options, transform) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_fill_style(style); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + canvas.fill_path(&path); }, - Canvas2dMsg::ClipPath(path) => self.canvas(canvas_id).clip_path(&path), - Canvas2dMsg::DrawImage(snapshot, dest_rect, source_rect, smoothing_enabled) => { - self.canvas(canvas_id).draw_image( + Canvas2dMsg::StrokePath( + path, + style, + line_options, + shadow_options, + composition_options, + transform, + ) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_stroke_style(style); + canvas.set_line_options(line_options); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + canvas.stroke_path(&path); + }, + Canvas2dMsg::ClipPath(path, transform) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.clip_path(&path); + }, + Canvas2dMsg::DrawImage( + snapshot, + dest_rect, + source_rect, + smoothing_enabled, + shadow_options, + composition_options, + transform, + ) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + canvas.draw_image( snapshot.to_owned(), dest_rect, source_rect, smoothing_enabled, ) }, - Canvas2dMsg::DrawEmptyImage(image_size, dest_rect, source_rect) => self - .canvas(canvas_id) - .draw_image(Snapshot::cleared(image_size), dest_rect, source_rect, false), + Canvas2dMsg::DrawEmptyImage( + image_size, + dest_rect, + source_rect, + shadow_options, + composition_options, + transform, + ) => { + let canvas = self.canvas(canvas_id); + canvas.set_transform(&transform); + canvas.set_shadow_options(shadow_options); + canvas.set_composition_options(composition_options); + self.canvas(canvas_id).draw_image( + Snapshot::cleared(image_size), + dest_rect, + source_rect, + false, + ) + }, Canvas2dMsg::DrawImageInOther( other_canvas_id, image_size, dest_rect, source_rect, smoothing, + shadow_options, + composition_options, + transform, ) => { let snapshot = self .canvas(canvas_id) .read_pixels(Some(source_rect.to_u32()), Some(image_size)); - self.canvas(other_canvas_id).draw_image( - snapshot, - dest_rect, - source_rect, - smoothing, - ); + let canvas = self.canvas(other_canvas_id); + canvas.set_transform(&transform); + canvas.set_composition_options(composition_options); + canvas.set_shadow_options(shadow_options); + canvas.draw_image(snapshot, dest_rect, source_rect, smoothing); }, - Canvas2dMsg::MeasureText(text, sender) => { - let metrics = self.canvas(canvas_id).measure_text(text); + Canvas2dMsg::MeasureText(text, sender, text_options) => { + let canvas = self.canvas(canvas_id); + canvas.set_text_options(text_options); + let metrics = canvas.measure_text(text); sender.send(metrics).unwrap(); }, Canvas2dMsg::RestoreContext => self.canvas(canvas_id).restore_context_state(), Canvas2dMsg::SaveContext => self.canvas(canvas_id).save_context_state(), - Canvas2dMsg::SetLineWidth(width) => self.canvas(canvas_id).set_line_width(width), - Canvas2dMsg::SetLineCap(cap) => self.canvas(canvas_id).set_line_cap(cap), - Canvas2dMsg::SetLineJoin(join) => self.canvas(canvas_id).set_line_join(join), - Canvas2dMsg::SetMiterLimit(limit) => self.canvas(canvas_id).set_miter_limit(limit), - Canvas2dMsg::SetLineDash(items) => self.canvas(canvas_id).set_line_dash(items), - Canvas2dMsg::SetLineDashOffset(offset) => { - self.canvas(canvas_id).set_line_dash_offset(offset) - }, - Canvas2dMsg::SetTransform(ref matrix) => self.canvas(canvas_id).set_transform(matrix), - Canvas2dMsg::SetGlobalAlpha(alpha) => self.canvas(canvas_id).set_global_alpha(alpha), - Canvas2dMsg::SetGlobalComposition(op) => { - self.canvas(canvas_id).set_global_composition(op) - }, Canvas2dMsg::GetImageData(dest_rect, canvas_size, sender) => { let snapshot = self .canvas(canvas_id) @@ -214,21 +287,6 @@ impl<'a> CanvasPaintThread<'a> { self.canvas(canvas_id) .put_image_data(snapshot.to_owned(), rect); }, - Canvas2dMsg::SetShadowOffsetX(value) => { - self.canvas(canvas_id).set_shadow_offset_x(value) - }, - Canvas2dMsg::SetShadowOffsetY(value) => { - self.canvas(canvas_id).set_shadow_offset_y(value) - }, - Canvas2dMsg::SetShadowBlur(value) => self.canvas(canvas_id).set_shadow_blur(value), - Canvas2dMsg::SetShadowColor(color) => self.canvas(canvas_id).set_shadow_color(color), - Canvas2dMsg::SetFont(font_style) => self.canvas(canvas_id).set_font(font_style), - Canvas2dMsg::SetTextAlign(text_align) => { - self.canvas(canvas_id).set_text_align(text_align) - }, - Canvas2dMsg::SetTextBaseline(text_baseline) => { - self.canvas(canvas_id).set_text_baseline(text_baseline) - }, Canvas2dMsg::UpdateImage(sender) => { self.canvas(canvas_id).update_image_rendering(); sender.send(()).unwrap(); @@ -455,4 +513,41 @@ impl Canvas<'_> { Canvas::Raqote(canvas_data) => canvas_data.recreate(size), } } + + fn set_text_options(&mut self, text_options: TextOptions) { + if let Some(font) = text_options.font { + self.set_font(font); + } + self.set_text_align(text_options.align); + self.set_text_baseline(text_options.baseline); + } + + fn set_shadow_options(&mut self, shadow_options: ShadowOptions) { + self.set_shadow_color(shadow_options.color); + self.set_shadow_offset_x(shadow_options.offset_x); + self.set_shadow_offset_y(shadow_options.offset_y); + self.set_shadow_blur(shadow_options.blur); + } + + fn set_composition_options(&mut self, composition_options: CompositionOptions) { + self.set_global_alpha(composition_options.alpha as f32); + self.set_global_composition(composition_options.composition_operation); + } + + fn set_line_options(&mut self, line_options: LineOptions) { + let LineOptions { + width, + cap_style, + join_style, + miter_limit, + dash, + dash_offset, + } = line_options; + self.set_line_width(width as f32); + self.set_line_cap(cap_style); + self.set_line_join(join_style); + self.set_miter_limit(miter_limit as f32); + self.set_line_dash(dash); + self.set_line_dash_offset(dash_offset as f32); + } } diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs index 2721aad1f38..b9f61494fe5 100644 --- a/components/script/canvas_state.rs +++ b/components/script/canvas_state.rs @@ -8,9 +8,10 @@ use std::str::FromStr; use std::sync::Arc; use canvas_traits::canvas::{ - Canvas2dMsg, CanvasId, CanvasMsg, CompositionOrBlending, Direction, FillOrStrokeStyle, - FillRule, LineCapStyle, LineJoinStyle, LinearGradientStyle, Path, RadialGradientStyle, - RepetitionStyle, TextAlign, TextBaseline, TextMetrics as CanvasTextMetrics, + Canvas2dMsg, CanvasId, CanvasMsg, CompositionOptions, CompositionOrBlending, Direction, + FillOrStrokeStyle, FillRule, LineCapStyle, LineJoinStyle, LineOptions, LinearGradientStyle, + Path, RadialGradientStyle, RepetitionStyle, ShadowOptions, TextAlign, TextBaseline, + TextMetrics as CanvasTextMetrics, TextOptions, }; use constellation_traits::ScriptToConstellationMessage; use cssparser::color::clamp_unit_f32; @@ -146,6 +147,41 @@ impl CanvasContextState { line_dash_offset: 0.0, } } + + fn text_options(&self) -> TextOptions { + TextOptions { + font: self.font_style.clone(), + align: self.text_align, + baseline: self.text_baseline, + } + } + + fn composition_options(&self) -> CompositionOptions { + CompositionOptions { + alpha: self.global_alpha, + composition_operation: self.global_composition, + } + } + + fn shadow_options(&self) -> ShadowOptions { + ShadowOptions { + offset_x: self.shadow_offset_x, + offset_y: self.shadow_offset_y, + blur: self.shadow_blur, + color: self.shadow_color, + } + } + + fn line_options(&self) -> LineOptions { + LineOptions { + width: self.line_width, + cap_style: self.line_cap, + join_style: self.line_join, + miter_limit: self.miter_limit, + dash: self.line_dash.iter().map(|x| *x as f32).collect(), + dash_offset: self.line_dash_offset, + } + } } #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)] @@ -302,7 +338,10 @@ impl CanvasState { return; } - self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(self.size.get().to_f32().into())); + self.send_canvas_2d_msg(Canvas2dMsg::ClearRect( + self.size.get().to_f32().into(), + self.state.borrow().transform, + )); } fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option> { @@ -563,6 +602,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); self.mark_as_dirty(canvas); @@ -609,6 +651,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); self.mark_as_dirty(canvas); @@ -657,6 +702,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); }, OffscreenRenderingContext::BitmapRenderer(ref context) => { @@ -669,6 +717,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); }, OffscreenRenderingContext::Detached => return Err(Error::InvalidState), @@ -678,6 +729,9 @@ impl CanvasState { image_size, dest_rect, source_rect, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); } @@ -728,6 +782,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); }, RenderingContext::BitmapRenderer(ref context) => { @@ -740,6 +797,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); }, RenderingContext::Placeholder(ref context) => { @@ -754,6 +814,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )), OffscreenRenderingContext::BitmapRenderer(ref context) => { let Some(snapshot) = context.get_image_data() else { @@ -765,6 +828,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); }, OffscreenRenderingContext::Detached => return Err(Error::InvalidState), @@ -777,6 +843,9 @@ impl CanvasState { image_size, dest_rect, source_rect, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); } @@ -824,6 +893,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); self.mark_as_dirty(canvas); Ok(()) @@ -870,6 +942,9 @@ impl CanvasState { dest_rect, source_rect, smoothing_enabled, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); self.mark_as_dirty(canvas); @@ -952,7 +1027,6 @@ impl CanvasState { .borrow_mut() .transform(state.transform.cast()); state.transform = transform; - self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(state.transform)); if let Some(inverse) = transform.inverse() { self.current_default_path .borrow_mut() @@ -964,14 +1038,20 @@ impl CanvasState { pub(crate) fn fill_rect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { let style = self.state.borrow().fill_style.to_fill_or_stroke_style(); - self.send_canvas_2d_msg(Canvas2dMsg::FillRect(rect, style)); + self.send_canvas_2d_msg(Canvas2dMsg::FillRect( + rect, + style, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, + )); } } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect pub(crate) fn clear_rect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { - self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect)); + self.send_canvas_2d_msg(Canvas2dMsg::ClearRect(rect, self.state.borrow().transform)); } } @@ -979,7 +1059,14 @@ impl CanvasState { pub(crate) fn stroke_rect(&self, x: f64, y: f64, width: f64, height: f64) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) { let style = self.state.borrow().stroke_style.to_fill_or_stroke_style(); - self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect(rect, style)); + self.send_canvas_2d_msg(Canvas2dMsg::StrokeRect( + rect, + style, + self.state.borrow().line_options(), + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, + )); } } @@ -994,7 +1081,6 @@ impl CanvasState { return; } self.state.borrow_mut().shadow_offset_x = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetX(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety @@ -1008,7 +1094,6 @@ impl CanvasState { return; } self.state.borrow_mut().shadow_offset_y = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowOffsetY(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur @@ -1022,7 +1107,6 @@ impl CanvasState { return; } self.state.borrow_mut().shadow_blur = value; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowBlur(value)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor @@ -1041,7 +1125,6 @@ impl CanvasState { ) { if let Ok(rgba) = parse_color(canvas, &value, can_gc) { self.state.borrow_mut().shadow_color = rgba; - self.send_canvas_2d_msg(Canvas2dMsg::SetShadowColor(rgba)) } } @@ -1286,7 +1369,6 @@ impl CanvasState { } self.state.borrow_mut().global_alpha = alpha; - self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalAlpha(alpha as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation @@ -1301,7 +1383,6 @@ impl CanvasState { pub(crate) fn set_global_composite_operation(&self, op_str: DOMString) { if let Ok(op) = CompositionOrBlending::from_str(&op_str) { self.state.borrow_mut().global_composition = op; - self.send_canvas_2d_msg(Canvas2dMsg::SetGlobalComposition(op)) } } @@ -1353,6 +1434,10 @@ impl CanvasState { max_width, style, is_rtl, + self.state.borrow().text_options(), + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, )); } @@ -1373,7 +1458,11 @@ impl CanvasState { } let (sender, receiver) = ipc::channel::().unwrap(); - self.send_canvas_2d_msg(Canvas2dMsg::MeasureText(text.into(), sender)); + self.send_canvas_2d_msg(Canvas2dMsg::MeasureText( + text.into(), + sender, + self.state.borrow().text_options(), + )); let metrics = receiver.recv().unwrap(); TextMetrics::new( @@ -1413,7 +1502,6 @@ impl CanvasState { None => return, // syntax error }; self.state.borrow_mut().font_style = Some((*resolved_font_style).clone()); - self.send_canvas_2d_msg(Canvas2dMsg::SetFont((*resolved_font_style).clone())); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-font @@ -1449,7 +1537,6 @@ impl CanvasState { CanvasTextAlign::Center => TextAlign::Center, }; self.state.borrow_mut().text_align = text_align; - self.send_canvas_2d_msg(Canvas2dMsg::SetTextAlign(text_align)); } pub(crate) fn text_baseline(&self) -> CanvasTextBaseline { @@ -1473,7 +1560,6 @@ impl CanvasState { CanvasTextBaseline::Bottom => TextBaseline::Bottom, }; self.state.borrow_mut().text_baseline = text_baseline; - self.send_canvas_2d_msg(Canvas2dMsg::SetTextBaseline(text_baseline)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-direction @@ -1507,7 +1593,6 @@ impl CanvasState { } self.state.borrow_mut().line_width = width; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineWidth(width as f32)) } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap @@ -1527,7 +1612,6 @@ impl CanvasState { CanvasLineCap::Square => LineCapStyle::Square, }; self.state.borrow_mut().line_cap = line_cap; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineCap(line_cap)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin @@ -1547,7 +1631,6 @@ impl CanvasState { CanvasLineJoin::Miter => LineJoinStyle::Miter, }; self.state.borrow_mut().line_join = line_join; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineJoin(line_join)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit @@ -1562,7 +1645,6 @@ impl CanvasState { } self.state.borrow_mut().miter_limit = limit; - self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32)) } /// @@ -1594,9 +1676,6 @@ impl CanvasState { // > Let the object's dash list be segments. self.state.borrow_mut().line_dash = line_dash.clone(); - self.send_canvas_2d_msg(Canvas2dMsg::SetLineDash( - line_dash.into_iter().map(|dash| dash as f32).collect(), - )) } /// @@ -1615,7 +1694,6 @@ impl CanvasState { // > other values must change the current value to the new value. self.state.borrow_mut().line_dash_offset = offset; - self.send_canvas_2d_msg(Canvas2dMsg::SetLineDashOffset(offset as f32)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata @@ -1858,7 +1936,13 @@ impl CanvasState { pub(crate) fn fill_(&self, path: Path, _fill_rule: CanvasFillRule) { // TODO: Process fill rule let style = self.state.borrow().fill_style.to_fill_or_stroke_style(); - self.send_canvas_2d_msg(Canvas2dMsg::FillPath(style, path)); + self.send_canvas_2d_msg(Canvas2dMsg::FillPath( + style, + path, + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, + )); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke @@ -1869,7 +1953,14 @@ impl CanvasState { pub(crate) fn stroke_(&self, path: Path) { let style = self.state.borrow().stroke_style.to_fill_or_stroke_style(); - self.send_canvas_2d_msg(Canvas2dMsg::StrokePath(style, path)); + self.send_canvas_2d_msg(Canvas2dMsg::StrokePath( + path, + style, + self.state.borrow().line_options(), + self.state.borrow().shadow_options(), + self.state.borrow().composition_options(), + self.state.borrow().transform, + )); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip @@ -1881,7 +1972,7 @@ 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.send_canvas_2d_msg(Canvas2dMsg::ClipPath(path, self.state.borrow().transform)); } // https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath diff --git a/components/shared/canvas/canvas.rs b/components/shared/canvas/canvas.rs index 0387d21b285..c1c78649a13 100644 --- a/components/shared/canvas/canvas.rs +++ b/components/shared/canvas/canvas.rs @@ -400,6 +400,38 @@ pub enum FillRule { #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct CanvasId(pub u64); +#[derive(Debug, Deserialize, MallocSizeOf, Serialize)] +pub struct CompositionOptions { + pub alpha: f64, + pub composition_operation: CompositionOrBlending, +} + +#[derive(Debug, Deserialize, MallocSizeOf, Serialize)] +pub struct ShadowOptions { + pub offset_x: f64, + pub offset_y: f64, + pub blur: f64, + pub color: AbsoluteColor, +} + +#[derive(Debug, Deserialize, MallocSizeOf, Serialize)] +pub struct LineOptions { + pub width: f64, + pub cap_style: LineCapStyle, + pub join_style: LineJoinStyle, + pub miter_limit: f64, + pub dash: Vec, + pub dash_offset: f64, +} + +#[derive(Debug, Deserialize, MallocSizeOf, Serialize)] +pub struct TextOptions { + pub font: Option, + pub align: TextAlign, + pub baseline: TextBaseline, +} + +#[allow(clippy::large_enum_variant)] #[derive(Debug, Deserialize, Serialize)] pub enum CanvasMsg { Canvas2d(Canvas2dMsg, CanvasId), @@ -410,37 +442,82 @@ pub enum CanvasMsg { #[derive(Debug, Deserialize, Serialize)] pub enum Canvas2dMsg { - DrawImage(IpcSnapshot, Rect, Rect, bool), - DrawEmptyImage(Size2D, Rect, Rect), - DrawImageInOther(CanvasId, Size2D, Rect, Rect, bool), - ClearRect(Rect), - ClipPath(Path), - FillPath(FillOrStrokeStyle, Path), - FillText(String, f64, f64, Option, FillOrStrokeStyle, bool), - FillRect(Rect, FillOrStrokeStyle), + DrawImage( + IpcSnapshot, + Rect, + Rect, + bool, + ShadowOptions, + CompositionOptions, + Transform2D, + ), + DrawEmptyImage( + Size2D, + Rect, + Rect, + ShadowOptions, + CompositionOptions, + Transform2D, + ), + DrawImageInOther( + CanvasId, + Size2D, + Rect, + Rect, + bool, + ShadowOptions, + CompositionOptions, + Transform2D, + ), + ClearRect(Rect, Transform2D), + ClipPath(Path, Transform2D), + FillPath( + FillOrStrokeStyle, + Path, + ShadowOptions, + CompositionOptions, + Transform2D, + ), + FillText( + String, + f64, + f64, + Option, + FillOrStrokeStyle, + bool, + TextOptions, + ShadowOptions, + CompositionOptions, + Transform2D, + ), + FillRect( + Rect, + FillOrStrokeStyle, + ShadowOptions, + CompositionOptions, + Transform2D, + ), GetImageData(Rect, Size2D, IpcSender), - MeasureText(String, IpcSender), + MeasureText(String, IpcSender, TextOptions), PutImageData(Rect, IpcSnapshot), RestoreContext, SaveContext, - StrokeRect(Rect, FillOrStrokeStyle), - StrokePath(FillOrStrokeStyle, Path), - SetLineWidth(f32), - SetLineCap(LineCapStyle), - SetLineJoin(LineJoinStyle), - SetMiterLimit(f32), - SetLineDash(Vec), - SetLineDashOffset(f32), - SetGlobalAlpha(f32), - SetGlobalComposition(CompositionOrBlending), - SetTransform(Transform2D), - SetShadowOffsetX(f64), - SetShadowOffsetY(f64), - SetShadowBlur(f64), - SetShadowColor(AbsoluteColor), - SetFont(FontStyleStruct), - SetTextAlign(TextAlign), - SetTextBaseline(TextBaseline), + StrokeRect( + Rect, + FillOrStrokeStyle, + LineOptions, + ShadowOptions, + CompositionOptions, + Transform2D, + ), + StrokePath( + Path, + FillOrStrokeStyle, + LineOptions, + ShadowOptions, + CompositionOptions, + Transform2D, + ), UpdateImage(IpcSender<()>), }