diff options
author | pylbrecht <palbrecht@mailbox.org> | 2020-02-19 15:29:04 +0100 |
---|---|---|
committer | pylbrecht <palbrecht@mailbox.org> | 2020-02-26 06:45:47 +0100 |
commit | 86ad6ed3b85a67032cb72a87535460547d98e266 (patch) | |
tree | d5ba80295cc709d674140de5dd327e5e94d74d73 /components/canvas/raqote_backend.rs | |
parent | 455fb18ecaa253d34aa77cb5354306db0cfcee1c (diff) | |
download | servo-86ad6ed3b85a67032cb72a87535460547d98e266.tar.gz servo-86ad6ed3b85a67032cb72a87535460547d98e266.zip |
Refactor arc() and ellipse() to use lyon_geom::Arc
Diffstat (limited to 'components/canvas/raqote_backend.rs')
-rw-r--r-- | components/canvas/raqote_backend.rs | 139 |
1 files changed, 57 insertions, 82 deletions
diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 362ad1c5c57..8c8e6254c0b 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -12,8 +12,9 @@ use crate::canvas_paint_thread::AntialiasMode; use canvas_traits::canvas::*; use cssparser::RGBA; use euclid::default::{Point2D, Rect, Size2D, Transform2D, Vector2D}; +use euclid::Angle; +use lyon_geom::Arc; use raqote::PathOp; -use std::f32::consts::PI; use std::marker::PhantomData; pub struct RaqoteBackend; @@ -684,25 +685,19 @@ impl GenericPathBuilder for PathBuilder { &mut self, origin: Point2D<f32>, radius: f32, - mut start_angle: f32, - mut end_angle: f32, + start_angle: f32, + end_angle: f32, anticlockwise: bool, ) { - if (!anticlockwise && start_angle > end_angle + 2. * PI) || - (anticlockwise && end_angle > start_angle + 2. * PI) - { - start_angle = start_angle % (2. * PI); - end_angle = end_angle % (2. * PI); - } - - if (anticlockwise && end_angle > 0.) || (!anticlockwise && end_angle < 0.) { - end_angle = -end_angle; - } - - self.0 - .as_mut() - .unwrap() - .arc(origin.x, origin.y, radius, start_angle, end_angle); + self.ellipse( + origin, + radius, + radius, + 0., + start_angle, + end_angle, + anticlockwise, + ); } fn bezier_curve_to( &mut self, @@ -727,77 +722,57 @@ impl GenericPathBuilder for PathBuilder { origin: Point2D<f32>, radius_x: f32, radius_y: f32, - _rotation_angle: f32, + rotation_angle: f32, start_angle: f32, - mut end_angle: f32, + end_angle: f32, anticlockwise: bool, ) { - let start_point = Point2D::new( - origin.x + start_angle.cos() * radius_x, - origin.y + end_angle.sin() * radius_y, - ); - self.line_to(start_point); - - if !anticlockwise && (end_angle < start_angle) { - let correction = ((start_angle - end_angle) / (2.0 * PI)).ceil(); - end_angle += correction * 2.0 * PI; - } else if anticlockwise && (start_angle < end_angle) { - let correction = ((end_angle - start_angle) / (2.0 * PI)).ceil(); - end_angle += correction * 2.0 * PI; - } - // Sweeping more than 2 * pi is a full circle. - if !anticlockwise && (end_angle - start_angle > 2.0 * PI) { - end_angle = start_angle + 2.0 * PI; - } else if anticlockwise && (start_angle - end_angle > 2.0 * PI) { - end_angle = start_angle - 2.0 * PI; + 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 mut arc_sweep_left = (end_angle - start_angle).abs(); - let sweep_direction = match anticlockwise { - true => -1.0, - false => 1.0, + 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 mut current_start_angle = start_angle; - while arc_sweep_left > 0.0 { - // We guarantee here the current point is the start point of the next - // curve segment. - let current_end_angle; - if arc_sweep_left > PI / 2.0 { - current_end_angle = current_start_angle + PI / 2.0 * sweep_direction; - } else { - current_end_angle = current_start_angle + arc_sweep_left * sweep_direction; - } - let current_start_point = Point2D::new( - origin.x + current_start_angle.cos() * radius_x, - origin.y + current_start_angle.sin() * radius_y, - ); - let current_end_point = Point2D::new( - origin.x + current_end_angle.cos() * radius_x, - origin.y + current_end_angle.sin() * radius_y, - ); - // Calculate kappa constant for partial curve. The sign of angle in the - // tangent will actually ensure this is negative for a counter clockwise - // sweep, so changing signs later isn't needed. - let kappa_factor = - (4.0 / 3.0) * ((current_end_angle - current_start_angle) / 4.0).tan(); - let kappa_x = kappa_factor * radius_x; - let kappa_y = kappa_factor * radius_y; - - let tangent_start = - Point2D::new(-(current_start_angle.sin()), current_start_angle.cos()); - let mut cp1 = current_start_point; - cp1 += Point2D::new(tangent_start.x * kappa_x, tangent_start.y * kappa_y).to_vector(); - let rev_tangent_end = Point2D::new(current_end_angle.sin(), -(current_end_angle.cos())); - let mut cp2 = current_end_point; - cp2 += - Point2D::new(rev_tangent_end.x * kappa_x, rev_tangent_end.y * kappa_y).to_vector(); - - self.bezier_curve_to(&cp1, &cp2, ¤t_end_point); - - arc_sweep_left -= PI / 2.0; - current_start_angle = current_end_angle; - } + + 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>> { |