diff options
Diffstat (limited to 'components/canvas')
-rw-r--r-- | components/canvas/backend.rs | 63 | ||||
-rw-r--r-- | components/canvas/canvas_data.rs | 14 | ||||
-rw-r--r-- | components/canvas/raqote_backend.rs | 71 |
3 files changed, 71 insertions, 77 deletions
diff --git a/components/canvas/backend.rs b/components/canvas/backend.rs index c83eebe3bee..53acbea8b8d 100644 --- a/components/canvas/backend.rs +++ b/components/canvas/backend.rs @@ -2,8 +2,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use canvas_traits::canvas::{FillOrStrokeStyle, LineCapStyle, LineJoinStyle}; +use canvas_traits::canvas::{ + CompositionOrBlending, FillOrStrokeStyle, LineCapStyle, LineJoinStyle, +}; +use euclid::Angle; use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D}; +use lyon_geom::Arc; use style::color::AbsoluteColor; use crate::canvas_data::{CanvasPaintState, Filter, TextRun}; @@ -14,10 +18,10 @@ pub(crate) trait Backend: Clone + Sized { type Color: Clone; type DrawOptions: DrawOptionsHelpers + Clone; type CompositionOp; - type CompositionOrBlending; type DrawTarget: GenericDrawTarget<Self>; type PathBuilder: GenericPathBuilder<Self>; type SourceSurface; + type Bytes<'a>: AsRef<[u8]>; type Path: PathHelpers<Self> + Clone; type GradientStop; type GradientStops; @@ -39,7 +43,7 @@ pub(crate) trait Backend: Clone + Sized { ); fn set_global_composition( &mut self, - op: Self::CompositionOrBlending, + op: CompositionOrBlending, state: &mut CanvasPaintState<'_, Self>, ); fn create_drawtarget(&self, size: Size2D<u64>) -> Self::DrawTarget; @@ -95,7 +99,6 @@ pub(crate) trait GenericDrawTarget<B: Backend> { fn pop_clip(&mut self); fn push_clip(&mut self, path: &B::Path); fn set_transform(&mut self, matrix: &Transform2D<f32>); - fn snapshot(&self) -> B::SourceSurface; fn stroke( &mut self, path: &B::Path, @@ -118,7 +121,8 @@ pub(crate) trait GenericDrawTarget<B: Backend> { stroke_options: &B::StrokeOptions, draw_options: &B::DrawOptions, ); - fn snapshot_data(&self) -> &[u8]; + fn surface(&self) -> B::SourceSurface; + fn bytes(&'_ self) -> B::Bytes<'_>; } /// A generic PathBuilder that abstracts the interface for azure's and raqote's PathBuilder. @@ -148,7 +152,54 @@ pub(crate) trait GenericPathBuilder<B: Backend> { start_angle: f32, end_angle: f32, anticlockwise: bool, - ); + ) { + let mut start = Angle::radians(start_angle); + let mut end = Angle::radians(end_angle); + + // Wrap angles mod 2 * PI if necessary + if !anticlockwise && start > end + Angle::two_pi() || + anticlockwise && end > start + Angle::two_pi() + { + start = start.positive(); + end = end.positive(); + } + + // Calculate the total arc we're going to sweep. + let sweep = match anticlockwise { + true => { + if end - start == Angle::two_pi() { + -Angle::two_pi() + } else if end > start { + -(Angle::two_pi() - (end - start)) + } else { + -(start - end) + } + }, + false => { + if start - end == Angle::two_pi() { + Angle::two_pi() + } else if start > end { + Angle::two_pi() - (start - end) + } else { + end - start + } + }, + }; + + let arc: Arc<f32> = Arc { + center: origin, + radii: Vector2D::new(radius_x, radius_y), + start_angle: start, + sweep_angle: sweep, + x_rotation: Angle::radians(rotation_angle), + }; + + self.line_to(arc.from()); + + arc.for_each_quadratic_bezier(&mut |q| { + self.quadratic_curve_to(&q.ctrl, &q.to); + }); + } fn get_current_point(&mut self) -> Option<Point2D<f32>>; fn line_to(&mut self, point: Point2D<f32>); fn move_to(&mut self, point: Point2D<f32>); diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 7d8b4a9cdbc..ea30589d0af 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -426,7 +426,7 @@ impl<'a, B: Backend> CanvasData<'a, B> { flags: ImageDescriptorFlags::empty(), }; let data = - SerializableImageData::Raw(IpcSharedMemory::from_bytes(draw_target.snapshot_data())); + SerializableImageData::Raw(IpcSharedMemory::from_bytes(draw_target.bytes().as_ref())); compositor_api.update_images(vec![ImageUpdate::AddImage(image_key, descriptor, data)]); CanvasData { state: backend.new_paint_state(), @@ -1183,7 +1183,7 @@ impl<'a, B: Backend> CanvasData<'a, B> { self.state.draw_options.set_alpha(alpha); } - pub(crate) fn set_global_composition(&mut self, op: B::CompositionOrBlending) { + pub(crate) fn set_global_composition(&mut self, op: CompositionOrBlending) { self.backend.set_global_composition(op, &mut self.state); } @@ -1209,7 +1209,7 @@ impl<'a, B: Backend> CanvasData<'a, B> { flags: ImageDescriptorFlags::empty(), }; let data = SerializableImageData::Raw(IpcSharedMemory::from_bytes( - self.drawtarget.snapshot_data(), + self.drawtarget.bytes().as_ref(), )); self.compositor_api @@ -1292,7 +1292,7 @@ impl<'a, B: Backend> CanvasData<'a, B> { 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(), + new_draw_target.surface(), &Point2D::new(shadow_src_rect.origin.x, shadow_src_rect.origin.y), &self.state.shadow_color, &Vector2D::new( @@ -1323,11 +1323,11 @@ impl<'a, B: Backend> CanvasData<'a, B> { { vec![] } else { - let bytes = self.drawtarget.snapshot_data(); - pixels::rgba8_get_rect(bytes, canvas_size, read_rect).to_vec() + pixels::rgba8_get_rect(self.drawtarget.bytes().as_ref(), canvas_size, read_rect) + .to_vec() } } else { - self.drawtarget.snapshot_data().to_vec() + self.drawtarget.bytes().as_ref().to_vec() }; Snapshot::from_vec( diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index e88de701336..efe0ffd05b8 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -7,12 +7,10 @@ use std::collections::HashMap; use canvas_traits::canvas::*; use cssparser::color::clamp_unit_f32; -use euclid::Angle; use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D}; use font_kit::font::Font; use fonts::{ByteIndex, FontIdentifier, FontTemplateRefMethods}; use log::warn; -use lyon_geom::Arc; use range::Range; use raqote::PathOp; use style::color::AbsoluteColor; @@ -40,10 +38,10 @@ impl Backend for RaqoteBackend { type Color = raqote::SolidSource; type DrawOptions = raqote::DrawOptions; type CompositionOp = raqote::BlendMode; - type CompositionOrBlending = CompositionOrBlending; type DrawTarget = raqote::DrawTarget; type PathBuilder = PathBuilder; type SourceSurface = Vec<u8>; // TODO: See if we can avoid the alloc (probably?) + type Bytes<'a> = &'a [u8]; type Path = raqote::Path; type GradientStop = raqote::GradientStop; type GradientStops = Vec<raqote::GradientStop>; @@ -84,7 +82,7 @@ impl Backend for RaqoteBackend { fn set_global_composition( &mut self, - op: Self::CompositionOrBlending, + op: CompositionOrBlending, state: &mut CanvasPaintState<'_, Self>, ) { state.draw_options.blend_mode = op.to_raqote_style(); @@ -598,8 +596,8 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget { fn set_transform(&mut self, matrix: &Transform2D<f32>) { self.set_transform(matrix); } - fn snapshot(&self) -> <RaqoteBackend as Backend>::SourceSurface { - self.snapshot_data().to_vec() + fn surface(&self) -> <RaqoteBackend as Backend>::SourceSurface { + self.bytes().to_vec() } fn stroke( &mut self, @@ -658,7 +656,7 @@ impl GenericDrawTarget<RaqoteBackend> for raqote::DrawTarget { ); } #[allow(unsafe_code)] - fn snapshot_data(&self) -> &[u8] { + fn bytes(&self) -> &[u8] { let v = self.get_data(); unsafe { std::slice::from_raw_parts(v.as_ptr() as *const u8, std::mem::size_of_val(v)) } } @@ -701,6 +699,7 @@ impl GenericPathBuilder<RaqoteBackend> for PathBuilder { anticlockwise, ); } + fn bezier_curve_to( &mut self, control_point1: &Point2D<f32>, @@ -716,66 +715,10 @@ impl GenericPathBuilder<RaqoteBackend> for PathBuilder { control_point3.y, ); } + fn close(&mut self) { self.0.as_mut().unwrap().close(); } - fn ellipse( - &mut self, - origin: Point2D<f32>, - radius_x: f32, - radius_y: f32, - rotation_angle: f32, - start_angle: f32, - end_angle: f32, - anticlockwise: bool, - ) { - let mut start = Angle::radians(start_angle); - let mut end = Angle::radians(end_angle); - - // Wrap angles mod 2 * PI if necessary - if !anticlockwise && start > end + Angle::two_pi() || - anticlockwise && end > start + Angle::two_pi() - { - start = start.positive(); - end = end.positive(); - } - - // Calculate the total arc we're going to sweep. - let sweep = match anticlockwise { - true => { - if end - start == Angle::two_pi() { - -Angle::two_pi() - } else if end > start { - -(Angle::two_pi() - (end - start)) - } else { - -(start - end) - } - }, - false => { - if start - end == Angle::two_pi() { - Angle::two_pi() - } else if start > end { - Angle::two_pi() - (start - end) - } else { - end - start - } - }, - }; - - let arc: Arc<f32> = Arc { - center: origin, - radii: Vector2D::new(radius_x, radius_y), - start_angle: start, - sweep_angle: sweep, - x_rotation: Angle::radians(rotation_angle), - }; - - self.line_to(arc.from()); - - arc.for_each_quadratic_bezier(&mut |q| { - self.quadratic_curve_to(&q.ctrl, &q.to); - }); - } fn svg_arc( &mut self, |