canvas: Implement line dash setters and getters (#36257)

Implement `setLineDash`, `getLineDash`, and `lineDashOffset` from
`CanvasPathDrawingStyles` mixin, according to the spec
https://html.spec.whatwg.org/multipage/canvas.html#canvaspathdrawingstyles.

Testing: Existing WPT.

---------

Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
This commit is contained in:
Steven Novaryo 2025-04-01 19:22:00 +08:00 committed by GitHub
parent bc6926d1fe
commit a77592e281
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 144 additions and 92 deletions

View file

@ -94,6 +94,8 @@ pub(crate) struct CanvasContextState {
#[no_trace]
line_join: LineJoinStyle,
miter_limit: f64,
line_dash: Vec<f64>,
line_dash_offset: f64,
#[no_trace]
transform: Transform2D<f32>,
shadow_offset_x: f64,
@ -134,6 +136,8 @@ impl CanvasContextState {
text_align: Default::default(),
text_baseline: Default::default(),
direction: Default::default(),
line_dash: Vec::new(),
line_dash_offset: 0.0,
}
}
}
@ -1286,6 +1290,59 @@ impl CanvasState {
self.send_canvas_2d_msg(Canvas2dMsg::SetMiterLimit(limit as f32))
}
/// <https://html.spec.whatwg.org/multipage/#dom-context-2d-getlinedash>
pub(crate) fn line_dash(&self) -> Vec<f64> {
// > return a sequence whose values are the values of
// > the object's dash list, in the same order.
self.state.borrow().line_dash.clone()
}
/// <https://html.spec.whatwg.org/multipage/#dom-context-2d-setlinedash>
pub(crate) fn set_line_dash(&self, segments: Vec<f64>) {
// > If any value in segments is not finite (e.g. an Infinity or a NaN value),
// > or if any value is negative (less than zero), then return (without throwing
// > an exception; user agents could show a message on a developer console,
// > though, as that would be helpful for debugging).
if segments
.iter()
.any(|segment| !segment.is_finite() || *segment < 0.0)
{
return;
}
// > If the number of elements in segments is odd, then let segments
// > be the concatenation of two copies of segments.
let mut line_dash: Vec<_> = segments.clone();
if segments.len() & 1 == 1 {
line_dash.extend(line_dash.clone());
}
// > 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(),
))
}
/// <https://html.spec.whatwg.org/multipage/#dom-context-2d-linedashoffset>
pub(crate) fn line_dash_offset(&self) -> f64 {
// > On getting, it must return the current value.
self.state.borrow().line_dash_offset
}
/// <https://html.spec.whatwg.org/multipage/#dom-context-2d-linedashoffset?
pub(crate) fn set_line_dash_offset(&self, offset: f64) {
// > On setting, infinite and NaN values must be ignored,
// > leaving the value unchanged;
if !offset.is_finite() {
return;
}
// > 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
pub(crate) fn create_image_data(
&self,