diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index 527d7f4b..337e0a4f 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -163,6 +163,11 @@ impl CanvasRenderingContext2D { self.current_state.line_dash = new_line_dash } + #[inline] + pub fn set_line_dash_offset(&mut self, new_line_dash_offset: f32) { + self.current_state.line_dash_offset = new_line_dash_offset + } + // Text styles #[inline] @@ -210,7 +215,9 @@ impl CanvasRenderingContext2D { let mut outline = path.into_outline(); if !self.current_state.line_dash.is_empty() { - let mut dash = OutlineDash::new(&outline, &self.current_state.line_dash); + let mut dash = OutlineDash::new(&outline, + &self.current_state.line_dash, + self.current_state.line_dash_offset); dash.dash(); outline = dash.into_outline(); } @@ -277,6 +284,7 @@ struct State { line_join: LineJoin, miter_limit: f32, line_dash: Vec, + line_dash_offset: f32, fill_paint: Paint, stroke_paint: Paint, text_align: TextAlign, @@ -294,6 +302,7 @@ impl State { line_join: LineJoin::Miter, miter_limit: 10.0, line_dash: vec![], + line_dash_offset: 0.0, fill_paint: Paint { color: ColorU::black() }, stroke_paint: Paint { color: ColorU::black() }, text_align: TextAlign::Left, diff --git a/geometry/src/dash.rs b/geometry/src/dash.rs index 0029ec92..a77df34b 100644 --- a/geometry/src/dash.rs +++ b/geometry/src/dash.rs @@ -13,6 +13,8 @@ use crate::outline::{Contour, Outline, PushSegmentFlags}; use std::mem; +const EPSILON: f32 = 0.0001; + pub struct OutlineDash<'a> { input: &'a Outline, output: Outline, @@ -21,8 +23,8 @@ pub struct OutlineDash<'a> { impl<'a> OutlineDash<'a> { #[inline] - pub fn new(input: &'a Outline, dashes: &'a [f32]) -> OutlineDash<'a> { - OutlineDash { input, output: Outline::new(), state: DashState::new(dashes) } + pub fn new(input: &'a Outline, dashes: &'a [f32], offset: f32) -> OutlineDash<'a> { + OutlineDash { input, output: Outline::new(), state: DashState::new(dashes, offset) } } pub fn dash(&mut self) { @@ -91,8 +93,6 @@ impl<'a, 'b, 'c> ContourDash<'a, 'b, 'c> { self.state.distance_left = self.state.dashes[self.state.current_dash_index]; } } - - const EPSILON: f32 = 0.0001; } } @@ -104,12 +104,25 @@ struct DashState<'a> { } impl<'a> DashState<'a> { - fn new(dashes: &'a [f32]) -> DashState<'a> { + fn new(dashes: &'a [f32], mut offset: f32) -> DashState<'a> { + let total: f32 = dashes.iter().cloned().sum(); + offset %= total; + + let mut current_dash_index = 0; + while current_dash_index < dashes.len() { + let dash = dashes[current_dash_index]; + if offset < dash { + break; + } + offset -= dash; + current_dash_index += 1; + } + DashState { output: Contour::new(), dashes, - current_dash_index: 0, - distance_left: dashes[0], + current_dash_index, + distance_left: offset, } }