mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
canvas: ensure there is a subpath in PathBuilderRef
(#37251)
This is also required by spec:
https://html.spec.whatwg.org/multipage/canvas.html#ensure-there-is-a-subpath
and if we not ensure it vello will trigger debug asserts. Enforcing this
at `PathBuilderRef` is the lowest possible level that avoids misuse (and
avoids IPC messages if we were to do this in content process) while
still keeping it from backend.
Testing: There are tests in WPT
Split of https://github.com/servo/servo/pull/36821
try run: 1544904469
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
b13f49ab09
commit
ffe9163892
3 changed files with 33 additions and 10 deletions
|
@ -154,7 +154,18 @@ struct PathBuilderRef<'a, B: Backend> {
|
|||
}
|
||||
|
||||
impl<B: Backend> PathBuilderRef<'_, B> {
|
||||
/// <https://html.spec.whatwg.org/multipage#ensure-there-is-a-subpath>
|
||||
fn ensure_there_is_a_subpath(&mut self, point: &Point2D<f32>) {
|
||||
if self.builder.get_current_point().is_none() {
|
||||
self.builder.move_to(*point);
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage#dom-context-2d-lineto>
|
||||
fn line_to(&mut self, pt: &Point2D<f32>) {
|
||||
// 2. If the object's path has no subpaths, then ensure there is a subpath for (x, y).
|
||||
self.ensure_there_is_a_subpath(pt);
|
||||
|
||||
let pt = self.transform.transform_point(*pt);
|
||||
self.builder.line_to(pt);
|
||||
}
|
||||
|
@ -182,14 +193,22 @@ impl<B: Backend> PathBuilderRef<'_, B> {
|
|||
self.move_to(&first);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage#dom-context-2d-quadraticcurveto>
|
||||
fn quadratic_curve_to(&mut self, cp: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||
// 2. Ensure there is a subpath for (cpx, cpy).
|
||||
self.ensure_there_is_a_subpath(cp);
|
||||
|
||||
self.builder.quadratic_curve_to(
|
||||
&self.transform.transform_point(*cp),
|
||||
&self.transform.transform_point(*endpoint),
|
||||
)
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage#dom-context-2d-beziercurveto>
|
||||
fn bezier_curve_to(&mut self, cp1: &Point2D<f32>, cp2: &Point2D<f32>, endpoint: &Point2D<f32>) {
|
||||
// 2. Ensure there is a subpath for (cp1x, cp1y).
|
||||
self.ensure_there_is_a_subpath(cp1);
|
||||
|
||||
self.builder.bezier_curve_to(
|
||||
&self.transform.transform_point(*cp1),
|
||||
&self.transform.transform_point(*cp2),
|
||||
|
@ -210,6 +229,7 @@ impl<B: Backend> PathBuilderRef<'_, B> {
|
|||
.arc(center, radius, start_angle, end_angle, ccw);
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage#dom-context-2d-arcto>
|
||||
fn arc_to(&mut self, cp1: &Point2D<f32>, cp2: &Point2D<f32>, radius: f32) {
|
||||
let cp0 = if let (Some(inverse), Some(point)) =
|
||||
(self.transform.inverse(), self.builder.get_current_point())
|
||||
|
@ -218,6 +238,9 @@ impl<B: Backend> PathBuilderRef<'_, B> {
|
|||
} else {
|
||||
*cp1
|
||||
};
|
||||
|
||||
// 2. Ensure there is a subpath for (x1, y1) is done by one of self.line_to calls
|
||||
|
||||
if (cp0.x == cp1.x && cp0.y == cp1.y) || cp1 == cp2 || radius == 0.0 {
|
||||
self.line_to(cp1);
|
||||
return;
|
||||
|
|
|
@ -710,7 +710,7 @@ impl GenericPathBuilder<RaqoteBackend> for PathBuilder {
|
|||
PathOp::MoveTo(point) | PathOp::LineTo(point) => Some(Point2D::new(point.x, point.y)),
|
||||
PathOp::CubicTo(_, _, point) => Some(Point2D::new(point.x, point.y)),
|
||||
PathOp::QuadTo(_, point) => Some(Point2D::new(point.x, point.y)),
|
||||
PathOp::Close => None,
|
||||
PathOp::Close => path.ops.first().and_then(get_first_point),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -733,6 +733,15 @@ impl GenericPathBuilder<RaqoteBackend> for PathBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_first_point(op: &PathOp) -> Option<euclid::Point2D<f32, euclid::UnknownUnit>> {
|
||||
match op {
|
||||
PathOp::MoveTo(point) | PathOp::LineTo(point) => Some(Point2D::new(point.x, point.y)),
|
||||
PathOp::CubicTo(point, _, _) => Some(Point2D::new(point.x, point.y)),
|
||||
PathOp::QuadTo(point, _) => Some(Point2D::new(point.x, point.y)),
|
||||
PathOp::Close => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToRaqoteStyle {
|
||||
type Target;
|
||||
|
||||
|
|
|
@ -37,9 +37,6 @@
|
|||
[corner-shape-render-precise.html?corner-top-left-shape=bevel&border-width=10px&border-color=black]
|
||||
expected: FAIL
|
||||
|
||||
[corner-shape-render-precise.html?corner-bottom-right-shape=bevel&corner-bottom-left-shape=bevel]
|
||||
expected: FAIL
|
||||
|
||||
[corner-shape-render-precise.html?corner-shape=superellipse(8)&border-radius=10px&box-shadow=10px 10px 0 10px black]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -91,11 +88,5 @@
|
|||
[corner-shape-render-precise.html?corner-shape=superellipse(-2)&border-top-left-radius=40%&border-width=20px]
|
||||
expected: FAIL
|
||||
|
||||
[corner-shape-render-precise.html?corner-top-left-shape=bevel&border-width=10px]
|
||||
expected: FAIL
|
||||
|
||||
[corner-shape-render-precise.html?corner-shape=notch&border-radius=30px&border-width=30px]
|
||||
expected: FAIL
|
||||
|
||||
[corner-shape-render-precise.html?corner-top-right-shape=bevel&border-width=10px]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue