Skip to content

Commit

Permalink
avm2: Implement Graphics.cubicCurveTo and CUBIC_CURVE_TO
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinnerbone committed Aug 27, 2023
1 parent eb2afb1 commit 19ad492
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 34 deletions.
38 changes: 24 additions & 14 deletions core/src/avm2/globals/flash/display/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,10 +809,26 @@ pub fn line_gradient_style<'gc>(
/// Implements `Graphics.cubicCurveTo`
pub fn cubic_curve_to<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Object<'gc>,
_args: &[Value<'gc>],
this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
avm2_stub_method!(activation, "flash.display.Graphics", "cubicCurveTo");
if let Some(this) = this.as_display_object() {
let control_a_x = args.get_f64(activation, 0)?;
let control_a_y = args.get_f64(activation, 1)?;
let control_b_x = args.get_f64(activation, 2)?;
let control_b_y = args.get_f64(activation, 3)?;
let anchor_x = args.get_f64(activation, 4)?;
let anchor_y = args.get_f64(activation, 5)?;

if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.draw_command(DrawCommand::CubicCurveTo {
control_a: Point::from_pixels(control_a_x, control_a_y),
control_b: Point::from_pixels(control_b_x, control_b_y),
anchor: Point::from_pixels(anchor_x, anchor_y),
});
}
}

Ok(Value::Undefined)
}

Expand Down Expand Up @@ -1194,17 +1210,11 @@ fn process_commands<'gc>(
Some(DrawCommand::LineTo(read_point()))
}
// CUBIC_CURVE_TO
6 => {
let _first = read_point();
let _second = read_point();
avm2_stub_method!(
activation,
"flash.display.Graphics",
"drawPath",
"CUBIC_CURVE_TO"
);
None
}
6 => Some(DrawCommand::CubicCurveTo {
control_a: read_point(),
control_b: read_point(),
anchor: read_point(),
}),
_ => panic!("Unexpected command value {command}"),
};

Expand Down
55 changes: 36 additions & 19 deletions render/src/shape_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use enum_map::Enum;
use smallvec::SmallVec;
use swf::{CharacterId, FillStyle, LineStyle, Rectangle, Shape, ShapeRecord, Twips};

/// Controls the accuracy of the approximated quadratic curve, when splitting up a cubic curve
const CUBIC_CURVE_TOLERANCE: f64 = 0.01;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum FillRule {
EvenOdd,
Expand Down Expand Up @@ -697,14 +700,17 @@ pub fn draw_command_fill_hit_test(commands: &[DrawCommand], test_point: swf::Poi
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),
);
});
.for_each_quadratic_bezier(
CUBIC_CURVE_TOLERANCE,
&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;
}
}
Expand Down Expand Up @@ -758,17 +764,28 @@ pub fn draw_command_stroke_hit_test(
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;
}
});
.for_each_quadratic_bezier(
CUBIC_CURVE_TOLERANCE,
&mut |quadratic_curve| {
if !hit
&& 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 {
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/swfs/avm2/graphics_direct_commands/Test.as
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
public function Test() {
trapezoid();
dashes();
// cubicCircle(); // currently broken in ruffle at time of writing
cubicCircle();
curveCircle();
drawPath();
}
Expand Down
Binary file modified tests/tests/swfs/avm2/graphics_direct_commands/output.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/tests/swfs/avm2/graphics_direct_commands/test.swf
Binary file not shown.

0 comments on commit 19ad492

Please sign in to comment.