Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions core/src/avm2/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,15 @@ pub struct SystemClasses<'gc> {
pub workerdomain: ClassObject<'gc>,
pub messagechannel: ClassObject<'gc>,
pub securitydomain: ClassObject<'gc>,
pub graphicsbitmapfill: ClassObject<'gc>,
pub graphicsendfill: ClassObject<'gc>,
pub graphicsgradientfill: ClassObject<'gc>,
pub graphicspath: ClassObject<'gc>,
pub graphicstrianglepath: ClassObject<'gc>,
pub graphicssolidfill: ClassObject<'gc>,
pub graphicsshaderfill: ClassObject<'gc>,
pub graphicsstroke: ClassObject<'gc>,

}

#[derive(Clone, Collect)]
Expand Down Expand Up @@ -357,6 +366,14 @@ impl<'gc> SystemClasses<'gc> {
workerdomain: object,
messagechannel: object,
securitydomain: object,
graphicsbitmapfill: object,
graphicsendfill: object,
graphicsgradientfill: object,
graphicspath: object,
graphicstrianglepath: object,
graphicssolidfill: object,
graphicsshaderfill: object,
graphicsstroke: object,
}
}
}
Expand Down Expand Up @@ -685,6 +702,21 @@ pub fn init_native_system_classes(activation: &mut Activation<'_, '_>) {
("flash.display", "Scene", scene),
("flash.display", "FrameLabel", framelabel),
("flash.display", "Graphics", graphics),
("flash.display", "GraphicsBitmapFill", graphicsbitmapfill),
("flash.display", "GraphicsEndFill", graphicsendfill),
(
"flash.display",
"GraphicsGradientFill",
graphicsgradientfill
),
("flash.display", "GraphicsPath", graphicspath),
(
"flash.display",
"GraphicsTrianglePath",
graphicstrianglepath
),
("flash.display", "GraphicsSolidFill", graphicssolidfill),
("flash.display", "GraphicsStroke", graphicsstroke),
("flash.display", "Loader", loader),
("flash.display", "LoaderInfo", loaderinfo),
("flash.display", "MorphShape", morphshape),
Expand Down
161 changes: 156 additions & 5 deletions core/src/avm2/globals/flash/display/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
use crate::avm2::{ArrayStorage, Error};
use crate::avm2_stub_method;
use crate::display_object::TDisplayObject;
use crate::drawing::Drawing;
use crate::prelude::TDisplayObjectContainer;
use crate::drawing::{Drawing, DrawingFill, DrawingPath};
use crate::string::{AvmString, WStr};
use ruffle_render::shape_utils::{DrawCommand, FillRule, GradientType};
use std::f64::consts::FRAC_1_SQRT_2;
Expand Down Expand Up @@ -1347,13 +1348,163 @@
/// Implements `Graphics.readGraphicsData`
pub fn read_graphics_data<'gc>(
activation: &mut Activation<'_, 'gc>,
_this: Value<'gc>,
_args: &[Value<'gc>],
this: Value<'gc>,
args: &[Value<'gc>],

Check warning on line 1352 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1351–1352)
) -> Result<Value<'gc>, Error<'gc>> {
avm2_stub_method!(activation, "flash.display.Graphics", "readGraphicsData");
let recurse = args.get_bool(0);
let this = this.as_object().unwrap();

Check warning on line 1356 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1355–1356)

let mut drawings: Vec<Drawing> = Vec::new();
let mut result = Vec::new();

Check warning on line 1359 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1358–1359)

if let Some(this) = this.as_display_object() {

Check warning on line 1361 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered line (1361)

if let Some(draw) = this.as_drawing() {
drawings.push(draw.clone());
}

Check warning on line 1365 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1363–1365)

if recurse {
if let Some(container) = this.as_container() {
for child in container.iter_render_list() {
if let Some(draw) = child.as_drawing() {
drawings.push(draw.clone());
}

Check warning on line 1372 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1367–1372)
}
}
}

Check warning on line 1375 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1374–1375)

for draw in drawings {
for path in draw.paths() {
match path {

Check warning on line 1379 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1377–1379)
DrawingPath::Fill(DrawingFill {
style, commands, ..

Check warning on line 1381 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered line (1381)
}) => {
match style {
FillStyle::Color(color) => {
let color_value = Value::Integer(color.to_rgb() as i32);
let alpha_value = Value::Number(255.0 / (color.a as f64));

Check warning on line 1386 in core/src/avm2/globals/flash/display/graphics.rs

View workflow job for this annotation

GitHub Actions / Coverage Report

Coverage

Uncovered lines (1383–1386)


result.push(
activation
.avm2()
.classes()
.graphicssolidfill
.construct(activation, &[color_value, alpha_value])?,
);
}
FillStyle::Bitmap {
id: _,
matrix,
is_smoothed:_, // According to the docs this value is hardcoded in return
is_repeating:_, // According to the docs this value is hardcoded in return
} => {

// TODO
//let bitmap = draw.bitmaps().get(*id as usize);
let args = [
Value::Number(matrix.a.into()),
Value::Number(matrix.b.into()),
Value::Number(matrix.c.into()),
Value::Number(matrix.d.into()),
Value::Number(matrix.tx.to_pixels().into()),
Value::Number(matrix.ty.to_pixels().into()),
];
let matrix = activation
.avm2()
.classes()
.matrix
.construct(activation, &args)?;

result.push(
activation
.avm2()
.classes()
.graphicsbitmapfill
.construct(activation, &[Value::Undefined, matrix.into(), Value::Bool(true), Value::Bool(false)])?,
);
}
_ => println!("unsupported style {style:?}"),
};


let mut path_commands = Vec::new();
let mut path_data = Vec::new();


let mut add_point = |p: &Point<Twips>| {
let x = p.x.to_pixels();
let y = p.y.to_pixels();
path_data.push(x);
path_data.push(y);
};


for command in commands {
match command {
DrawCommand::MoveTo(point) => {
path_commands.push(1 /* MOVE_TO */);
add_point(&point);
}
DrawCommand::LineTo(point) => {
path_commands.push(2 /* LINE_TO */);
add_point(&point);
}
DrawCommand::QuadraticCurveTo { control, anchor } => {
path_commands.push(3 /* CURVE_TO */);
add_point(&control);
add_point(&anchor);
}
_ => println!("unsupported command {command:?}"),
}
}


let commands_storage = VectorStorage::from_values(
path_commands.into_iter().map(|v| v.into()).collect(),
true,
Some(activation.avm2().class_defs().int),
);
let commands_vector = VectorObject::from_vector(commands_storage, activation);


let data_storage = VectorStorage::from_values(
path_data.into_iter().map(|v| v.into()).collect(),
true,
Some(activation.avm2().class_defs().number),
);
let data_vector = VectorObject::from_vector(data_storage, activation);


result.push(
activation
.avm2()
.classes()
.graphicspath
.construct(activation, &[commands_vector.into(), data_vector.into()])?,
);


// Only do this at the end?
result.push(
activation
.avm2()
.classes()
.graphicsendfill
.construct(activation, &[])?,
);
}
_ => println!("unsupported path: {path:?}"),
}
}
}
}


let value_type = activation.avm2().class_defs().igraphicsdata;
let new_storage = VectorStorage::new(0, false, Some(value_type));
Ok(VectorObject::from_vector(new_storage, activation).into())
let storage = VectorStorage::from_values(result, false, Some(value_type));
Ok(VectorObject::from_vector(storage, activation).into())
}

fn read_point<'gc>(
Expand Down
2 changes: 1 addition & 1 deletion core/src/display_object/graphic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl<'gc> Graphic<'gc> {
}

pub fn drawing_mut(&self) -> RefMut<'_, Drawing> {
self.0.drawing.get_or_init(Default::default).borrow_mut()
self.0.drawing.get_or_init(||Box::new(RefCell::new(Drawing::from_swf_shape(&self.0.shared.get().shape)))).borrow_mut()
}

pub fn set_avm2_class(self, mc: &Mutation<'gc>, class: Avm2ClassObject<'gc>) {
Expand Down
22 changes: 13 additions & 9 deletions core/src/drawing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ impl Drawing {
}
}
}

pub fn paths(&self) -> &[DrawingPath] {
return self.paths.as_slice();
}
}

impl BitmapSource for Drawing {
Expand All @@ -430,21 +434,21 @@ impl BitmapSource for Drawing {
}

#[derive(Debug, Clone)]
struct DrawingFill {
style: FillStyle,
rule: FillRule,
commands: Vec<DrawCommand>,
pub struct DrawingFill {
pub style: FillStyle,
pub rule: FillRule,
pub commands: Vec<DrawCommand>,
}

#[derive(Debug, Clone)]
struct DrawingLine {
style: LineStyle,
commands: Vec<DrawCommand>,
is_closed: bool,
pub struct DrawingLine {
pub style: LineStyle,
pub commands: Vec<DrawCommand>,
pub is_closed: bool,
}

#[derive(Debug, Clone)]
enum DrawingPath {
pub enum DrawingPath {
Fill(DrawingFill),
Line(DrawingLine),
}
Expand Down
Loading