swf: Merged core::Matrix into swf::Matrix

This commit is contained in:
Nathan Adams 2020-05-19 18:50:37 +02:00
parent 61e464099c
commit eda862c719
20 changed files with 209 additions and 237 deletions

1
Cargo.lock generated
View File

@ -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)",

View File

@ -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!(

View File

@ -1,4 +1,4 @@
use crate::matrix::Matrix;
use swf::Matrix;
use swf::Twips;
#[derive(Clone, Debug, PartialEq)]

View File

@ -767,7 +767,7 @@ pub trait TDisplayObject<'gc>: 'gc + Collect + Debug + Into<DisplayObject<'gc>>
// 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<crate::transform::Transform> {
std::cell::Ref::map(self.0.read(), |o| o.$field.transform())
}
fn matrix(&self) -> std::cell::Ref<crate::matrix::Matrix> {
fn matrix(&self) -> std::cell::Ref<swf::Matrix> {
std::cell::Ref::map(self.0.read(), |o| o.$field.matrix())
}
fn matrix_mut(
&mut self,
context: gc_arena::MutationContext<'gc, '_>,
) -> std::cell::RefMut<crate::matrix::Matrix> {
) -> std::cell::RefMut<swf::Matrix> {
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)
}

View File

@ -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);

View File

@ -161,7 +161,7 @@ impl MorphShapeStatic {
.collect();
FillStyle::LinearGradient(Gradient {
matrix: start.matrix.clone(),
matrix: start.matrix,
spread: start.spread,
interpolation: start.interpolation,
records,

View File

@ -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(),
},
),

View File

@ -18,7 +18,6 @@ pub mod events;
mod font;
mod library;
mod loader;
pub mod matrix;
mod player;
mod prelude;
mod property_map;

View File

@ -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.

View File

@ -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<ShapeData> {
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();

View File

@ -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;

View File

@ -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 {

View File

@ -375,7 +375,7 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
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<T: RenderTarget> WgpuRenderBackend<T> {
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<T: RenderTarget> WgpuRenderBackend<T> {
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<T: RenderTarget> WgpuRenderBackend<T> {
shape.id,
IncompleteDrawType::Bitmap {
texture_transform: swf_bitmap_to_gl_matrix(
matrix.clone(),
*matrix,
texture.width,
texture.height,
),
@ -1057,7 +1057,7 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
return;
};
use ruffle_core::matrix::Matrix;
use ruffle_core::swf::Matrix;
let transform = Transform {
matrix: transform.matrix
* Matrix {

View File

@ -56,15 +56,15 @@ pub fn ruffle_path_to_lyon_path(commands: Vec<DrawCommand>, 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;

View File

@ -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"]

View File

@ -830,23 +830,23 @@ impl<R: Read> Reader<R> {
fn read_matrix(&mut self) -> Result<Matrix> {
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,

View File

@ -203,7 +203,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
.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<TagTestData> {
.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<TagTestData> {
.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<TagTestData> {
.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<TagTestData> {
},
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<TagTestData> {
},
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
},
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<TagTestData> {
},
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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<TagTestData> {
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,

View File

@ -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,

View File

@ -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<swf::Matrix> 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()
}
}

View File

@ -475,31 +475,28 @@ impl<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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]);
}