diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index eb2cf963e702..f9c32c34979f 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -83,7 +83,7 @@ pub trait Backend { /// azure's and raqote's PathBuilder. pub trait GenericPathBuilder { fn arc( - &self, + &mut self, origin: Point2D, radius: f32, start_angle: f32, @@ -91,14 +91,14 @@ pub trait GenericPathBuilder { anticlockwise: bool, ); fn bezier_curve_to( - &self, + &mut self, control_point1: &Point2D, control_point2: &Point2D, control_point3: &Point2D, ); - fn close(&self); + fn close(&mut self); fn ellipse( - &self, + &mut self, origin: Point2D, radius_x: f32, radius_y: f32, @@ -107,32 +107,32 @@ pub trait GenericPathBuilder { end_angle: f32, anticlockwise: bool, ); - fn get_current_point(&self) -> Point2D; - fn line_to(&self, point: Point2D); - fn move_to(&self, point: Point2D); - fn quadratic_curve_to(&self, control_point: &Point2D, end_point: &Point2D); - fn finish(&self) -> Path; + fn get_current_point(&mut self) -> Point2D; + fn line_to(&mut self, point: Point2D); + fn move_to(&mut self, point: Point2D); + fn quadratic_curve_to(&mut self, control_point: &Point2D, end_point: &Point2D); + fn finish(&mut self) -> Path; } /// A wrapper around a stored PathBuilder and an optional transformation that should be /// applied to any points to ensure they are in the matching device space. struct PathBuilderRef<'a> { - builder: &'a Box, + builder: &'a mut Box, transform: Transform2D, } impl<'a> PathBuilderRef<'a> { - fn line_to(&self, pt: &Point2D) { + fn line_to(&mut self, pt: &Point2D) { let pt = self.transform.transform_point(pt); self.builder.line_to(pt); } - fn move_to(&self, pt: &Point2D) { + fn move_to(&mut self, pt: &Point2D) { let pt = self.transform.transform_point(pt); self.builder.move_to(pt); } - fn rect(&self, rect: &Rect) { + fn rect(&mut self, rect: &Rect) { let (first, second, third, fourth) = ( Point2D::new(rect.origin.x, rect.origin.y), Point2D::new(rect.origin.x + rect.size.width, rect.origin.y), @@ -151,14 +151,14 @@ impl<'a> PathBuilderRef<'a> { self.builder.close(); } - fn quadratic_curve_to(&self, cp: &Point2D, endpoint: &Point2D) { + fn quadratic_curve_to(&mut self, cp: &Point2D, endpoint: &Point2D) { self.builder.quadratic_curve_to( &self.transform.transform_point(cp), &self.transform.transform_point(endpoint), ) } - fn bezier_curve_to(&self, cp1: &Point2D, cp2: &Point2D, endpoint: &Point2D) { + fn bezier_curve_to(&mut self, cp1: &Point2D, cp2: &Point2D, endpoint: &Point2D) { self.builder.bezier_curve_to( &self.transform.transform_point(cp1), &self.transform.transform_point(cp2), @@ -166,14 +166,21 @@ impl<'a> PathBuilderRef<'a> { ) } - fn arc(&self, center: &Point2D, radius: f32, start_angle: f32, end_angle: f32, ccw: bool) { + fn arc( + &mut self, + center: &Point2D, + radius: f32, + start_angle: f32, + end_angle: f32, + ccw: bool, + ) { let center = self.transform.transform_point(center); self.builder .arc(center, radius, start_angle, end_angle, ccw); } pub fn ellipse( - &self, + &mut self, center: &Point2D, radius_x: f32, radius_y: f32, @@ -194,7 +201,7 @@ impl<'a> PathBuilderRef<'a> { ); } - fn current_point(&self) -> Option> { + fn current_point(&mut self) -> Option> { let inverse = match self.transform.inverse() { Some(i) => i, None => return None, @@ -209,7 +216,12 @@ impl<'a> PathBuilderRef<'a> { // The prototypes are derived from azure's methods. pub trait GenericDrawTarget { fn clear_rect(&self, rect: &Rect); - fn copy_surface(&self, surface: SourceSurface, source: Rect, destination: Point2D); + fn copy_surface( + &mut self, + surface: SourceSurface, + source: Rect, + destination: Point2D, + ); fn create_gradient_stops( &self, gradient_stops: Vec, @@ -244,24 +256,24 @@ pub trait GenericDrawTarget { sigma: f32, operator: CompositionOp, ); - fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions); - fn fill_rect(&self, rect: &Rect, pattern: Pattern, draw_options: Option<&DrawOptions>); + fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions); + fn fill_rect(&mut self, rect: &Rect, pattern: Pattern, draw_options: Option<&DrawOptions>); fn get_format(&self) -> SurfaceFormat; fn get_size(&self) -> Size2D; fn get_transform(&self) -> Transform2D; - fn pop_clip(&self); - fn push_clip(&self, path: &Path); - fn set_transform(&self, matrix: &Transform2D); + fn pop_clip(&mut self); + fn push_clip(&mut self, path: &Path); + fn set_transform(&mut self, matrix: &Transform2D); fn snapshot(&self) -> SourceSurface; fn stroke( - &self, + &mut self, path: &Path, pattern: Pattern, stroke_options: &StrokeOptions, draw_options: &DrawOptions, ); fn stroke_line( - &self, + &mut self, start: Point2D, end: Point2D, pattern: Pattern, @@ -269,7 +281,7 @@ pub trait GenericDrawTarget { draw_options: &DrawOptions, ); fn stroke_rect( - &self, + &mut self, rect: &Rect, pattern: Pattern, stroke_options: &StrokeOptions, @@ -332,19 +344,19 @@ pub enum SourceSurface { Raqote(()), } +#[derive(Clone)] pub enum Path { #[cfg(feature = "azure_backend")] Azure(azure::azure_hl::Path), #[cfg(feature = "raqote_backend")] - Raqote(()), + Raqote(raqote::Path), } -#[derive(Clone)] -pub enum Pattern { +pub enum Pattern<'a> { #[cfg(feature = "azure_backend")] Azure(azure::azure_hl::Pattern), #[cfg(feature = "raqote_backend")] - Raqote(()), + Raqote(raqote::Source<'a>), } pub enum DrawSurfaceOptions { @@ -359,7 +371,7 @@ pub enum DrawOptions { #[cfg(feature = "azure_backend")] Azure(azure::azure_hl::DrawOptions), #[cfg(feature = "raqote_backend")] - Raqote(()), + Raqote(raqote::DrawOptions), } #[derive(Clone)] @@ -367,7 +379,7 @@ pub enum StrokeOptions<'a> { #[cfg(feature = "azure_backend")] Azure(azure::azure_hl::StrokeOptions<'a>), #[cfg(feature = "raqote_backend")] - Raqote(PhantomData<&'a ()>), + Raqote(raqote::StrokeStyle, PhantomData<&'a ()>), } #[derive(Clone, Copy)] @@ -426,7 +438,7 @@ impl<'a> CanvasData<'a> { } pub fn draw_image( - &self, + &mut self, image_data: Vec, image_size: Size2D, dest_rect: Rect, @@ -442,14 +454,15 @@ impl<'a> CanvasData<'a> { image_data.into() }; - let writer = |draw_target: &GenericDrawTarget| { + let draw_options = self.state.draw_options.clone(); + let writer = |draw_target: &mut GenericDrawTarget| { write_image( draw_target, image_data, source_rect.size, dest_rect, smoothing_enabled, - &self.state.draw_options, + &draw_options, ); }; @@ -462,7 +475,7 @@ impl<'a> CanvasData<'a> { // TODO(pylbrecht) pass another closure for raqote self.draw_with_shadow(&rect, writer); } else { - writer(&*self.drawtarget); + writer(&mut *self.drawtarget); } } @@ -485,7 +498,7 @@ impl<'a> CanvasData<'a> { ); } - pub fn fill_rect(&self, rect: &Rect) { + pub fn fill_rect(&mut self, rect: &Rect) { if self.state.fill_style.is_zero_size_gradient() { return; // Paint nothing if gradient size is zero. } @@ -498,7 +511,7 @@ impl<'a> CanvasData<'a> { ); if self.need_to_draw_shadow() { - self.draw_with_shadow(&draw_rect, |new_draw_target: &GenericDrawTarget| { + self.draw_with_shadow(&draw_rect, |new_draw_target: &mut GenericDrawTarget| { new_draw_target.fill_rect( &draw_rect, self.state.fill_style.clone(), @@ -518,13 +531,13 @@ impl<'a> CanvasData<'a> { self.drawtarget.clear_rect(rect); } - pub fn stroke_rect(&self, rect: &Rect) { + pub fn stroke_rect(&mut self, rect: &Rect) { if self.state.stroke_style.is_zero_size_gradient() { return; // Paint nothing if gradient size is zero. } if self.need_to_draw_shadow() { - self.draw_with_shadow(&rect, |new_draw_target: &GenericDrawTarget| { + self.draw_with_shadow(&rect, |new_draw_target: &mut GenericDrawTarget| { new_draw_target.stroke_rect( rect, self.state.stroke_style.clone(), @@ -570,7 +583,7 @@ impl<'a> CanvasData<'a> { // If a user-space builder exists, create a finished path from it. let new_state = match *self.path_state.as_mut().unwrap() { - PathState::UserSpacePathBuilder(ref builder, ref mut transform) => { + PathState::UserSpacePathBuilder(ref mut builder, ref mut transform) => { Some((builder.finish(), transform.take())) }, PathState::DeviceSpacePathBuilder(..) | PathState::UserSpacePath(..) => None, @@ -595,8 +608,8 @@ impl<'a> CanvasData<'a> { // If a device-space builder is present, create a user-space path from its // finished path by inverting the initial transformation. - let new_state = match self.path_state.as_ref().unwrap() { - PathState::DeviceSpacePathBuilder(ref builder) => { + let new_state = match *self.path_state.as_mut().unwrap() { + PathState::DeviceSpacePathBuilder(ref mut builder) => { let path = builder.finish(); let inverse = match self.drawtarget.get_transform().inverse() { Some(m) => m, @@ -605,7 +618,7 @@ impl<'a> CanvasData<'a> { return; }, }; - let builder = path.transformed_copy_to_builder(&inverse); + let mut builder = path.transformed_copy_to_builder(&inverse); Some(builder.finish()) }, PathState::UserSpacePathBuilder(..) | PathState::UserSpacePath(..) => None, @@ -631,7 +644,7 @@ impl<'a> CanvasData<'a> { self.ensure_path(); self.drawtarget.fill( - &self.path(), + &self.path().clone(), self.state.fill_style.clone(), &self.state.draw_options, ); @@ -644,7 +657,7 @@ impl<'a> CanvasData<'a> { self.ensure_path(); self.drawtarget.stroke( - &self.path(), + &self.path().clone(), self.state.stroke_style.clone(), &self.state.stroke_opts, &self.state.draw_options, @@ -653,7 +666,8 @@ impl<'a> CanvasData<'a> { pub fn clip(&mut self) { self.ensure_path(); - self.drawtarget.push_clip(&self.path()); + let path = self.path().clone(); + self.drawtarget.push_clip(&path); } pub fn is_point_in_path( @@ -695,19 +709,20 @@ impl<'a> CanvasData<'a> { // and overwriting path_state in other ones. The following awkward use of duplicate // matches works around the resulting borrow errors. let new_state = { - match self.path_state.as_ref().unwrap() { - &PathState::UserSpacePathBuilder(_, None) | - &PathState::DeviceSpacePathBuilder(_) => None, - &PathState::UserSpacePathBuilder(ref builder, Some(ref transform)) => { + match *self.path_state.as_mut().unwrap() { + PathState::UserSpacePathBuilder(_, None) | PathState::DeviceSpacePathBuilder(_) => { + None + }, + PathState::UserSpacePathBuilder(ref mut builder, Some(ref transform)) => { let path = builder.finish(); Some(PathState::DeviceSpacePathBuilder( path.transformed_copy_to_builder(transform), )) }, - &PathState::UserSpacePath(ref path, Some(ref transform)) => Some( + PathState::UserSpacePath(ref path, Some(ref transform)) => Some( PathState::DeviceSpacePathBuilder(path.transformed_copy_to_builder(transform)), ), - &PathState::UserSpacePath(ref path, None) => Some(PathState::UserSpacePathBuilder( + PathState::UserSpacePath(ref path, None) => Some(PathState::UserSpacePathBuilder( path.copy_to_builder(), None, )), @@ -717,14 +732,14 @@ impl<'a> CanvasData<'a> { // There's a new builder value that needs to be stored. Some(state) => self.path_state = Some(state), // There's an existing builder value that can be returned immediately. - None => match self.path_state.as_ref().unwrap() { - &PathState::UserSpacePathBuilder(ref builder, None) => { + None => match *self.path_state.as_mut().unwrap() { + PathState::UserSpacePathBuilder(ref mut builder, None) => { return PathBuilderRef { builder, transform: Transform2D::identity(), }; }, - &PathState::DeviceSpacePathBuilder(ref builder) => { + PathState::DeviceSpacePathBuilder(ref mut builder) => { return PathBuilderRef { builder, transform: self.drawtarget.get_transform(), @@ -734,16 +749,16 @@ impl<'a> CanvasData<'a> { }, } - match self.path_state.as_ref().unwrap() { - &PathState::UserSpacePathBuilder(ref builder, None) => PathBuilderRef { + match *self.path_state.as_mut().unwrap() { + PathState::UserSpacePathBuilder(ref mut builder, None) => PathBuilderRef { builder, transform: Transform2D::identity(), }, - &PathState::DeviceSpacePathBuilder(ref builder) => PathBuilderRef { + PathState::DeviceSpacePathBuilder(ref mut builder) => PathBuilderRef { builder, transform: self.drawtarget.get_transform(), }, - &PathState::UserSpacePathBuilder(..) | &PathState::UserSpacePath(..) => unreachable!(), + PathState::UserSpacePathBuilder(..) | PathState::UserSpacePath(..) => unreachable!(), } } @@ -1024,7 +1039,7 @@ impl<'a> CanvasData<'a> { } fn create_draw_target_for_shadow(&self, source_rect: &Rect) -> Box { - let draw_target = self.drawtarget.create_similar_draw_target( + let mut draw_target = self.drawtarget.create_similar_draw_target( &Size2D::new( source_rect.size.width as i32, source_rect.size.height as i32, @@ -1040,11 +1055,11 @@ impl<'a> CanvasData<'a> { fn draw_with_shadow(&self, rect: &Rect, draw_shadow_source: F) where - F: FnOnce(&GenericDrawTarget), + F: FnOnce(&mut GenericDrawTarget), { let shadow_src_rect = self.state.transform.transform_rect(rect); - let new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect); - draw_shadow_source(&*new_draw_target); + let mut new_draw_target = self.create_draw_target_for_shadow(&shadow_src_rect); + draw_shadow_source(&mut *new_draw_target); self.drawtarget.draw_surface_with_shadow( new_draw_target.snapshot(), &Point2D::new( @@ -1098,8 +1113,8 @@ impl<'a> Drop for CanvasData<'a> { #[derive(Clone)] pub struct CanvasPaintState<'a> { pub draw_options: DrawOptions, - pub fill_style: Pattern, - pub stroke_style: Pattern, + pub fill_style: Pattern<'a>, + pub stroke_style: Pattern<'a>, pub stroke_opts: StrokeOptions<'a>, /// The current 2D transform matrix. pub transform: Transform2D, diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 6e49026606e3..3099b8c70247 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -72,11 +72,12 @@ impl Backend for RaqoteBackend { impl<'a> CanvasPaintState<'a> { pub fn new(_antialias: AntialiasMode) -> CanvasPaintState<'a> { + let solid_src = raqote::SolidSource { r: 0, g: 0, b: 0, a: 255 }; CanvasPaintState { - draw_options: DrawOptions::Raqote(()), - fill_style: Pattern::Raqote(()), - stroke_style: Pattern::Raqote(()), - stroke_opts: StrokeOptions::Raqote(PhantomData), + draw_options: DrawOptions::Raqote(raqote::DrawOptions::new()), + fill_style: Pattern::Raqote(raqote::Source::Solid(solid_src)), + stroke_style: Pattern::Raqote(raqote::Source::Solid(solid_src)), + stroke_opts: StrokeOptions::Raqote(Default::default(), PhantomData), transform: Transform2D::identity(), shadow_offset_x: 0.0, shadow_offset_y: 0.0, @@ -86,33 +87,56 @@ impl<'a> CanvasPaintState<'a> { } } -impl Pattern { +impl Pattern<'_> { pub fn is_zero_size_gradient(&self) -> bool { match *self { - Pattern::Raqote(()) => unimplemented!(), + Pattern::Raqote(_) => unimplemented!(), + } + } + pub fn as_raqote(&self) -> &raqote::Source { + match self { + Pattern::Raqote(p) => p, } } } impl<'a> StrokeOptions<'a> { pub fn set_line_width(&mut self, _val: f32) { - unimplemented!() + match self { + StrokeOptions::Raqote(options, _) => options.width = _val, + } } pub fn set_miter_limit(&mut self, _val: f32) { - unimplemented!() + match self { + StrokeOptions::Raqote(options, _) => options.miter_limit = _val, + } } pub fn set_line_join(&mut self, _val: LineJoinStyle) { - unimplemented!() + match self { + StrokeOptions::Raqote(options, _) => options.join = _val.to_raqote_style(), + } } pub fn set_line_cap(&mut self, _val: LineCapStyle) { - unimplemented!() + match self { + StrokeOptions::Raqote(options, _) => options.cap = _val.to_raqote_style(), + } + } + pub fn as_raqote(&self) -> &raqote::StrokeStyle { + match self { + StrokeOptions::Raqote(options, _) => options, + } } } impl DrawOptions { pub fn set_alpha(&mut self, _val: f32) { match self { - DrawOptions::Raqote(()) => unimplemented!(), + DrawOptions::Raqote(draw_options) => draw_options.alpha = _val, + } + } + pub fn as_raqote(&self) -> &raqote::DrawOptions { + match self { + DrawOptions::Raqote(options) => options, } } } @@ -132,40 +156,42 @@ impl Path { pub fn copy_to_builder(&self) -> Box { unimplemented!() } + + pub fn as_raqote(&self) -> &raqote::Path { + match self { + Path::Raqote(p) => p, + } + } } impl GenericDrawTarget for raqote::DrawTarget { fn clear_rect(&self, _rect: &Rect) { - unimplemented!() + unimplemented!(); } - fn copy_surface( - &self, + &mut self, _surface: SourceSurface, _source: Rect, _destination: Point2D, ) { - unimplemented!() + unimplemented!(); } - fn create_gradient_stops( &self, _gradient_stops: Vec, _extend_mode: ExtendMode, ) -> GradientStops { - unimplemented!() + unimplemented!(); } - fn create_path_builder(&self) -> Box { - unimplemented!() + Box::new(PathBuilder::new()) } - fn create_similar_draw_target( &self, _size: &Size2D, _format: SurfaceFormat, ) -> Box { - unimplemented!() + unimplemented!(); } fn create_source_surface_from_data( &self, @@ -173,7 +199,7 @@ impl GenericDrawTarget for raqote::DrawTarget { _size: Size2D, _stride: i32, ) -> Option { - unimplemented!() + unimplemented!(); } fn draw_surface( &self, @@ -183,7 +209,7 @@ impl GenericDrawTarget for raqote::DrawTarget { _filter: Filter, _draw_options: &DrawOptions, ) { - unimplemented!() + unimplemented!(); } fn draw_surface_with_shadow( &self, @@ -194,69 +220,181 @@ impl GenericDrawTarget for raqote::DrawTarget { _sigma: f32, _operator: CompositionOp, ) { - unimplemented!() + unimplemented!(); } - fn fill(&self, _path: &Path, _pattern: Pattern, _draw_options: &DrawOptions) { - unimplemented!() + fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) { + self.fill(path.as_raqote(), pattern.as_raqote(), draw_options.as_raqote()); } - fn fill_rect(&self, _rect: &Rect, _pattern: Pattern, _draw_options: Option<&DrawOptions>) { - unimplemented!() + fn fill_rect( + &mut self, + _rect: &Rect, + _pattern: Pattern, + _draw_options: Option<&DrawOptions>, + ) { + unimplemented!(); } fn get_format(&self) -> SurfaceFormat { - unimplemented!() + unimplemented!(); } fn get_size(&self) -> Size2D { - unimplemented!() + unimplemented!(); } fn get_transform(&self) -> Transform2D { - unimplemented!() + *self.get_transform() } - fn pop_clip(&self) { - unimplemented!() + fn pop_clip(&mut self) { + self.pop_clip(); } - fn push_clip(&self, _path: &Path) { - unimplemented!() + fn push_clip(&mut self, path: &Path) { + self.push_clip(path.as_raqote()); } - fn set_transform(&self, _matrix: &Transform2D) { - unimplemented!() + fn set_transform(&mut self, matrix: &Transform2D) { + self.set_transform(matrix); } fn snapshot(&self) -> SourceSurface { - unimplemented!() + unimplemented!(); } fn stroke( - &self, - _path: &Path, - _pattern: Pattern, - _stroke_options: &StrokeOptions, - _draw_options: &DrawOptions, + &mut self, + path: &Path, + pattern: Pattern, + stroke_options: &StrokeOptions, + draw_options: &DrawOptions, ) { - unimplemented!() + self.stroke( + path.as_raqote(), + pattern.as_raqote(), + stroke_options.as_raqote(), + draw_options.as_raqote(), + ); } fn stroke_line( - &self, + &mut self, _start: Point2D, _end: Point2D, _pattern: Pattern, _stroke_options: &StrokeOptions, _draw_options: &DrawOptions, ) { - unimplemented!() + unimplemented!(); } fn stroke_rect( - &self, + &mut self, _rect: &Rect, _pattern: Pattern, _stroke_options: &StrokeOptions, _draw_options: &DrawOptions, ) { - unimplemented!() + unimplemented!(); } - fn snapshot_data(&self, _f: &Fn(&[u8]) -> Vec) -> Vec { - unimplemented!() + unimplemented!(); } - fn snapshot_data_owned(&self) -> Vec { - unimplemented!() + unimplemented!(); + } +} + +struct PathBuilder(Option); + +impl PathBuilder { + fn new() -> PathBuilder { + PathBuilder(Some(raqote::PathBuilder::new())) + } +} + +impl GenericPathBuilder for PathBuilder { + fn arc( + &mut self, + origin: Point2D, + radius: f32, + start_angle: f32, + end_angle: f32, + _anticlockwise: bool, + ) { + self.0.as_mut().unwrap().arc(origin.x, origin.y, radius, start_angle, end_angle); + } + fn bezier_curve_to( + &mut self, + control_point1: &Point2D, + control_point2: &Point2D, + control_point3: &Point2D, + ) { + self.0.as_mut().unwrap().cubic_to( + control_point1.x, + control_point1.y, + control_point2.x, + control_point2.y, + control_point3.x, + control_point3.y, + ); + } + fn close(&mut self) { + self.0.as_mut().unwrap().close(); + } + fn ellipse( + &mut self, + _origin: Point2D, + _radius_x: f32, + _radius_y: f32, + _rotation_angle: f32, + _start_angle: f32, + _end_angle: f32, + _anticlockwise: bool, + ) { + unimplemented!(); + } + fn get_current_point(&mut self) -> Point2D { + unimplemented!(); + } + fn line_to(&mut self, point: Point2D) { + self.0.as_mut().unwrap().line_to(point.x, point.y); + } + fn move_to(&mut self, point: Point2D) { + self.0.as_mut().unwrap().move_to(point.x, point.y); + } + fn quadratic_curve_to(&mut self, control_point: &Point2D, end_point: &Point2D) { + self.0.as_mut().unwrap().quad_to(control_point.x, control_point.y, end_point.x, end_point.y); + } + fn finish(&mut self) -> Path { + Path::Raqote(self.0.take().unwrap().finish()) + } +} + +pub trait ToRaqoteStyle { + type Target; + + fn to_raqote_style(self) -> Self::Target; +} + +impl ToRaqoteStyle for LineJoinStyle { + type Target = raqote::LineJoin; + + fn to_raqote_style(self) -> raqote::LineJoin { + match self { + LineJoinStyle::Round => raqote::LineJoin::Round, + LineJoinStyle::Bevel => raqote::LineJoin::Bevel, + LineJoinStyle::Miter => raqote::LineJoin::Miter, + } + } +} + +impl ToRaqoteStyle for LineCapStyle { + type Target = raqote::LineCap; + + fn to_raqote_style(self) -> raqote::LineCap { + match self { + LineCapStyle::Butt => raqote::LineCap::Butt, + LineCapStyle::Round => raqote::LineCap::Round, + LineCapStyle::Square => raqote::LineCap::Square, + } + } +} + +// TODO(pylbrecht) +#[cfg(feature = "raqote_backend")] +impl Clone for Pattern<'_> { + fn clone(&self) -> Self { + unimplemented!(); } }