From eda862c7199d0c0f69213fdd00d53b34da75b72b Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Tue, 19 May 2020 18:50:37 +0200 Subject: [PATCH] swf: Merged core::Matrix into swf::Matrix --- Cargo.lock | 1 + core/src/avm1/globals/movie_clip.rs | 12 +- core/src/bounding_box.rs | 2 +- core/src/display_object.rs | 8 +- core/src/display_object/button.rs | 4 +- core/src/display_object/morph_shape.rs | 2 +- core/src/display_object/text.rs | 2 +- core/src/lib.rs | 1 - core/src/prelude.rs | 2 +- render/canvas/src/lib.rs | 13 +- render/common_tess/src/lib.rs | 48 ++++---- render/webgl/src/lib.rs | 2 +- render/wgpu/src/lib.rs | 10 +- render/wgpu/src/utils.rs | 36 +++--- swf/Cargo.toml | 3 + swf/src/read.rs | 32 ++--- swf/src/test_data.rs | 160 ++++++++++++------------- swf/src/types.rs | 33 +---- {core/src => swf/src/types}/matrix.rs | 46 +++---- swf/src/write.rs | 29 ++--- 20 files changed, 209 insertions(+), 237 deletions(-) rename {core/src => swf/src/types}/matrix.rs (98%) diff --git a/Cargo.lock b/Cargo.lock index 60a31b5db..dfb0311a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2172,6 +2172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "swf" version = "0.1.2" dependencies = [ + "approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "enumset 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index a59e8f9ed..d3cb8175e 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -305,12 +305,12 @@ fn begin_gradient_fill<'gc>( + height / 2.0; // TODO: This is wrong, doesn't account for rotations. Matrix { - translate_x: Twips::from_pixels(tx), - translate_y: Twips::from_pixels(ty), - scale_x: width as f32 / 1638.4, - scale_y: height as f32 / 1638.4, - rotate_skew_0: 0.0, - rotate_skew_1: 0.0, + tx: Twips::from_pixels(tx), + ty: Twips::from_pixels(ty), + a: width as f32 / 1638.4, + d: height as f32 / 1638.4, + b: 0.0, + c: 0.0, } } else { log::warn!( diff --git a/core/src/bounding_box.rs b/core/src/bounding_box.rs index fac8bbb12..1c4805158 100644 --- a/core/src/bounding_box.rs +++ b/core/src/bounding_box.rs @@ -1,4 +1,4 @@ -use crate::matrix::Matrix; +use swf::Matrix; use swf::Twips; #[derive(Clone, Debug, PartialEq)] diff --git a/core/src/display_object.rs b/core/src/display_object.rs index c6aac2db8..219a42f31 100644 --- a/core/src/display_object.rs +++ b/core/src/display_object.rs @@ -767,7 +767,7 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug + Into> // PlaceObject tags only apply if this onject has not been dynamically moved by AS code. if !self.transformed_by_script() { if let Some(matrix) = &place_object.matrix { - self.set_matrix(gc_context, &matrix.clone().into()); + self.set_matrix(gc_context, &matrix); } if let Some(color_transform) = &place_object.color_transform { self.set_color_transform(gc_context, &color_transform.clone().into()); @@ -918,19 +918,19 @@ macro_rules! impl_display_object { fn transform(&self) -> std::cell::Ref { std::cell::Ref::map(self.0.read(), |o| o.$field.transform()) } - fn matrix(&self) -> std::cell::Ref { + fn matrix(&self) -> std::cell::Ref { std::cell::Ref::map(self.0.read(), |o| o.$field.matrix()) } fn matrix_mut( &mut self, context: gc_arena::MutationContext<'gc, '_>, - ) -> std::cell::RefMut { + ) -> std::cell::RefMut { std::cell::RefMut::map(self.0.write(context), |o| o.$field.matrix_mut(context)) } fn set_matrix( &mut self, context: gc_arena::MutationContext<'gc, '_>, - matrix: &crate::matrix::Matrix, + matrix: &swf::Matrix, ) { self.0.write(context).$field.set_matrix(context, matrix) } diff --git a/core/src/display_object/button.rs b/core/src/display_object/button.rs index 763444b55..20c071c22 100644 --- a/core/src/display_object/button.rs +++ b/core/src/display_object/button.rs @@ -247,7 +247,7 @@ impl<'gc> ButtonData<'gc> { .instantiate_by_id(record.id, context.gc_context) { child.set_parent(context.gc_context, Some(self_display_object)); - child.set_matrix(context.gc_context, &record.matrix.clone().into()); + child.set_matrix(context.gc_context, &record.matrix); child.set_color_transform( context.gc_context, &record.color_transform.clone().into(), @@ -280,7 +280,7 @@ impl<'gc> ButtonData<'gc> { { Ok(mut child) => { { - child.set_matrix(context.gc_context, &record.matrix.clone().into()); + child.set_matrix(context.gc_context, &record.matrix); child.set_parent(context.gc_context, Some(self_display_object)); child.set_depth(context.gc_context, record.depth.into()); child.post_instantiation(avm, context, child, None); diff --git a/core/src/display_object/morph_shape.rs b/core/src/display_object/morph_shape.rs index 5c4922af1..96fea938e 100644 --- a/core/src/display_object/morph_shape.rs +++ b/core/src/display_object/morph_shape.rs @@ -161,7 +161,7 @@ impl MorphShapeStatic { .collect(); FillStyle::LinearGradient(Gradient { - matrix: start.matrix.clone(), + matrix: start.matrix, spread: start.spread, interpolation: start.interpolation, records, diff --git a/core/src/display_object/text.rs b/core/src/display_object/text.rs index 08ec933a6..3f6d9ec67 100644 --- a/core/src/display_object/text.rs +++ b/core/src/display_object/text.rs @@ -33,7 +33,7 @@ impl<'gc> Text<'gc> { swf, id: tag.id, bounds: tag.bounds.clone().into(), - text_transform: tag.matrix.clone().into(), + text_transform: tag.matrix, text_blocks: tag.records.clone(), }, ), diff --git a/core/src/lib.rs b/core/src/lib.rs index 74df5807b..ed803113d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -18,7 +18,6 @@ pub mod events; mod font; mod library; mod loader; -pub mod matrix; mod player; mod prelude; mod property_map; diff --git a/core/src/prelude.rs b/core/src/prelude.rs index b55e8dc5e..09447c9b5 100644 --- a/core/src/prelude.rs +++ b/core/src/prelude.rs @@ -2,8 +2,8 @@ pub use crate::bounding_box::BoundingBox; pub use crate::color_transform::ColorTransform; pub use crate::display_object::{DisplayObject, TDisplayObject}; pub use crate::impl_display_object; -pub use crate::matrix::Matrix; pub use log::{error, info, trace, warn}; +pub use swf::Matrix; pub use swf::{CharacterId, Color, Twips}; /// A depth for a Flash display object in AVM1. diff --git a/render/canvas/src/lib.rs b/render/canvas/src/lib.rs index 5d3b78826..b12f6d172 100644 --- a/render/canvas/src/lib.rs +++ b/render/canvas/src/lib.rs @@ -743,8 +743,8 @@ fn swf_shape_to_svg( pixelated_property_value: &str, ) -> ShapeData { use fnv::FnvHashSet; - use ruffle_core::matrix::Matrix; use ruffle_core::shape_utils::DrawPath; + use ruffle_core::swf::Matrix; use svg::node::element::{ path::Data, Definitions, Image, LinearGradient, Path as SvgPath, Pattern, RadialGradient, Stop, @@ -802,7 +802,7 @@ fn swf_shape_to_svg( format!("rgba({},{},{},{})", r, g, b, f32::from(*a) / 255.0) } FillStyle::LinearGradient(gradient) => { - let matrix: Matrix = Matrix::from(gradient.matrix.clone()); + let matrix: Matrix = gradient.matrix; let shift = Matrix { a: 32768.0 / width, d: 32768.0 / height, @@ -849,7 +849,7 @@ fn swf_shape_to_svg( fill_id } FillStyle::RadialGradient(gradient) => { - let matrix = Matrix::from(gradient.matrix.clone()); + let matrix = gradient.matrix; let shift = Matrix { a: 32768.0, d: 32768.0, @@ -900,7 +900,7 @@ fn swf_shape_to_svg( gradient, focal_point, } => { - let matrix = Matrix::from(gradient.matrix.clone()); + let matrix = gradient.matrix; let shift = Matrix { a: 32768.0, d: 32768.0, @@ -990,7 +990,7 @@ fn swf_shape_to_svg( defs = defs.add(bitmap_pattern); bitmap_defs.insert(*id); } - let a = Matrix::from(matrix.clone()); + let a = *matrix; let bitmap_matrix = a; let svg_pattern = Pattern::new() @@ -1160,7 +1160,6 @@ fn swf_shape_to_canvas_commands( _pixelated_property_value: &str, context: &CanvasRenderingContext2d, ) -> Option { - use ruffle_core::matrix::Matrix; use ruffle_core::shape_utils::DrawPath; use swf::{FillStyle, LineCapStyle, LineJoinStyle}; @@ -1240,7 +1239,7 @@ fn swf_shape_to_canvas_commands( // when cached? (Issue #412) image.set_src(*bitmap_data); - let a = Matrix::from(matrix.clone()); + let a = *matrix; let matrix = matrix_factory.create_svg_matrix(); diff --git a/render/common_tess/src/lib.rs b/render/common_tess/src/lib.rs index bcde08420..0899efeee 100644 --- a/render/common_tess/src/lib.rs +++ b/render/common_tess/src/lib.rs @@ -99,7 +99,7 @@ impl ShapeTessellator { ratios, colors, num_colors: gradient.records.len() as u32, - matrix: swf_to_gl_matrix(gradient.matrix.clone()), + matrix: swf_to_gl_matrix(gradient.matrix), repeat_mode: gradient.spread, focal_point: 0.0, }; @@ -141,7 +141,7 @@ impl ShapeTessellator { ratios, colors, num_colors: gradient.records.len() as u32, - matrix: swf_to_gl_matrix(gradient.matrix.clone()), + matrix: swf_to_gl_matrix(gradient.matrix), repeat_mode: gradient.spread, focal_point: 0.0, }; @@ -186,7 +186,7 @@ impl ShapeTessellator { ratios, colors, num_colors: gradient.records.len() as u32, - matrix: swf_to_gl_matrix(gradient.matrix.clone()), + matrix: swf_to_gl_matrix(gradient.matrix), repeat_mode: gradient.spread, focal_point: *focal_point, }; @@ -220,11 +220,7 @@ impl ShapeTessellator { (get_bitmap_dimensions)(*id).unwrap_or((1, 1)); let bitmap = Bitmap { - matrix: swf_bitmap_to_gl_matrix( - matrix.clone(), - bitmap_width, - bitmap_height, - ), + matrix: swf_bitmap_to_gl_matrix(*matrix, bitmap_width, bitmap_height), id: *id, is_smoothed: *is_smoothed, is_repeating: *is_repeating, @@ -342,15 +338,15 @@ pub struct Bitmap { #[allow(clippy::many_single_char_names)] fn swf_to_gl_matrix(m: swf::Matrix) -> [[f32; 3]; 3] { - let tx = m.translate_x.get() as f32; - let ty = m.translate_y.get() as f32; - let det = m.scale_x * m.scale_y - m.rotate_skew_1 * m.rotate_skew_0; - let mut a = m.scale_y / det; - let mut b = -m.rotate_skew_1 / det; - let mut c = -(tx * m.scale_y - m.rotate_skew_1 * ty) / det; - let mut d = -m.rotate_skew_0 / det; - let mut e = m.scale_x / det; - let mut f = (tx * m.rotate_skew_0 - m.scale_x * ty) / det; + let tx = m.tx.get() as f32; + let ty = m.ty.get() as f32; + let det = m.a * m.d - m.c * m.b; + let mut a = m.d / det; + let mut b = -m.c / det; + let mut c = -(tx * m.d - m.c * ty) / det; + let mut d = -m.b / det; + let mut e = m.a / det; + let mut f = (tx * m.b - m.a * ty) / det; a *= 20.0 / 32768.0; b *= 20.0 / 32768.0; @@ -369,15 +365,15 @@ fn swf_bitmap_to_gl_matrix(m: swf::Matrix, bitmap_width: u32, bitmap_height: u32 let bitmap_width = bitmap_width as f32; let bitmap_height = bitmap_height as f32; - let tx = m.translate_x.get() as f32; - let ty = m.translate_y.get() as f32; - let det = m.scale_x * m.scale_y - m.rotate_skew_1 * m.rotate_skew_0; - let mut a = m.scale_y / det; - let mut b = -m.rotate_skew_1 / det; - let mut c = -(tx * m.scale_y - m.rotate_skew_1 * ty) / det; - let mut d = -m.rotate_skew_0 / det; - let mut e = m.scale_x / det; - let mut f = (tx * m.rotate_skew_0 - m.scale_x * ty) / det; + let tx = m.tx.get() as f32; + let ty = m.ty.get() as f32; + let det = m.a * m.d - m.c * m.b; + let mut a = m.d / det; + let mut b = -m.c / det; + let mut c = -(tx * m.d - m.c * ty) / det; + let mut d = -m.b / det; + let mut e = m.a / det; + let mut f = (tx * m.b - m.a * ty) / det; a *= 20.0 / bitmap_width; b *= 20.0 / bitmap_width; diff --git a/render/webgl/src/lib.rs b/render/webgl/src/lib.rs index eb7a230ce..def697b3e 100644 --- a/render/webgl/src/lib.rs +++ b/render/webgl/src/lib.rs @@ -911,7 +911,7 @@ impl RenderBackend for WebGlRenderBackend { } // Scale the quad to the bitmap's dimensions. - use ruffle_core::matrix::Matrix; + use ruffle_core::swf::Matrix; let scale_transform = Transform { matrix: transform.matrix * Matrix { diff --git a/render/wgpu/src/lib.rs b/render/wgpu/src/lib.rs index 6679a6631..8583cf030 100644 --- a/render/wgpu/src/lib.rs +++ b/render/wgpu/src/lib.rs @@ -375,7 +375,7 @@ impl WgpuRenderBackend { repeat_mode: gradient_spread_mode_index(gradient.spread), focal_point: 0.0, }; - let matrix = swf_to_gl_matrix(gradient.matrix.clone()); + let matrix = swf_to_gl_matrix(gradient.matrix); flush_draw( shape.id, @@ -444,7 +444,7 @@ impl WgpuRenderBackend { repeat_mode: gradient_spread_mode_index(gradient.spread), focal_point: 0.0, }; - let matrix = swf_to_gl_matrix(gradient.matrix.clone()); + let matrix = swf_to_gl_matrix(gradient.matrix); flush_draw( shape.id, @@ -516,7 +516,7 @@ impl WgpuRenderBackend { repeat_mode: gradient_spread_mode_index(gradient.spread), focal_point: *focal_point, }; - let matrix = swf_to_gl_matrix(gradient.matrix.clone()); + let matrix = swf_to_gl_matrix(gradient.matrix); flush_draw( shape.id, @@ -583,7 +583,7 @@ impl WgpuRenderBackend { shape.id, IncompleteDrawType::Bitmap { texture_transform: swf_bitmap_to_gl_matrix( - matrix.clone(), + *matrix, texture.width, texture.height, ), @@ -1057,7 +1057,7 @@ impl RenderBackend for WgpuRenderBackend { return; }; - use ruffle_core::matrix::Matrix; + use ruffle_core::swf::Matrix; let transform = Transform { matrix: transform.matrix * Matrix { diff --git a/render/wgpu/src/utils.rs b/render/wgpu/src/utils.rs index 90543d059..6e07d4a67 100644 --- a/render/wgpu/src/utils.rs +++ b/render/wgpu/src/utils.rs @@ -56,15 +56,15 @@ pub fn ruffle_path_to_lyon_path(commands: Vec, is_closed: bool) -> #[allow(clippy::many_single_char_names)] pub fn swf_to_gl_matrix(m: swf::Matrix) -> [[f32; 4]; 4] { - let tx = m.translate_x.get() as f32; - let ty = m.translate_y.get() as f32; - let det = m.scale_x * m.scale_y - m.rotate_skew_1 * m.rotate_skew_0; - let mut a = m.scale_y / det; - let mut b = -m.rotate_skew_1 / det; - let mut c = -(tx * m.scale_y - m.rotate_skew_1 * ty) / det; - let mut d = -m.rotate_skew_0 / det; - let mut e = m.scale_x / det; - let mut f = (tx * m.rotate_skew_0 - m.scale_x * ty) / det; + let tx = m.tx.get() as f32; + let ty = m.ty.get() as f32; + let det = m.a * m.d - m.c * m.b; + let mut a = m.d / det; + let mut b = -m.c / det; + let mut c = -(tx * m.d - m.c * ty) / det; + let mut d = -m.b / det; + let mut e = m.a / det; + let mut f = (tx * m.b - m.a * ty) / det; a *= 20.0 / 32768.0; b *= 20.0 / 32768.0; @@ -92,15 +92,15 @@ pub fn swf_bitmap_to_gl_matrix( let bitmap_width = bitmap_width as f32; let bitmap_height = bitmap_height as f32; - let tx = m.translate_x.get() as f32; - let ty = m.translate_y.get() as f32; - let det = m.scale_x * m.scale_y - m.rotate_skew_1 * m.rotate_skew_0; - let mut a = m.scale_y / det; - let mut b = -m.rotate_skew_1 / det; - let mut c = -(tx * m.scale_y - m.rotate_skew_1 * ty) / det; - let mut d = -m.rotate_skew_0 / det; - let mut e = m.scale_x / det; - let mut f = (tx * m.rotate_skew_0 - m.scale_x * ty) / det; + let tx = m.tx.get() as f32; + let ty = m.ty.get() as f32; + let det = m.a * m.d - m.c * m.b; + let mut a = m.d / det; + let mut b = -m.c / det; + let mut c = -(tx * m.d - m.c * ty) / det; + let mut d = -m.b / det; + let mut e = m.a / det; + let mut f = (tx * m.b - m.a * ty) / det; a *= 20.0 / bitmap_width; b *= 20.0 / bitmap_width; diff --git a/swf/Cargo.toml b/swf/Cargo.toml index 891a5bd69..3ce5004a7 100644 --- a/swf/Cargo.toml +++ b/swf/Cargo.toml @@ -19,6 +19,9 @@ log = "0.4" flate2 = {version = "1.0", optional = true} xz2 = {version = "0.1.6", optional = true} +[dev-dependencies] +approx = "0.3.2" + [features] default = ["libflate"] lzma = ["xz2"] \ No newline at end of file diff --git a/swf/src/read.rs b/swf/src/read.rs index 3d58a73fe..9627780bf 100644 --- a/swf/src/read.rs +++ b/swf/src/read.rs @@ -830,23 +830,23 @@ impl Reader { fn read_matrix(&mut self) -> Result { self.byte_align(); - let mut m = Matrix::new(); + let mut m = Matrix::identity(); // Scale if self.read_bit()? { let num_bits = self.read_ubits(5)? as usize; - m.scale_x = self.read_fbits(num_bits)?; - m.scale_y = self.read_fbits(num_bits)?; + m.a = self.read_fbits(num_bits)?; + m.d = self.read_fbits(num_bits)?; } // Rotate/Skew if self.read_bit()? { let num_bits = self.read_ubits(5)? as usize; - m.rotate_skew_0 = self.read_fbits(num_bits)?; - m.rotate_skew_1 = self.read_fbits(num_bits)?; + m.b = self.read_fbits(num_bits)?; + m.c = self.read_fbits(num_bits)?; } // Translate (always present) let num_bits = self.read_ubits(5)? as usize; - m.translate_x = self.read_sbits_twips(num_bits)?; - m.translate_y = self.read_sbits_twips(num_bits)?; + m.tx = self.read_sbits_twips(num_bits)?; + m.ty = self.read_sbits_twips(num_bits)?; Ok(m) } @@ -3092,12 +3092,12 @@ pub mod tests { assert_eq!( matrix, Matrix { - translate_x: Twips::from_pixels(0.0), - translate_y: Twips::from_pixels(0.0), - scale_x: 1f32, - scale_y: 1f32, - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, + tx: Twips::from_pixels(0.0), + ty: Twips::from_pixels(0.0), + a: 1f32, + d: 1f32, + b: 0f32, + c: 0f32, } ); } @@ -3173,7 +3173,7 @@ pub mod tests { let fill_style = FillStyle::Bitmap { id: 20, - matrix: Matrix::new(), + matrix: Matrix::identity(), is_smoothed: false, is_repeating: true, }; @@ -3182,8 +3182,8 @@ pub mod tests { fill_style ); - let mut matrix = Matrix::new(); - matrix.translate_x = Twips::from_pixels(1.0); + let mut matrix = Matrix::identity(); + matrix.tx = Twips::from_pixels(1.0); let fill_style = FillStyle::Bitmap { id: 33, matrix, diff --git a/swf/src/test_data.rs b/swf/src/test_data.rs index dace54cc1..e3a7a2a22 100644 --- a/swf/src/test_data.rs +++ b/swf/src/test_data.rs @@ -203,7 +203,7 @@ pub fn tag_tests() -> Vec { .into_iter() .collect(), depth: 1, - matrix: Matrix::new(), + matrix: Matrix::identity(), color_transform: ColorTransform::new(), filters: vec![], blend_mode: BlendMode::Normal, @@ -214,7 +214,7 @@ pub fn tag_tests() -> Vec { .into_iter() .collect(), depth: 1, - matrix: Matrix::new(), + matrix: Matrix::identity(), color_transform: ColorTransform::new(), filters: vec![], blend_mode: BlendMode::Normal, @@ -242,7 +242,7 @@ pub fn tag_tests() -> Vec { .into_iter() .collect(), depth: 1, - matrix: Matrix::new(), + matrix: Matrix::identity(), color_transform: ColorTransform { r_multiply: 1f32, g_multiply: 1f32, @@ -266,7 +266,7 @@ pub fn tag_tests() -> Vec { .into_iter() .collect(), depth: 1, - matrix: Matrix::new(), + matrix: Matrix::identity(), color_transform: ColorTransform { r_multiply: 0f32, g_multiply: 1f32, @@ -737,12 +737,12 @@ pub fn tag_tests() -> Vec { }, fill_styles: vec![FillStyle::LinearGradient(Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(40.0), - translate_y: Twips::from_pixels(40.0), - scale_x: 0.024429321, - scale_y: 0.024429321, - rotate_skew_0: 0.024429321, - rotate_skew_1: -0.024429321, + tx: Twips::from_pixels(40.0), + ty: Twips::from_pixels(40.0), + a: 0.024429321, + d: 0.024429321, + b: 0.024429321, + c: -0.024429321, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::RGB, @@ -840,12 +840,12 @@ pub fn tag_tests() -> Vec { }, fill_styles: vec![FillStyle::LinearGradient(Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(48.4), - translate_y: Twips::from_pixels(34.65), - scale_x: 0.0058898926, - scale_y: 0.030914307, - rotate_skew_0: 0.0, - rotate_skew_1: 0.0, + tx: Twips::from_pixels(48.4), + ty: Twips::from_pixels(34.65), + a: 0.0058898926, + d: 0.030914307, + b: 0.0, + c: 0.0, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::RGB, @@ -958,12 +958,12 @@ pub fn tag_tests() -> Vec { fill_styles: vec![FillStyle::FocalGradient { gradient: Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(116.05), - translate_y: Twips::from_pixels(135.05), - scale_x: 0.11468506, - scale_y: 0.18927002, - rotate_skew_0: 0.0, - rotate_skew_1: 0.0, + tx: Twips::from_pixels(116.05), + ty: Twips::from_pixels(135.05), + a: 0.11468506, + d: 0.18927002, + b: 0.0, + c: 0.0, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::RGB, @@ -1081,12 +1081,12 @@ pub fn tag_tests() -> Vec { fill_styles: vec![FillStyle::FocalGradient { gradient: Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(164.0), - translate_y: Twips::from_pixels(150.05), - scale_x: 0.036087036, - scale_y: 0.041992188, - rotate_skew_0: 0.1347351, - rotate_skew_1: -0.15675354, + tx: Twips::from_pixels(164.0), + ty: Twips::from_pixels(150.05), + a: 0.036087036, + d: 0.041992188, + b: 0.1347351, + c: -0.15675354, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::RGB, @@ -1217,12 +1217,12 @@ pub fn tag_tests() -> Vec { }, fill_styles: vec![FillStyle::RadialGradient(Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(100.00), - translate_y: Twips::from_pixels(100.00), - scale_x: 0.1725769, - scale_y: 0.1725769, - rotate_skew_0: 0.0, - rotate_skew_1: 0.0, + tx: Twips::from_pixels(100.00), + ty: Twips::from_pixels(100.00), + a: 0.1725769, + d: 0.1725769, + b: 0.0, + c: 0.0, }, spread: GradientSpread::Reflect, interpolation: GradientInterpolation::LinearRGB, @@ -1305,12 +1305,12 @@ pub fn tag_tests() -> Vec { }, fill_styles: vec![FillStyle::RadialGradient(Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(100.00), - translate_y: Twips::from_pixels(100.00), - scale_x: 0.000015258789, - scale_y: 0.000015258789, - rotate_skew_0: 0.084503174, - rotate_skew_1: -0.084503174, + tx: Twips::from_pixels(100.00), + ty: Twips::from_pixels(100.00), + a: 0.000015258789, + d: 0.000015258789, + b: 0.084503174, + c: -0.084503174, }, spread: GradientSpread::Reflect, interpolation: GradientInterpolation::LinearRGB, @@ -1514,12 +1514,12 @@ pub fn tag_tests() -> Vec { styles: ShapeStyles { fill_styles: vec![FillStyle::RadialGradient(Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(24.95), - translate_y: Twips::from_pixels(24.95), - scale_x: 0.030731201f32, - scale_y: 0.030731201f32, - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, + tx: Twips::from_pixels(24.95), + ty: Twips::from_pixels(24.95), + a: 0.030731201f32, + d: 0.030731201f32, + b: 0f32, + c: 0f32, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::RGB, @@ -1637,12 +1637,12 @@ pub fn tag_tests() -> Vec { FillStyle::FocalGradient { gradient: Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(49.55), - translate_y: Twips::from_pixels(46.55), - scale_x: 0.06199646f32, - scale_y: 0.06199646f32, - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, + tx: Twips::from_pixels(49.55), + ty: Twips::from_pixels(46.55), + a: 0.06199646f32, + d: 0.06199646f32, + b: 0f32, + c: 0f32, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::LinearRGB, @@ -1701,12 +1701,12 @@ pub fn tag_tests() -> Vec { join_style: LineJoinStyle::Round, fill_style: Some(FillStyle::LinearGradient(Gradient { matrix: Matrix { - translate_x: Twips::from_pixels(50.0), - translate_y: Twips::from_pixels(50.0), - scale_x: 0.07324219f32, - scale_y: 0.07324219f32, - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, + tx: Twips::from_pixels(50.0), + ty: Twips::from_pixels(50.0), + a: 0.07324219f32, + d: 0.07324219f32, + b: 0f32, + c: 0f32, }, spread: GradientSpread::Pad, interpolation: GradientInterpolation::RGB, @@ -1888,7 +1888,7 @@ pub fn tag_tests() -> Vec { y_min: Twips::from_pixels(4.1), y_max: Twips::from_pixels(18.45), }, - matrix: Matrix::new(), + matrix: Matrix::identity(), records: vec![TextRecord { font_id: Some(1), color: Some(Color { @@ -2090,7 +2090,7 @@ pub fn tag_tests() -> Vec { version: 2, action: PlaceObjectAction::Place(1), depth: 1, - matrix: Some(Matrix::new()), + matrix: Some(Matrix::identity()), color_transform: None, ratio: None, name: None, @@ -2113,7 +2113,7 @@ pub fn tag_tests() -> Vec { version: 2, action: PlaceObjectAction::Place(2), depth: 1, - matrix: Some(Matrix::new()), + matrix: Some(Matrix::identity()), color_transform: None, ratio: None, name: None, @@ -2143,7 +2143,7 @@ pub fn tag_tests() -> Vec { version: 2, action: PlaceObjectAction::Place(2), depth: 1, - matrix: Some(Matrix::new()), + matrix: Some(Matrix::identity()), color_transform: None, ratio: None, name: None, @@ -2186,12 +2186,12 @@ pub fn tag_tests() -> Vec { action: PlaceObjectAction::Place(1), depth: 1, matrix: Some(Matrix { - translate_x: Twips::from_pixels(0.0), - translate_y: Twips::from_pixels(0.0), - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, - scale_x: 1.0f32, - scale_y: 1.0f32, + tx: Twips::from_pixels(0.0), + ty: Twips::from_pixels(0.0), + b: 0f32, + c: 0f32, + a: 1.0f32, + d: 1.0f32, }), color_transform: None, ratio: None, @@ -2216,12 +2216,12 @@ pub fn tag_tests() -> Vec { action: PlaceObjectAction::Place(2), depth: 1, matrix: Some(Matrix { - translate_x: Twips::from_pixels(10.0), - translate_y: Twips::from_pixels(10.0), - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, - scale_x: 2.0f32, - scale_y: 2.0f32, + tx: Twips::from_pixels(10.0), + ty: Twips::from_pixels(10.0), + b: 0f32, + c: 0f32, + a: 2.0f32, + d: 2.0f32, }), color_transform: Some(ColorTransform { a_multiply: 1.0f32, @@ -2352,12 +2352,12 @@ pub fn tag_tests() -> Vec { action: PlaceObjectAction::Place(2), depth: 1, matrix: Some(Matrix { - translate_x: Twips::from_pixels(10.0), - translate_y: Twips::from_pixels(10.0), - rotate_skew_0: 0.0, - rotate_skew_1: 0.0, - scale_x: 1.0, - scale_y: 1.0, + tx: Twips::from_pixels(10.0), + ty: Twips::from_pixels(10.0), + b: 0.0, + c: 0.0, + a: 1.0, + d: 1.0, }), color_transform: None, ratio: None, diff --git a/swf/src/types.rs b/swf/src/types.rs index 7c707c00f..22e5ff415 100644 --- a/swf/src/types.rs +++ b/swf/src/types.rs @@ -6,6 +6,10 @@ use enumset::{EnumSet, EnumSetType}; use std::collections::HashSet; +mod matrix; + +pub use matrix::Matrix; + /// A complete header and tags in the SWF file. /// This is returned by the `swf::read_swf` convenience method. #[derive(Debug, PartialEq)] @@ -206,35 +210,6 @@ impl Default for ColorTransform { } } -#[derive(Debug, PartialEq, Clone)] -pub struct Matrix { - pub translate_x: Twips, - pub translate_y: Twips, - pub scale_x: f32, - pub scale_y: f32, - pub rotate_skew_0: f32, - pub rotate_skew_1: f32, -} - -impl Matrix { - pub fn new() -> Matrix { - Matrix { - translate_x: Default::default(), - translate_y: Default::default(), - scale_x: 1f32, - scale_y: 1f32, - rotate_skew_0: 0f32, - rotate_skew_1: 0f32, - } - } -} - -impl Default for Matrix { - fn default() -> Self { - Self::new() - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Language { Unknown, diff --git a/core/src/matrix.rs b/swf/src/types/matrix.rs similarity index 98% rename from core/src/matrix.rs rename to swf/src/types/matrix.rs index f11ede8be..0b73bb876 100644 --- a/core/src/matrix.rs +++ b/swf/src/types/matrix.rs @@ -1,16 +1,38 @@ -use swf::Twips; +use crate::Twips; #[derive(Copy, Clone, Debug, PartialEq)] pub struct Matrix { + /// Serialized as `scale_x` in SWF files pub a: f32, + + /// Serialized as `rotate_skew_0` in SWF files pub b: f32, + + /// Serialized as `rotate_skew_1` in SWF files pub c: f32, + + /// Serialized as `scale_y` in SWF files pub d: f32, + + /// Serialized as `transform_x` in SWF files pub tx: Twips, + + /// Serialized as `transform_y` in SWF files pub ty: Twips, } impl Matrix { + pub fn identity() -> Self { + Self { + a: 1.0, + c: 0.0, + tx: Twips::new(0), + b: 0.0, + d: 1.0, + ty: Twips::new(0), + } + } + pub fn invert(&mut self) { let (tx, ty) = (self.tx.get() as f32, self.ty.get() as f32); let det = self.a * self.d - self.b * self.c; @@ -33,19 +55,6 @@ impl Matrix { } } -impl From for Matrix { - fn from(matrix: swf::Matrix) -> Matrix { - Matrix { - a: matrix.scale_x, - b: matrix.rotate_skew_0, - c: matrix.rotate_skew_1, - d: matrix.scale_y, - tx: matrix.translate_x, - ty: matrix.translate_y, - } - } -} - impl std::ops::Mul for Matrix { type Output = Self; fn mul(self, rhs: Self) -> Self { @@ -77,14 +86,7 @@ impl std::ops::Mul<(Twips, Twips)> for Matrix { impl std::default::Default for Matrix { fn default() -> Matrix { - Matrix { - a: 1.0, - c: 0.0, - tx: Twips::new(0), - b: 0.0, - d: 1.0, - ty: Twips::new(0), - } + Matrix::identity() } } diff --git a/swf/src/write.rs b/swf/src/write.rs index d31f74f6d..d0d068f16 100644 --- a/swf/src/write.rs +++ b/swf/src/write.rs @@ -475,31 +475,28 @@ impl Writer { fn write_matrix(&mut self, m: &Matrix) -> Result<()> { self.flush_bits()?; // Scale - let has_scale = m.scale_x != 1f32 || m.scale_y != 1f32; + let has_scale = m.a != 1f32 || m.d != 1f32; self.write_bit(has_scale)?; if has_scale { - let num_bits = max(count_fbits(m.scale_x), count_fbits(m.scale_y)); + let num_bits = max(count_fbits(m.a), count_fbits(m.d)); self.write_ubits(5, num_bits.into())?; - self.write_fbits(num_bits, m.scale_x)?; - self.write_fbits(num_bits, m.scale_y)?; + self.write_fbits(num_bits, m.a)?; + self.write_fbits(num_bits, m.d)?; } // Rotate/Skew - let has_rotate_skew = m.rotate_skew_0 != 0f32 || m.rotate_skew_1 != 0f32; + let has_rotate_skew = m.b != 0f32 || m.c != 0f32; self.write_bit(has_rotate_skew)?; if has_rotate_skew { - let num_bits = max(count_fbits(m.rotate_skew_0), count_fbits(m.rotate_skew_1)); + let num_bits = max(count_fbits(m.b), count_fbits(m.c)); self.write_ubits(5, num_bits.into())?; - self.write_fbits(num_bits, m.rotate_skew_0)?; - self.write_fbits(num_bits, m.rotate_skew_1)?; + self.write_fbits(num_bits, m.b)?; + self.write_fbits(num_bits, m.c)?; } // Translate (always written) - let num_bits = max( - count_sbits_twips(m.translate_x), - count_sbits_twips(m.translate_y), - ); + let num_bits = max(count_sbits_twips(m.tx), count_sbits_twips(m.ty)); self.write_ubits(5, num_bits.into())?; - self.write_sbits_twips(num_bits, m.translate_x)?; - self.write_sbits_twips(num_bits, m.translate_y)?; + self.write_sbits_twips(num_bits, m.tx)?; + self.write_sbits_twips(num_bits, m.ty)?; Ok(()) } @@ -1911,7 +1908,7 @@ impl Writer { if let Some(ref matrix) = place_object.matrix { writer.write_matrix(matrix)?; } else { - writer.write_matrix(&Matrix::new())?; + writer.write_matrix(&Matrix::identity())?; } if let Some(ref color_transform) = place_object.color_transform { writer.write_color_transform_no_alpha(color_transform)?; @@ -3037,7 +3034,7 @@ mod tests { buf } - let m = Matrix::new(); + let m = Matrix::identity(); assert_eq!(write_to_buf(&m), [0]); }