aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpylbrecht <palbrecht@mailbox.org>2020-02-19 15:29:04 +0100
committerpylbrecht <palbrecht@mailbox.org>2020-02-26 06:45:47 +0100
commit86ad6ed3b85a67032cb72a87535460547d98e266 (patch)
treed5ba80295cc709d674140de5dd327e5e94d74d73
parent455fb18ecaa253d34aa77cb5354306db0cfcee1c (diff)
downloadservo-86ad6ed3b85a67032cb72a87535460547d98e266.tar.gz
servo-86ad6ed3b85a67032cb72a87535460547d98e266.zip
Refactor arc() and ellipse() to use lyon_geom::Arc
-rw-r--r--Cargo.lock1
-rw-r--r--components/canvas/Cargo.toml1
-rw-r--r--components/canvas/raqote_backend.rs139
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.round.html.ini4
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini4
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.3.html.ini4
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.scale.html.ini4
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.transformation.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.worker.js.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.worker.js.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.worker.js.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.worker.js.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.worker.js.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.html.ini4
-rw-r--r--tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.worker.js.ini4
21 files changed, 59 insertions, 155 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8d7bea14ee6..d00b2cd9c52 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -516,6 +516,7 @@ dependencies = [
"half",
"ipc-channel",
"log",
+ "lyon_geom 0.14.0",
"num-traits",
"pixels",
"raqote",
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml
index e35d2dd6a2f..058a8341852 100644
--- a/components/canvas/Cargo.toml
+++ b/components/canvas/Cargo.toml
@@ -30,6 +30,7 @@ gleam = "0.6.7"
half = "1"
ipc-channel = "0.12"
log = "0.4"
+lyon_geom = "0.14"
num-traits = "0.2"
raqote = {git = "https://github.com/jrmuizel/raqote", optional = true}
pixels = {path = "../pixels"}
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, &current_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>> {
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.round.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.round.html.ini
deleted file mode 100644
index 63fd4382c1e..00000000000
--- a/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.round.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.line.cap.round.html]
- [lineCap 'round' is rendered correctly]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini
deleted file mode 100644
index 522695b4c56..00000000000
--- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arc.twopie.1.html]
- [arc() draws nothing when end = start + 2pi-e and anticlockwise]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.3.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.3.html.ini
deleted file mode 100644
index c1e40e7c3d9..00000000000
--- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.3.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arc.twopie.3.html]
- [arc() draws a full circle when end = start + 2pi+e and anticlockwise]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.scale.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.scale.html.ini
deleted file mode 100644
index 583a1a2cf0c..00000000000
--- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.scale.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.scale.html]
- [arcTo scales the curve, not just the control points]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini
deleted file mode 100644
index 3ceefeb7d1a..00000000000
--- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[2d.path.arcTo.shape.curve2.html]
- type: testharness
- [arcTo() curves in the right kind of shape]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.transformation.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.transformation.html.ini
deleted file mode 100644
index 569cfc2fb80..00000000000
--- a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arcTo.transformation.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.transformation.html]
- [arcTo joins up to the last subpath point correctly]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.html.ini b/tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.html.ini
deleted file mode 100644
index 63fd4382c1e..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.line.cap.round.html]
- [lineCap 'round' is rendered correctly]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.worker.js.ini
deleted file mode 100644
index 8f7f3a0f347..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/line-styles/2d.line.cap.round.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.line.cap.round.worker.html]
- [lineCap 'round' is rendered correctly]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.html.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.html.ini
deleted file mode 100644
index 522695b4c56..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arc.twopie.1.html]
- [arc() draws nothing when end = start + 2pi-e and anticlockwise]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.worker.js.ini
deleted file mode 100644
index ba0a32aebbd..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.1.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arc.twopie.1.worker.html]
- [arc() draws nothing when end = start + 2pi-e and anticlockwise]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.html.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.html.ini
deleted file mode 100644
index c1e40e7c3d9..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arc.twopie.3.html]
- [arc() draws a full circle when end = start + 2pi+e and anticlockwise]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.worker.js.ini
deleted file mode 100644
index 07e0bb88d27..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arc.twopie.3.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arc.twopie.3.worker.html]
- [arc() draws a full circle when end = start + 2pi+e and anticlockwise]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.html.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.html.ini
deleted file mode 100644
index 583a1a2cf0c..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.scale.html]
- [arcTo scales the curve, not just the control points]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.worker.js.ini
deleted file mode 100644
index 875612e1fa9..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.scale.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.scale.worker.html]
- [arcTo scales the curve, not just the control points]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.html.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.html.ini
deleted file mode 100644
index 604b5e8b6bf..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.shape.curve2.html]
- [arcTo() curves in the right kind of shape]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.worker.js.ini
deleted file mode 100644
index 822ca101f8b..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.shape.curve2.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.shape.curve2.worker.html]
- [arcTo() curves in the right kind of shape]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.html.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.html.ini
deleted file mode 100644
index 569cfc2fb80..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.transformation.html]
- [arcTo joins up to the last subpath point correctly]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.worker.js.ini b/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.worker.js.ini
deleted file mode 100644
index 15980b4b69d..00000000000
--- a/tests/wpt/metadata/offscreen-canvas/path-objects/2d.path.arcTo.transformation.worker.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[2d.path.arcTo.transformation.worker.html]
- [arcTo joins up to the last subpath point correctly]
- expected: FAIL
-