swf: Simplify read of `PlaceObject` tags

`tag_length` isn't really necessary since each tag is read using
a dedicated `swf::Reader`, which keeps track of the tag boundary
internally.

As a result, `tag_len` can be avoided passed around many times in
`movie_clip.rs`.
This commit is contained in:
relrelb 2022-11-05 13:33:43 +02:00 committed by relrelb
parent 8f214ff9a3
commit c516fef65d
2 changed files with 27 additions and 81 deletions

View File

@ -1339,16 +1339,16 @@ impl<'gc> MovieClip<'gc> {
match tag_code {
TagCode::DoAction => self.do_action(context, reader, tag_len),
TagCode::PlaceObject if run_display_actions && !context.is_action_script_3() => {
self.place_object(context, reader, tag_len, 1)
self.place_object(context, reader, 1)
}
TagCode::PlaceObject2 if run_display_actions && !context.is_action_script_3() => {
self.place_object(context, reader, tag_len, 2)
self.place_object(context, reader, 2)
}
TagCode::PlaceObject3 if run_display_actions && !context.is_action_script_3() => {
self.place_object(context, reader, tag_len, 3)
self.place_object(context, reader, 3)
}
TagCode::PlaceObject4 if run_display_actions && !context.is_action_script_3() => {
self.place_object(context, reader, tag_len, 4)
self.place_object(context, reader, 4)
}
TagCode::RemoveObject if run_display_actions && !context.is_action_script_3() => {
self.remove_object(context, reader, 1)
@ -1357,22 +1357,22 @@ impl<'gc> MovieClip<'gc> {
self.remove_object(context, reader, 2)
}
TagCode::PlaceObject if run_display_actions && context.is_action_script_3() => {
self.queue_place_object(context, reader, tag_len, 1)
self.queue_place_object(context, reader, 1)
}
TagCode::PlaceObject2 if run_display_actions && context.is_action_script_3() => {
self.queue_place_object(context, reader, tag_len, 2)
self.queue_place_object(context, reader, 2)
}
TagCode::PlaceObject3 if run_display_actions && context.is_action_script_3() => {
self.queue_place_object(context, reader, tag_len, 3)
self.queue_place_object(context, reader, 3)
}
TagCode::PlaceObject4 if run_display_actions && context.is_action_script_3() => {
self.queue_place_object(context, reader, tag_len, 4)
self.queue_place_object(context, reader, 4)
}
TagCode::RemoveObject if run_display_actions && context.is_action_script_3() => {
self.queue_remove_object(context, reader, tag_len, 1)
self.queue_remove_object(context, reader, 1)
}
TagCode::RemoveObject2 if run_display_actions && context.is_action_script_3() => {
self.queue_remove_object(context, reader, tag_len, 2)
self.queue_remove_object(context, reader, 2)
}
TagCode::SetBackgroundColor => self.set_background_color(context, reader),
TagCode::StartSound if run_sounds => self.start_sound_1(context, reader),
@ -1675,60 +1675,28 @@ impl<'gc> MovieClip<'gc> {
self.0.write(context.gc_context).current_frame += 1;
frame_pos = reader.get_ref().as_ptr() as u64 - tag_stream_start;
use swf::TagCode;
let tag_callback = |reader: &mut _, tag_code, tag_len| {
let tag_callback = |reader: &mut _, tag_code, _tag_len| {
use swf::TagCode;
match tag_code {
TagCode::PlaceObject => {
index += 1;
let mut mc = self.0.write(context.gc_context);
mc.goto_place_object(
reader,
tag_len,
1,
&mut goto_commands,
is_rewind,
index,
)
mc.goto_place_object(reader, 1, &mut goto_commands, is_rewind, index)
}
TagCode::PlaceObject2 => {
index += 1;
let mut mc = self.0.write(context.gc_context);
mc.goto_place_object(
reader,
tag_len,
2,
&mut goto_commands,
is_rewind,
index,
)
mc.goto_place_object(reader, 2, &mut goto_commands, is_rewind, index)
}
TagCode::PlaceObject3 => {
index += 1;
let mut mc = self.0.write(context.gc_context);
mc.goto_place_object(
reader,
tag_len,
3,
&mut goto_commands,
is_rewind,
index,
)
mc.goto_place_object(reader, 3, &mut goto_commands, is_rewind, index)
}
TagCode::PlaceObject4 => {
index += 1;
let mut mc = self.0.write(context.gc_context);
mc.goto_place_object(
reader,
tag_len,
4,
&mut goto_commands,
is_rewind,
index,
)
mc.goto_place_object(reader, 4, &mut goto_commands, is_rewind, index)
}
TagCode::RemoveObject => self.goto_remove_object(
reader,
@ -1808,7 +1776,6 @@ impl<'gc> MovieClip<'gc> {
let new_tag = QueuedTag {
tag_type: QueuedTagAction::Place(params.version),
tag_start: params.tag_start,
tag_len: params.tag_len,
};
let bucket = write
.queued_tags
@ -2343,7 +2310,7 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
_ => unreachable!(),
};
if let Err(e) = self.place_object(context, &mut reader, tag.tag_len, version) {
if let Err(e) = self.place_object(context, &mut reader, version) {
log::error!("Error running queued tag: {:?}, got {}", tag.tag_type, e);
}
}
@ -2914,7 +2881,6 @@ impl<'gc> MovieClipData<'gc> {
fn goto_place_object<'a>(
&mut self,
reader: &mut SwfStream<'a>,
tag_len: usize,
version: u8,
goto_commands: &mut Vec<GotoPlaceObject<'a>>,
is_rewind: bool,
@ -2923,7 +2889,7 @@ impl<'gc> MovieClipData<'gc> {
let tag_start =
reader.get_ref().as_ptr() as u64 - self.static_data.swf.as_ref().as_ptr() as u64;
let place_object = if version == 1 {
reader.read_place_object(tag_len)
reader.read_place_object()
} else {
reader.read_place_object_2_or_3(version)
}?;
@ -2936,7 +2902,6 @@ impl<'gc> MovieClipData<'gc> {
is_rewind,
index,
tag_start,
tag_len,
version,
);
if let Some(i) = goto_commands.iter().position(|o| o.depth() == depth) {
@ -3663,14 +3628,13 @@ impl<'gc, 'a> MovieClip<'gc> {
self,
context: &mut UpdateContext<'_, 'gc, '_>,
reader: &mut SwfStream<'a>,
tag_len: usize,
version: u8,
) -> Result<(), Error> {
let mut write = self.0.write(context.gc_context);
let tag_start =
reader.get_ref().as_ptr() as u64 - write.static_data.swf.as_ref().as_ptr() as u64;
let place_object = if version == 1 {
reader.read_place_object(tag_len)
reader.read_place_object()
} else {
reader.read_place_object_2_or_3(version)
}?;
@ -3678,7 +3642,6 @@ impl<'gc, 'a> MovieClip<'gc> {
let new_tag = QueuedTag {
tag_type: QueuedTagAction::Place(version),
tag_start,
tag_len,
};
let bucket = write
.queued_tags
@ -3694,11 +3657,10 @@ impl<'gc, 'a> MovieClip<'gc> {
self,
context: &mut UpdateContext<'_, 'gc, '_>,
reader: &mut SwfStream<'a>,
tag_len: usize,
version: u8,
) -> Result<(), Error> {
let place_object = if version == 1 {
reader.read_place_object(tag_len)
reader.read_place_object()
} else {
reader.read_place_object_2_or_3(version)
}?;
@ -3753,7 +3715,6 @@ impl<'gc, 'a> MovieClip<'gc> {
self,
context: &mut UpdateContext<'_, 'gc, '_>,
reader: &mut SwfStream<'a>,
tag_len: usize,
version: u8,
) -> Result<(), Error> {
let mut write = self.0.write(context.gc_context);
@ -3768,7 +3729,6 @@ impl<'gc, 'a> MovieClip<'gc> {
let new_tag = QueuedTag {
tag_type: QueuedTagAction::Remove(version),
tag_start,
tag_len,
};
let bucket = write
.queued_tags
@ -3998,9 +3958,6 @@ struct GotoPlaceObject<'a> {
/// not possible and we want to add children after the goto completes.
tag_start: u64,
/// The length of the PlaceObject tag at `tag_start`.
tag_len: usize,
/// The version of the PlaceObject tag at `tag_start`.
version: u8,
}
@ -4012,7 +3969,6 @@ impl<'a> GotoPlaceObject<'a> {
is_rewind: bool,
index: usize,
tag_start: u64,
tag_len: usize,
version: u8,
) -> Self {
if is_rewind {
@ -4050,7 +4006,6 @@ impl<'a> GotoPlaceObject<'a> {
place_object,
index,
tag_start,
tag_len,
version,
}
}
@ -4177,7 +4132,6 @@ impl QueuedTagList {
pub struct QueuedTag {
pub tag_type: QueuedTagAction,
pub tag_start: u64,
pub tag_len: usize,
}
/// The type of queued tag.

View File

@ -591,9 +591,7 @@ impl<'a> Reader<'a> {
TagCode::DefineSprite => Tag::DefineSprite(tag_reader.read_define_sprite()?),
TagCode::PlaceObject => {
Tag::PlaceObject(Box::new(tag_reader.read_place_object(length)?))
}
TagCode::PlaceObject => Tag::PlaceObject(Box::new(tag_reader.read_place_object()?)),
TagCode::PlaceObject2 => {
Tag::PlaceObject(Box::new(tag_reader.read_place_object_2_or_3(2)?))
}
@ -1834,20 +1832,14 @@ impl<'a> Reader<'a> {
Ok(exports)
}
pub fn read_place_object(&mut self, tag_length: usize) -> Result<PlaceObject<'a>> {
// TODO: What's a best way to know if the tag has a color transform?
// You only know if there is still data remaining after the matrix.
// This sucks.
let mut vector = [0; 128];
self.get_mut().read_exact(&mut vector[..tag_length])?;
let mut reader = Reader::new(&vector[..], self.version);
pub fn read_place_object(&mut self) -> Result<PlaceObject<'a>> {
Ok(PlaceObject {
version: 1,
action: PlaceObjectAction::Place(reader.read_u16()?),
depth: reader.read_u16()?,
matrix: Some(reader.read_matrix()?),
color_transform: if !reader.get_ref().is_empty() {
Some(reader.read_color_transform(false)?)
action: PlaceObjectAction::Place(self.read_u16()?),
depth: self.read_u16()?,
matrix: Some(self.read_matrix()?),
color_transform: if !self.get_ref().is_empty() {
Some(self.read_color_transform(false)?)
} else {
None
},