mirror of
https://github.com/servo/servo.git
synced 2025-07-19 13:23:46 +01:00
canvas: Move current_default_path to script CanvasState (#38114)
This PR moves current path handling from canvas paint thread to script's `CanvasState`. Because we used manual impl for arcto and some prechecks for early fail before sending IPC we also needed to fix some bugs in Path impl. Testing: Existing WPT tests work towards #38022 try run: https://github.com/sagudev/servo/actions/runs/16316090028 Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
parent
bbed6cddcd
commit
a070f24450
4 changed files with 82 additions and 594 deletions
|
@ -175,6 +175,9 @@ pub(crate) struct CanvasState {
|
|||
#[no_trace]
|
||||
missing_image_urls: DomRefCell<Vec<ServoUrl>>,
|
||||
saved_states: DomRefCell<Vec<CanvasContextState>>,
|
||||
/// <https://html.spec.whatwg.org/multipage/#current-default-path>
|
||||
#[no_trace]
|
||||
current_default_path: DomRefCell<Path>,
|
||||
}
|
||||
|
||||
impl CanvasState {
|
||||
|
@ -212,6 +215,7 @@ impl CanvasState {
|
|||
saved_states: DomRefCell::new(Vec::new()),
|
||||
image_key,
|
||||
origin,
|
||||
current_default_path: DomRefCell::new(Path::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,6 +292,7 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
pub(crate) fn reset_to_initial_state(&self) {
|
||||
*self.current_default_path.borrow_mut() = Path::new();
|
||||
self.saved_states.borrow_mut().clear();
|
||||
*self.state.borrow_mut() = CanvasContextState::new();
|
||||
}
|
||||
|
@ -941,8 +946,18 @@ impl CanvasState {
|
|||
(source_rect, dest_rect)
|
||||
}
|
||||
|
||||
fn update_transform(&self) {
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(self.state.borrow().transform))
|
||||
fn update_transform(&self, transform: Transform2D<f32>) {
|
||||
let mut state = self.state.borrow_mut();
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.transform(state.transform.cast());
|
||||
state.transform = transform;
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::SetTransform(state.transform));
|
||||
if let Some(inverse) = transform.inverse() {
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.transform(inverse.cast());
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect
|
||||
|
@ -1830,14 +1845,13 @@ impl CanvasState {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath
|
||||
pub(crate) fn begin_path(&self) {
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::BeginPath);
|
||||
*self.current_default_path.borrow_mut() = Path::new();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
|
||||
pub(crate) fn fill(&self, _fill_rule: CanvasFillRule) {
|
||||
// TODO: Process fill rule
|
||||
let style = self.state.borrow().fill_style.to_fill_or_stroke_style();
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::Fill(style));
|
||||
pub(crate) fn fill(&self, fill_rule: CanvasFillRule) {
|
||||
let path = self.current_default_path.borrow().clone();
|
||||
self.fill_(path, fill_rule);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
|
||||
|
@ -1849,8 +1863,8 @@ impl CanvasState {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke
|
||||
pub(crate) fn stroke(&self) {
|
||||
let style = self.state.borrow().stroke_style.to_fill_or_stroke_style();
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::Stroke(style));
|
||||
let path = self.current_default_path.borrow().clone();
|
||||
self.stroke_(path);
|
||||
}
|
||||
|
||||
pub(crate) fn stroke_(&self, path: Path) {
|
||||
|
@ -1859,9 +1873,9 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
|
||||
pub(crate) fn clip(&self, _fill_rule: CanvasFillRule) {
|
||||
// TODO: Process fill rule
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::Clip);
|
||||
pub(crate) fn clip(&self, fill_rule: CanvasFillRule) {
|
||||
let path = self.current_default_path.borrow().clone();
|
||||
self.clip_(path, fill_rule);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
|
||||
|
@ -1878,18 +1892,9 @@ impl CanvasState {
|
|||
y: f64,
|
||||
fill_rule: CanvasFillRule,
|
||||
) -> bool {
|
||||
if !(x.is_finite() && y.is_finite()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let fill_rule = match fill_rule {
|
||||
CanvasFillRule::Nonzero => FillRule::Nonzero,
|
||||
CanvasFillRule::Evenodd => FillRule::Evenodd,
|
||||
};
|
||||
let (sender, receiver) =
|
||||
profiled_ipc::channel::<bool>(global.time_profiler_chan().clone()).unwrap();
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::IsPointInCurrentPath(x, y, fill_rule, sender));
|
||||
receiver.recv().unwrap()
|
||||
let mut path = self.current_default_path.borrow().clone();
|
||||
path.transform(self.state.borrow().transform.cast());
|
||||
self.is_point_in_path_(global, path, x, y, fill_rule)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-ispointinpath
|
||||
|
@ -1915,8 +1920,7 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
let transform = self.state.borrow().transform;
|
||||
self.state.borrow_mut().transform = transform.pre_scale(x as f32, y as f32);
|
||||
self.update_transform()
|
||||
self.update_transform(transform.pre_scale(x as f32, y as f32))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate
|
||||
|
@ -1927,10 +1931,10 @@ impl CanvasState {
|
|||
|
||||
let (sin, cos) = (angle.sin(), angle.cos());
|
||||
let transform = self.state.borrow().transform;
|
||||
self.state.borrow_mut().transform =
|
||||
self.update_transform(
|
||||
Transform2D::new(cos as f32, sin as f32, -sin as f32, cos as f32, 0.0, 0.0)
|
||||
.then(&transform);
|
||||
self.update_transform()
|
||||
.then(&transform),
|
||||
)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-translate
|
||||
|
@ -1940,8 +1944,7 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
let transform = self.state.borrow().transform;
|
||||
self.state.borrow_mut().transform = transform.pre_translate(vec2(x as f32, y as f32));
|
||||
self.update_transform()
|
||||
self.update_transform(transform.pre_translate(vec2(x as f32, y as f32)))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-transform
|
||||
|
@ -1957,10 +1960,10 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
let transform = self.state.borrow().transform;
|
||||
self.state.borrow_mut().transform =
|
||||
self.update_transform(
|
||||
Transform2D::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32)
|
||||
.then(&transform);
|
||||
self.update_transform()
|
||||
.then(&transform),
|
||||
)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-gettransform
|
||||
|
@ -1983,9 +1986,9 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
// Step 2. Reset the current transformation matrix to the matrix described by:
|
||||
self.state.borrow_mut().transform =
|
||||
Transform2D::new(a as f32, b as f32, c as f32, d as f32, e as f32, f as f32);
|
||||
self.update_transform()
|
||||
self.update_transform(Transform2D::new(
|
||||
a as f32, b as f32, c as f32, d as f32, e as f32, f as f32,
|
||||
))
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform-matrix>
|
||||
|
@ -2008,58 +2011,42 @@ impl CanvasState {
|
|||
}
|
||||
|
||||
// Step 3. Reset the current transformation matrix to matrix.
|
||||
self.state.borrow_mut().transform = matrix.cast();
|
||||
self.update_transform();
|
||||
self.update_transform(matrix.cast());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform
|
||||
pub(crate) fn reset_transform(&self) {
|
||||
self.state.borrow_mut().transform = Transform2D::identity();
|
||||
self.update_transform()
|
||||
self.update_transform(Transform2D::identity())
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath
|
||||
pub(crate) fn close_path(&self) {
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::ClosePath);
|
||||
self.current_default_path.borrow_mut().close_path();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto
|
||||
pub(crate) fn move_to(&self, x: f64, y: f64) {
|
||||
if !(x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
}
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::MoveTo(Point2D::new(x as f32, y as f32)));
|
||||
self.current_default_path.borrow_mut().move_to(x, y);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto
|
||||
pub(crate) fn line_to(&self, x: f64, y: f64) {
|
||||
if !(x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
}
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::LineTo(Point2D::new(x as f32, y as f32)));
|
||||
self.current_default_path.borrow_mut().line_to(x, y);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rect
|
||||
pub(crate) fn rect(&self, x: f64, y: f64, width: f64, height: f64) {
|
||||
if [x, y, width, height].iter().all(|val| val.is_finite()) {
|
||||
let rect = Rect::new(
|
||||
Point2D::new(x as f32, y as f32),
|
||||
Size2D::new(width as f32, height as f32),
|
||||
);
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::Rect(rect));
|
||||
}
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.rect(x, y, width, height);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto
|
||||
pub(crate) fn quadratic_curve_to(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
|
||||
if !(cpx.is_finite() && cpy.is_finite() && x.is_finite() && y.is_finite()) {
|
||||
return;
|
||||
}
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::QuadraticCurveTo(
|
||||
Point2D::new(cpx as f32, cpy as f32),
|
||||
Point2D::new(x as f32, y as f32),
|
||||
));
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.quadratic_curve_to(cpx, cpy, x, y);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto
|
||||
|
@ -2072,20 +2059,9 @@ impl CanvasState {
|
|||
x: f64,
|
||||
y: f64,
|
||||
) {
|
||||
if !(cp1x.is_finite() &&
|
||||
cp1y.is_finite() &&
|
||||
cp2x.is_finite() &&
|
||||
cp2y.is_finite() &&
|
||||
x.is_finite() &&
|
||||
y.is_finite())
|
||||
{
|
||||
return;
|
||||
}
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::BezierCurveTo(
|
||||
Point2D::new(cp1x as f32, cp1y as f32),
|
||||
Point2D::new(cp2x as f32, cp2y as f32),
|
||||
Point2D::new(x as f32, y as f32),
|
||||
));
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
|
||||
|
@ -2098,39 +2074,18 @@ impl CanvasState {
|
|||
end: f64,
|
||||
ccw: bool,
|
||||
) -> ErrorResult {
|
||||
if !([x, y, r, start, end].iter().all(|x| x.is_finite())) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if r < 0.0 {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::Arc(
|
||||
Point2D::new(x as f32, y as f32),
|
||||
r as f32,
|
||||
start as f32,
|
||||
end as f32,
|
||||
ccw,
|
||||
));
|
||||
Ok(())
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.arc(x, y, r, start, end, ccw)
|
||||
.map_err(|_| Error::IndexSize)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto
|
||||
pub(crate) fn arc_to(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> ErrorResult {
|
||||
if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) {
|
||||
return Ok(());
|
||||
}
|
||||
if r < 0.0 {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::ArcTo(
|
||||
Point2D::new(cp1x as f32, cp1y as f32),
|
||||
Point2D::new(cp2x as f32, cp2y as f32),
|
||||
r as f32,
|
||||
));
|
||||
Ok(())
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.arc_to(cp1x, cp1y, cp2x, cp2y, r)
|
||||
.map_err(|_| Error::IndexSize)
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-context-2d-ellipse>
|
||||
|
@ -2146,26 +2101,10 @@ impl CanvasState {
|
|||
end: f64,
|
||||
ccw: bool,
|
||||
) -> ErrorResult {
|
||||
if !([x, y, rx, ry, rotation, start, end]
|
||||
.iter()
|
||||
.all(|x| x.is_finite()))
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
if rx < 0.0 || ry < 0.0 {
|
||||
return Err(Error::IndexSize);
|
||||
}
|
||||
|
||||
self.send_canvas_2d_msg(Canvas2dMsg::Ellipse(
|
||||
Point2D::new(x as f32, y as f32),
|
||||
rx as f32,
|
||||
ry as f32,
|
||||
rotation as f32,
|
||||
start as f32,
|
||||
end as f32,
|
||||
ccw,
|
||||
));
|
||||
Ok(())
|
||||
self.current_default_path
|
||||
.borrow_mut()
|
||||
.ellipse(x, y, rx, ry, rotation, start, end, ccw)
|
||||
.map_err(|_| Error::IndexSize)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue