swf: Use Fixed in more places

This commit is contained in:
Mike Welsh 2021-05-30 13:30:06 -07:00
parent 34d54dbc05
commit 2b98c878f0
17 changed files with 103 additions and 100 deletions

View File

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

View File

@ -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<LineJoinStyle, Error> {
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 {

View File

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

View File

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

View File

@ -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<dyn std::error::Error>;
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()
}
}

View File

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

View File

@ -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<f32> = Vec::with_capacity(8);

View File

@ -1365,7 +1365,7 @@ impl From<TessGradient> 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,
}
}

View File

@ -202,7 +202,7 @@ impl From<TessGradient> 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(),
}
}
}

View File

@ -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 = [

View File

@ -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<f32> {
Ok((self.read_i16()? as f32) / 256.0)
fn read_fixed8(&mut self) -> Result<Fixed8> {
Ok(Fixed8::from_bits(self.read_i16()?))
}
#[inline]
fn read_fixed16(&mut self) -> Result<f64> {
Ok((self.read_i32()? as f64) / 65536.0)
fn read_fixed16(&mut self) -> Result<Fixed16> {
Ok(Fixed16::from_bits(self.read_i32()?))
}
#[inline]

View File

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

View File

@ -112,7 +112,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
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<TagTestData> {
..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<TagTestData> {
},
],
},
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<TagTestData> {
},
],
},
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<TagTestData> {
},
],
},
focal_point: 0.56640625f32,
focal_point: Fixed8::from_f64(0.56640625),
},
],
line_styles: vec![
@ -1735,7 +1735,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
},
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<TagTestData> {
},
},
],
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<TagTestData> {
},
},
],
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,
})),
]),

View File

@ -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<GradientRecord>,
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<f64>,
pub divisor: f64,
pub bias: f64,
pub matrix: Vec<Fixed16>,
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<GradientRecord>,
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],
}

View File

@ -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<W: Write> Writer<W> {
}
}
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,

View File

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

View File

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