diff --git a/core/src/avm1/globals/movie_clip.rs b/core/src/avm1/globals/movie_clip.rs index c85c6ea9c..79c4dcdd6 100644 --- a/core/src/avm1/globals/movie_clip.rs +++ b/core/src/avm1/globals/movie_clip.rs @@ -20,8 +20,8 @@ use crate::vminterface::Instantiator; use gc_arena::MutationContext; use std::borrow::Cow; use swf::{ - FillStyle, Gradient, GradientInterpolation, GradientRecord, GradientSpread, LineCapStyle, - LineJoinStyle, LineStyle, Twips, + FillStyle, Fixed8, Gradient, GradientInterpolation, GradientRecord, GradientSpread, + LineCapStyle, LineJoinStyle, LineStyle, Twips, }; macro_rules! mc_method { @@ -277,9 +277,10 @@ fn line_style<'gc>( { Some("miter") => { if let Some(limit) = args.get(7) { - LineJoinStyle::Miter(limit.coerce_to_f64(activation)?.max(0.0).min(255.0) as f32) + let limit = limit.coerce_to_f64(activation)?.max(0.0).min(255.0); + LineJoinStyle::Miter(Fixed8::from_f64(limit)) } else { - LineJoinStyle::Miter(3.0) + LineJoinStyle::Miter(Fixed8::from_f32(3.0)) } } Some("bevel") => LineJoinStyle::Bevel, @@ -401,7 +402,7 @@ fn begin_gradient_fill<'gc>( if let Some(focal_point) = args.get(7) { FillStyle::FocalGradient { gradient, - focal_point: focal_point.coerce_to_f64(activation)? as f32, + focal_point: Fixed8::from_f64(focal_point.coerce_to_f64(activation)?), } } else { FillStyle::RadialGradient(gradient) diff --git a/core/src/avm2/globals/flash/display/graphics.rs b/core/src/avm2/globals/flash/display/graphics.rs index 42f7448a4..e5062f5aa 100644 --- a/core/src/avm2/globals/flash/display/graphics.rs +++ b/core/src/avm2/globals/flash/display/graphics.rs @@ -10,7 +10,7 @@ use crate::avm2::Error; use crate::display_object::TDisplayObject; use crate::shape_utils::DrawCommand; use gc_arena::{GcCell, MutationContext}; -use swf::{Color, FillStyle, LineCapStyle, LineJoinStyle, LineStyle, Twips}; +use swf::{Color, FillStyle, Fixed8, LineCapStyle, LineJoinStyle, LineStyle, Twips}; /// Implements `flash.display.Graphics`'s instance constructor. pub fn instance_init<'gc>( @@ -151,14 +151,14 @@ fn caps_to_cap_style<'gc>( fn joints_to_join_style<'gc>( activation: &mut Activation<'_, 'gc, '_>, joints: Value<'gc>, - miter_limit: f32, + miter_limit: f64, ) -> Result { let joints_string = joints.coerce_to_string(activation); let joints_str = joints_string.as_deref(); match (joints, joints_str) { (Value::Null, _) | (_, Ok("round")) => Ok(LineJoinStyle::Round), - (_, Ok("miter")) => Ok(LineJoinStyle::Miter(miter_limit)), + (_, Ok("miter")) => Ok(LineJoinStyle::Miter(Fixed8::from_f64(miter_limit))), (_, Ok("bevel")) => Ok(LineJoinStyle::Bevel), (_, Ok(_)) => Err("ArgumentError: joints is invalid".into()), (_, Err(_)) => Err(joints_string.unwrap_err()), @@ -223,7 +223,7 @@ pub fn line_style<'gc>( let width = Twips::from_pixels(thickness.min(255.0).max(0.0)); let color = color_from_args(color, alpha); - let join_style = joints_to_join_style(activation, joints, miter_limit as f32)?; + let join_style = joints_to_join_style(activation, joints, miter_limit)?; let (allow_scale_x, allow_scale_y) = scale_mode_to_allow_scale_bits(&scale_mode)?; let line_style = LineStyle { diff --git a/core/src/avm2/globals/flash/display/loaderinfo.rs b/core/src/avm2/globals/flash/display/loaderinfo.rs index 738e1aa23..ae803a35b 100644 --- a/core/src/avm2/globals/flash/display/loaderinfo.rs +++ b/core/src/avm2/globals/flash/display/loaderinfo.rs @@ -171,7 +171,7 @@ pub fn frame_rate<'gc>( return Err("Error: The stage's loader info does not have a frame rate".into()) } LoaderStream::Swf(root, _) => { - return Ok(root.frame_rate().into()); + return Ok(root.frame_rate().to_f64().into()); } } } diff --git a/core/src/display_object/morph_shape.rs b/core/src/display_object/morph_shape.rs index 8585651ad..56c499ca4 100644 --- a/core/src/display_object/morph_shape.rs +++ b/core/src/display_object/morph_shape.rs @@ -6,7 +6,7 @@ use crate::tag_utils::SwfMovie; use crate::types::{Degrees, Percent}; use gc_arena::{Collect, Gc, GcCell, MutationContext}; use std::sync::Arc; -use swf::Twips; +use swf::{Fixed8, Twips}; #[derive(Clone, Debug, Collect, Copy)] #[collect(no_drop)] @@ -369,7 +369,7 @@ fn lerp_fill(start: &swf::FillStyle, end: &swf::FillStyle, a: f32, b: f32) -> sw }, ) => FillStyle::FocalGradient { gradient: lerp_gradient(start, end, a, b), - focal_point: a * start_focal + b * end_focal, + focal_point: *start_focal * Fixed8::from_f32(a) + *end_focal * Fixed8::from_f32(b), }, // All other combinations should not occur, because SWF stores the start/end fill as the same type, always. diff --git a/core/src/tag_utils.rs b/core/src/tag_utils.rs index 2ac4ac309..3e03bbac8 100644 --- a/core/src/tag_utils.rs +++ b/core/src/tag_utils.rs @@ -3,7 +3,7 @@ use crate::vminterface::AvmType; use gc_arena::Collect; use std::path::Path; use std::sync::Arc; -use swf::{HeaderExt, Rectangle, TagCode, Twips}; +use swf::{Fixed8, HeaderExt, Rectangle, TagCode, Twips}; pub type Error = Box; pub type DecodeResult = Result<(), Error>; @@ -173,7 +173,7 @@ impl SwfMovie { self.header.num_frames() } - pub fn frame_rate(&self) -> f32 { + pub fn frame_rate(&self) -> Fixed8 { self.header.frame_rate() } } diff --git a/render/canvas/src/lib.rs b/render/canvas/src/lib.rs index cadcc8052..52ba78d6e 100644 --- a/render/canvas/src/lib.rs +++ b/render/canvas/src/lib.rs @@ -973,7 +973,7 @@ fn swf_shape_to_svg( let mut svg_gradient = RadialGradient::new() .set("id", format!("f{}", num_defs)) - .set("fx", focal_point / 2.0) + .set("fx", focal_point.to_f32() / 2.0) .set("gradientUnits", "userSpaceOnUse") .set("cx", "0") .set("cy", "0") @@ -1155,7 +1155,7 @@ fn swf_shape_to_svg( ); if let LineJoinStyle::Miter(miter_limit) = style.join_style { - svg_path = svg_path.set("stroke-miterlimit", miter_limit); + svg_path = svg_path.set("stroke-miterlimit", miter_limit.to_f32()); } let mut data = Data::new(); @@ -1411,7 +1411,7 @@ fn swf_shape_to_canvas_commands( let (line_join, miter_limit) = match style.join_style { LineJoinStyle::Round => ("round", 999_999.0), LineJoinStyle::Bevel => ("bevel", 999_999.0), - LineJoinStyle::Miter(ml) => ("miter", ml), + LineJoinStyle::Miter(ml) => ("miter", ml.to_f32()), }; let path = Path2d::new().unwrap(); diff --git a/render/common_tess/src/lib.rs b/render/common_tess/src/lib.rs index 5b7baf2fc..280fd8754 100644 --- a/render/common_tess/src/lib.rs +++ b/render/common_tess/src/lib.rs @@ -87,7 +87,7 @@ impl ShapeTessellator { DrawType::Gradient(swf_gradient_to_uniforms( GradientType::Linear, gradient, - 0.0, + swf::Fixed8::ZERO, )), &mut mesh, &mut lyon_mesh, @@ -117,7 +117,7 @@ impl ShapeTessellator { DrawType::Gradient(swf_gradient_to_uniforms( GradientType::Radial, gradient, - 0.0, + swf::Fixed8::ZERO, )), &mut mesh, &mut lyon_mesh, @@ -232,6 +232,7 @@ impl ShapeTessellator { swf::LineJoinStyle::Bevel => tessellation::LineJoin::Bevel, swf::LineJoinStyle::Miter(limit) => { // Avoid lyon assert with small miter limits. + let limit = limit.to_f32(); if limit >= StrokeOptions::MINIMUM_MITER_LIMIT { options = options.with_miter_limit(limit); tessellation::LineJoin::MiterClip @@ -299,7 +300,7 @@ pub struct Gradient { pub colors: Vec<[f32; 4]>, pub num_colors: usize, pub repeat_mode: swf::GradientSpread, - pub focal_point: f32, + pub focal_point: swf::Fixed8, pub interpolation: swf::GradientInterpolation, } @@ -415,7 +416,7 @@ const MAX_GRADIENT_COLORS: usize = 15; fn swf_gradient_to_uniforms( gradient_type: GradientType, gradient: &swf::Gradient, - focal_point: f32, + focal_point: swf::Fixed8, ) -> Gradient { let mut colors: Vec<[f32; 4]> = Vec::with_capacity(8); let mut ratios: Vec = Vec::with_capacity(8); diff --git a/render/webgl/src/lib.rs b/render/webgl/src/lib.rs index 25a844fd8..b75cf3821 100644 --- a/render/webgl/src/lib.rs +++ b/render/webgl/src/lib.rs @@ -1365,7 +1365,7 @@ impl From for Gradient { swf::GradientSpread::Repeat => 1, swf::GradientSpread::Reflect => 2, }, - focal_point: gradient.focal_point, + focal_point: gradient.focal_point.to_f32(), interpolation: gradient.interpolation, } } diff --git a/render/wgpu/src/lib.rs b/render/wgpu/src/lib.rs index 6f9a683ad..1ccf154e7 100644 --- a/render/wgpu/src/lib.rs +++ b/render/wgpu/src/lib.rs @@ -202,7 +202,7 @@ impl From for GradientUniforms { swf::GradientSpread::Reflect => 2, }, interpolation: (gradient.interpolation == swf::GradientInterpolation::LinearRgb) as i32, - focal_point: gradient.focal_point, + focal_point: gradient.focal_point.to_f32(), } } } diff --git a/swf/examples/writing.rs b/swf/examples/writing.rs index 8df0952a0..cf3878182 100644 --- a/swf/examples/writing.rs +++ b/swf/examples/writing.rs @@ -10,7 +10,7 @@ fn main() { y_min: Twips::from_pixels(0.0), y_max: Twips::from_pixels(400.0), }, - frame_rate: 60.0, + frame_rate: Fixed8::from_f32(60.0), num_frames: 1, }; let tags = [ diff --git a/swf/src/extensions.rs b/swf/src/extensions.rs index 612ddb235..9c18a33ad 100644 --- a/swf/src/extensions.rs +++ b/swf/src/extensions.rs @@ -1,6 +1,7 @@ use crate::byteorder::{LittleEndian, ReadBytesExt}; use crate::error::Result; use crate::string::SwfStr; +use crate::{Fixed16, Fixed8}; use std::io::{self, Read}; pub trait ReadSwfExt<'a> { @@ -66,13 +67,13 @@ pub trait ReadSwfExt<'a> { } #[inline] - fn read_fixed8(&mut self) -> Result { - Ok((self.read_i16()? as f32) / 256.0) + fn read_fixed8(&mut self) -> Result { + Ok(Fixed8::from_bits(self.read_i16()?)) } #[inline] - fn read_fixed16(&mut self) -> Result { - Ok((self.read_i32()? as f64) / 65536.0) + fn read_fixed16(&mut self) -> Result { + Ok(Fixed16::from_bits(self.read_i32()?)) } #[inline] diff --git a/swf/src/read.rs b/swf/src/read.rs index 99fa9d79b..4ddc34a3a 100644 --- a/swf/src/read.rs +++ b/swf/src/read.rs @@ -2288,7 +2288,7 @@ impl<'a> Reader<'a> { })) } 6 => { - let mut matrix = [0f64; 20]; + let mut matrix = [Fixed16::ZERO; 20]; for m in &mut matrix { *m = self.read_fixed16()?; } @@ -2625,7 +2625,7 @@ impl<'a> Reader<'a> { let deblocking = if version >= 4 { self.read_fixed8()? } else { - 0.0 + Fixed8::ZERO }; let data = self.read_slice(data_size)?; let alpha_data = self.read_slice_to_end(); @@ -2890,10 +2890,10 @@ pub mod tests { 0b11101011, ]; let mut reader = Reader::new(&buf[..], 1); - assert_eq!(reader.read_fixed8().unwrap(), 0f32); - assert_eq!(reader.read_fixed8().unwrap(), 1f32); - assert_eq!(reader.read_fixed8().unwrap(), 6.5f32); - assert_eq!(reader.read_fixed8().unwrap(), -20.75f32); + assert_eq!(reader.read_fixed8().unwrap(), Fixed8::from_f32(0.0)); + assert_eq!(reader.read_fixed8().unwrap(), Fixed8::from_f32(1.0)); + assert_eq!(reader.read_fixed8().unwrap(), Fixed8::from_f32(6.5)); + assert_eq!(reader.read_fixed8().unwrap(), Fixed8::from_f32(-20.75)); } #[test] diff --git a/swf/src/test_data.rs b/swf/src/test_data.rs index b5ab9863a..1e29a8500 100644 --- a/swf/src/test_data.rs +++ b/swf/src/test_data.rs @@ -112,7 +112,7 @@ pub fn tag_tests() -> Vec { Tag::DefineBitsJpeg3(DefineBitsJpeg3 { id: 1, version: 3, - deblocking: 0.0, + deblocking: Fixed8::ZERO, data: &[ 255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 67, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -245,8 +245,8 @@ pub fn tag_tests() -> Vec { ..Default::default() }, filters: vec![Filter::BlurFilter(Box::new(BlurFilter { - blur_x: 5f64, - blur_y: 5f64, + blur_x: Fixed16::from_f32(5.0), + blur_y: Fixed16::from_f32(5.0), num_passes: 1, }))], blend_mode: BlendMode::Difference, @@ -986,7 +986,7 @@ pub fn tag_tests() -> Vec { }, ], }, - focal_point: 0.97265625, + focal_point: Fixed8::from_f64(0.97265625), }], line_styles: vec![LineStyle { width: Twips::from_pixels(10.0), @@ -1109,7 +1109,7 @@ pub fn tag_tests() -> Vec { }, ], }, - focal_point: -0.9921875, + focal_point: Fixed8::from_f64(-0.9921875), }], line_styles: vec![LineStyle { width: Twips::from_pixels(2.0), @@ -1656,7 +1656,7 @@ pub fn tag_tests() -> Vec { }, ], }, - focal_point: 0.56640625f32, + focal_point: Fixed8::from_f64(0.56640625), }, ], line_styles: vec![ @@ -1735,7 +1735,7 @@ pub fn tag_tests() -> Vec { }, start_cap: LineCapStyle::Round, end_cap: LineCapStyle::Round, - join_style: LineJoinStyle::Miter(56f32), + join_style: LineJoinStyle::Miter(Fixed8::from_f32(56.0)), fill_style: None, allow_scale_x: true, allow_scale_y: false, @@ -2249,11 +2249,11 @@ pub fn tag_tests() -> Vec { }, }, ], - blur_x: 5f64, - blur_y: 5f64, - angle: 0.7853851318359375f64, - distance: 5f64, - strength: 1f32, + blur_x: Fixed16::from_f32(5.0), + blur_y: Fixed16::from_f32(5.0), + angle: Fixed16::from_f64(0.7853851318359375), + distance: Fixed16::from_f32(5.0), + strength: Fixed8::ONE, is_inner: true, is_knockout: true, is_on_top: false, @@ -2280,19 +2280,19 @@ pub fn tag_tests() -> Vec { }, }, ], - blur_x: 30f64, - blur_y: 30f64, - angle: 0.174530029296875f64, - distance: 5f64, - strength: 0.19921875f32, + blur_x: Fixed16::from_f32(30.0), + blur_y: Fixed16::from_f32(30.0), + angle: Fixed16::from_f64(0.174530029296875), + distance: Fixed16::from_f32(5.0), + strength: Fixed8::from_f64(0.19921875), is_inner: false, is_knockout: false, is_on_top: true, num_passes: 1, })), Filter::BlurFilter(Box::new(BlurFilter { - blur_x: 30f64, - blur_y: 20f64, + blur_x: Fixed16::from_f32(30.0), + blur_y: Fixed16::from_f32(20.0), num_passes: 2, })), ]), diff --git a/swf/src/types.rs b/swf/src/types.rs index c54021945..3d3c85ba2 100644 --- a/swf/src/types.rs +++ b/swf/src/types.rs @@ -40,7 +40,7 @@ pub struct Header { pub compression: Compression, pub version: u8, pub stage_size: Rectangle, - pub frame_rate: f32, + pub frame_rate: Fixed8, pub num_frames: u16, } @@ -50,7 +50,7 @@ impl Header { compression: Compression::None, version, stage_size: Default::default(), - frame_rate: 1.0, + frame_rate: Fixed8::ONE, num_frames: 0, } } @@ -100,7 +100,7 @@ impl HeaderExt { /// The frame rate of the SWF, in frames per second. #[inline] - pub fn frame_rate(&self) -> f32 { + pub fn frame_rate(&self) -> Fixed8 { self.header.frame_rate } @@ -590,11 +590,11 @@ pub enum Filter { #[derive(Debug, PartialEq, Clone)] pub struct DropShadowFilter { pub color: Color, - pub blur_x: f64, - pub blur_y: f64, - pub angle: f64, - pub distance: f64, - pub strength: f32, + pub blur_x: Fixed16, + pub blur_y: Fixed16, + pub angle: Fixed16, + pub distance: Fixed16, + pub strength: Fixed8, pub is_inner: bool, pub is_knockout: bool, pub num_passes: u8, @@ -602,17 +602,17 @@ pub struct DropShadowFilter { #[derive(Debug, PartialEq, Clone)] pub struct BlurFilter { - pub blur_x: f64, - pub blur_y: f64, + pub blur_x: Fixed16, + pub blur_y: Fixed16, pub num_passes: u8, } #[derive(Debug, PartialEq, Clone)] pub struct GlowFilter { pub color: Color, - pub blur_x: f64, - pub blur_y: f64, - pub strength: f32, + pub blur_x: Fixed16, + pub blur_y: Fixed16, + pub strength: Fixed8, pub is_inner: bool, pub is_knockout: bool, pub num_passes: u8, @@ -622,11 +622,11 @@ pub struct GlowFilter { pub struct BevelFilter { pub shadow_color: Color, pub highlight_color: Color, - pub blur_x: f64, - pub blur_y: f64, - pub angle: f64, - pub distance: f64, - pub strength: f32, + pub blur_x: Fixed16, + pub blur_y: Fixed16, + pub angle: Fixed16, + pub distance: Fixed16, + pub strength: Fixed8, pub is_inner: bool, pub is_knockout: bool, pub is_on_top: bool, @@ -636,11 +636,11 @@ pub struct BevelFilter { #[derive(Debug, PartialEq, Clone)] pub struct GradientGlowFilter { pub colors: Vec, - pub blur_x: f64, - pub blur_y: f64, - pub angle: f64, - pub distance: f64, - pub strength: f32, + pub blur_x: Fixed16, + pub blur_y: Fixed16, + pub angle: Fixed16, + pub distance: Fixed16, + pub strength: Fixed8, pub is_inner: bool, pub is_knockout: bool, pub is_on_top: bool, @@ -651,9 +651,9 @@ pub struct GradientGlowFilter { pub struct ConvolutionFilter { pub num_matrix_rows: u8, pub num_matrix_cols: u8, - pub matrix: Vec, - pub divisor: f64, - pub bias: f64, + pub matrix: Vec, + pub divisor: Fixed16, + pub bias: Fixed16, pub default_color: Color, pub is_clamped: bool, pub is_preserve_alpha: bool, @@ -661,17 +661,17 @@ pub struct ConvolutionFilter { #[derive(Debug, PartialEq, Clone)] pub struct ColorMatrixFilter { - pub matrix: [f64; 20], + pub matrix: [Fixed16; 20], } #[derive(Debug, PartialEq, Clone)] pub struct GradientBevelFilter { pub colors: Vec, - pub blur_x: f64, - pub blur_y: f64, - pub angle: f64, - pub distance: f64, - pub strength: f32, + pub blur_x: Fixed16, + pub blur_y: Fixed16, + pub angle: Fixed16, + pub distance: Fixed16, + pub strength: Fixed8, pub is_inner: bool, pub is_knockout: bool, pub is_on_top: bool, @@ -973,7 +973,7 @@ pub enum FillStyle { RadialGradient(Gradient), FocalGradient { gradient: Gradient, - focal_point: f32, + focal_point: Fixed8, }, Bitmap { id: CharacterId, @@ -1052,7 +1052,7 @@ pub enum LineCapStyle { pub enum LineJoinStyle { Round, Bevel, - Miter(f32), + Miter(Fixed8), } #[derive(Debug, PartialEq, Clone, Copy)] @@ -1394,7 +1394,7 @@ pub struct VideoFrame<'a> { pub struct DefineBitsJpeg3<'a> { pub id: CharacterId, pub version: u8, - pub deblocking: f32, + pub deblocking: Fixed8, pub data: &'a [u8], pub alpha_data: &'a [u8], } diff --git a/swf/src/write.rs b/swf/src/write.rs index cc43df1ad..629237a95 100644 --- a/swf/src/write.rs +++ b/swf/src/write.rs @@ -25,7 +25,7 @@ use std::io::{self, Write}; /// compression: Compression::Zlib, /// version: 6, /// stage_size: Rectangle { x_min: Twips::from_pixels(0.0), x_max: Twips::from_pixels(400.0), y_min: Twips::from_pixels(0.0), y_max: Twips::from_pixels(400.0) }, -/// frame_rate: 60.0, +/// frame_rate: Fixed8::from_f32(60.0), /// num_frames: 1, /// }; /// let tags = [ @@ -281,12 +281,12 @@ impl Writer { } } - fn write_fixed8(&mut self, n: f32) -> io::Result<()> { - self.write_i16((n * 256f32) as i16) + fn write_fixed8(&mut self, n: Fixed8) -> io::Result<()> { + self.write_i16(n.get()) } - fn write_fixed16(&mut self, n: f64) -> io::Result<()> { - self.write_i32((n * 65536f64) as i32) + fn write_fixed16(&mut self, n: Fixed16) -> io::Result<()> { + self.write_i32(n.get()) } fn write_encoded_u32(&mut self, mut n: u32) -> Result<()> { @@ -2660,7 +2660,7 @@ mod tests { y_min: Twips::from_pixels(0.0), y_max: Twips::from_pixels(480.0), }, - frame_rate: 60.0, + frame_rate: Fixed8::from_f32(60.0), num_frames: 1, }; write_swf(&header, &[], &mut buf)?; @@ -2687,10 +2687,10 @@ mod tests { let mut buf = Vec::new(); { let mut writer = Writer::new(&mut buf, 1); - writer.write_fixed8(0f32).unwrap(); - writer.write_fixed8(1f32).unwrap(); - writer.write_fixed8(6.5f32).unwrap(); - writer.write_fixed8(-20.75f32).unwrap(); + writer.write_fixed8(Fixed8::ZERO).unwrap(); + writer.write_fixed8(Fixed8::ONE).unwrap(); + writer.write_fixed8(Fixed8::from_f32(6.5)).unwrap(); + writer.write_fixed8(Fixed8::from_f32(-20.75)).unwrap(); } assert_eq!( buf, diff --git a/tests/tests/regression_tests.rs b/tests/tests/regression_tests.rs index 51c35ec42..c9970281d 100644 --- a/tests/tests/regression_tests.rs +++ b/tests/tests/regression_tests.rs @@ -881,7 +881,7 @@ fn run_swf( let base_path = Path::new(swf_path).parent().unwrap(); let (mut executor, channel) = NullExecutor::new(); let movie = SwfMovie::from_path(swf_path, None)?; - let frame_time = 1000.0 / movie.frame_rate() as f64; + let frame_time = 1000.0 / movie.frame_rate().to_f64(); let trace_output = Rc::new(RefCell::new(Vec::new())); let player = Player::new( diff --git a/web/src/lib.rs b/web/src/lib.rs index a5ce91b84..871b3e8a2 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -991,7 +991,7 @@ impl Ruffle { let metadata = MovieMetadata { width: width.to_pixels(), height: height.to_pixels(), - frame_rate: swf_header.frame_rate(), + frame_rate: swf_header.frame_rate().to_f32(), num_frames: swf_header.num_frames(), swf_version: swf_header.version(), background_color,