swf: Extract `Rectangle` to a separate file

And make it generic, as a first step towards making it a general-purpose
data structure for the whole codebase. Some potential replacements are:
* `BoundingBox` in `render/src/bounding_box.rs`.
* `BoxBounds` in `core/src/html/dimensions.rs`.
* Parameters to a bunch of `BitmapData` methods in
  `core/src/bitmap/bitmap_data.rs`.
This commit is contained in:
relrelb 2022-09-23 00:40:12 +03:00 committed by relrelb
parent 898ccfba5d
commit e1d01b0a5e
13 changed files with 57 additions and 54 deletions

View File

@ -124,7 +124,7 @@ pub fn constructor<'gc>(
fn new_rectangle<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
rectangle: Rectangle,
rectangle: Rectangle<Twips>,
) -> Result<Value<'gc>, Error<'gc>> {
let x = rectangle.x_min.to_pixels();
let y = rectangle.y_min.to_pixels();
@ -138,7 +138,7 @@ fn new_rectangle<'gc>(
fn object_to_rectangle<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
object: Object<'gc>,
) -> Result<Option<Rectangle>, Error<'gc>> {
) -> Result<Option<Rectangle<Twips>>, Error<'gc>> {
const NAMES: &[&str] = &["x", "y", "width", "height"];
let mut values = [0; 4];
for (&name, value) in NAMES.iter().zip(&mut values) {

View File

@ -771,7 +771,7 @@ pub fn set_blend_mode<'gc>(
fn new_rectangle<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
rectangle: Rectangle,
rectangle: Rectangle<Twips>,
) -> Result<Object<'gc>, Error<'gc>> {
let x = rectangle.x_min.to_pixels();
let y = rectangle.y_min.to_pixels();
@ -803,7 +803,7 @@ fn scroll_rect<'gc>(
fn object_to_rectangle<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
object: Object<'gc>,
) -> Result<Rectangle, Error<'gc>> {
) -> Result<Rectangle<Twips>, Error<'gc>> {
const NAMES: &[&str] = &["x", "y", "width", "height"];
let mut values = [0.0; 4];
for (&name, value) in NAMES.iter().zip(&mut values) {

View File

@ -107,13 +107,13 @@ pub struct DisplayObjectBase<'gc> {
/// The 'internal' scroll rect used for rendering and methods like 'localToGlobal'.
/// This is updated from 'pre_render'
#[collect(require_static)]
scroll_rect: Option<Rectangle>,
scroll_rect: Option<Rectangle<Twips>>,
/// The 'next' scroll rect, which we will copy to 'scroll_rect' from 'pre_render'.
/// This is used by the ActionScript 'DisplayObject.scrollRect' getter, which sees
/// changes immediately (without needing wait for a render)
#[collect(require_static)]
next_scroll_rect: Rectangle,
next_scroll_rect: Rectangle<Twips>,
}
impl<'gc> Default for DisplayObjectBase<'gc> {
@ -1031,15 +1031,19 @@ pub trait TDisplayObject<'gc>:
self.base_mut(gc_context).set_maskee(node);
}
fn scroll_rect(&self) -> Option<Rectangle> {
fn scroll_rect(&self) -> Option<Rectangle<Twips>> {
self.base().scroll_rect.clone()
}
fn next_scroll_rect(&self) -> Rectangle {
fn next_scroll_rect(&self) -> Rectangle<Twips> {
self.base().next_scroll_rect.clone()
}
fn set_next_scroll_rect(&self, gc_context: MutationContext<'gc, '_>, rectangle: Rectangle) {
fn set_next_scroll_rect(
&self,
gc_context: MutationContext<'gc, '_>,
rectangle: Rectangle<Twips>,
) {
self.base_mut(gc_context).next_scroll_rect = rectangle;
}

View File

@ -1780,7 +1780,7 @@ bitflags::bitflags! {
struct EditTextStatic {
swf: Arc<SwfMovie>,
id: CharacterId,
bounds: swf::Rectangle,
bounds: swf::Rectangle<Twips>,
layout: Option<swf::TextLayout>,
initial_text: Option<WString>,
}

View File

@ -156,11 +156,11 @@ where
}
}
impl<T> From<BoxBounds<T>> for Rectangle
impl<T> From<BoxBounds<T>> for Rectangle<Twips>
where
T: Into<Twips> + Add<T, Output = T>,
{
fn from(bounds: BoxBounds<T>) -> Rectangle {
fn from(bounds: BoxBounds<T>) -> Rectangle<Twips> {
Rectangle {
x_min: bounds.offset_x.into(),
x_max: bounds.extent_x.into(),
@ -170,11 +170,11 @@ where
}
}
impl<T> From<Rectangle> for BoxBounds<T>
impl<T> From<Rectangle<Twips>> for BoxBounds<T>
where
T: From<Twips>,
{
fn from(bounds: Rectangle) -> Self {
fn from(bounds: Rectangle<Twips>) -> Self {
Self {
offset_x: T::from(bounds.x_min),
extent_x: T::from(bounds.x_max),

View File

@ -28,7 +28,7 @@ fn into_swf_rectangle() {
let pos = Position::from((Twips::new(3), Twips::new(5)));
let size = Size::from((Twips::new(20), Twips::new(80)));
let bounds = BoxBounds::from_position_and_size(pos, size);
let rect: Rectangle = bounds.into();
let rect: Rectangle<Twips> = bounds.into();
assert_eq!(
rect,

View File

@ -173,7 +173,7 @@ impl SwfMovie {
self.header.is_action_script_3()
}
pub fn stage_size(&self) -> &Rectangle {
pub fn stage_size(&self) -> &Rectangle<Twips> {
self.header.stage_size()
}

View File

@ -154,8 +154,8 @@ impl BoundingBox {
}
}
impl From<swf::Rectangle> for BoundingBox {
fn from(rect: swf::Rectangle) -> Self {
impl From<swf::Rectangle<Twips>> for BoundingBox {
fn from(rect: swf::Rectangle<Twips>) -> Self {
Self {
x_min: rect.x_min,
y_min: rect.y_min,
@ -166,8 +166,8 @@ impl From<swf::Rectangle> for BoundingBox {
}
}
impl From<&swf::Rectangle> for BoundingBox {
fn from(rect: &swf::Rectangle) -> Self {
impl From<&swf::Rectangle<Twips>> for BoundingBox {
fn from(rect: &swf::Rectangle<Twips>) -> Self {
Self {
x_min: rect.x_min,
y_min: rect.y_min,

View File

@ -3,7 +3,7 @@ use crate::matrix::Matrix;
use smallvec::SmallVec;
use swf::{CharacterId, FillStyle, LineStyle, Shape, ShapeRecord, Twips};
pub fn calculate_shape_bounds(shape_records: &[swf::ShapeRecord]) -> swf::Rectangle {
pub fn calculate_shape_bounds(shape_records: &[swf::ShapeRecord]) -> swf::Rectangle<Twips> {
let mut bounds = swf::Rectangle {
x_min: Twips::new(i32::MAX),
y_min: Twips::new(i32::MAX),

View File

@ -602,7 +602,7 @@ impl<'a> Reader<'a> {
Ok(tag)
}
pub fn read_rectangle(&mut self) -> Result<Rectangle> {
pub fn read_rectangle(&mut self) -> Result<Rectangle<Twips>> {
let mut bits = self.bits();
let num_bits = bits.read_ubits(5)?;
Ok(Rectangle {

View File

@ -12,11 +12,13 @@ use std::str::FromStr;
mod color;
mod fixed;
mod matrix;
mod rectangle;
mod twips;
pub use color::Color;
pub use fixed::{Fixed16, Fixed8};
pub use matrix::Matrix;
pub use rectangle::Rectangle;
pub use twips::Twips;
/// A complete header and tags in the SWF file.
@ -46,7 +48,7 @@ pub struct SwfBuf {
pub struct Header {
pub compression: Compression,
pub version: u8,
pub stage_size: Rectangle,
pub stage_size: Rectangle<Twips>,
pub frame_rate: Fixed8,
pub num_frames: u16,
}
@ -138,7 +140,7 @@ impl HeaderExt {
/// The stage dimensions of this SWF.
#[inline]
pub fn stage_size(&self) -> &Rectangle {
pub fn stage_size(&self) -> &Rectangle<Twips> {
&self.header.stage_size
}
@ -189,24 +191,6 @@ pub enum Compression {
Lzma,
}
/// A rectangular region defined by minimum
/// and maximum x- and y-coordinate positions
/// measured in [`Twips`].
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Rectangle {
/// The minimum x-position of the rectangle.
pub x_min: Twips,
/// The maximum x-position of the rectangle.
pub x_max: Twips,
/// The minimum y-position of the rectangle.
pub y_min: Twips,
/// The maximum y-position of the rectangle.
pub y_max: Twips,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ColorTransform {
pub r_multiply: Fixed8,
@ -635,7 +619,7 @@ pub enum Tag<'a> {
DefineMorphShape(Box<DefineMorphShape>),
DefineScalingGrid {
id: CharacterId,
splitter_rect: Rectangle,
splitter_rect: Rectangle<Twips>,
},
DefineShape(Shape),
DefineSound(Box<Sound<'a>>),
@ -724,8 +708,8 @@ pub struct ShapeContext {
pub struct Shape {
pub version: u8,
pub id: CharacterId,
pub shape_bounds: Rectangle,
pub edge_bounds: Rectangle,
pub shape_bounds: Rectangle<Twips>,
pub edge_bounds: Rectangle<Twips>,
pub flags: ShapeFlag,
pub styles: ShapeStyles,
pub shape: Vec<ShapeRecord>,
@ -1215,8 +1199,8 @@ bitflags! {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MorphShape {
pub shape_bounds: Rectangle,
pub edge_bounds: Rectangle,
pub shape_bounds: Rectangle<Twips>,
pub edge_bounds: Rectangle<Twips>,
pub fill_styles: Vec<FillStyle>,
pub line_styles: Vec<LineStyle>,
pub shape: Vec<ShapeRecord>,
@ -1266,7 +1250,7 @@ pub struct Glyph {
pub shape_records: Vec<ShapeRecord>,
pub code: u16,
pub advance: i16,
pub bounds: Option<Rectangle>,
pub bounds: Option<Rectangle<Twips>>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
@ -1314,7 +1298,7 @@ pub struct DefineBinaryData<'a> {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Text {
pub id: CharacterId,
pub bounds: Rectangle,
pub bounds: Rectangle<Twips>,
pub matrix: Matrix,
pub records: Vec<TextRecord>,
}
@ -1338,7 +1322,7 @@ pub struct GlyphEntry {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EditText<'a> {
pub(crate) id: CharacterId,
pub(crate) bounds: Rectangle,
pub(crate) bounds: Rectangle<Twips>,
pub(crate) font_id: CharacterId,
pub(crate) font_class: &'a SwfStr,
pub(crate) height: Twips,
@ -1357,12 +1341,12 @@ impl<'a> EditText<'a> {
}
#[inline]
pub fn bounds(&self) -> &Rectangle {
pub fn bounds(&self) -> &Rectangle<Twips> {
&self.bounds
}
#[inline]
pub fn with_bounds(mut self, bounds: Rectangle) -> Self {
pub fn with_bounds(mut self, bounds: Rectangle<Twips>) -> Self {
self.bounds = bounds;
self
}

View File

@ -0,0 +1,15 @@
/// A rectangular region defined by minimum and maximum x- and y-coordinate positions.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Rectangle<T> {
/// The minimum x-position of the rectangle.
pub x_min: T,
/// The maximum x-position of the rectangle.
pub x_max: T,
/// The minimum y-position of the rectangle.
pub y_min: T,
/// The maximum y-position of the rectangle.
pub y_max: T,
}

View File

@ -288,7 +288,7 @@ impl<W: Write> Writer<W> {
Ok(())
}
fn write_rectangle(&mut self, rectangle: &Rectangle) -> Result<()> {
fn write_rectangle(&mut self, rectangle: &Rectangle<Twips>) -> Result<()> {
let num_bits = [
rectangle.x_min,
rectangle.x_max,
@ -2614,7 +2614,7 @@ mod tests {
#[test]
fn write_rectangle_zero() {
let rect: Rectangle = Default::default();
let rect: Rectangle<Twips> = Default::default();
let mut buf = Vec::new();
{
let mut writer = Writer::new(&mut buf, 1);