render: Add DrawCommand::CubicCurveTo
This commit is contained in:
parent
076977cc75
commit
eb2afb19c4
|
@ -3972,6 +3972,7 @@ dependencies = [
|
|||
"jpeg-decoder",
|
||||
"lru",
|
||||
"lyon",
|
||||
"lyon_geom",
|
||||
"num-derive 0.4.0",
|
||||
"num-traits",
|
||||
"png",
|
||||
|
|
|
@ -3,7 +3,7 @@ use ruffle_render::backend::{RenderBackend, ShapeHandle};
|
|||
use ruffle_render::bitmap::{BitmapHandle, BitmapInfo, BitmapSize, BitmapSource};
|
||||
use ruffle_render::commands::CommandHandler;
|
||||
use ruffle_render::shape_utils::{
|
||||
quadratic_curve_bounds, DistilledShape, DrawCommand, DrawPath, FillRule,
|
||||
cubic_curve_bounds, quadratic_curve_bounds, DistilledShape, DrawCommand, DrawPath, FillRule,
|
||||
};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use swf::{FillStyle, LineStyle, Point, Rectangle, Twips};
|
||||
|
@ -458,5 +458,16 @@ fn stretch_bounds(
|
|||
DrawCommand::QuadraticCurveTo { control, anchor } => {
|
||||
bounds.union(&quadratic_curve_bounds(from, stroke_width, control, anchor))
|
||||
}
|
||||
DrawCommand::CubicCurveTo {
|
||||
control_a,
|
||||
control_b,
|
||||
anchor,
|
||||
} => bounds.union(&cubic_curve_bounds(
|
||||
from,
|
||||
stroke_width,
|
||||
control_a,
|
||||
control_b,
|
||||
anchor,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ flate2 = "1.0.27"
|
|||
smallvec = { version = "1.11.0", features = ["union"] }
|
||||
downcast-rs = "1.2.0"
|
||||
lyon = { version = "1.0.1", optional = true }
|
||||
lyon_geom = "1.0.1"
|
||||
thiserror = "1.0"
|
||||
wasm-bindgen = { version = "=0.2.87", optional = true }
|
||||
enum-map = "2.6.1"
|
||||
|
|
|
@ -830,6 +830,18 @@ fn draw_commands_to_path2d(commands: &[DrawCommand], is_closed: bool) -> Path2d
|
|||
anchor.x.get().into(),
|
||||
anchor.y.get().into(),
|
||||
),
|
||||
DrawCommand::CubicCurveTo {
|
||||
control_a,
|
||||
control_b,
|
||||
anchor,
|
||||
} => path.bezier_curve_to(
|
||||
control_a.x.get().into(),
|
||||
control_a.y.get().into(),
|
||||
control_b.x.get().into(),
|
||||
control_b.y.get().into(),
|
||||
anchor.x.get().into(),
|
||||
anchor.y.get().into(),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,11 @@ pub enum DrawCommand {
|
|||
control: swf::Point<Twips>,
|
||||
anchor: swf::Point<Twips>,
|
||||
},
|
||||
CubicCurveTo {
|
||||
control_a: swf::Point<Twips>,
|
||||
control_b: swf::Point<Twips>,
|
||||
anchor: swf::Point<Twips>,
|
||||
},
|
||||
}
|
||||
|
||||
impl DrawCommand {
|
||||
|
@ -130,7 +135,8 @@ impl DrawCommand {
|
|||
match self {
|
||||
DrawCommand::MoveTo(point)
|
||||
| DrawCommand::LineTo(point)
|
||||
| DrawCommand::QuadraticCurveTo { anchor: point, .. } => *point,
|
||||
| DrawCommand::QuadraticCurveTo { anchor: point, .. }
|
||||
| DrawCommand::CubicCurveTo { anchor: point, .. } => *point,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -680,6 +686,27 @@ pub fn draw_command_fill_hit_test(commands: &[DrawCommand], test_point: swf::Poi
|
|||
winding += winding_number_curve(test_point, cursor, *control, *anchor);
|
||||
cursor = *anchor;
|
||||
}
|
||||
DrawCommand::CubicCurveTo {
|
||||
control_a,
|
||||
control_b,
|
||||
anchor,
|
||||
} => {
|
||||
lyon_geom::CubicBezierSegment {
|
||||
from: lyon_geom::Point::new(cursor.x.to_pixels(), cursor.y.to_pixels()),
|
||||
ctrl1: lyon_geom::Point::new(control_a.x.to_pixels(), control_a.y.to_pixels()),
|
||||
ctrl2: lyon_geom::Point::new(control_b.x.to_pixels(), control_b.y.to_pixels()),
|
||||
to: lyon_geom::Point::new(anchor.x.to_pixels(), anchor.y.to_pixels()),
|
||||
}
|
||||
.for_each_quadratic_bezier(0.01, &mut |quadratic_curve| {
|
||||
winding += winding_number_curve(
|
||||
test_point,
|
||||
swf::Point::from_pixels(quadratic_curve.from.x, quadratic_curve.from.y),
|
||||
swf::Point::from_pixels(quadratic_curve.ctrl.x, quadratic_curve.ctrl.y),
|
||||
swf::Point::from_pixels(quadratic_curve.to.x, quadratic_curve.to.y),
|
||||
);
|
||||
});
|
||||
cursor = *anchor;
|
||||
}
|
||||
}
|
||||
}
|
||||
if cursor != fill_start {
|
||||
|
@ -719,6 +746,35 @@ pub fn draw_command_stroke_hit_test(
|
|||
}
|
||||
cursor = *anchor;
|
||||
}
|
||||
DrawCommand::CubicCurveTo {
|
||||
control_a,
|
||||
control_b,
|
||||
anchor,
|
||||
} => {
|
||||
let mut hit = false;
|
||||
lyon_geom::CubicBezierSegment {
|
||||
from: lyon_geom::Point::new(cursor.x.to_pixels(), cursor.y.to_pixels()),
|
||||
ctrl1: lyon_geom::Point::new(control_a.x.to_pixels(), control_a.y.to_pixels()),
|
||||
ctrl2: lyon_geom::Point::new(control_b.x.to_pixels(), control_b.y.to_pixels()),
|
||||
to: lyon_geom::Point::new(anchor.x.to_pixels(), anchor.y.to_pixels()),
|
||||
}
|
||||
.for_each_quadratic_bezier(0.01, &mut |quadratic_curve| {
|
||||
if hit_test_stroke_curve(
|
||||
test_point,
|
||||
swf::Point::from_pixels(quadratic_curve.from.x, quadratic_curve.from.y),
|
||||
swf::Point::from_pixels(quadratic_curve.ctrl.x, quadratic_curve.ctrl.y),
|
||||
swf::Point::from_pixels(quadratic_curve.to.x, quadratic_curve.to.y),
|
||||
stroke_widths,
|
||||
) {
|
||||
hit = true;
|
||||
}
|
||||
});
|
||||
cursor = *anchor;
|
||||
|
||||
if hit {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1222,6 +1278,31 @@ pub fn quadratic_curve_bounds(
|
|||
))
|
||||
}
|
||||
|
||||
pub fn cubic_curve_bounds(
|
||||
start: swf::Point<Twips>,
|
||||
stroke_width: Twips,
|
||||
control_a: swf::Point<Twips>,
|
||||
control_b: swf::Point<Twips>,
|
||||
anchor: swf::Point<Twips>,
|
||||
) -> Rectangle<Twips> {
|
||||
// [NA] Should we just move most of our math in this file to lyon_geom?
|
||||
let bounds = lyon_geom::CubicBezierSegment {
|
||||
from: lyon_geom::Point::new(start.x.to_pixels(), start.y.to_pixels()),
|
||||
ctrl1: lyon_geom::Point::new(control_a.x.to_pixels(), control_a.y.to_pixels()),
|
||||
ctrl2: lyon_geom::Point::new(control_b.x.to_pixels(), control_b.y.to_pixels()),
|
||||
to: lyon_geom::Point::new(anchor.x.to_pixels(), anchor.y.to_pixels()),
|
||||
}
|
||||
.bounding_box();
|
||||
|
||||
let radius = stroke_width / 2;
|
||||
Rectangle {
|
||||
x_min: Twips::from_pixels(bounds.min.x) - radius,
|
||||
x_max: Twips::from_pixels(bounds.max.x) + radius,
|
||||
y_min: Twips::from_pixels(bounds.min.y) - radius,
|
||||
y_max: Twips::from_pixels(bounds.max.y) + radius,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -353,6 +353,16 @@ fn ruffle_path_to_lyon_path(commands: &[DrawCommand], is_closed: bool) -> Path {
|
|||
}
|
||||
builder.quadratic_bezier_to(point(*control), point(*anchor));
|
||||
}
|
||||
DrawCommand::CubicCurveTo {
|
||||
control_a,
|
||||
control_b,
|
||||
anchor,
|
||||
} => {
|
||||
if let Some(cursor) = cursor.take() {
|
||||
builder.begin(point(cursor));
|
||||
}
|
||||
builder.cubic_bezier_to(point(*control_a), point(*control_b), point(*anchor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue