Skip to content

Commit

Permalink
core: Use actual bounding box of curves instead of an approximation
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinnerbone committed Jul 19, 2023
1 parent 00ea618 commit b8081ac
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 11 deletions.
62 changes: 53 additions & 9 deletions core/src/drawing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,15 @@ impl Drawing {
if self.fill_start == self.cursor {
// If this is the initial command after a move, include the starting point.
let command = DrawCommand::MoveTo(self.cursor);
self.shape_bounds = stretch_bounds(&self.shape_bounds, &command, stroke_width);
self.edge_bounds = stretch_bounds(&self.edge_bounds, &command, Twips::ZERO);
self.shape_bounds =
stretch_bounds(&self.shape_bounds, &command, stroke_width, self.cursor);
self.edge_bounds =
stretch_bounds(&self.edge_bounds, &command, Twips::ZERO, self.cursor);
}
self.shape_bounds = stretch_bounds(&self.shape_bounds, &command, stroke_width);
self.edge_bounds = stretch_bounds(&self.edge_bounds, &command, Twips::ZERO);
self.shape_bounds =
stretch_bounds(&self.shape_bounds, &command, stroke_width, self.cursor);
self.edge_bounds =
stretch_bounds(&self.edge_bounds, &command, Twips::ZERO, self.cursor);
}

self.cursor = command.end_point();
Expand Down Expand Up @@ -441,17 +445,57 @@ fn stretch_bounds(
bounds: &Rectangle<Twips>,
command: &DrawCommand,
stroke_width: Twips,
from: Point<Twips>,
) -> Rectangle<Twips> {
let radius = stroke_width / 2;
let bounds = bounds.clone();
match *command {
DrawCommand::MoveTo(point) | DrawCommand::LineTo(point) => bounds
.encompass(Point::new(point.x - radius, point.y - radius))
.encompass(Point::new(point.x + radius, point.y + radius)),
DrawCommand::CurveTo { control, anchor } => bounds
.encompass(Point::new(control.x - radius, control.y - radius))
.encompass(Point::new(control.x + radius, control.y + radius))
.encompass(Point::new(anchor.x - radius, anchor.y - radius))
.encompass(Point::new(anchor.x + radius, anchor.y + radius)),
DrawCommand::CurveTo { control, anchor } => {
// extremes
let from_x = from.x.to_pixels();
let from_y = from.y.to_pixels();
let anchor_x = anchor.x.to_pixels();
let anchor_y = anchor.y.to_pixels();
let control_x = control.x.to_pixels();
let control_y = control.y.to_pixels();

let mut min_x = from_x.min(anchor_x);
let mut min_y = from_y.min(anchor_y);
let mut max_x = from_x.max(anchor_x);
let mut max_y = from_y.max(anchor_y);

if control_x < min_x || control_x > max_x {
let t_x = ((from_x - control_x) / (from_x - (control_x * 2.0) + anchor_x))
.clamp(0.0, 1.0);
let s_x = 1.0 - t_x;
let q_x = s_x * s_x * from_x + (s_x * 2.0) * t_x * control_x + t_x * t_x * anchor_x;

min_x = min_x.min(q_x);
max_x = max_x.max(q_x);
}

if control_y < min_y || control_y > max_y {
let t_y = ((from_y - control_y) / (from_y - (control_y * 2.0) + anchor_y))
.clamp(0.0, 1.0);
let s_y = 1.0 - t_y;
let q_y = s_y * s_y * from_y + (s_y * 2.0) * t_y * control_y + t_y * t_y * anchor_y;

min_y = min_y.min(q_y);
max_y = max_y.max(q_y);
}

bounds
.encompass(Point::new(
Twips::from_pixels(min_x) - radius,
Twips::from_pixels(min_y) - radius,
))
.encompass(Point::new(
Twips::from_pixels(max_x) + radius,
Twips::from_pixels(max_y) + radius,
))
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions tests/tests/swfs/avm2/displayobject_getbounds_shape/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
num_frames = 1

[image_comparison]
tolerance = 0

[player_options]
with_renderer = { optional = false, sample_count = 1 }
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# Test adapted from Shumway at https://github.com/mozilla/shumway/tree/master/test/swfs/acid

num_frames = 1
ignore = true # https://github.com/ruffle-rs/ruffle/issues/12117

[image_comparison]
tolerance = 0
tolerance = 3

[player_options]
with_renderer = { optional = false, sample_count = 1 }

0 comments on commit b8081ac

Please sign in to comment.