From 4aad4ff858899dfb8d3315ec2b944b4325877cfa Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Thu, 20 Jun 2019 10:21:50 +0200 Subject: [PATCH 01/34] Implement DrawOptions.set_alpha() --- components/canvas/canvas_data.rs | 2 +- components/canvas/raqote_backend.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 43e48bc8a65..46d1229b78f 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -358,7 +358,7 @@ pub enum DrawOptions { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::DrawOptions), #[cfg(feature = "canvas2d-raqote")] - Raqote(()), + Raqote(raqote::DrawOptions), } #[derive(Clone)] diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index e33203226c8..ada5fbc672d 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -73,7 +73,7 @@ impl Backend for RaqoteBackend { impl<'a> CanvasPaintState<'a> { pub fn new(_antialias: AntialiasMode) -> CanvasPaintState<'a> { CanvasPaintState { - draw_options: DrawOptions::Raqote(()), + draw_options: DrawOptions::Raqote(raqote::DrawOptions::new()), fill_style: Pattern::Raqote(()), stroke_style: Pattern::Raqote(()), stroke_opts: StrokeOptions::Raqote(PhantomData), @@ -112,7 +112,7 @@ impl<'a> StrokeOptions<'a> { impl DrawOptions { pub fn set_alpha(&mut self, _val: f32) { match self { - DrawOptions::Raqote(()) => unimplemented!(), + DrawOptions::Raqote(draw_options) => draw_options.alpha = _val, } } } From 4179f91f93dbe4f59c6c693dd96315dbc0a734bf Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Thu, 20 Jun 2019 10:58:06 +0200 Subject: [PATCH 02/34] Implement StrokeOptions --- components/canvas/canvas_data.rs | 2 +- components/canvas/raqote_backend.rs | 48 ++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 46d1229b78f..da47f1ab93b 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -366,7 +366,7 @@ pub enum StrokeOptions<'a> { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::StrokeOptions<'a>), #[cfg(feature = "canvas2d-raqote")] - Raqote(PhantomData<&'a ()>), + Raqote(raqote::StrokeStyle, PhantomData<&'a ()>), } #[derive(Clone, Copy)] diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index ada5fbc672d..5540759d5a0 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -76,7 +76,7 @@ impl<'a> CanvasPaintState<'a> { draw_options: DrawOptions::Raqote(raqote::DrawOptions::new()), fill_style: Pattern::Raqote(()), stroke_style: Pattern::Raqote(()), - stroke_opts: StrokeOptions::Raqote(PhantomData), + stroke_opts: StrokeOptions::Raqote(Default::default(), PhantomData), transform: Transform2D::identity(), shadow_offset_x: 0.0, shadow_offset_y: 0.0, @@ -96,16 +96,24 @@ impl Pattern { 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(), + } } } @@ -260,3 +268,33 @@ impl GenericDrawTarget for raqote::DrawTarget { unimplemented!() } } + +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, + } + } +} From f9e398d9f68b58c40493a70695a650f61b6a60ad Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Mon, 24 Jun 2019 19:59:21 +0200 Subject: [PATCH 03/34] Make GenericPathBuilder take &mut self --- components/canvas/canvas_data.rs | 78 ++++++++++++++++------------- components/canvas/raqote_backend.rs | 51 +++++++++++++++++++ 2 files changed, 94 insertions(+), 35 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index da47f1ab93b..c1f539a909f 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -84,7 +84,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, @@ -92,14 +92,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, @@ -108,32 +108,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), @@ -150,14 +150,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), @@ -165,14 +165,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, @@ -193,7 +200,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, @@ -569,7 +576,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, @@ -594,8 +601,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, @@ -604,7 +611,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, @@ -694,19 +701,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, )), @@ -716,14 +724,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(), @@ -733,16 +741,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!(), } } diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 5540759d5a0..5a5c0f49e44 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -269,6 +269,57 @@ impl GenericDrawTarget for raqote::DrawTarget { } } +impl GenericPathBuilder for raqote::PathBuilder { + fn arc( + &mut self, + origin: Point2D, + radius: f32, + start_angle: f32, + end_angle: f32, + anticlockwise: bool, + ) { + unimplemented!(); + } + fn bezier_curve_to( + &mut self, + control_point1: &Point2D, + control_point2: &Point2D, + control_point3: &Point2D, + ) { + unimplemented!(); + } + fn close(&mut self) { + unimplemented!(); + } + 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) { + unimplemented!(); + } + fn move_to(&mut self, point: Point2D) { + unimplemented!(); + } + fn quadratic_curve_to(&mut self, control_point: &Point2D, end_point: &Point2D) { + unimplemented!(); + } + fn finish(&mut self) -> Path { + unimplemented!(); + } +} + pub trait ToRaqoteStyle { type Target; From 9f9013946a5235a2cc00d9f9d023ab7f2272fbfd Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Tue, 25 Jun 2019 16:48:03 +0200 Subject: [PATCH 04/34] Implement provided raqote::PathBuilder's methods for GenericPathBuilder --- components/canvas/raqote_backend.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 5a5c0f49e44..831ce1b945f 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -278,7 +278,7 @@ impl GenericPathBuilder for raqote::PathBuilder { end_angle: f32, anticlockwise: bool, ) { - unimplemented!(); + self.arc(origin.x, origin.y, radius, start_angle, end_angle); } fn bezier_curve_to( &mut self, @@ -286,10 +286,17 @@ impl GenericPathBuilder for raqote::PathBuilder { control_point2: &Point2D, control_point3: &Point2D, ) { - unimplemented!(); + self.cubic_to( + control_point1.x, + control_point1.y, + control_point2.x, + control_point2.y, + control_point3.x, + control_point3.y, + ); } fn close(&mut self) { - unimplemented!(); + self.close(); } fn ellipse( &mut self, @@ -307,16 +314,16 @@ impl GenericPathBuilder for raqote::PathBuilder { unimplemented!(); } fn line_to(&mut self, point: Point2D) { - unimplemented!(); + self.line_to(point.x, point.y); } fn move_to(&mut self, point: Point2D) { - unimplemented!(); + self.move_to(point.x, point.y); } fn quadratic_curve_to(&mut self, control_point: &Point2D, end_point: &Point2D) { - unimplemented!(); + self.quad_to(control_point.x, control_point.y, end_point.x, end_point.y); } fn finish(&mut self) -> Path { - unimplemented!(); + self.finish() } } From b43c5c30e39e75850e408c8d8f30f55c18e536a7 Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Tue, 2 Jul 2019 19:14:15 +0200 Subject: [PATCH 05/34] WIP: Make GenericPathBuilder's methods take &mut self --- components/canvas/canvas_data.rs | 26 +++-- components/canvas/raqote_backend.rs | 144 ++++++++++++++-------------- 2 files changed, 88 insertions(+), 82 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index c1f539a909f..9152dff6dbd 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -215,7 +215,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, @@ -250,24 +255,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, @@ -275,7 +280,7 @@ pub trait GenericDrawTarget { draw_options: &DrawOptions, ); fn stroke_rect( - &self, + &mut self, rect: &Rect, pattern: Pattern, stroke_options: &StrokeOptions, @@ -659,7 +664,8 @@ impl<'a> CanvasData<'a> { pub fn clip(&mut self) { self.ensure_path(); - self.drawtarget.push_clip(&self.path()); + let path = self.path(); + self.drawtarget.push_clip(&path); } pub fn is_point_in_path( diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 831ce1b945f..d49716dc6a2 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -143,129 +143,129 @@ impl Path { } impl GenericDrawTarget for raqote::DrawTarget { - fn clear_rect(&self, _rect: &Rect) { - unimplemented!() + fn clear_rect(&self, rect: &Rect) { + unimplemented!(); } - fn copy_surface( - &self, - _surface: SourceSurface, - _source: Rect, - _destination: Point2D, + &mut self, + surface: SourceSurface, + source: Rect, + destination: Point2D, ) { - unimplemented!() + unimplemented!(); } - fn create_gradient_stops( &self, - _gradient_stops: Vec, - _extend_mode: ExtendMode, + gradient_stops: Vec, + extend_mode: ExtendMode, ) -> GradientStops { - unimplemented!() + unimplemented!(); } fn create_path_builder(&self) -> Box { - unimplemented!() + unimplemented!(); } - fn create_similar_draw_target( &self, - _size: &Size2D, - _format: SurfaceFormat, + size: &Size2D, + format: SurfaceFormat, ) -> Box { - unimplemented!() + unimplemented!(); } fn create_source_surface_from_data( &self, - _data: &[u8], - _size: Size2D, - _stride: i32, + data: &[u8], + size: Size2D, + stride: i32, ) -> Option { - unimplemented!() + unimplemented!(); } fn draw_surface( &self, - _surface: SourceSurface, - _dest: Rect, - _source: Rect, - _filter: Filter, - _draw_options: &DrawOptions, + surface: SourceSurface, + dest: Rect, + source: Rect, + filter: Filter, + draw_options: &DrawOptions, ) { - unimplemented!() + unimplemented!(); } fn draw_surface_with_shadow( &self, - _surface: SourceSurface, - _dest: &Point2D, - _color: &Color, - _offset: &Vector2D, - _sigma: f32, - _operator: CompositionOp, + surface: SourceSurface, + dest: &Point2D, + color: &Color, + offset: &Vector2D, + 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) { + unimplemented!(); } - 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!() + unimplemented!(); } - fn pop_clip(&self) { - unimplemented!() + fn pop_clip(&mut self) { + unimplemented!(); } - fn push_clip(&self, _path: &Path) { - unimplemented!() + fn push_clip(&mut self, path: &Path) { + unimplemented!(); } - fn set_transform(&self, _matrix: &Transform2D) { - unimplemented!() + fn set_transform(&mut self, matrix: &Transform2D) { + unimplemented!(); } 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!() + unimplemented!(); } fn stroke_line( - &self, - _start: Point2D, - _end: Point2D, - _pattern: Pattern, - _stroke_options: &StrokeOptions, - _draw_options: &DrawOptions, + &mut self, + start: Point2D, + end: Point2D, + pattern: Pattern, + stroke_options: &StrokeOptions, + draw_options: &DrawOptions, ) { - unimplemented!() + unimplemented!(); } fn stroke_rect( - &self, - _rect: &Rect, - _pattern: Pattern, - _stroke_options: &StrokeOptions<'_>, - _draw_options: &DrawOptions, + &mut self, + rect: &Rect, + pattern: Pattern, + stroke_options: &StrokeOptions, + draw_options: &DrawOptions, ) { - unimplemented!() + unimplemented!(); } - - fn snapshot_data(&self, _f: &dyn Fn(&[u8]) -> Vec) -> Vec { - unimplemented!() + fn snapshot_data(&self, f: &Fn(&[u8]) -> Vec) -> Vec { + unimplemented!(); } - fn snapshot_data_owned(&self) -> Vec { - unimplemented!() + unimplemented!(); } } From 4e51caeb7eb741e0fa99503ac0005bcf75ea5c78 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 3 Jul 2019 21:24:48 -0400 Subject: [PATCH 06/34] Deal with fallout from mutable trait method change. --- components/canvas/canvas_data.rs | 34 ++++---- components/canvas/raqote_backend.rs | 127 +++++++++++++++------------- 2 files changed, 85 insertions(+), 76 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 9152dff6dbd..d6abe8836f0 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -343,11 +343,12 @@ pub enum SourceSurface { Raqote(()), } +#[derive(Clone)] pub enum Path { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::Path), #[cfg(feature = "canvas2d-raqote")] - Raqote(()), + Raqote(raqote::Path), } #[derive(Clone)] @@ -437,7 +438,7 @@ impl<'a> CanvasData<'a> { } pub fn draw_image( - &self, + &mut self, image_data: Vec, image_size: Size2D, dest_rect: Rect, @@ -453,14 +454,15 @@ impl<'a> CanvasData<'a> { image_data.into() }; - let writer = |draw_target: &dyn GenericDrawTarget| { + let draw_options = self.state.draw_options.clone(); + let writer = |draw_target: &mut dyn GenericDrawTarget| { write_image( draw_target, image_data, source_rect.size, dest_rect, smoothing_enabled, - &self.state.draw_options, + &draw_options, ); }; @@ -473,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); } } @@ -496,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. } @@ -509,7 +511,7 @@ impl<'a> CanvasData<'a> { ); if self.need_to_draw_shadow() { - self.draw_with_shadow(&draw_rect, |new_draw_target: &dyn GenericDrawTarget| { + self.draw_with_shadow(&draw_rect, |new_draw_target: &mut dyn GenericDrawTarget| { new_draw_target.fill_rect( &draw_rect, self.state.fill_style.clone(), @@ -529,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: &dyn GenericDrawTarget| { + self.draw_with_shadow(&rect, |new_draw_target: &mut dyn GenericDrawTarget| { new_draw_target.stroke_rect( rect, self.state.stroke_style.clone(), @@ -642,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, ); @@ -655,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, @@ -664,7 +666,7 @@ impl<'a> CanvasData<'a> { pub fn clip(&mut self) { self.ensure_path(); - let path = self.path(); + let path = self.path().clone(); self.drawtarget.push_clip(&path); } @@ -1037,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, @@ -1053,11 +1055,11 @@ impl<'a> CanvasData<'a> { fn draw_with_shadow(&self, rect: &Rect, draw_shadow_source: F) where - F: FnOnce(&dyn GenericDrawTarget), + F: FnOnce(&mut dyn 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( diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index d49716dc6a2..18d69176d9a 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -143,72 +143,71 @@ impl Path { } impl GenericDrawTarget for raqote::DrawTarget { - fn clear_rect(&self, rect: &Rect) { + fn clear_rect(&self, _rect: &Rect) { unimplemented!(); } fn copy_surface( &mut self, - surface: SourceSurface, - source: Rect, - destination: Point2D, + _surface: SourceSurface, + _source: Rect, + _destination: Point2D, ) { unimplemented!(); } fn create_gradient_stops( &self, - gradient_stops: Vec, - extend_mode: ExtendMode, + _gradient_stops: Vec, + _extend_mode: ExtendMode, ) -> GradientStops { unimplemented!(); } - fn create_path_builder(&self) -> Box { - unimplemented!(); + Box::new(PathBuilder::new()) } fn create_similar_draw_target( &self, - size: &Size2D, - format: SurfaceFormat, + _size: &Size2D, + _format: SurfaceFormat, ) -> Box { unimplemented!(); } fn create_source_surface_from_data( &self, - data: &[u8], - size: Size2D, - stride: i32, + _data: &[u8], + _size: Size2D, + _stride: i32, ) -> Option { unimplemented!(); } fn draw_surface( &self, - surface: SourceSurface, - dest: Rect, - source: Rect, - filter: Filter, - draw_options: &DrawOptions, + _surface: SourceSurface, + _dest: Rect, + _source: Rect, + _filter: Filter, + _draw_options: &DrawOptions, ) { unimplemented!(); } fn draw_surface_with_shadow( &self, - surface: SourceSurface, - dest: &Point2D, - color: &Color, - offset: &Vector2D, - sigma: f32, - operator: CompositionOp, + _surface: SourceSurface, + _dest: &Point2D, + _color: &Color, + _offset: &Vector2D, + _sigma: f32, + _operator: CompositionOp, ) { unimplemented!(); } - fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) { + fn fill(&mut self, _path: &Path, _pattern: Pattern, _draw_options: &DrawOptions) { unimplemented!(); } fn fill_rect( &mut self, - rect: &Rect, - pattern: Pattern, - draw_options: Option<&DrawOptions>, + _rect: &Rect, + _pattern: Pattern, + _draw_options: Option<&DrawOptions>, ) { unimplemented!(); } @@ -224,10 +223,10 @@ impl GenericDrawTarget for raqote::DrawTarget { fn pop_clip(&mut self) { unimplemented!(); } - fn push_clip(&mut self, path: &Path) { + fn push_clip(&mut self, _path: &Path) { unimplemented!(); } - fn set_transform(&mut self, matrix: &Transform2D) { + fn set_transform(&mut self, _matrix: &Transform2D) { unimplemented!(); } fn snapshot(&self) -> SourceSurface { @@ -235,33 +234,33 @@ impl GenericDrawTarget for raqote::DrawTarget { } fn stroke( &mut self, - path: &Path, - pattern: Pattern, - stroke_options: &StrokeOptions, - draw_options: &DrawOptions, + _path: &Path, + _pattern: Pattern, + _stroke_options: &StrokeOptions, + _draw_options: &DrawOptions, ) { unimplemented!(); } fn stroke_line( &mut self, - start: Point2D, - end: Point2D, - pattern: Pattern, - stroke_options: &StrokeOptions, - draw_options: &DrawOptions, + _start: Point2D, + _end: Point2D, + _pattern: Pattern, + _stroke_options: &StrokeOptions, + _draw_options: &DrawOptions, ) { unimplemented!(); } fn stroke_rect( &mut self, - rect: &Rect, - pattern: Pattern, - stroke_options: &StrokeOptions, - draw_options: &DrawOptions, + _rect: &Rect, + _pattern: Pattern, + _stroke_options: &StrokeOptions, + _draw_options: &DrawOptions, ) { unimplemented!(); } - fn snapshot_data(&self, f: &Fn(&[u8]) -> Vec) -> Vec { + fn snapshot_data(&self, _f: &dyn Fn(&[u8]) -> Vec) -> Vec { unimplemented!(); } fn snapshot_data_owned(&self) -> Vec { @@ -269,16 +268,24 @@ impl GenericDrawTarget for raqote::DrawTarget { } } -impl GenericPathBuilder for raqote::PathBuilder { +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, + _anticlockwise: bool, ) { - self.arc(origin.x, origin.y, radius, start_angle, end_angle); + self.0.as_mut().unwrap().arc(origin.x, origin.y, radius, start_angle, end_angle); } fn bezier_curve_to( &mut self, @@ -286,7 +293,7 @@ impl GenericPathBuilder for raqote::PathBuilder { control_point2: &Point2D, control_point3: &Point2D, ) { - self.cubic_to( + self.0.as_mut().unwrap().cubic_to( control_point1.x, control_point1.y, control_point2.x, @@ -296,17 +303,17 @@ impl GenericPathBuilder for raqote::PathBuilder { ); } fn close(&mut self) { - self.close(); + 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, + _origin: Point2D, + _radius_x: f32, + _radius_y: f32, + _rotation_angle: f32, + _start_angle: f32, + _end_angle: f32, + _anticlockwise: bool, ) { unimplemented!(); } @@ -314,16 +321,16 @@ impl GenericPathBuilder for raqote::PathBuilder { unimplemented!(); } fn line_to(&mut self, point: Point2D) { - self.line_to(point.x, point.y); + self.0.as_mut().unwrap().line_to(point.x, point.y); } fn move_to(&mut self, point: Point2D) { - self.move_to(point.x, point.y); + self.0.as_mut().unwrap().move_to(point.x, point.y); } fn quadratic_curve_to(&mut self, control_point: &Point2D, end_point: &Point2D) { - self.quad_to(control_point.x, control_point.y, end_point.x, end_point.y); + self.0.as_mut().unwrap().quad_to(control_point.x, control_point.y, end_point.x, end_point.y); } fn finish(&mut self) -> Path { - self.finish() + Path::Raqote(self.0.take().unwrap().finish()) } } From 398929ffefd1b718e22cbcdc6fa53824d9c3dfe4 Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Sun, 7 Jul 2019 20:26:10 +0200 Subject: [PATCH 07/34] Implement fill() for raqote::DrawTarget --- components/canvas/canvas_data.rs | 8 +++---- components/canvas/raqote_backend.rs | 37 ++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index d6abe8836f0..8288e823eea 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -352,11 +352,11 @@ pub enum Path { } #[derive(Clone)] -pub enum Pattern { +pub enum Pattern<'a> { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::Pattern), #[cfg(feature = "canvas2d-raqote")] - Raqote(()), + Raqote(raqote::Source<'a>), } pub enum DrawSurfaceOptions { @@ -1113,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 18d69176d9a..a80443af4a2 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -72,10 +72,11 @@ 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(raqote::DrawOptions::new()), - fill_style: Pattern::Raqote(()), - stroke_style: Pattern::Raqote(()), + 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, @@ -86,10 +87,15 @@ 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, } } } @@ -123,6 +129,11 @@ impl DrawOptions { DrawOptions::Raqote(draw_options) => draw_options.alpha = _val, } } + pub fn as_raqote(&self) -> &raqote::DrawOptions { + match self { + DrawOptions::Raqote(options) => options, + } + } } impl Path { @@ -140,6 +151,12 @@ 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 { @@ -200,8 +217,8 @@ impl GenericDrawTarget for raqote::DrawTarget { ) { unimplemented!(); } - fn fill(&mut 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( &mut self, @@ -363,3 +380,11 @@ impl ToRaqoteStyle for LineCapStyle { } } } + +// TODO(pylbrecht) +#[cfg(feature = "raqote_backend")] +impl Clone for Pattern<'_> { + fn clone(&self) -> Self { + unimplemented!(); + } +} From 7005c24e40eb45d9bcfce8116a952793ad82ccc9 Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Mon, 8 Jul 2019 18:29:17 +0200 Subject: [PATCH 08/34] Implement some of GenericDrawTarget's methods for raqote --- components/canvas/raqote_backend.rs | 32 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index a80443af4a2..20e0416f3ca 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -121,6 +121,11 @@ impl<'a> StrokeOptions<'a> { StrokeOptions::Raqote(options, _) => options.cap = _val.to_raqote_style(), } } + pub fn as_raqote(&self) -> &raqote::StrokeStyle { + match self { + StrokeOptions::Raqote(options, _) => options, + } + } } impl DrawOptions { @@ -235,28 +240,33 @@ impl GenericDrawTarget for raqote::DrawTarget { unimplemented!(); } fn get_transform(&self) -> Transform2D { - unimplemented!(); + *self.get_transform() } fn pop_clip(&mut self) { - unimplemented!(); + self.pop_clip(); } - fn push_clip(&mut self, _path: &Path) { - unimplemented!(); + fn push_clip(&mut self, path: &Path) { + self.push_clip(path.as_raqote()); } - fn set_transform(&mut self, _matrix: &Transform2D) { - unimplemented!(); + fn set_transform(&mut self, matrix: &Transform2D) { + self.set_transform(matrix); } fn snapshot(&self) -> SourceSurface { unimplemented!(); } fn stroke( &mut self, - _path: &Path, - _pattern: Pattern, - _stroke_options: &StrokeOptions, - _draw_options: &DrawOptions, + 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( &mut self, From cbe385c7d7648cb544fb45ad4259e71c5f353475 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 16:13:45 +0200 Subject: [PATCH 09/34] Add a way to convert a FillOrStrokeStyle to a raqote Source For now most of it unimplemented but it'll allow for some more testing --- components/canvas/raqote_backend.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 20e0416f3ca..8c49d9c7c01 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -398,3 +398,25 @@ impl Clone for Pattern<'_> { unimplemented!(); } } + +pub trait ToRaqoteSource<'a> { + fn to_raqote_source(self) -> Option>; +} + +impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { + fn to_raqote_source(self) -> Option> { + use canvas_traits::canvas::FillOrStrokeStyle::*; + + match self { + Color(rgba) => Some(raqote::Source::Solid(raqote::SolidSource { + r: rgba.red, + g: rgba.green, + b: rgba.blue, + a: rgba.alpha, + })), + LinearGradient(_) => unimplemented!(), + RadialGradient(_) => unimplemented!(), + Surface(_) => unimplemented!(), + } + } +} From 93f1053b0e790f7205ca8f00ba8f00dcde9ed248 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 16:15:21 +0200 Subject: [PATCH 10/34] Implement set_fill_style --- components/canvas/raqote_backend.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 8c49d9c7c01..18244d5c51c 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -34,11 +34,13 @@ impl Backend for RaqoteBackend { fn set_fill_style<'a>( &mut self, - _style: FillOrStrokeStyle, - _state: &mut CanvasPaintState<'a>, + style: FillOrStrokeStyle, + state: &mut CanvasPaintState<'a>, _drawtarget: &dyn GenericDrawTarget, ) { - unimplemented!() + if let Some(source) = style.to_raqote_source() { + state.fill_style = Pattern::Raqote(source); + } } fn set_stroke_style<'a>( From 0a878da500d1027ffc6f70e0b20c373b6c4e3765 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 16:22:40 +0200 Subject: [PATCH 11/34] Implement Pattern::is_zero_size_gradient There are probably other times where this would be true but I'll worry about that later --- components/canvas/raqote_backend.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 18244d5c51c..e301e31562f 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -91,8 +91,17 @@ impl<'a> CanvasPaintState<'a> { impl Pattern<'_> { pub fn is_zero_size_gradient(&self) -> bool { - match *self { - Pattern::Raqote(_) => unimplemented!(), + match self { + Pattern::Raqote(p) => { + use raqote::Source::*; + + match p { + LinearGradient(g, ..) | RadialGradient(g, ..) | TwoCircleRadialGradient(g, ..) => { + g.stops.is_empty() + }, + _ => false + } + }, } } pub fn as_raqote(&self) -> &raqote::Source { From c39af71aebc7bdad70e24840f7d915a8766aeb50 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 16:26:29 +0200 Subject: [PATCH 12/34] Add an implementation for fill_rect Again, this is probably incomplete but it'll do for now --- components/canvas/raqote_backend.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index e301e31562f..1bfc27b5ab4 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -238,11 +238,23 @@ impl GenericDrawTarget for raqote::DrawTarget { } fn fill_rect( &mut self, - _rect: &Rect, - _pattern: Pattern, + rect: &Rect, + pattern: Pattern, _draw_options: Option<&DrawOptions>, ) { - unimplemented!(); + let mut pb = raqote::PathBuilder::new(); + pb.rect( + rect.origin.x, + rect.origin.y, + rect.size.width, + rect.size.height, + ); + raqote::DrawTarget::fill( + self, + &pb.finish(), + pattern.as_raqote(), + &raqote::DrawOptions::new(), + ); } fn get_format(&self) -> SurfaceFormat { unimplemented!(); From 559b28ce7b0b073bfcf4f5e8d1339dda991ce807 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 16:30:11 +0200 Subject: [PATCH 13/34] Implement snapshot_data --- components/canvas/raqote_backend.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 1bfc27b5ab4..b212a2622ea 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -310,8 +310,15 @@ impl GenericDrawTarget for raqote::DrawTarget { ) { unimplemented!(); } - fn snapshot_data(&self, _f: &dyn Fn(&[u8]) -> Vec) -> Vec { - unimplemented!(); + #[allow(unsafe_code)] + fn snapshot_data(&self, f: &dyn Fn(&[u8]) -> Vec) -> Vec { + let v = self.get_data(); + f(unsafe { + std::slice::from_raw_parts( + v.as_ptr() as *const u8, + v.len() * std::mem::size_of::(), + ) + }) } fn snapshot_data_owned(&self) -> Vec { unimplemented!(); From ed0dbafc72b99ab2d2e97c7ed748d32026e9d880 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 16:40:38 +0200 Subject: [PATCH 14/34] Implement need_to_draw_shadow --- components/canvas/canvas_data.rs | 2 +- components/canvas/raqote_backend.rs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 8288e823eea..1602c8c7467 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -317,7 +317,7 @@ pub enum Color { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::Color), #[cfg(feature = "canvas2d-raqote")] - Raqote(()), + Raqote(raqote::SolidSource), } #[derive(Clone)] diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index b212a2622ea..573ee2bb8ff 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -20,8 +20,8 @@ impl Backend for RaqoteBackend { unimplemented!() } - fn need_to_draw_shadow(&self, _color: &Color) -> bool { - unimplemented!() + fn need_to_draw_shadow(&self, color: &Color) -> bool { + color.as_raqote().a != 0 } fn size_from_pattern(&self, _rect: &Rect, _pattern: &Pattern) -> Option> { @@ -84,7 +84,7 @@ impl<'a> CanvasPaintState<'a> { shadow_offset_x: 0.0, shadow_offset_y: 0.0, shadow_blur: 0.0, - shadow_color: Color::Raqote(()), + shadow_color: Color::Raqote(raqote::SolidSource { r: 0, g: 0, b: 0, a: 0 }), } } } @@ -450,3 +450,11 @@ impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { } } } + +impl Color { + fn as_raqote(&self) -> &raqote::SolidSource { + match self { + Color::Raqote(s) => s, + } + } +} From 14ee093a5b57953073432ead358cbbc80b1b1837 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 17:10:59 +0200 Subject: [PATCH 15/34] Implement size_from_pattern I tried to mimic the azure implementation but raqote doesn't have a concept of horizontal or vertical repeat so this might be wrong/incomplete but this is the last function needed to finally have some tests pass --- components/canvas/raqote_backend.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 573ee2bb8ff..1c31346661a 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -24,8 +24,18 @@ impl Backend for RaqoteBackend { color.as_raqote().a != 0 } - fn size_from_pattern(&self, _rect: &Rect, _pattern: &Pattern) -> Option> { - unimplemented!() + fn size_from_pattern(&self, rect: &Rect, pattern: &Pattern) -> Option> { + match pattern { + Pattern::Raqote(raqote::Source::Image(image, extend, ..)) => { + match extend { + raqote::ExtendMode::Repeat => { + Some(rect.size) + }, + _ => Some(Size2D::new(image.width as f32, image.height as f32)) + } + }, + _ => None + } } fn set_shadow_color<'a>(&mut self, _color: RGBA, _state: &mut CanvasPaintState<'a>) { From 7b6c8c85d5d5d944980551eeda71888115e6c589 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 17:13:21 +0200 Subject: [PATCH 16/34] Update raqote --- Cargo.lock | 18 +++++++++++++++--- Cargo.toml | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f70b092b45f..85b9eec7569 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2500,7 +2500,7 @@ dependencies = [ [[package]] name = "libflate" -version = "0.1.19" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3004,7 +3004,7 @@ dependencies = [ "immeta 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of 0.0.1", "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3802,6 +3802,11 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rle-decode-fast" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ron" version = "0.1.7" @@ -4871,6 +4876,11 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "task_info" version = "0.0.1" @@ -6042,7 +6052,7 @@ dependencies = [ "checksum leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40a8225d44241fd324a8af2806ba635fc7c8a7e9a7de4d5cf3ef54e71f5926fc" "checksum libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)" = "ec350a9417dfd244dc9a6c4a71e13895a4db6b92f0b106f07ebbc3f3bc580cee" "checksum libdbus-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99c78106156a964aadc1c59f7798276967be6705243b60f3ab7e131e3841db88" -"checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" +"checksum libflate 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "45c97cf62125b79dcac52d506acdc4799f21a198597806947fd5f40dc7b93412" "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9" @@ -6154,6 +6164,7 @@ dependencies = [ "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac" "checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399" "checksum rust-webvr 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab628b77aaacca496483788a5e0184d42af6dc0e938551aa5be20676c84dd196" "checksum rust-webvr-api 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d01034b181187e7d048ef4c5caaf95d28d0f7973834907fe7dd74b2bfb66e8" @@ -6213,6 +6224,7 @@ dependencies = [ "checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" "checksum syn 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "158521e6f544e7e3dcfc370ac180794aa38cb34a1b1e07609376d4adcf429b93" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" diff --git a/Cargo.toml b/Cargo.toml index 97e2f43df59..8633e7c72fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,3 +28,4 @@ opt-level = 3 # Those are here to dedupe winapi since mio is still using winapi 0.2. mio = { git = "https://github.com/servo/mio.git", branch = "servo" } iovec = { git = "https://github.com/servo/iovec.git", branch = "servo" } + From 24313a82a16f7cf278e552f1a6934c04b824a5db Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 17:17:17 +0200 Subject: [PATCH 17/34] Make tidy happy --- components/canvas/raqote_backend.rs | 54 +++++++++++++++++++---------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 1c31346661a..f3237498727 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -26,15 +26,11 @@ impl Backend for RaqoteBackend { fn size_from_pattern(&self, rect: &Rect, pattern: &Pattern) -> Option> { match pattern { - Pattern::Raqote(raqote::Source::Image(image, extend, ..)) => { - match extend { - raqote::ExtendMode::Repeat => { - Some(rect.size) - }, - _ => Some(Size2D::new(image.width as f32, image.height as f32)) - } + Pattern::Raqote(raqote::Source::Image(image, extend, ..)) => match extend { + raqote::ExtendMode::Repeat => Some(rect.size), + _ => Some(Size2D::new(image.width as f32, image.height as f32)), }, - _ => None + _ => None, } } @@ -84,7 +80,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 }; + let solid_src = raqote::SolidSource { + r: 0, + g: 0, + b: 0, + a: 255, + }; CanvasPaintState { draw_options: DrawOptions::Raqote(raqote::DrawOptions::new()), fill_style: Pattern::Raqote(raqote::Source::Solid(solid_src)), @@ -94,7 +95,12 @@ impl<'a> CanvasPaintState<'a> { shadow_offset_x: 0.0, shadow_offset_y: 0.0, shadow_blur: 0.0, - shadow_color: Color::Raqote(raqote::SolidSource { r: 0, g: 0, b: 0, a: 0 }), + shadow_color: Color::Raqote(raqote::SolidSource { + r: 0, + g: 0, + b: 0, + a: 0, + }), } } } @@ -106,10 +112,10 @@ impl Pattern<'_> { use raqote::Source::*; match p { - LinearGradient(g, ..) | RadialGradient(g, ..) | TwoCircleRadialGradient(g, ..) => { - g.stops.is_empty() - }, - _ => false + LinearGradient(g, ..) | + RadialGradient(g, ..) | + TwoCircleRadialGradient(g, ..) => g.stops.is_empty(), + _ => false, } }, } @@ -244,7 +250,11 @@ impl GenericDrawTarget for raqote::DrawTarget { unimplemented!(); } fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) { - self.fill(path.as_raqote(), pattern.as_raqote(), draw_options.as_raqote()); + self.fill( + path.as_raqote(), + pattern.as_raqote(), + draw_options.as_raqote(), + ); } fn fill_rect( &mut self, @@ -299,7 +309,7 @@ impl GenericDrawTarget for raqote::DrawTarget { pattern.as_raqote(), stroke_options.as_raqote(), draw_options.as_raqote(), - ); + ); } fn stroke_line( &mut self, @@ -352,7 +362,10 @@ impl GenericPathBuilder for PathBuilder { end_angle: f32, _anticlockwise: bool, ) { - self.0.as_mut().unwrap().arc(origin.x, origin.y, radius, start_angle, end_angle); + self.0 + .as_mut() + .unwrap() + .arc(origin.x, origin.y, radius, start_angle, end_angle); } fn bezier_curve_to( &mut self, @@ -394,7 +407,12 @@ impl GenericPathBuilder for PathBuilder { 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); + 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()) From 9229dc4d85e6da7566e344e9a00a68f90e094104 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 17:34:00 +0200 Subject: [PATCH 18/34] Implement clear_rect --- components/canvas/canvas_data.rs | 4 ++-- components/canvas/raqote_backend.rs | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 1602c8c7467..d9b36ad5816 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -214,7 +214,7 @@ impl<'a> PathBuilderRef<'a> { // This defines required methods for DrawTarget of azure and raqote // The prototypes are derived from azure's methods. pub trait GenericDrawTarget { - fn clear_rect(&self, rect: &Rect); + fn clear_rect(&mut self, rect: &Rect); fn copy_surface( &mut self, surface: SourceSurface, @@ -527,7 +527,7 @@ impl<'a> CanvasData<'a> { } } - pub fn clear_rect(&self, rect: &Rect) { + pub fn clear_rect(&mut self, rect: &Rect) { self.drawtarget.clear_rect(rect); } diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index f3237498727..d33a6597ba5 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -192,8 +192,25 @@ impl Path { } impl GenericDrawTarget for raqote::DrawTarget { - fn clear_rect(&self, _rect: &Rect) { - unimplemented!(); + fn clear_rect(&mut self, rect: &Rect) { + let mut pb = raqote::PathBuilder::new(); + pb.rect( + rect.origin.x, + rect.origin.y, + rect.size.width, + rect.size.height, + ); + raqote::DrawTarget::fill( + self, + &pb.finish(), + &raqote::Source::Solid(raqote::SolidSource { + r: 0, + g: 0, + b: 0, + a: 0, + }), + &raqote::DrawOptions::new(), + ); } fn copy_surface( &mut self, From e90d1a1d8d6a189e883288fdbeda0f45d8861d11 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 18:11:43 +0200 Subject: [PATCH 19/34] Implement stroke_line and set_stroke_style --- components/canvas/raqote_backend.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index d33a6597ba5..89db6ca62ae 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -51,11 +51,13 @@ impl Backend for RaqoteBackend { fn set_stroke_style<'a>( &mut self, - _style: FillOrStrokeStyle, - _state: &mut CanvasPaintState<'a>, + style: FillOrStrokeStyle, + state: &mut CanvasPaintState<'a>, _drawtarget: &dyn GenericDrawTarget, ) { - unimplemented!() + if let Some(pattern) = style.to_raqote_source() { + state.stroke_style = Pattern::Raqote(pattern) + } } fn set_global_composition<'a>( @@ -330,13 +332,21 @@ impl GenericDrawTarget for raqote::DrawTarget { } fn stroke_line( &mut self, - _start: Point2D, - _end: Point2D, - _pattern: Pattern, - _stroke_options: &StrokeOptions, - _draw_options: &DrawOptions, + start: Point2D, + end: Point2D, + pattern: Pattern, + stroke_options: &StrokeOptions, + draw_options: &DrawOptions, ) { - unimplemented!(); + let mut pb = raqote::PathBuilder::new(); + pb.move_to(start.x, start.y); + pb.line_to(end.x, end.y); + + self.stroke( + &pb.finish(), + pattern.as_raqote(), + stroke_options.as_raqote(), + draw_options.as_raqote()); } fn stroke_rect( &mut self, From fda815bcbb1d5f44c5ccccd553343e7ec785eed0 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 18:18:19 +0200 Subject: [PATCH 20/34] Properly pass draw_options in fill_rect --- components/canvas/raqote_backend.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 89db6ca62ae..1708ffd0ca1 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -279,7 +279,7 @@ impl GenericDrawTarget for raqote::DrawTarget { &mut self, rect: &Rect, pattern: Pattern, - _draw_options: Option<&DrawOptions>, + draw_options: Option<&DrawOptions>, ) { let mut pb = raqote::PathBuilder::new(); pb.rect( @@ -288,11 +288,17 @@ impl GenericDrawTarget for raqote::DrawTarget { rect.size.width, rect.size.height, ); + let draw_options = if let Some(options) = draw_options { + *options.as_raqote() + } else { + raqote::DrawOptions::new() + }; + raqote::DrawTarget::fill( self, &pb.finish(), pattern.as_raqote(), - &raqote::DrawOptions::new(), + &draw_options, ); } fn get_format(&self) -> SurfaceFormat { From 97364dc6af65d6af0b60005deb1262f87a90ccd2 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 18:25:11 +0200 Subject: [PATCH 21/34] Implement get_size --- components/canvas/raqote_backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 1708ffd0ca1..2300f7d8668 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -305,7 +305,7 @@ impl GenericDrawTarget for raqote::DrawTarget { unimplemented!(); } fn get_size(&self) -> Size2D { - unimplemented!(); + Size2D::new(self.width(), self.height()) } fn get_transform(&self) -> Transform2D { *self.get_transform() From 777ef4f3e834a08f95f3e2b715739121fdbc8c29 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 18:25:19 +0200 Subject: [PATCH 22/34] Implement snapshot_data_owned --- components/canvas/raqote_backend.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 2300f7d8668..4dbab3686d6 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -373,8 +373,15 @@ impl GenericDrawTarget for raqote::DrawTarget { ) }) } + #[allow(unsafe_code)] fn snapshot_data_owned(&self) -> Vec { - unimplemented!(); + let v = self.get_data(); + unsafe { + std::slice::from_raw_parts( + v.as_ptr() as *const u8, + v.len() * std::mem::size_of::(), + ).into() + } } } From 97674082d3c20607478174840188c813911b6419 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 18:49:02 +0200 Subject: [PATCH 23/34] Pass BlendMode::Clear to the fill method of DrawTarget in clear_rect This makes some tests regarding clearing rects pass. Otherwise the rect wouldn't get cleared properly and it'd keep its original color but get an alpha of 0 --- components/canvas/raqote_backend.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 4dbab3686d6..af8d1a484e3 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -202,6 +202,8 @@ impl GenericDrawTarget for raqote::DrawTarget { rect.size.width, rect.size.height, ); + let mut options = raqote::DrawOptions::new(); + options.blend_mode = raqote::BlendMode::Clear; raqote::DrawTarget::fill( self, &pb.finish(), @@ -211,7 +213,7 @@ impl GenericDrawTarget for raqote::DrawTarget { b: 0, a: 0, }), - &raqote::DrawOptions::new(), + &options, ); } fn copy_surface( From 1dee418ff16a0c680ed6436cbce7850f9b21d79a Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 21:27:23 +0200 Subject: [PATCH 24/34] Set the line cap to butt when drawing a rect with a 0 width/height Otherwise raqote will draw the cap even though it shouldn't because the spec says so --- components/canvas/canvas_data.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index d9b36ad5816..1a1e6fd1cea 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -546,11 +546,13 @@ impl<'a> CanvasData<'a> { ); }); } else if rect.size.width == 0. || rect.size.height == 0. { + let mut stroke_opts = self.state.stroke_opts.clone(); + stroke_opts.set_line_cap(LineCapStyle::Butt); self.drawtarget.stroke_line( rect.origin, rect.bottom_right(), self.state.stroke_style.clone(), - &self.state.stroke_opts, + &stroke_opts, &self.state.draw_options, ); } else { From a9fd26729bdfd7e19b890b2f0d7365838c82da94 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 22:06:31 +0200 Subject: [PATCH 25/34] Match the azure backend regarding cap stuff I think this is wrong because it won't respect cap style at all when stroking lines but we'll cross that bridge when we get to it --- components/canvas/raqote_backend.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index af8d1a484e3..0c8c6f5b1ac 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -349,11 +349,17 @@ impl GenericDrawTarget for raqote::DrawTarget { let mut pb = raqote::PathBuilder::new(); pb.move_to(start.x, start.y); pb.line_to(end.x, end.y); + let mut stroke_options = stroke_options.as_raqote().clone(); + let cap = match stroke_options.join { + raqote::LineJoin::Round => raqote::LineCap::Round, + _ => raqote::LineCap::Butt, + }; + stroke_options.cap = cap; self.stroke( &pb.finish(), pattern.as_raqote(), - stroke_options.as_raqote(), + &stroke_options, draw_options.as_raqote()); } fn stroke_rect( From a28d00013c442076326eb1f5088f0f1ed9847413 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Thu, 8 Aug 2019 23:46:52 +0200 Subject: [PATCH 26/34] Implement set_shadow_color, set_global_composition and stroke_rect --- components/canvas/raqote_backend.rs | 105 +++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 0c8c6f5b1ac..d4675f2c2dc 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -34,8 +34,8 @@ impl Backend for RaqoteBackend { } } - fn set_shadow_color<'a>(&mut self, _color: RGBA, _state: &mut CanvasPaintState<'a>) { - unimplemented!() + fn set_shadow_color<'a>(&mut self, color: RGBA, state: &mut CanvasPaintState<'a>) { + state.shadow_color = Color::Raqote(color.to_raqote_style()); } fn set_fill_style<'a>( @@ -62,10 +62,10 @@ impl Backend for RaqoteBackend { fn set_global_composition<'a>( &mut self, - _op: CompositionOrBlending, - _state: &mut CanvasPaintState<'a>, + op: CompositionOrBlending, + state: &mut CanvasPaintState<'a>, ) { - unimplemented!() + state.draw_options.as_raqote_mut().blend_mode = op.to_raqote_style(); } fn create_drawtarget(&self, size: Size2D) -> Box { @@ -168,6 +168,11 @@ impl DrawOptions { DrawOptions::Raqote(options) => options, } } + fn as_raqote_mut(&mut self) -> &mut raqote::DrawOptions { + match self { + DrawOptions::Raqote(options) => options, + } + } } impl Path { @@ -364,12 +369,24 @@ impl GenericDrawTarget for raqote::DrawTarget { } fn stroke_rect( &mut self, - _rect: &Rect, - _pattern: Pattern, - _stroke_options: &StrokeOptions, - _draw_options: &DrawOptions, + rect: &Rect, + pattern: Pattern, + stroke_options: &StrokeOptions, + draw_options: &DrawOptions, ) { - unimplemented!(); + let mut pb = raqote::PathBuilder::new(); + pb.rect( + rect.origin.x, + rect.origin.y, + rect.size.width, + rect.size.height, + ); + + self.stroke(&pb.finish(), + pattern.as_raqote(), + stroke_options.as_raqote(), + draw_options.as_raqote(), + ); } #[allow(unsafe_code)] fn snapshot_data(&self, f: &dyn Fn(&[u8]) -> Vec) -> Vec { @@ -534,3 +551,71 @@ impl Color { } } } + +impl ToRaqoteStyle for RGBA { + type Target = raqote::SolidSource; + + fn to_raqote_style(self) -> Self::Target { + raqote::SolidSource { + r: self.red, + g: self.green, + b: self.blue, + a: self.alpha, + } + } +} + +impl ToRaqoteStyle for CompositionOrBlending { + type Target = raqote::BlendMode; + + fn to_raqote_style(self) -> Self::Target { + match self { + CompositionOrBlending::Composition(op) => op.to_raqote_style(), + CompositionOrBlending::Blending(op) => op.to_raqote_style(), + } + } +} + +impl ToRaqoteStyle for BlendingStyle { + type Target = raqote::BlendMode; + + fn to_raqote_style(self) -> Self::Target { + match self { + BlendingStyle::Multiply => raqote::BlendMode::Multiply, + BlendingStyle::Screen => raqote::BlendMode::Screen, + BlendingStyle::Overlay => raqote::BlendMode::Overlay, + BlendingStyle::Darken => raqote::BlendMode::Darken, + BlendingStyle::Lighten => raqote::BlendMode::Lighten, + BlendingStyle::ColorDodge => raqote::BlendMode::ColorDodge, + BlendingStyle::HardLight => raqote::BlendMode::HardLight, + BlendingStyle::SoftLight => raqote::BlendMode::SoftLight, + BlendingStyle::Difference => raqote::BlendMode::Difference, + BlendingStyle::Exclusion => raqote::BlendMode::Exclusion, + BlendingStyle::Hue => raqote::BlendMode::Hue, + BlendingStyle::Saturation => raqote::BlendMode::Saturation, + BlendingStyle::Color => raqote::BlendMode::Color, + BlendingStyle::Luminosity => raqote::BlendMode::Luminosity, + BlendingStyle::ColorBurn => unimplemented!("raqote doesn't support colorburn"), + } + } +} + +impl ToRaqoteStyle for CompositionStyle { + type Target = raqote::BlendMode; + + fn to_raqote_style(self) -> Self::Target { + match self { + CompositionStyle::SrcIn => raqote::BlendMode::SrcIn, + CompositionStyle::SrcOut => raqote::BlendMode::SrcOut, + CompositionStyle::SrcOver => raqote::BlendMode::SrcOver, + CompositionStyle::SrcAtop => raqote::BlendMode::SrcAtop, + CompositionStyle::DestIn => raqote::BlendMode::DstIn, + CompositionStyle::DestOut => raqote::BlendMode::DstOut, + CompositionStyle::DestOver => raqote::BlendMode::DstOver, + CompositionStyle::DestAtop => raqote::BlendMode::DstAtop, + CompositionStyle::Copy => raqote::BlendMode::Src, + CompositionStyle::Lighter => raqote::BlendMode::Add, + CompositionStyle::Xor => raqote::BlendMode::Xor, + } + } +} From 4c73e4bb3fe1c6c6fec41bfb5dc82ef251a8bbd0 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Sun, 11 Aug 2019 14:30:29 +0200 Subject: [PATCH 27/34] Imlplement get_composition_op --- components/canvas/canvas_data.rs | 2 +- components/canvas/raqote_backend.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 1a1e6fd1cea..9eb9eb55889 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -325,7 +325,7 @@ pub enum CompositionOp { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::CompositionOp), #[cfg(feature = "canvas2d-raqote")] - Raqote(()), + Raqote(raqote::BlendMode), } pub enum SurfaceFormat { diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index d4675f2c2dc..6a566ee6934 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -16,8 +16,8 @@ use std::marker::PhantomData; pub struct RaqoteBackend; impl Backend for RaqoteBackend { - fn get_composition_op(&self, _opts: &DrawOptions) -> CompositionOp { - unimplemented!() + fn get_composition_op(&self, opts: &DrawOptions) -> CompositionOp { + CompositionOp::Raqote(opts.as_raqote().blend_mode) } fn need_to_draw_shadow(&self, color: &Color) -> bool { From 0a3c6637bb8397b439e1fac3f1e6335356482923 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Sun, 11 Aug 2019 14:31:02 +0200 Subject: [PATCH 28/34] Implement create_similar_draw_target --- components/canvas/raqote_backend.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 6a566ee6934..52d75e61b6e 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -241,10 +241,10 @@ impl GenericDrawTarget for raqote::DrawTarget { } fn create_similar_draw_target( &self, - _size: &Size2D, + size: &Size2D, _format: SurfaceFormat, ) -> Box { - unimplemented!(); + Box::new(raqote::DrawTarget::new(size.width, size.height)) } fn create_source_surface_from_data( &self, From 3dd0b462c2c181813ef297ea2cde5c6666eedca4 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Sun, 11 Aug 2019 14:31:20 +0200 Subject: [PATCH 29/34] Make tidy happy again --- components/canvas/raqote_backend.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 52d75e61b6e..4ceb0c26f5b 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -301,12 +301,7 @@ impl GenericDrawTarget for raqote::DrawTarget { raqote::DrawOptions::new() }; - raqote::DrawTarget::fill( - self, - &pb.finish(), - pattern.as_raqote(), - &draw_options, - ); + raqote::DrawTarget::fill(self, &pb.finish(), pattern.as_raqote(), &draw_options); } fn get_format(&self) -> SurfaceFormat { unimplemented!(); @@ -365,7 +360,8 @@ impl GenericDrawTarget for raqote::DrawTarget { &pb.finish(), pattern.as_raqote(), &stroke_options, - draw_options.as_raqote()); + draw_options.as_raqote(), + ); } fn stroke_rect( &mut self, @@ -382,10 +378,11 @@ impl GenericDrawTarget for raqote::DrawTarget { rect.size.height, ); - self.stroke(&pb.finish(), - pattern.as_raqote(), - stroke_options.as_raqote(), - draw_options.as_raqote(), + self.stroke( + &pb.finish(), + pattern.as_raqote(), + stroke_options.as_raqote(), + draw_options.as_raqote(), ); } #[allow(unsafe_code)] @@ -405,7 +402,8 @@ impl GenericDrawTarget for raqote::DrawTarget { std::slice::from_raw_parts( v.as_ptr() as *const u8, v.len() * std::mem::size_of::(), - ).into() + ) + .into() } } } From 8cb8e7c627a1e094ceb78e4629f42919818b0491 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Sun, 11 Aug 2019 15:18:19 +0200 Subject: [PATCH 30/34] WIP: Fix azure backend --- components/canvas/azure_backend.rs | 127 +++++++++++++++++------------ components/canvas/canvas_data.rs | 2 +- 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/components/canvas/azure_backend.rs b/components/canvas/azure_backend.rs index 57e53e6ab7e..905e4ee8f46 100644 --- a/components/canvas/azure_backend.rs +++ b/components/canvas/azure_backend.rs @@ -18,6 +18,8 @@ use canvas_traits::canvas::*; use cssparser::RGBA; use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D}; +use std::marker::PhantomData; + pub struct AzureBackend; impl Backend for AzureBackend { @@ -31,7 +33,7 @@ impl Backend for AzureBackend { fn size_from_pattern(&self, rect: &Rect, pattern: &Pattern) -> Option> { match pattern { - Pattern::Azure(azure_hl::Pattern::Surface(ref surface)) => { + Pattern::Azure(azure_hl::Pattern::Surface(ref surface), _) => { let surface_size = surface.size(); let size = match (surface.repeat_x, surface.repeat_y) { (true, true) => rect.size, @@ -43,7 +45,7 @@ impl Backend for AzureBackend { }; Some(size) }, - Pattern::Azure(_) => None, + Pattern::Azure(..) => None, } } @@ -58,7 +60,7 @@ impl Backend for AzureBackend { drawtarget: &dyn GenericDrawTarget, ) { if let Some(pattern) = style.to_azure_pattern(drawtarget) { - state.fill_style = Pattern::Azure(pattern) + state.fill_style = Pattern::Azure(pattern, PhantomData::default()) } } @@ -69,7 +71,7 @@ impl Backend for AzureBackend { drawtarget: &dyn GenericDrawTarget, ) { if let Some(pattern) = style.to_azure_pattern(drawtarget) { - state.stroke_style = Pattern::Azure(pattern) + state.stroke_style = Pattern::Azure(pattern, PhantomData::default()) } } @@ -108,12 +110,14 @@ impl<'a> CanvasPaintState<'a> { azure_hl::CompositionOp::Over, antialias.into_azure(), )), - fill_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new( - azure_hl::Color::black(), - ))), - stroke_style: Pattern::Azure(azure_hl::Pattern::Color(ColorPattern::new( - azure_hl::Color::black(), - ))), + fill_style: Pattern::Azure( + azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black())), + PhantomData::default(), + ), + stroke_style: Pattern::Azure( + azure_hl::Pattern::Color(ColorPattern::new(azure_hl::Color::black())), + PhantomData::default(), + ), stroke_opts: StrokeOptions::Azure(azure_hl::StrokeOptions::new( 1.0, JoinStyle::MiterOrBevel, @@ -132,14 +136,15 @@ impl<'a> CanvasPaintState<'a> { impl GenericPathBuilder for azure_hl::PathBuilder { fn arc( - &self, + &mut self, origin: Point2D, radius: f32, start_angle: f32, end_angle: f32, anticlockwise: bool, ) { - self.arc( + azure_hl::PathBuilder::arc( + self, origin as Point2D, radius as AzFloat, start_angle as AzFloat, @@ -148,22 +153,23 @@ impl GenericPathBuilder for azure_hl::PathBuilder { ); } fn bezier_curve_to( - &self, + &mut self, control_point1: &Point2D, control_point2: &Point2D, control_point3: &Point2D, ) { - self.bezier_curve_to( + azure_hl::PathBuilder::bezier_curve_to( + self, control_point1 as &Point2D, control_point2 as &Point2D, control_point3 as &Point2D, ); } - fn close(&self) { - self.close(); + fn close(&mut self) { + azure_hl::PathBuilder::close(self); } fn ellipse( - &self, + &mut self, origin: Point2D, radius_x: f32, radius_y: f32, @@ -172,7 +178,8 @@ impl GenericPathBuilder for azure_hl::PathBuilder { end_angle: f32, anticlockwise: bool, ) { - self.ellipse( + azure_hl::PathBuilder::ellipse( + self, origin as Point2D, radius_x as AzFloat, radius_y as AzFloat, @@ -182,34 +189,40 @@ impl GenericPathBuilder for azure_hl::PathBuilder { anticlockwise, ); } - fn get_current_point(&self) -> Point2D { - let AzPoint { x, y } = self.get_current_point(); + fn get_current_point(&mut self) -> Point2D { + let AzPoint { x, y } = azure_hl::PathBuilder::get_current_point(self); Point2D::new(x as f32, y as f32) } - fn line_to(&self, point: Point2D) { - self.line_to(point as Point2D); + fn line_to(&mut self, point: Point2D) { + azure_hl::PathBuilder::line_to(self, point as Point2D); } - fn move_to(&self, point: Point2D) { - self.move_to(point as Point2D); + fn move_to(&mut self, point: Point2D) { + azure_hl::PathBuilder::move_to(self, point as Point2D); } - fn quadratic_curve_to(&self, control_point: &Point2D, end_point: &Point2D) { - self.quadratic_curve_to( + fn quadratic_curve_to(&mut self, control_point: &Point2D, end_point: &Point2D) { + azure_hl::PathBuilder::quadratic_curve_to( + self, control_point as &Point2D, end_point as &Point2D, ); } - fn finish(&self) -> Path { - Path::Azure(self.finish()) + fn finish(&mut self) -> Path { + Path::Azure(azure_hl::PathBuilder::finish(self)) } } impl GenericDrawTarget for azure_hl::DrawTarget { - fn clear_rect(&self, rect: &Rect) { - self.clear_rect(rect as &Rect); + fn clear_rect(&mut self, rect: &Rect) { + azure_hl::DrawTarget::clear_rect(self, rect as &Rect); } - fn copy_surface(&self, surface: SourceSurface, source: Rect, destination: Point2D) { - self.copy_surface(surface.into_azure(), source, destination); + fn copy_surface( + &mut self, + surface: SourceSurface, + source: Rect, + destination: Point2D, + ) { + azure_hl::DrawTarget::copy_surface(self, surface.into_azure(), source, destination); } fn create_gradient_stops( @@ -282,15 +295,22 @@ impl GenericDrawTarget for azure_hl::DrawTarget { operator.into_azure(), ); } - fn fill(&self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) { - self.fill( + fn fill(&mut self, path: &Path, pattern: Pattern, draw_options: &DrawOptions) { + azure_hl::DrawTarget::fill( + self, path.as_azure(), pattern.as_azure().to_pattern_ref(), draw_options.as_azure(), ); } - fn fill_rect(&self, rect: &Rect, pattern: Pattern, draw_options: Option<&DrawOptions>) { - self.fill_rect( + fn fill_rect( + &mut self, + rect: &Rect, + pattern: Pattern, + draw_options: Option<&DrawOptions>, + ) { + azure_hl::DrawTarget::fill_rect( + self, rect as &Rect, pattern.as_azure().to_pattern_ref(), draw_options.map(|x| x.as_azure()), @@ -306,26 +326,27 @@ impl GenericDrawTarget for azure_hl::DrawTarget { fn get_transform(&self) -> Transform2D { self.get_transform() as Transform2D } - fn pop_clip(&self) { - self.pop_clip(); + fn pop_clip(&mut self) { + azure_hl::DrawTarget::pop_clip(self); } - fn push_clip(&self, path: &Path) { - self.push_clip(path.as_azure()); + fn push_clip(&mut self, path: &Path) { + azure_hl::DrawTarget::push_clip(self, path.as_azure()); } - fn set_transform(&self, matrix: &Transform2D) { - self.set_transform(matrix as &Transform2D); + fn set_transform(&mut self, matrix: &Transform2D) { + azure_hl::DrawTarget::set_transform(self, matrix as &Transform2D); } fn snapshot(&self) -> SourceSurface { SourceSurface::Azure(self.snapshot()) } fn stroke( - &self, + &mut self, path: &Path, pattern: Pattern, stroke_options: &StrokeOptions, draw_options: &DrawOptions, ) { - self.stroke( + azure_hl::DrawTarget::stroke( + self, path.as_azure(), pattern.as_azure().to_pattern_ref(), stroke_options.as_azure(), @@ -333,7 +354,7 @@ impl GenericDrawTarget for azure_hl::DrawTarget { ); } fn stroke_line( - &self, + &mut self, start: Point2D, end: Point2D, pattern: Pattern, @@ -354,7 +375,8 @@ impl GenericDrawTarget for azure_hl::DrawTarget { stroke_options.mDashPattern, ); - self.stroke_line( + azure_hl::DrawTarget::stroke_line( + self, start, end, pattern.as_azure().to_pattern_ref(), @@ -363,13 +385,14 @@ impl GenericDrawTarget for azure_hl::DrawTarget { ); } fn stroke_rect( - &self, + &mut self, rect: &Rect, pattern: Pattern, stroke_options: &StrokeOptions, draw_options: &DrawOptions, ) { - self.stroke_rect( + azure_hl::DrawTarget::stroke_rect( + self, rect as &Rect, pattern.as_azure().to_pattern_ref(), stroke_options.as_azure(), @@ -469,10 +492,10 @@ impl Path { } } -impl Pattern { +impl Pattern<'_> { fn as_azure(&self) -> &azure_hl::Pattern { match self { - Pattern::Azure(p) => p, + Pattern::Azure(p, _) => p, } } } @@ -723,10 +746,10 @@ impl ToAzureStyle for RGBA { } } -impl Pattern { +impl Pattern<'_> { pub fn is_zero_size_gradient(&self) -> bool { match *self { - Pattern::Azure(azure_hl::Pattern::LinearGradient(ref gradient)) => { + Pattern::Azure(azure_hl::Pattern::LinearGradient(ref gradient), _) => { gradient.is_zero_size() }, _ => false, diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 9eb9eb55889..3f66525b7c0 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -354,7 +354,7 @@ pub enum Path { #[derive(Clone)] pub enum Pattern<'a> { #[cfg(feature = "canvas2d-azure")] - Azure(azure::azure_hl::Pattern), + Azure(azure::azure_hl::Pattern, PhantomData<&'a ()>), #[cfg(feature = "canvas2d-raqote")] Raqote(raqote::Source<'a>), } From dc78b6a9892936d17ed52d589db7acfc797ac837 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Fri, 16 Aug 2019 23:02:42 +0200 Subject: [PATCH 31/34] Implement a few functions to make tests in draw-image and draw-path pass --- components/canvas/canvas_data.rs | 6 +-- components/canvas/raqote_backend.rs | 63 +++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 3f66525b7c0..c2feabeac02 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -239,7 +239,7 @@ pub trait GenericDrawTarget { stride: i32, ) -> Option; fn draw_surface( - &self, + &mut self, surface: SourceSurface, dest: Rect, source: Rect, @@ -340,7 +340,7 @@ pub enum SourceSurface { #[cfg(feature = "canvas2d-azure")] Azure(azure::azure_hl::SourceSurface), #[cfg(feature = "canvas2d-raqote")] - Raqote(()), + Raqote(Vec), // TODO: See if we can avoid the alloc (probably?) } #[derive(Clone)] @@ -1133,7 +1133,7 @@ pub struct CanvasPaintState<'a> { /// dest_rect: Area of the destination target where the pixels will be copied /// smoothing_enabled: It determines if smoothing is applied to the image result fn write_image( - draw_target: &dyn GenericDrawTarget, + draw_target: &mut dyn GenericDrawTarget, image_data: Vec, image_size: Size2D, dest_rect: Rect, diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 4ceb0c26f5b..2aea31ad460 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -188,7 +188,7 @@ impl Path { } pub fn copy_to_builder(&self) -> Box { - unimplemented!() + Box::new(PathBuilder(Some(raqote::PathBuilder::from(self.as_raqote().clone())))) } pub fn as_raqote(&self) -> &raqote::Path { @@ -221,13 +221,23 @@ impl GenericDrawTarget for raqote::DrawTarget { &options, ); } + #[allow(unsafe_code)] fn copy_surface( &mut self, - _surface: SourceSurface, - _source: Rect, - _destination: Point2D, + surface: SourceSurface, + source: Rect, + destination: Point2D, ) { - unimplemented!(); + let mut dt = raqote::DrawTarget::new(source.size.width, source.size.height); + let data = surface.as_raqote(); + let s = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) }; + dt.get_data_mut().copy_from_slice(s); + raqote::DrawTarget::copy_surface( + self, + &dt, + source.to_box2d(), + destination + ); } fn create_gradient_stops( &self, @@ -248,21 +258,40 @@ impl GenericDrawTarget for raqote::DrawTarget { } fn create_source_surface_from_data( &self, - _data: &[u8], + data: &[u8], _size: Size2D, _stride: i32, ) -> Option { - unimplemented!(); + Some(SourceSurface::Raqote(data.to_vec())) } + #[allow(unsafe_code)] fn draw_surface( - &self, - _surface: SourceSurface, - _dest: Rect, - _source: Rect, + &mut self, + surface: SourceSurface, + dest: Rect, + source: Rect, _filter: Filter, - _draw_options: &DrawOptions, + draw_options: &DrawOptions, ) { - unimplemented!(); + let v = surface.as_raqote(); + let image = raqote::Image { + width: source.size.width as i32, + height: source.size.height as i32, + data: unsafe { + std::slice::from_raw_parts( + v.as_ptr() as *const u32, + v.len() * std::mem::size_of::(), + ) }, + }; + raqote::DrawTarget::draw_image_with_size_at( + self, + dest.size.width as f32, + dest.size.height as f32, + dest.origin.x as f32, + dest.origin.y as f32, + &image, + draw_options.as_raqote(), + ); } fn draw_surface_with_shadow( &self, @@ -617,3 +646,11 @@ impl ToRaqoteStyle for CompositionStyle { } } } + +impl SourceSurface { + fn as_raqote(&self) -> &Vec { + match self { + SourceSurface::Raqote(s) => s, + } + } +} From 8a57876482c87c4a5c5d76da4a2db948b44a539d Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Fri, 16 Aug 2019 23:08:24 +0200 Subject: [PATCH 32/34] Implement get_format Since raqote doesn't have multiple formats for its surfaces, this is a noop to avoid crashing with the unimplemented --- Cargo.toml | 1 - components/canvas/raqote_backend.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8633e7c72fe..97e2f43df59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,4 +28,3 @@ opt-level = 3 # Those are here to dedupe winapi since mio is still using winapi 0.2. mio = { git = "https://github.com/servo/mio.git", branch = "servo" } iovec = { git = "https://github.com/servo/iovec.git", branch = "servo" } - diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 2aea31ad460..4b789aac30a 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -333,7 +333,7 @@ impl GenericDrawTarget for raqote::DrawTarget { raqote::DrawTarget::fill(self, &pb.finish(), pattern.as_raqote(), &draw_options); } fn get_format(&self) -> SurfaceFormat { - unimplemented!(); + SurfaceFormat::Raqote(()) } fn get_size(&self) -> Size2D { Size2D::new(self.width(), self.height()) From 168a52622133b01bd1e912d9f6135cbb1c5a52dd Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Wed, 21 Aug 2019 19:07:50 +0200 Subject: [PATCH 33/34] Implement Source::Surface for FillOrStrokeStyle with raqote --- components/canvas/raqote_backend.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 4b789aac30a..a3ae8eb67ea 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -554,6 +554,7 @@ pub trait ToRaqoteSource<'a> { } impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { + #[allow(unsafe_code)] fn to_raqote_source(self) -> Option> { use canvas_traits::canvas::FillOrStrokeStyle::*; @@ -566,7 +567,19 @@ impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { })), LinearGradient(_) => unimplemented!(), RadialGradient(_) => unimplemented!(), - Surface(_) => unimplemented!(), + Surface(ref surface) => { + let data = &surface.surface_data[..]; + Some(raqote::Source::Image( + raqote::Image { + data: unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) }, + width: surface.surface_size.width as i32, + height: surface.surface_size.height as i32, + }, + raqote::ExtendMode::Repeat, // TODO: repeat-x, repeat-y ? + raqote::FilterMode::Bilinear, + raqote::Transform::identity(), + )) + }, } } } From f829eaea03c3c84e773798cffc29186f7e4c007d Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Wed, 21 Aug 2019 19:17:03 +0200 Subject: [PATCH 34/34] Fix the build and tidy and address nits --- Cargo.lock | 7 +++-- components/canvas/azure_backend.rs | 5 ++-- components/canvas/raqote_backend.rs | 44 ++++++++++++----------------- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 85b9eec7569..17087b400a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,7 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "azure" version = "0.36.1" -source = "git+https://github.com/servo/rust-azure#37a57b3d862bcf345d1413c7ebb534ff69daab3b" +source = "git+https://github.com/servo/rust-azure#5996612af3139cc3c5eafb019d8218f8ca1634de" dependencies = [ "cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2504,8 +2504,9 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3711,7 +3712,7 @@ dependencies = [ [[package]] name = "raqote" version = "0.6.2-alpha.0" -source = "git+https://github.com/jrmuizel/raqote#2d9a0fbb419d10e066fb49e121a45fce1e1f2abe" +source = "git+https://github.com/jrmuizel/raqote#b3675e6cc1ac1d854605918f6613b64636d5e47b" dependencies = [ "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "font-kit 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/canvas/azure_backend.rs b/components/canvas/azure_backend.rs index 905e4ee8f46..fa48d869c40 100644 --- a/components/canvas/azure_backend.rs +++ b/components/canvas/azure_backend.rs @@ -256,7 +256,7 @@ impl GenericDrawTarget for azure_hl::DrawTarget { .map(|s| SourceSurface::Azure(s)) } fn draw_surface( - &self, + &mut self, surface: SourceSurface, dest: Rect, source: Rect, @@ -269,7 +269,8 @@ impl GenericDrawTarget for azure_hl::DrawTarget { draw_options.as_azure().composition, azure_hl::AntialiasMode::None, ); - self.draw_surface( + azure_hl::DrawTarget::draw_surface( + self, surface.into_azure(), dest.to_azure_style(), source.to_azure_style(), diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index a3ae8eb67ea..279402fa77a 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -140,14 +140,14 @@ impl<'a> StrokeOptions<'a> { StrokeOptions::Raqote(options, _) => options.miter_limit = _val, } } - pub fn set_line_join(&mut self, _val: LineJoinStyle) { + pub fn set_line_join(&mut self, val: LineJoinStyle) { match self { - StrokeOptions::Raqote(options, _) => options.join = _val.to_raqote_style(), + StrokeOptions::Raqote(options, _) => options.join = val.to_raqote_style(), } } - pub fn set_line_cap(&mut self, _val: LineCapStyle) { + pub fn set_line_cap(&mut self, val: LineCapStyle) { match self { - StrokeOptions::Raqote(options, _) => options.cap = _val.to_raqote_style(), + StrokeOptions::Raqote(options, _) => options.cap = val.to_raqote_style(), } } pub fn as_raqote(&self) -> &raqote::StrokeStyle { @@ -158,9 +158,9 @@ impl<'a> StrokeOptions<'a> { } impl DrawOptions { - pub fn set_alpha(&mut self, _val: f32) { + pub fn set_alpha(&mut self, val: f32) { match self { - DrawOptions::Raqote(draw_options) => draw_options.alpha = _val, + DrawOptions::Raqote(draw_options) => draw_options.alpha = val, } } pub fn as_raqote(&self) -> &raqote::DrawOptions { @@ -188,7 +188,9 @@ impl Path { } pub fn copy_to_builder(&self) -> Box { - Box::new(PathBuilder(Some(raqote::PathBuilder::from(self.as_raqote().clone())))) + Box::new(PathBuilder(Some(raqote::PathBuilder::from( + self.as_raqote().clone(), + )))) } pub fn as_raqote(&self) -> &raqote::Path { @@ -232,12 +234,7 @@ impl GenericDrawTarget for raqote::DrawTarget { let data = surface.as_raqote(); let s = unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) }; dt.get_data_mut().copy_from_slice(s); - raqote::DrawTarget::copy_surface( - self, - &dt, - source.to_box2d(), - destination - ); + raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination); } fn create_gradient_stops( &self, @@ -278,10 +275,11 @@ impl GenericDrawTarget for raqote::DrawTarget { width: source.size.width as i32, height: source.size.height as i32, data: unsafe { - std::slice::from_raw_parts( - v.as_ptr() as *const u32, - v.len() * std::mem::size_of::(), - ) }, + std::slice::from_raw_parts( + v.as_ptr() as *const u32, + v.len() * std::mem::size_of::(), + ) + }, }; raqote::DrawTarget::draw_image_with_size_at( self, @@ -541,14 +539,6 @@ impl ToRaqoteStyle for LineCapStyle { } } -// TODO(pylbrecht) -#[cfg(feature = "raqote_backend")] -impl Clone for Pattern<'_> { - fn clone(&self) -> Self { - unimplemented!(); - } -} - pub trait ToRaqoteSource<'a> { fn to_raqote_source(self) -> Option>; } @@ -571,7 +561,9 @@ impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { let data = &surface.surface_data[..]; Some(raqote::Source::Image( raqote::Image { - data: unsafe { std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) }, + data: unsafe { + std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / 4) + }, width: surface.surface_size.width as i32, height: surface.surface_size.height as i32, },