diff --git a/core/src/avm2/globals/flash/display/displayobject.rs b/core/src/avm2/globals/flash/display/displayobject.rs index 1666d6f8c..2412790b5 100644 --- a/core/src/avm2/globals/flash/display/displayobject.rs +++ b/core/src/avm2/globals/flash/display/displayobject.rs @@ -19,7 +19,7 @@ use crate::types::{Degrees, Percent}; use crate::vminterface::Instantiator; use gc_arena::{GcCell, MutationContext}; use std::str::FromStr; -use swf::Twips; +use crate::prelude::Twips; use swf::{BlendMode, Rectangle}; /// Implements `flash.display.DisplayObject`'s instance constructor. diff --git a/core/src/avm2/globals/flash/events/mouse_event.rs b/core/src/avm2/globals/flash/events/mouse_event.rs index e8ef34e9c..070a83e94 100644 --- a/core/src/avm2/globals/flash/events/mouse_event.rs +++ b/core/src/avm2/globals/flash/events/mouse_event.rs @@ -4,7 +4,7 @@ use crate::avm2::value::Value; use crate::avm2::Error; use crate::avm2::Multiname; use crate::display_object::TDisplayObject; -use swf::Twips; +use crate::prelude::Twips; /// Implements `stageX`'s getter. pub fn get_stage_x<'gc>( diff --git a/core/src/display_object/edit_text.rs b/core/src/display_object/edit_text.rs index d40895b8c..e2de81656 100644 --- a/core/src/display_object/edit_text.rs +++ b/core/src/display_object/edit_text.rs @@ -30,7 +30,8 @@ use ruffle_render::commands::CommandHandler; use ruffle_render::shape_utils::DrawCommand; use ruffle_render::transform::Transform; use std::{cell::Ref, cell::RefMut, sync::Arc}; -use swf::{Color, Twips}; +use swf::Color; +use crate::prelude::Twips; /// The kind of autosizing behavior an `EditText` should have, if any #[derive(Copy, Clone, Debug, Collect, PartialEq, Eq)] diff --git a/core/src/display_object/interactive.rs b/core/src/display_object/interactive.rs index 283e0f1b5..cfb0ce480 100644 --- a/core/src/display_object/interactive.rs +++ b/core/src/display_object/interactive.rs @@ -21,7 +21,7 @@ use ruffle_macros::enum_trait_object; use std::cell::{Ref, RefMut}; use std::fmt::Debug; use std::time::Duration; -use swf::Twips; +use crate::prelude::Twips; /// Find the lowest common ancestor between the display objects in `from` and /// `to`. diff --git a/core/src/font.rs b/core/src/font.rs index de0eb5be1..88533ca70 100644 --- a/core/src/font.rs +++ b/core/src/font.rs @@ -691,7 +691,7 @@ mod tests { use crate::string::WStr; use gc_arena::{rootless_arena, MutationContext}; use ruffle_render::backend::{null::NullRenderer, ViewportDimensions}; - use swf::Twips; + use crate::prelude::Twips; fn with_device_font(callback: F) where diff --git a/core/src/html/layout.rs b/core/src/html/layout.rs index 8dd71f247..874ba5180 100644 --- a/core/src/html/layout.rs +++ b/core/src/html/layout.rs @@ -11,7 +11,7 @@ use gc_arena::Collect; use ruffle_render::shape_utils::DrawCommand; use std::cmp::{max, min}; use std::sync::Arc; -use swf::Twips; +use crate::prelude::Twips; /// Draw an underline on a particular drawing. /// diff --git a/core/src/tag_utils.rs b/core/src/tag_utils.rs index b4b3ecd56..278a0f43d 100644 --- a/core/src/tag_utils.rs +++ b/core/src/tag_utils.rs @@ -1,7 +1,8 @@ use gc_arena::Collect; use std::sync::Arc; -use swf::{CharacterId, Fixed8, HeaderExt, Rectangle, TagCode, Twips}; +use swf::{CharacterId, Fixed8, HeaderExt, Rectangle, TagCode}; use thiserror::Error; +use crate::prelude::Twips; #[derive(Error, Debug)] pub enum Error { diff --git a/render/src/bounding_box.rs b/render/src/bounding_box.rs index f07835d93..29f45704f 100644 --- a/render/src/bounding_box.rs +++ b/render/src/bounding_box.rs @@ -1,5 +1,5 @@ use crate::matrix::Matrix; -use swf::Twips; +use crate::prelude::Twips; #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct BoundingBox { diff --git a/swf/src/read.rs b/swf/src/read.rs index 09532506b..f212d8d66 100644 --- a/swf/src/read.rs +++ b/swf/src/read.rs @@ -9,6 +9,7 @@ use bitstream_io::BitRead; use byteorder::{LittleEndian, ReadBytesExt}; use simple_asn1::ASN1Block; use std::io::{self, Read}; +use crate::types::Twips; /// Parse a decompressed SWF. /// diff --git a/swf/src/types/matrix.rs b/swf/src/types/matrix.rs index ba7144293..681a14cac 100644 --- a/swf/src/types/matrix.rs +++ b/swf/src/types/matrix.rs @@ -1,4 +1,5 @@ -use crate::{Fixed16, Twips}; +use crate::Fixed16; +use crate::types::twips::Twips; use std::ops; /// The transformation matrix used by Flash display objects. diff --git a/swf/src/types/point.rs b/swf/src/types/point.rs new file mode 100644 index 000000000..4db62e9b0 --- /dev/null +++ b/swf/src/types/point.rs @@ -0,0 +1,172 @@ +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, PartialOrd, Ord)] +pub struct points(f32, f32); +impl Point { + + /// The `Point` object with a value of `(0, 0)`. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(swf::Point::ZERO.to_pixels(), (0.0, 0.0)); + /// ``` + pub const ZERO: Self = Self(0.0,0.0); + + /// The `Point` object with a value of `1` pixel. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(swf::Point::ONE.to_pixels(), 1.0); + /// ``` + pub const ONE: Self = Self(1.0,1.0); + + /// Creates a new `Point` object. Note that the `Point` value is in Point, + /// not pixels. Use the [`from_pixels`] method to convert from pixel units. + /// + /// [`from_pixels`]: Point::from_pixels + /// + /// # Examples + /// + /// ```rust + /// use swf::Point; + /// + /// let Point = Point::new(40,40); + /// ``` + pub fn new(x: X,y: Y) -> Self { + Self(x,y) + } + + /// Returns the values of Point. + /// + /// # Examples + /// + /// ```rust + /// use swf::Point; + /// + /// let Point = Point::new(47,47); + /// assert_eq!(Point.get(), (47,47)); + /// ``` + pub const fn get(self) -> (i32,i32) { + (Twips::get(self.0),Twips::get(self.1)) + } + + /// Converts the given number of `pixels` into Point. + /// + /// This may be a lossy conversion; any precision more than a twip (1/20 pixels) is truncated. + /// + /// # Examples + /// + /// ```rust + /// use swf::Point; + /// + /// // 40 pixels is equivalent to 800 Twips. + /// let Point = Point::from_pixels(40.0); + /// assert_eq!(Point.get(), 800); + /// + /// // Output is truncated if more precise than a twip (1/20 pixels). + /// let Point = Point::from_pixels(40.018); + /// assert_eq!(Point.get(), 800); + /// ``` + pub fn from_pixels(pixels:(f64,f64)) -> Self { + Self(Twips::new((pixels.0 * Self::TWIPS_PER_PIXEL)as i32),Twips::new((pixels.1 * Self::TWIPS_PER_PIXEL)as i32)) + } + + /// Converts this Point value into pixel units. + /// + /// This is a lossless operation. + /// + /// # Examples + /// + /// ```rust + /// use swf::Point; + /// + /// // 800 Point is equivalent to 40 pixels. + /// let Point = Point::new(800); + /// assert_eq!(Point.to_pixels(), 40.0); + /// + /// // Point are sub-pixel: 713 Point represent 35.65 pixels. + /// let Point = Point::new(713); + /// assert_eq!(Point.to_pixels(), 35.65); + /// ``` + pub fn to_pixels(self) -> (f64,f64) { + (f64::from(Twips::to_pixels(self.0)),f64::from(Twips::to_pixels(self.1)) ) + } + + /// Saturating integer subtraction. Computes `self - rhs`, saturating at the numeric bounds + /// of [`i32`] instead of overflowing. + /// + /// # Examples + /// + /// ```rust + /// use swf::Point; + /// + /// assert_eq!(Point::new(40).saturating_sub(Point::new(20)), Point::new(20)); + /// assert_eq!(Point::new(i32::MIN).saturating_sub(Point::new(5)), Point::new(i32::MIN)); + /// assert_eq!(Point::new(i32::MAX).saturating_sub(Point::new(-100)), Point::new(i32::MAX)); + /// ``` + #[must_use] + pub const fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0),self.1.saturating_sub(rhs.0)) + } +} + +impl std::ops::Add for Point { + type Output = Self; + fn add(self, other: Self) -> Self { + Self(self.0 + other.0,self.1 + other.1) + } +} + +impl std::ops::AddAssign for Point { + fn add_assign(&mut self, other: Self){ + self.0 += other.0; + self.1 += other.1; + } +} + +impl std::ops::Sub for Point { + type Output = Self; + fn sub(self, other: Self) -> Self { + Self(self.0 - other.0,self.1 - other.1) + } +} + +impl std::ops::SubAssign for Point { + fn sub_assign(&mut self, other: Self) { + self.0 -= other.0; + self.1 -= other.1; + } +} + +impl std::ops::Mul for Point { + type Output = Self; + fn mul(self, other: i32) -> Self { + Self(self.0 * other,self.1 * other) + } +} + +impl std::ops::MulAssign for Point { + fn mul_assign(&mut self, other: i32) { + self.0 *= other; + self.1 *= other; + } +} + +impl std::ops::Div for Point { + type Output = Self; + fn div(self, other: i32) -> Self { + Self(self.0 / other,self.1 / other) + } +} +impl std::ops::DivAssign for Point { + fn div_assign(&mut self, other: i32) { + self.0 /= other; + self.1 /= other; + } +} + +impl std::fmt::Display for Point { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "( {} , {} )", self.to_pixels().0, self.to_pixels().1) + } +} diff --git a/swf/src/types/twips.rs b/swf/src/types/twips.rs index 0cf3760f6..a404566c6 100644 --- a/swf/src/types/twips.rs +++ b/swf/src/types/twips.rs @@ -42,7 +42,7 @@ impl Twips { /// # Examples /// /// ```rust - /// use swf::Twips; + /// use crate::prelude::Twips; /// /// let twips = Twips::new(40); /// ``` @@ -55,7 +55,7 @@ impl Twips { /// # Examples /// /// ```rust - /// use swf::Twips; + /// use crate::prelude::Twips; /// /// let twips = Twips::new(47); /// assert_eq!(twips.get(), 47); @@ -71,7 +71,7 @@ impl Twips { /// # Examples /// /// ```rust - /// use swf::Twips; + /// use crate::prelude::Twips; /// /// // 40 pixels is equivalent to 800 twips. /// let twips = Twips::from_pixels(40.0); @@ -97,7 +97,7 @@ impl Twips { /// # Examples /// /// ```rust - /// use swf::Twips; + /// use crate::prelude::Twips; /// /// // 800 twips is equivalent to 40 pixels. /// let twips = Twips::new(800); diff --git a/swf/src/types/twips_2d.rs b/swf/src/types/twips_2d.rs index 73c85e983..1277e66db 100644 --- a/swf/src/types/twips_2d.rs +++ b/swf/src/types/twips_2d.rs @@ -1,3 +1,6 @@ +use swf::types::twips; +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, PartialOrd, Ord)] +pub struct Twips2d(Twips, Twips); impl Twips2d { /// There are 20 Twips2d in a pixel. pub const TWIPS_PER_PIXEL: f64 = 20.0; diff --git a/swf/src/write.rs b/swf/src/write.rs index dd0d37fe3..05890271b 100644 --- a/swf/src/write.rs +++ b/swf/src/write.rs @@ -3,6 +3,7 @@ use crate::{ string::SwfStr, tag_code::TagCode, types::*, + types::Twips }; use bitstream_io::BitWrite; use byteorder::{LittleEndian, WriteBytesExt};