swf: Return slices in swf::Reader
Avoid copies by returning slices of the decompressed input.
This commit is contained in:
parent
bf94f5dbaa
commit
19034b76e4
|
@ -209,11 +209,15 @@ pub trait SeekableDecoder: Decoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `StreamTagReader` reads through the SWF tag data of a `MovieClip`, extracting
|
||||||
|
/// audio data from the `SoundStreamBlock` tags. It can be used as an `Iterator` that
|
||||||
|
/// will return consecutive slices of the underlying audio data.
|
||||||
/// `StreamTagReader` reads through the SWF tag data of a `MovieClip`, extracting
|
/// `StreamTagReader` reads through the SWF tag data of a `MovieClip`, extracting
|
||||||
/// audio data from the `SoundStreamBlock` tags. It can be used as an `Iterator` that
|
/// audio data from the `SoundStreamBlock` tags. It can be used as an `Iterator` that
|
||||||
/// will return consecutive slices of the underlying audio data.
|
/// will return consecutive slices of the underlying audio data.
|
||||||
struct StreamTagReader {
|
struct StreamTagReader {
|
||||||
reader: swf::read::Reader<Cursor<SwfSlice>>,
|
swf_data: SwfSlice,
|
||||||
|
pos: usize,
|
||||||
current_frame: u16,
|
current_frame: u16,
|
||||||
current_audio_data: SwfSlice,
|
current_audio_data: SwfSlice,
|
||||||
compression: AudioCompression,
|
compression: AudioCompression,
|
||||||
|
@ -224,10 +228,10 @@ impl StreamTagReader {
|
||||||
/// `swf_data` should be the tag data of a MovieClip.
|
/// `swf_data` should be the tag data of a MovieClip.
|
||||||
fn new(compression: AudioCompression, swf_data: SwfSlice) -> Self {
|
fn new(compression: AudioCompression, swf_data: SwfSlice) -> Self {
|
||||||
let current_audio_data = SwfSlice::empty(swf_data.movie.clone());
|
let current_audio_data = SwfSlice::empty(swf_data.movie.clone());
|
||||||
let version = swf_data.version();
|
|
||||||
Self {
|
Self {
|
||||||
|
swf_data,
|
||||||
|
pos: 0,
|
||||||
compression,
|
compression,
|
||||||
reader: swf::read::Reader::new(Cursor::new(swf_data), version),
|
|
||||||
current_frame: 1,
|
current_frame: 1,
|
||||||
current_audio_data,
|
current_audio_data,
|
||||||
}
|
}
|
||||||
|
@ -250,40 +254,32 @@ impl Iterator for StreamTagReader {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
let tag_callback =
|
let swf_data = &self.swf_data;
|
||||||
|reader: &mut swf::read::Reader<Cursor<SwfSlice>>, tag_code, tag_len| match tag_code {
|
let tag_callback = |reader: &mut swf::read::Reader<'_>, tag_code, tag_len| match tag_code {
|
||||||
TagCode::ShowFrame => {
|
TagCode::ShowFrame => {
|
||||||
*current_frame += 1;
|
*current_frame += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
TagCode::SoundStreamBlock => {
|
TagCode::SoundStreamBlock => {
|
||||||
// TODO: Implement index ops on `SwfSlice`.
|
// TODO: Implement index ops on `SwfSlice`.
|
||||||
let pos = reader.get_ref().position() as usize;
|
//let pos = reader.get_ref().as_ptr() as usize - swf_data.as_ref().as_ptr() as usize;
|
||||||
let pos = reader.get_ref().get_ref().start + pos;
|
|
||||||
found = true;
|
found = true;
|
||||||
if tag_len >= skip_len {
|
if tag_len >= skip_len {
|
||||||
*audio_data = SwfSlice {
|
*audio_data = swf_data
|
||||||
movie: std::sync::Arc::clone(&reader.get_ref().get_ref().movie),
|
.to_subslice(&reader.get_ref()[skip_len..tag_len])
|
||||||
start: pos + skip_len,
|
.unwrap()
|
||||||
end: pos + tag_len,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
*audio_data = SwfSlice {
|
*audio_data = swf_data.to_subslice(&reader.get_ref()[..tag_len]).unwrap()
|
||||||
movie: std::sync::Arc::clone(&reader.get_ref().get_ref().movie),
|
|
||||||
start: pos,
|
|
||||||
end: pos + tag_len,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = crate::tag_utils::decode_tags(
|
let version = swf_data.version();
|
||||||
&mut self.reader,
|
let mut reader = swf::read::Reader::new(&self.swf_data.as_ref()[self.pos..], version);
|
||||||
tag_callback,
|
let _ = crate::tag_utils::decode_tags(&mut reader, tag_callback, TagCode::SoundStreamBlock);
|
||||||
TagCode::SoundStreamBlock,
|
self.pos = reader.get_ref().as_ptr() as usize - swf_data.as_ref().as_ptr() as usize;
|
||||||
);
|
|
||||||
|
|
||||||
if found {
|
if found {
|
||||||
Some(self.current_audio_data.clone())
|
Some(self.current_audio_data.clone())
|
||||||
|
|
|
@ -39,8 +39,9 @@ impl<'gc> Button<'gc> {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut actions = vec![];
|
let mut actions = vec![];
|
||||||
for action in &button.actions {
|
for action in &button.actions {
|
||||||
let action_data =
|
let action_data = source_movie
|
||||||
source_movie.owned_subslice(action.action_data.clone(), &source_movie.movie);
|
.to_unbounded_subslice(action.action_data)
|
||||||
|
.unwrap();
|
||||||
for condition in &action.conditions {
|
for condition in &action.conditions {
|
||||||
let button_action = ButtonAction {
|
let button_action = ButtonAction {
|
||||||
action_data: action_data.clone(),
|
action_data: action_data.clone(),
|
||||||
|
|
|
@ -207,7 +207,28 @@ impl<'gc> EditText<'gc> {
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
EditTextStatic {
|
EditTextStatic {
|
||||||
swf: swf_movie,
|
swf: swf_movie,
|
||||||
text: swf_tag,
|
text: EditTextStaticData {
|
||||||
|
id: swf_tag.id,
|
||||||
|
bounds: swf_tag.bounds,
|
||||||
|
font_id: swf_tag.font_id,
|
||||||
|
font_class_name: swf_tag.font_class_name.map(str::to_string),
|
||||||
|
height: swf_tag.height,
|
||||||
|
color: swf_tag.color.clone(),
|
||||||
|
max_length: swf_tag.max_length,
|
||||||
|
layout: swf_tag.layout.clone(),
|
||||||
|
variable_name: swf_tag.variable_name.to_string(),
|
||||||
|
initial_text: swf_tag.initial_text.map(str::to_string),
|
||||||
|
is_word_wrap: swf_tag.is_word_wrap,
|
||||||
|
is_multiline: swf_tag.is_multiline,
|
||||||
|
is_password: swf_tag.is_password,
|
||||||
|
is_read_only: swf_tag.is_read_only,
|
||||||
|
is_auto_size: swf_tag.is_auto_size,
|
||||||
|
is_selectable: swf_tag.is_selectable,
|
||||||
|
has_border: swf_tag.has_border,
|
||||||
|
was_static: swf_tag.was_static,
|
||||||
|
is_html: swf_tag.is_html,
|
||||||
|
is_device_font: swf_tag.is_device_font,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
is_multiline,
|
is_multiline,
|
||||||
|
@ -225,7 +246,7 @@ impl<'gc> EditText<'gc> {
|
||||||
intrinsic_bounds,
|
intrinsic_bounds,
|
||||||
bounds,
|
bounds,
|
||||||
autosize: AutoSizeMode::None,
|
autosize: AutoSizeMode::None,
|
||||||
variable,
|
variable: variable.map(str::to_string),
|
||||||
bound_stage_object: None,
|
bound_stage_object: None,
|
||||||
firing_variable_binding: false,
|
firing_variable_binding: false,
|
||||||
selection: None,
|
selection: None,
|
||||||
|
@ -272,7 +293,7 @@ impl<'gc> EditText<'gc> {
|
||||||
indent: Twips::from_pixels(0.0),
|
indent: Twips::from_pixels(0.0),
|
||||||
leading: Twips::from_pixels(0.0),
|
leading: Twips::from_pixels(0.0),
|
||||||
}),
|
}),
|
||||||
variable_name: "".to_string(), //TODO: should be null
|
variable_name: "", //TODO: should be null
|
||||||
initial_text: None,
|
initial_text: None,
|
||||||
is_word_wrap: false,
|
is_word_wrap: false,
|
||||||
is_multiline: false,
|
is_multiline: false,
|
||||||
|
@ -598,7 +619,7 @@ impl<'gc> EditText<'gc> {
|
||||||
.initial_text
|
.initial_text
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let _ = self.set_text(text, &mut activation.context);
|
let _ = self.set_text(text.to_string(), &mut activation.context);
|
||||||
|
|
||||||
self.0.write(activation.context.gc_context).variable = variable;
|
self.0.write(activation.context.gc_context).variable = variable;
|
||||||
self.try_bind_text_field_variable(activation, true);
|
self.try_bind_text_field_variable(activation, true);
|
||||||
|
@ -1535,15 +1556,37 @@ impl<'gc> TDisplayObject<'gc> for EditText<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Static data shared between all instances of a text object.
|
/// Static data shared between all instances of a text object.
|
||||||
#[allow(dead_code)]
|
#[derive(Debug, Clone, Collect)]
|
||||||
#[derive(Debug, Clone)]
|
#[collect(no_drop)]
|
||||||
struct EditTextStatic {
|
struct EditTextStatic {
|
||||||
swf: Arc<SwfMovie>,
|
swf: Arc<SwfMovie>,
|
||||||
text: swf::EditText,
|
text: EditTextStaticData,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct EditTextStaticData {
|
||||||
|
id: CharacterId,
|
||||||
|
bounds: swf::Rectangle,
|
||||||
|
font_id: Option<CharacterId>, // TODO(Herschel): Combine with height
|
||||||
|
font_class_name: Option<String>,
|
||||||
|
height: Option<Twips>,
|
||||||
|
color: Option<Color>,
|
||||||
|
max_length: Option<u16>,
|
||||||
|
layout: Option<swf::TextLayout>,
|
||||||
|
variable_name: String,
|
||||||
|
initial_text: Option<String>,
|
||||||
|
is_word_wrap: bool,
|
||||||
|
is_multiline: bool,
|
||||||
|
is_password: bool,
|
||||||
|
is_read_only: bool,
|
||||||
|
is_auto_size: bool,
|
||||||
|
is_selectable: bool,
|
||||||
|
has_border: bool,
|
||||||
|
was_static: bool,
|
||||||
|
is_html: bool,
|
||||||
|
is_device_font: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'gc> gc_arena::Collect for EditTextStatic {
|
unsafe impl<'gc> Collect for EditTextStaticData {
|
||||||
#[inline]
|
|
||||||
fn needs_trace() -> bool {
|
fn needs_trace() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,18 +170,10 @@ impl<'gc> MovieClip<'gc> {
|
||||||
// Should be able to hoist this up somewhere, or use MaybeUninit.
|
// Should be able to hoist this up somewhere, or use MaybeUninit.
|
||||||
let mut static_data = (&*self.0.read().static_data).clone();
|
let mut static_data = (&*self.0.read().static_data).clone();
|
||||||
let data = self.0.read().static_data.swf.clone();
|
let data = self.0.read().static_data.swf.clone();
|
||||||
let mut reader = data.read_from(self.0.read().tag_stream_pos);
|
let mut reader = data.read_from(0);
|
||||||
let mut cur_frame = 1;
|
let mut cur_frame = 1;
|
||||||
let mut ids = fnv::FnvHashMap::default();
|
let mut ids = fnv::FnvHashMap::default();
|
||||||
let version = reader.version();
|
let tag_callback = |reader: &mut SwfStream<'_>, tag_code, tag_len| match tag_code {
|
||||||
let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| {
|
|
||||||
let data = *reader.get_inner().get_ref();
|
|
||||||
let tag_pos = reader.get_inner().position() as usize;
|
|
||||||
let tag_slice = data
|
|
||||||
.get(tag_pos..tag_pos + tag_len)
|
|
||||||
.ok_or("Unexpected end of tag")?;
|
|
||||||
let reader = &mut SwfStream::new(std::io::Cursor::new(tag_slice), version);
|
|
||||||
match tag_code {
|
|
||||||
TagCode::FileAttributes => {
|
TagCode::FileAttributes => {
|
||||||
let attributes = reader.read_file_attributes()?;
|
let attributes = reader.read_file_attributes()?;
|
||||||
let avm_type = if attributes.is_action_script_3 {
|
let avm_type = if attributes.is_action_script_3 {
|
||||||
|
@ -366,34 +358,31 @@ impl<'gc> MovieClip<'gc> {
|
||||||
.0
|
.0
|
||||||
.write(context.gc_context)
|
.write(context.gc_context)
|
||||||
.preload_remove_object(context, reader, &mut ids, 2),
|
.preload_remove_object(context, reader, &mut ids, 2),
|
||||||
TagCode::ShowFrame => self.0.write(context.gc_context).preload_show_frame(
|
TagCode::ShowFrame => {
|
||||||
context,
|
self.0
|
||||||
reader,
|
.write(context.gc_context)
|
||||||
&mut cur_frame,
|
.preload_show_frame(context, reader, &mut cur_frame)
|
||||||
),
|
}
|
||||||
TagCode::ScriptLimits => self
|
TagCode::ScriptLimits => self
|
||||||
.0
|
.0
|
||||||
.write(context.gc_context)
|
.write(context.gc_context)
|
||||||
.script_limits(reader, context.avm1),
|
.script_limits(reader, context.avm1),
|
||||||
TagCode::SoundStreamHead => self
|
TagCode::SoundStreamHead => self.0.write(context.gc_context).preload_sound_stream_head(
|
||||||
.0
|
|
||||||
.write(context.gc_context)
|
|
||||||
.preload_sound_stream_head(context, reader, cur_frame, &mut static_data, 1),
|
|
||||||
TagCode::SoundStreamHead2 => self
|
|
||||||
.0
|
|
||||||
.write(context.gc_context)
|
|
||||||
.preload_sound_stream_head(context, reader, cur_frame, &mut static_data, 2),
|
|
||||||
TagCode::SoundStreamBlock => {
|
|
||||||
self.0.write(context.gc_context).preload_sound_stream_block(
|
|
||||||
context,
|
context,
|
||||||
reader,
|
reader,
|
||||||
cur_frame,
|
cur_frame,
|
||||||
&mut static_data,
|
&mut static_data,
|
||||||
tag_len,
|
1,
|
||||||
)
|
),
|
||||||
}
|
TagCode::SoundStreamHead2 => self
|
||||||
|
.0
|
||||||
|
.write(context.gc_context)
|
||||||
|
.preload_sound_stream_head(context, reader, cur_frame, &mut static_data, 2),
|
||||||
|
TagCode::SoundStreamBlock => self
|
||||||
|
.0
|
||||||
|
.write(context.gc_context)
|
||||||
|
.preload_sound_stream_block(context, reader, cur_frame, &mut static_data, tag_len),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End);
|
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::End);
|
||||||
self.0.write(context.gc_context).static_data =
|
self.0.write(context.gc_context).static_data =
|
||||||
|
@ -409,7 +398,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
fn do_init_action(
|
fn do_init_action(
|
||||||
self,
|
self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&[u8]>,
|
reader: &mut SwfStream<'_>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let movie = self.movie().unwrap();
|
let movie = self.movie().unwrap();
|
||||||
|
@ -454,7 +443,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
fn do_abc(
|
fn do_abc(
|
||||||
self,
|
self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&[u8]>,
|
reader: &mut SwfStream<'_>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let movie = self.movie().unwrap();
|
let movie = self.movie().unwrap();
|
||||||
|
@ -499,7 +488,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
fn symbol_class(
|
fn symbol_class(
|
||||||
self,
|
self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&[u8]>,
|
reader: &mut SwfStream<'_>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let movie = self
|
let movie = self
|
||||||
.movie()
|
.movie()
|
||||||
|
@ -560,7 +549,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn scene_and_frame_labels(
|
fn scene_and_frame_labels(
|
||||||
self,
|
self,
|
||||||
reader: &mut SwfStream<&[u8]>,
|
reader: &mut SwfStream<'_>,
|
||||||
static_data: &mut MovieClipStatic,
|
static_data: &mut MovieClipStatic,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let mut sfl_data = reader.read_define_scene_and_frame_label_data()?;
|
let mut sfl_data = reader.read_define_scene_and_frame_label_data()?;
|
||||||
|
@ -587,7 +576,9 @@ impl<'gc> MovieClip<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for FrameLabelData { frame_num, label } in sfl_data.frame_labels {
|
for FrameLabelData { frame_num, label } in sfl_data.frame_labels {
|
||||||
static_data.frame_labels.insert(label, frame_num as u16 + 1);
|
static_data
|
||||||
|
.frame_labels
|
||||||
|
.insert(label.to_string(), frame_num as u16 + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -918,11 +909,9 @@ impl<'gc> MovieClip<'gc> {
|
||||||
if frame > 0 && frame <= self.total_frames() {
|
if frame > 0 && frame <= self.total_frames() {
|
||||||
let mut cur_frame = 1;
|
let mut cur_frame = 1;
|
||||||
let clip = self.0.read();
|
let clip = self.0.read();
|
||||||
let len = clip.tag_stream_len();
|
|
||||||
let mut reader = clip.static_data.swf.read_from(0);
|
let mut reader = clip.static_data.swf.read_from(0);
|
||||||
while cur_frame <= frame && reader.get_ref().position() < len as u64 {
|
while cur_frame <= frame && !reader.get_ref().is_empty() {
|
||||||
let tag_callback =
|
let tag_callback = |reader: &mut Reader<'_>, tag_code, tag_len| {
|
||||||
|reader: &mut Reader<std::io::Cursor<&[u8]>>, tag_code, tag_len| {
|
|
||||||
match tag_code {
|
match tag_code {
|
||||||
TagCode::ShowFrame => cur_frame += 1,
|
TagCode::ShowFrame => cur_frame += 1,
|
||||||
TagCode::DoAction if cur_frame == frame => {
|
TagCode::DoAction if cur_frame == frame => {
|
||||||
|
@ -1004,22 +993,14 @@ impl<'gc> MovieClip<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mc = self.0.read();
|
let mc = self.0.read();
|
||||||
let _tag_pos = mc.tag_stream_pos;
|
let tag_stream_start = mc.static_data.swf.as_ref().as_ptr() as u64;
|
||||||
let data = mc.static_data.swf.clone();
|
let data = mc.static_data.swf.clone();
|
||||||
let mut reader = data.read_from(mc.tag_stream_pos);
|
let mut reader = data.read_from(mc.tag_stream_pos);
|
||||||
let mut has_stream_block = false;
|
let mut has_stream_block = false;
|
||||||
drop(mc);
|
drop(mc);
|
||||||
|
|
||||||
let version = reader.version();
|
|
||||||
use swf::TagCode;
|
use swf::TagCode;
|
||||||
let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| {
|
let tag_callback = |reader: &mut SwfStream<'_>, tag_code, tag_len| match tag_code {
|
||||||
let data = *reader.get_inner().get_ref();
|
|
||||||
let tag_pos = reader.get_inner().position() as usize;
|
|
||||||
let tag_slice = data
|
|
||||||
.get(tag_pos..tag_pos + tag_len)
|
|
||||||
.ok_or("Not enough data for tag")?;
|
|
||||||
let reader = &mut SwfStream::new(std::io::Cursor::new(tag_slice), version);
|
|
||||||
match tag_code {
|
|
||||||
TagCode::DoAction => self.do_action(self_display_object, context, reader, tag_len),
|
TagCode::DoAction => self.do_action(self_display_object, context, reader, tag_len),
|
||||||
TagCode::PlaceObject if run_display_actions => {
|
TagCode::PlaceObject if run_display_actions => {
|
||||||
self.place_object(self_display_object, context, reader, tag_len, 1)
|
self.place_object(self_display_object, context, reader, tag_len, 1)
|
||||||
|
@ -1033,12 +1014,8 @@ impl<'gc> MovieClip<'gc> {
|
||||||
TagCode::PlaceObject4 if run_display_actions => {
|
TagCode::PlaceObject4 if run_display_actions => {
|
||||||
self.place_object(self_display_object, context, reader, tag_len, 4)
|
self.place_object(self_display_object, context, reader, tag_len, 4)
|
||||||
}
|
}
|
||||||
TagCode::RemoveObject if run_display_actions => {
|
TagCode::RemoveObject if run_display_actions => self.remove_object(context, reader, 1),
|
||||||
self.remove_object(context, reader, 1)
|
TagCode::RemoveObject2 if run_display_actions => self.remove_object(context, reader, 2),
|
||||||
}
|
|
||||||
TagCode::RemoveObject2 if run_display_actions => {
|
|
||||||
self.remove_object(context, reader, 2)
|
|
||||||
}
|
|
||||||
TagCode::SetBackgroundColor => self.set_background_color(context, reader),
|
TagCode::SetBackgroundColor => self.set_background_color(context, reader),
|
||||||
TagCode::StartSound => self.start_sound_1(context, reader),
|
TagCode::StartSound => self.start_sound_1(context, reader),
|
||||||
TagCode::SoundStreamBlock => {
|
TagCode::SoundStreamBlock => {
|
||||||
|
@ -1046,11 +1023,11 @@ impl<'gc> MovieClip<'gc> {
|
||||||
self.sound_stream_block(context, reader)
|
self.sound_stream_block(context, reader)
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
|
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
|
||||||
|
|
||||||
self.0.write(context.gc_context).tag_stream_pos = reader.get_ref().position();
|
self.0.write(context.gc_context).tag_stream_pos =
|
||||||
|
reader.get_ref().as_ptr() as u64 - tag_stream_start;
|
||||||
|
|
||||||
// If we are playing a streaming sound, there should(?) be a `SoundStreamBlock` on each frame.
|
// If we are playing a streaming sound, there should(?) be a `SoundStreamBlock` on each frame.
|
||||||
if !has_stream_block {
|
if !has_stream_block {
|
||||||
|
@ -1150,7 +1127,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
|
|
||||||
// This map will maintain a map of depth -> placement commands.
|
// This map will maintain a map of depth -> placement commands.
|
||||||
// TODO: Move this to UpdateContext to avoid allocations.
|
// TODO: Move this to UpdateContext to avoid allocations.
|
||||||
let mut goto_commands = vec![];
|
let mut goto_commands: Vec<GotoPlaceObject<'_>> = vec![];
|
||||||
|
|
||||||
self.0.write(context.gc_context).stop_audio_stream(context);
|
self.0.write(context.gc_context).stop_audio_stream(context);
|
||||||
|
|
||||||
|
@ -1192,12 +1169,11 @@ impl<'gc> MovieClip<'gc> {
|
||||||
|
|
||||||
// Step through the intermediate frames, and aggregate the deltas of each frame.
|
// Step through the intermediate frames, and aggregate the deltas of each frame.
|
||||||
let mc = self.0.read();
|
let mc = self.0.read();
|
||||||
|
let tag_stream_start = mc.static_data.swf.as_ref().as_ptr() as u64;
|
||||||
let mut frame_pos = mc.tag_stream_pos;
|
let mut frame_pos = mc.tag_stream_pos;
|
||||||
let data = mc.static_data.swf.clone();
|
let data = mc.static_data.swf.clone();
|
||||||
let mut reader = data.read_from(mc.tag_stream_pos);
|
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
let len = mc.tag_stream_len() as u64;
|
|
||||||
// Sanity; let's make sure we don't seek way too far.
|
// Sanity; let's make sure we don't seek way too far.
|
||||||
// TODO: This should be self.frames_loaded() when we implement that.
|
// TODO: This should be self.frames_loaded() when we implement that.
|
||||||
let clamped_frame = if frame <= mc.total_frames() {
|
let clamped_frame = if frame <= mc.total_frames() {
|
||||||
|
@ -1207,69 +1183,36 @@ impl<'gc> MovieClip<'gc> {
|
||||||
};
|
};
|
||||||
drop(mc);
|
drop(mc);
|
||||||
|
|
||||||
while self.current_frame() < clamped_frame && frame_pos < len {
|
let mut reader = data.read_from(frame_pos);
|
||||||
|
while self.current_frame() < clamped_frame && !reader.get_ref().is_empty() {
|
||||||
self.0.write(context.gc_context).current_frame += 1;
|
self.0.write(context.gc_context).current_frame += 1;
|
||||||
frame_pos = reader.get_inner().position();
|
frame_pos = reader.get_ref().as_ptr() as u64 - tag_stream_start;
|
||||||
|
|
||||||
let version = reader.version();
|
|
||||||
use swf::TagCode;
|
use swf::TagCode;
|
||||||
let tag_callback = |reader: &mut SwfStream<&[u8]>, tag_code, tag_len| {
|
let tag_callback = |reader: &mut SwfStream<'gc>, tag_code, tag_len| match tag_code {
|
||||||
let data = *reader.get_inner().get_ref();
|
|
||||||
let tag_pos = reader.get_inner().position() as usize;
|
|
||||||
let tag_slice = &data[tag_pos..tag_pos + tag_len];
|
|
||||||
let reader = &mut SwfStream::new(std::io::Cursor::new(tag_slice), version);
|
|
||||||
match tag_code {
|
|
||||||
TagCode::PlaceObject => {
|
TagCode::PlaceObject => {
|
||||||
index += 1;
|
index += 1;
|
||||||
let mut mc = self.0.write(context.gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
|
|
||||||
mc.goto_place_object(
|
mc.goto_place_object(reader, tag_len, 1, &mut goto_commands, is_rewind, index)
|
||||||
reader,
|
|
||||||
tag_len,
|
|
||||||
1,
|
|
||||||
&mut goto_commands,
|
|
||||||
is_rewind,
|
|
||||||
index,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
TagCode::PlaceObject2 => {
|
TagCode::PlaceObject2 => {
|
||||||
index += 1;
|
index += 1;
|
||||||
let mut mc = self.0.write(context.gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
|
|
||||||
mc.goto_place_object(
|
mc.goto_place_object(reader, tag_len, 2, &mut goto_commands, is_rewind, index)
|
||||||
reader,
|
|
||||||
tag_len,
|
|
||||||
2,
|
|
||||||
&mut goto_commands,
|
|
||||||
is_rewind,
|
|
||||||
index,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
TagCode::PlaceObject3 => {
|
TagCode::PlaceObject3 => {
|
||||||
index += 1;
|
index += 1;
|
||||||
let mut mc = self.0.write(context.gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
|
|
||||||
mc.goto_place_object(
|
mc.goto_place_object(reader, tag_len, 3, &mut goto_commands, is_rewind, index)
|
||||||
reader,
|
|
||||||
tag_len,
|
|
||||||
3,
|
|
||||||
&mut goto_commands,
|
|
||||||
is_rewind,
|
|
||||||
index,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
TagCode::PlaceObject4 => {
|
TagCode::PlaceObject4 => {
|
||||||
index += 1;
|
index += 1;
|
||||||
let mut mc = self.0.write(context.gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
|
|
||||||
mc.goto_place_object(
|
mc.goto_place_object(reader, tag_len, 4, &mut goto_commands, is_rewind, index)
|
||||||
reader,
|
|
||||||
tag_len,
|
|
||||||
4,
|
|
||||||
&mut goto_commands,
|
|
||||||
is_rewind,
|
|
||||||
index,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
TagCode::RemoveObject => {
|
TagCode::RemoveObject => {
|
||||||
self.goto_remove_object(reader, 1, context, &mut goto_commands, is_rewind)
|
self.goto_remove_object(reader, 1, context, &mut goto_commands, is_rewind)
|
||||||
|
@ -1278,7 +1221,6 @@ impl<'gc> MovieClip<'gc> {
|
||||||
self.goto_remove_object(reader, 2, context, &mut goto_commands, is_rewind)
|
self.goto_remove_object(reader, 2, context, &mut goto_commands, is_rewind)
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
|
let _ = tag_utils::decode_tags(&mut reader, tag_callback, TagCode::ShowFrame);
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1229,7 @@ impl<'gc> MovieClip<'gc> {
|
||||||
// Run the list of goto commands to actually create and update the display objects.
|
// Run the list of goto commands to actually create and update the display objects.
|
||||||
let run_goto_command = |clip: MovieClip<'gc>,
|
let run_goto_command = |clip: MovieClip<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
params: &GotoPlaceObject| {
|
params: &GotoPlaceObject<'_>| {
|
||||||
let child_entry = clip.child_by_depth(params.depth());
|
let child_entry = clip.child_by_depth(params.depth());
|
||||||
match child_entry {
|
match child_entry {
|
||||||
// Apply final delta to display parameters.
|
// Apply final delta to display parameters.
|
||||||
|
@ -1564,10 +1506,10 @@ impl<'gc> MovieClip<'gc> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn goto_remove_object<'a>(
|
fn goto_remove_object<'a>(
|
||||||
mut self,
|
mut self,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
version: u8,
|
version: u8,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
goto_commands: &mut Vec<GotoPlaceObject>,
|
goto_commands: &mut Vec<GotoPlaceObject<'a>>,
|
||||||
is_rewind: bool,
|
is_rewind: bool,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let remove_object = if version == 1 {
|
let remove_object = if version == 1 {
|
||||||
|
@ -1940,10 +1882,10 @@ impl<'gc> MovieClipData<'gc> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn goto_place_object<'a>(
|
fn goto_place_object<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
version: u8,
|
version: u8,
|
||||||
goto_commands: &mut Vec<GotoPlaceObject>,
|
goto_commands: &mut Vec<GotoPlaceObject<'a>>,
|
||||||
is_rewind: bool,
|
is_rewind: bool,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
|
@ -2100,7 +2042,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_bits_lossless(
|
fn define_bits_lossless(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let define_bits_lossless = reader.read_define_bits_lossless(version)?;
|
let define_bits_lossless = reader.read_define_bits_lossless(version)?;
|
||||||
|
@ -2125,7 +2067,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_morph_shape(
|
fn define_morph_shape(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
morph_shapes: &mut fnv::FnvHashMap<CharacterId, MorphShapeStatic>,
|
morph_shapes: &mut fnv::FnvHashMap<CharacterId, MorphShapeStatic>,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
|
@ -2140,7 +2082,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_shape(
|
fn define_shape(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let swf_shape = reader.read_define_shape(version)?;
|
let swf_shape = reader.read_define_shape(version)?;
|
||||||
|
@ -2157,7 +2099,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn preload_place_object(
|
fn preload_place_object(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
ids: &mut fnv::FnvHashMap<Depth, CharacterId>,
|
ids: &mut fnv::FnvHashMap<Depth, CharacterId>,
|
||||||
morph_shapes: &mut fnv::FnvHashMap<CharacterId, MorphShapeStatic>,
|
morph_shapes: &mut fnv::FnvHashMap<CharacterId, MorphShapeStatic>,
|
||||||
|
@ -2207,15 +2149,13 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn preload_sound_stream_block(
|
fn preload_sound_stream_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
cur_frame: FrameNumber,
|
cur_frame: FrameNumber,
|
||||||
static_data: &mut MovieClipStatic,
|
static_data: &mut MovieClipStatic,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
if static_data.audio_stream_info.is_some() {
|
if static_data.audio_stream_info.is_some() {
|
||||||
let pos = reader.get_ref().position() as usize;
|
let data = &reader.get_ref()[..tag_len];
|
||||||
let data = reader.get_ref().get_ref();
|
|
||||||
let data = &data[pos..pos + tag_len];
|
|
||||||
context
|
context
|
||||||
.audio
|
.audio
|
||||||
.preload_sound_stream_block(self.id(), cur_frame, data);
|
.preload_sound_stream_block(self.id(), cur_frame, data);
|
||||||
|
@ -2228,7 +2168,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn preload_sound_stream_head(
|
fn preload_sound_stream_head(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
cur_frame: FrameNumber,
|
cur_frame: FrameNumber,
|
||||||
static_data: &mut MovieClipStatic,
|
static_data: &mut MovieClipStatic,
|
||||||
_version: u8,
|
_version: u8,
|
||||||
|
@ -2245,7 +2185,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_bits(
|
fn define_bits(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -2278,7 +2218,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_bits_jpeg_2(
|
fn define_bits_jpeg_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -2305,7 +2245,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_bits_jpeg_3(
|
fn define_bits_jpeg_3(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -2345,7 +2285,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_bits_jpeg_4(
|
fn define_bits_jpeg_4(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -2386,7 +2326,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_button_1(
|
fn define_button_1(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let swf_button = reader.read_define_button_1()?;
|
let swf_button = reader.read_define_button_1()?;
|
||||||
let button = Button::from_swf_tag(
|
let button = Button::from_swf_tag(
|
||||||
|
@ -2406,7 +2346,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_button_2(
|
fn define_button_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let swf_button = reader.read_define_button_2()?;
|
let swf_button = reader.read_define_button_2()?;
|
||||||
let button = Button::from_swf_tag(
|
let button = Button::from_swf_tag(
|
||||||
|
@ -2426,7 +2366,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_button_cxform(
|
fn define_button_cxform(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let button_colors = reader.read_define_button_cxform(tag_len)?;
|
let button_colors = reader.read_define_button_cxform(tag_len)?;
|
||||||
|
@ -2456,7 +2396,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_button_sound(
|
fn define_button_sound(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let button_sounds = reader.read_define_button_sound()?;
|
let button_sounds = reader.read_define_button_sound()?;
|
||||||
if let Some(button) = context
|
if let Some(button) = context
|
||||||
|
@ -2486,7 +2426,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_edit_text(
|
fn define_edit_text(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let swf_edit_text = reader.read_define_edit_text()?;
|
let swf_edit_text = reader.read_define_edit_text()?;
|
||||||
let edit_text = EditText::from_swf_tag(context, self.movie(), swf_edit_text);
|
let edit_text = EditText::from_swf_tag(context, self.movie(), swf_edit_text);
|
||||||
|
@ -2501,7 +2441,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_font_1(
|
fn define_font_1(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let font = reader.read_define_font_1()?;
|
let font = reader.read_define_font_1()?;
|
||||||
let glyphs = font
|
let glyphs = font
|
||||||
|
@ -2518,7 +2458,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
let font = swf::Font {
|
let font = swf::Font {
|
||||||
id: font.id,
|
id: font.id,
|
||||||
version: 0,
|
version: 0,
|
||||||
name: "".to_string(),
|
name: "",
|
||||||
glyphs,
|
glyphs,
|
||||||
language: swf::Language::Unknown,
|
language: swf::Language::Unknown,
|
||||||
layout: None,
|
layout: None,
|
||||||
|
@ -2540,7 +2480,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_font_2(
|
fn define_font_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let font = reader.read_define_font_2(2)?;
|
let font = reader.read_define_font_2(2)?;
|
||||||
let font_object = Font::from_swf_tag(context.gc_context, context.renderer, &font).unwrap();
|
let font_object = Font::from_swf_tag(context.gc_context, context.renderer, &font).unwrap();
|
||||||
|
@ -2555,7 +2495,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_font_3(
|
fn define_font_3(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let font = reader.read_define_font_2(3)?;
|
let font = reader.read_define_font_2(3)?;
|
||||||
let font_object = Font::from_swf_tag(context.gc_context, context.renderer, &font).unwrap();
|
let font_object = Font::from_swf_tag(context.gc_context, context.renderer, &font).unwrap();
|
||||||
|
@ -2571,7 +2511,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_font_4(
|
fn define_font_4(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_reader: &mut SwfStream<&'a [u8]>,
|
_reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
log::warn!("DefineFont4 tag (TLF text) is not implemented");
|
log::warn!("DefineFont4 tag (TLF text) is not implemented");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2581,7 +2521,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_sound(
|
fn define_sound(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let sound = reader.read_define_sound()?;
|
let sound = reader.read_define_sound()?;
|
||||||
if let Ok(handle) = context.audio.register_sound(&sound) {
|
if let Ok(handle) = context.audio.register_sound(&sound) {
|
||||||
|
@ -2601,7 +2541,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_sprite(
|
fn define_sprite(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
morph_shapes: &mut fnv::FnvHashMap<CharacterId, MorphShapeStatic>,
|
morph_shapes: &mut fnv::FnvHashMap<CharacterId, MorphShapeStatic>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
|
@ -2636,7 +2576,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn define_text(
|
fn define_text(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let text = reader.read_define_text(version)?;
|
let text = reader.read_define_text(version)?;
|
||||||
|
@ -2649,11 +2589,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn script_limits(
|
fn script_limits(&mut self, reader: &mut SwfStream<'a>, avm: &mut Avm1<'gc>) -> DecodeResult {
|
||||||
&mut self,
|
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
|
||||||
avm: &mut Avm1<'gc>,
|
|
||||||
) -> DecodeResult {
|
|
||||||
let max_recursion_depth = reader.read_u16()?;
|
let max_recursion_depth = reader.read_u16()?;
|
||||||
let _timeout_in_seconds = reader.read_u16()?;
|
let _timeout_in_seconds = reader.read_u16()?;
|
||||||
|
|
||||||
|
@ -2666,7 +2602,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn export_assets(
|
fn export_assets(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let exports = reader.read_export_assets()?;
|
let exports = reader.read_export_assets()?;
|
||||||
for export in exports {
|
for export in exports {
|
||||||
|
@ -2677,7 +2613,8 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
|
|
||||||
// TODO: do other types of Character need to know their exported name?
|
// TODO: do other types of Character need to know their exported name?
|
||||||
if let Some(Character::MovieClip(movie_clip)) = character {
|
if let Some(Character::MovieClip(movie_clip)) = character {
|
||||||
*movie_clip.0.read().static_data.exported_name.borrow_mut() = Some(export.name);
|
*movie_clip.0.read().static_data.exported_name.borrow_mut() =
|
||||||
|
Some(export.name.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2687,16 +2624,15 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn frame_label(
|
fn frame_label(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
cur_frame: FrameNumber,
|
cur_frame: FrameNumber,
|
||||||
static_data: &mut MovieClipStatic,
|
static_data: &mut MovieClipStatic,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let mut frame_label = reader.read_frame_label(tag_len)?;
|
let frame_label = reader.read_frame_label(tag_len)?;
|
||||||
// Frame labels are case insensitive (ASCII).
|
// Frame labels are case insensitive (ASCII).
|
||||||
frame_label.label.make_ascii_lowercase();
|
let label = frame_label.label.to_ascii_lowercase();
|
||||||
if let std::collections::hash_map::Entry::Vacant(v) =
|
if let std::collections::hash_map::Entry::Vacant(v) = static_data.frame_labels.entry(label)
|
||||||
static_data.frame_labels.entry(frame_label.label)
|
|
||||||
{
|
{
|
||||||
v.insert(cur_frame);
|
v.insert(cur_frame);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2709,7 +2645,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn jpeg_tables(
|
fn jpeg_tables(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -2727,7 +2663,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn preload_remove_object(
|
fn preload_remove_object(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
ids: &mut fnv::FnvHashMap<Depth, CharacterId>,
|
ids: &mut fnv::FnvHashMap<Depth, CharacterId>,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
|
@ -2744,7 +2680,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
|
||||||
fn preload_show_frame(
|
fn preload_show_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_reader: &mut SwfStream<&'a [u8]>,
|
_reader: &mut SwfStream<'a>,
|
||||||
cur_frame: &mut FrameNumber,
|
cur_frame: &mut FrameNumber,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
*cur_frame += 1;
|
*cur_frame += 1;
|
||||||
|
@ -2759,7 +2695,7 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
self,
|
self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let movie = self.movie().unwrap();
|
let movie = self.movie().unwrap();
|
||||||
|
@ -2795,7 +2731,7 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
self,
|
self,
|
||||||
self_display_object: DisplayObject<'gc>,
|
self_display_object: DisplayObject<'gc>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
tag_len: usize,
|
tag_len: usize,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
|
@ -2837,7 +2773,7 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
fn remove_object(
|
fn remove_object(
|
||||||
mut self,
|
mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
version: u8,
|
version: u8,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let remove_object = if version == 1 {
|
let remove_object = if version == 1 {
|
||||||
|
@ -2861,7 +2797,7 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
fn set_background_color(
|
fn set_background_color(
|
||||||
self,
|
self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
// Set background color if none set
|
// Set background color if none set
|
||||||
// bgcolor attribute on the HTML embed would override this
|
// bgcolor attribute on the HTML embed would override this
|
||||||
|
@ -2878,7 +2814,7 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
fn sound_stream_block(
|
fn sound_stream_block(
|
||||||
self,
|
self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
_reader: &mut SwfStream<&'a [u8]>,
|
_reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let mut mc = self.0.write(context.gc_context);
|
let mut mc = self.0.write(context.gc_context);
|
||||||
if mc.playing() {
|
if mc.playing() {
|
||||||
|
@ -2911,7 +2847,7 @@ impl<'gc, 'a> MovieClip<'gc> {
|
||||||
fn start_sound_1(
|
fn start_sound_1(
|
||||||
self,
|
self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut SwfStream<&'a [u8]>,
|
reader: &mut SwfStream<'a>,
|
||||||
) -> DecodeResult {
|
) -> DecodeResult {
|
||||||
let start_sound = reader.read_start_sound_1()?;
|
let start_sound = reader.read_start_sound_1()?;
|
||||||
if let Some(handle) = context
|
if let Some(handle) = context
|
||||||
|
@ -2996,19 +2932,19 @@ impl MovieClipStatic {
|
||||||
/// Stores the placement settings for display objects during a
|
/// Stores the placement settings for display objects during a
|
||||||
/// goto command.
|
/// goto command.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct GotoPlaceObject {
|
struct GotoPlaceObject<'a> {
|
||||||
/// The frame number that this character was first placed on.
|
/// The frame number that this character was first placed on.
|
||||||
frame: FrameNumber,
|
frame: FrameNumber,
|
||||||
/// The display properties of the object.
|
/// The display properties of the object.
|
||||||
place_object: swf::PlaceObject,
|
place_object: swf::PlaceObject<'a>,
|
||||||
/// Increasing index of this place command, for sorting.
|
/// Increasing index of this place command, for sorting.
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GotoPlaceObject {
|
impl<'a> GotoPlaceObject<'a> {
|
||||||
fn new(
|
fn new(
|
||||||
frame: FrameNumber,
|
frame: FrameNumber,
|
||||||
mut place_object: swf::PlaceObject,
|
mut place_object: swf::PlaceObject<'a>,
|
||||||
is_rewind: bool,
|
is_rewind: bool,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -3063,7 +2999,7 @@ impl GotoPlaceObject {
|
||||||
self.place_object.depth.into()
|
self.place_object.depth.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge(&mut self, next: &mut GotoPlaceObject) {
|
fn merge(&mut self, next: &mut GotoPlaceObject<'a>) {
|
||||||
use swf::PlaceObjectAction;
|
use swf::PlaceObjectAction;
|
||||||
let cur_place = &mut self.place_object;
|
let cur_place = &mut self.place_object;
|
||||||
let next_place = &mut next.place_object;
|
let next_place = &mut next.place_object;
|
||||||
|
@ -3136,14 +3072,15 @@ impl ClipAction {
|
||||||
/// Instead, we have to construct a fake `SwfMovie` just to hold one clip
|
/// Instead, we have to construct a fake `SwfMovie` just to hold one clip
|
||||||
/// action.
|
/// action.
|
||||||
pub fn from_action_and_movie(
|
pub fn from_action_and_movie(
|
||||||
other: swf::ClipAction,
|
other: swf::ClipAction<'_>,
|
||||||
movie: Arc<SwfMovie>,
|
movie: Arc<SwfMovie>,
|
||||||
) -> impl Iterator<Item = Self> {
|
) -> impl Iterator<Item = Self> {
|
||||||
use swf::ClipEventFlag;
|
use swf::ClipEventFlag;
|
||||||
|
|
||||||
let len = other.action_data.len();
|
|
||||||
let key_code = other.key_code;
|
let key_code = other.key_code;
|
||||||
let movie = Arc::new(movie.from_movie_and_subdata(other.action_data, &movie));
|
let action_data = SwfSlice::from(movie)
|
||||||
|
.to_unbounded_subslice(other.action_data)
|
||||||
|
.unwrap();
|
||||||
other.events.into_iter().map(move |event| Self {
|
other.events.into_iter().map(move |event| Self {
|
||||||
event: match event {
|
event: match event {
|
||||||
ClipEventFlag::Construct => ClipEvent::Construct,
|
ClipEventFlag::Construct => ClipEvent::Construct,
|
||||||
|
@ -3170,11 +3107,7 @@ impl ClipAction {
|
||||||
ClipEventFlag::ReleaseOutside => ClipEvent::ReleaseOutside,
|
ClipEventFlag::ReleaseOutside => ClipEvent::ReleaseOutside,
|
||||||
ClipEventFlag::Unload => ClipEvent::Unload,
|
ClipEventFlag::Unload => ClipEvent::Unload,
|
||||||
},
|
},
|
||||||
action_data: SwfSlice {
|
action_data: action_data.clone(),
|
||||||
movie: Arc::clone(&movie),
|
|
||||||
start: 0,
|
|
||||||
end: len,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,7 +393,7 @@ pub struct FontDescriptor {
|
||||||
impl FontDescriptor {
|
impl FontDescriptor {
|
||||||
/// Obtain a font descriptor from a SWF font tag.
|
/// Obtain a font descriptor from a SWF font tag.
|
||||||
pub fn from_swf_tag(val: &swf::Font) -> Self {
|
pub fn from_swf_tag(val: &swf::Font) -> Self {
|
||||||
let mut name = val.name.clone();
|
let mut name = val.name.to_string();
|
||||||
|
|
||||||
if let Some(first_null) = name.find('\0') {
|
if let Some(first_null) = name.find('\0') {
|
||||||
name.truncate(first_null);
|
name.truncate(first_null);
|
||||||
|
|
|
@ -189,7 +189,7 @@ impl TextFormat {
|
||||||
/// This requires an `UpdateContext` as we will need to retrieve some font
|
/// This requires an `UpdateContext` as we will need to retrieve some font
|
||||||
/// information from the actually-referenced font.
|
/// information from the actually-referenced font.
|
||||||
pub fn from_swf_tag<'gc>(
|
pub fn from_swf_tag<'gc>(
|
||||||
et: swf::EditText,
|
et: swf::EditText<'_>,
|
||||||
swf_movie: Arc<SwfMovie>,
|
swf_movie: Arc<SwfMovie>,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -198,7 +198,7 @@ impl TextFormat {
|
||||||
let font = et.font_id.and_then(|fid| movie_library.get_font(fid));
|
let font = et.font_id.and_then(|fid| movie_library.get_font(fid));
|
||||||
let font_class = et
|
let font_class = et
|
||||||
.font_class_name
|
.font_class_name
|
||||||
.clone()
|
.map(str::to_string)
|
||||||
.or_else(|| font.map(|font| font.descriptor().class().to_string()))
|
.or_else(|| font.map(|font| font.descriptor().class().to_string()))
|
||||||
.unwrap_or_else(|| "Times New Roman".to_string());
|
.unwrap_or_else(|| "Times New Roman".to_string());
|
||||||
let align = et.layout.clone().map(|l| l.align);
|
let align = et.layout.clone().map(|l| l.align);
|
||||||
|
@ -211,7 +211,7 @@ impl TextFormat {
|
||||||
// Times New Roman non-bold, non-italic. This will need to be revised
|
// Times New Roman non-bold, non-italic. This will need to be revised
|
||||||
// when we start supporting device fonts.
|
// when we start supporting device fonts.
|
||||||
Self {
|
Self {
|
||||||
font: Some(font_class),
|
font: Some(font_class.to_string()),
|
||||||
size: et.height.map(|h| h.to_pixels()),
|
size: et.height.map(|h| h.to_pixels()),
|
||||||
color: et.color,
|
color: et.color,
|
||||||
align,
|
align,
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use crate::backend::navigator::url_from_relative_path;
|
use crate::backend::navigator::url_from_relative_path;
|
||||||
use crate::property_map::PropertyMap;
|
use crate::property_map::PropertyMap;
|
||||||
use gc_arena::Collect;
|
use gc_arena::Collect;
|
||||||
use std::convert::TryInto;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use swf::{Header, TagCode};
|
use swf::{Header, TagCode};
|
||||||
|
|
||||||
pub type Error = Box<dyn std::error::Error>;
|
pub type Error = Box<dyn std::error::Error>;
|
||||||
pub type DecodeResult = Result<(), Error>;
|
pub type DecodeResult = Result<(), Error>;
|
||||||
pub type SwfStream<R> = swf::read::Reader<std::io::Cursor<R>>;
|
pub type SwfStream<'a> = swf::read::Reader<'a>;
|
||||||
|
|
||||||
/// An open, fully parsed SWF movie ready to play back, either in a Player or a
|
/// An open, fully parsed SWF movie ready to play back, either in a Player or a
|
||||||
/// MovieClip.
|
/// MovieClip.
|
||||||
|
@ -75,21 +74,9 @@ impl SwfMovie {
|
||||||
/// Construct a movie based on the contents of the SWF datastream.
|
/// Construct a movie based on the contents of the SWF datastream.
|
||||||
pub fn from_data(swf_data: &[u8], url: Option<String>) -> Result<Self, Error> {
|
pub fn from_data(swf_data: &[u8], url: Option<String>) -> Result<Self, Error> {
|
||||||
let swf_stream = swf::read::read_swf_header(&swf_data[..])?;
|
let swf_stream = swf::read::read_swf_header(&swf_data[..])?;
|
||||||
let header = swf_stream.header;
|
|
||||||
let mut reader = swf_stream.reader;
|
|
||||||
|
|
||||||
// Decompress the entire SWF in memory.
|
|
||||||
// Sometimes SWFs will have an incorrectly compressed stream,
|
|
||||||
// but will otherwise decompress fine up to the End tag.
|
|
||||||
// So just warn on this case and try to continue gracefully.
|
|
||||||
let mut data = Vec::with_capacity(header.uncompressed_length.try_into().unwrap());
|
|
||||||
if let Err(e) = reader.get_mut().read_to_end(&mut data) {
|
|
||||||
return Err(format!("Error decompressing SWF, may be corrupt: {}", e).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
header,
|
header: swf_stream.header,
|
||||||
data,
|
data: swf_stream.data,
|
||||||
url,
|
url,
|
||||||
parameters: PropertyMap::new(),
|
parameters: PropertyMap::new(),
|
||||||
})
|
})
|
||||||
|
@ -169,20 +156,6 @@ impl SwfSlice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a new slice with a given dataset only.
|
|
||||||
///
|
|
||||||
/// This is used primarily for converting owned data back into a slice: we
|
|
||||||
/// reattach the SWF data to a fresh movie and return a new slice into it.
|
|
||||||
pub fn owned_subslice(&self, data: Vec<u8>, source: &SwfMovie) -> Self {
|
|
||||||
let len = data.len();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
movie: Arc::new(self.movie.from_movie_and_subdata(data, source)),
|
|
||||||
start: 0,
|
|
||||||
end: len,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a new SwfSlice from a regular slice.
|
/// Construct a new SwfSlice from a regular slice.
|
||||||
///
|
///
|
||||||
/// This function returns None if the given slice is not a subslice of the
|
/// This function returns None if the given slice is not a subslice of the
|
||||||
|
@ -232,16 +205,15 @@ impl SwfSlice {
|
||||||
/// If the resulting slice would be outside the bounds of the underlying
|
/// If the resulting slice would be outside the bounds of the underlying
|
||||||
/// movie, or the given reader refers to a different underlying movie, this
|
/// movie, or the given reader refers to a different underlying movie, this
|
||||||
/// function returns None.
|
/// function returns None.
|
||||||
pub fn resize_to_reader(&self, reader: &mut SwfStream<&[u8]>, size: usize) -> Option<SwfSlice> {
|
pub fn resize_to_reader(&self, reader: &mut SwfStream<'_>, size: usize) -> Option<SwfSlice> {
|
||||||
if self.movie.data().as_ptr() as usize <= reader.get_ref().get_ref().as_ptr() as usize
|
if self.movie.data().as_ptr() as usize <= reader.get_ref().as_ptr() as usize
|
||||||
&& (reader.get_ref().get_ref().as_ptr() as usize)
|
&& (reader.get_ref().as_ptr() as usize)
|
||||||
< self.movie.data().as_ptr() as usize + self.movie.data().len()
|
< self.movie.data().as_ptr() as usize + self.movie.data().len()
|
||||||
{
|
{
|
||||||
let outer_offset =
|
let outer_offset =
|
||||||
reader.get_ref().get_ref().as_ptr() as usize - self.movie.data().as_ptr() as usize;
|
reader.get_ref().as_ptr() as usize - self.movie.data().as_ptr() as usize;
|
||||||
let inner_offset = reader.get_ref().position() as usize;
|
let new_start = outer_offset;
|
||||||
let new_start = outer_offset + inner_offset;
|
let new_end = outer_offset + size;
|
||||||
let new_end = outer_offset + inner_offset + size;
|
|
||||||
|
|
||||||
let len = self.movie.data().len();
|
let len = self.movie.data().len();
|
||||||
|
|
||||||
|
@ -289,29 +261,26 @@ impl SwfSlice {
|
||||||
/// Construct a reader for this slice.
|
/// Construct a reader for this slice.
|
||||||
///
|
///
|
||||||
/// The `from` parameter is the offset to start reading the slice from.
|
/// The `from` parameter is the offset to start reading the slice from.
|
||||||
pub fn read_from(&self, from: u64) -> swf::read::Reader<std::io::Cursor<&[u8]>> {
|
pub fn read_from(&self, from: u64) -> swf::read::Reader<'_> {
|
||||||
let mut cursor = std::io::Cursor::new(self.data());
|
swf::read::Reader::new(&self.data()[from as usize..], self.movie.version())
|
||||||
cursor.set_position(from);
|
|
||||||
swf::read::Reader::new(cursor, self.movie.version())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_tags<'a, R, F>(
|
pub fn decode_tags<'a, F>(
|
||||||
reader: &'a mut SwfStream<R>,
|
reader: &mut SwfStream<'a>,
|
||||||
mut tag_callback: F,
|
mut tag_callback: F,
|
||||||
stop_tag: TagCode,
|
stop_tag: TagCode,
|
||||||
) -> Result<(), Box<dyn std::error::Error>>
|
) -> Result<(), Box<dyn std::error::Error>>
|
||||||
where
|
where
|
||||||
R: 'a + AsRef<[u8]>,
|
F: for<'b> FnMut(&'b mut SwfStream<'a>, TagCode, usize) -> DecodeResult,
|
||||||
F: FnMut(&mut SwfStream<R>, TagCode, usize) -> DecodeResult,
|
|
||||||
{
|
{
|
||||||
use std::io::{Seek, SeekFrom};
|
|
||||||
loop {
|
loop {
|
||||||
let (tag_code, tag_len) = reader.read_tag_code_and_length()?;
|
let (tag_code, tag_len) = reader.read_tag_code_and_length()?;
|
||||||
let end_pos = reader.get_ref().position() + tag_len as u64;
|
|
||||||
|
|
||||||
let tag = TagCode::from_u16(tag_code);
|
let tag = TagCode::from_u16(tag_code);
|
||||||
|
let tag_slice = &reader.get_ref()[..tag_len];
|
||||||
|
let end_slice = &reader.get_ref()[tag_len..];
|
||||||
if let Some(tag) = tag {
|
if let Some(tag) = tag {
|
||||||
|
*reader.get_mut() = tag_slice;
|
||||||
let result = tag_callback(reader, tag, tag_len);
|
let result = tag_callback(reader, tag, tag_len);
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
|
@ -319,14 +288,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
if stop_tag == tag {
|
if stop_tag == tag {
|
||||||
reader.get_mut().seek(SeekFrom::Start(end_pos))?;
|
*reader.get_mut() = end_slice;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Unknown tag code: {:?}", tag_code);
|
log::warn!("Unknown tag code: {:?}", tag_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.get_mut().seek(SeekFrom::Start(end_pos))?;
|
*reader.get_mut() = end_slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use path_slash::PathExt;
|
use path_slash::PathExt;
|
||||||
use ruffle_core::swf::read_swf;
|
use ruffle_core::swf::{read_swf, read_swf_header};
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -65,7 +65,8 @@ fn scan_file(file: DirEntry, name: String) -> FileResults {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match catch_unwind(|| read_swf(&data[..])) {
|
let swf_stream = read_swf_header(&data[..]).unwrap();
|
||||||
|
match catch_unwind(|| read_swf(&swf_stream)) {
|
||||||
Ok(swf) => match swf {
|
Ok(swf) => match swf {
|
||||||
Ok(_swf) => FileResults { name, error: None },
|
Ok(_swf) => FileResults { name, error: None },
|
||||||
Err(e) => FileResults {
|
Err(e) => FileResults {
|
||||||
|
|
|
@ -4,7 +4,8 @@ use std::io::BufReader;
|
||||||
fn main() {
|
fn main() {
|
||||||
let file = File::open("tests/swfs/SimpleRedBackground.swf").unwrap();
|
let file = File::open("tests/swfs/SimpleRedBackground.swf").unwrap();
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
let swf = swf::read_swf(reader).unwrap();
|
let swf_stream = swf::read_swf_header(reader).unwrap();
|
||||||
|
let swf = swf::read_swf(&swf_stream).unwrap();
|
||||||
println!("The SWF has {} frame(s).", swf.header.num_frames);
|
println!("The SWF has {} frame(s).", swf.header.num_frames);
|
||||||
println!("The SWF has {} tag(s).", swf.tags.len());
|
println!("The SWF has {} tag(s).", swf.tags.len());
|
||||||
}
|
}
|
||||||
|
|
|
@ -873,15 +873,12 @@ pub mod tests {
|
||||||
|
|
||||||
pub fn read_abc_from_file(path: &str) -> Vec<u8> {
|
pub fn read_abc_from_file(path: &str) -> Vec<u8> {
|
||||||
use crate::types::Tag;
|
use crate::types::Tag;
|
||||||
use std::fs::File;
|
let data = std::fs::read(path).unwrap();
|
||||||
|
let swf_stream = crate::read_swf_header(&data[..]).unwrap();
|
||||||
let mut file = File::open(path).unwrap();
|
let swf = crate::read_swf(&swf_stream).unwrap();
|
||||||
let mut data = Vec::new();
|
|
||||||
file.read_to_end(&mut data).unwrap();
|
|
||||||
let swf = crate::read_swf(&data[..]).unwrap();
|
|
||||||
for tag in swf.tags {
|
for tag in swf.tags {
|
||||||
if let Tag::DoAbc(do_abc) = tag {
|
if let Tag::DoAbc(do_abc) = tag {
|
||||||
return do_abc.data;
|
return do_abc.data.to_vec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("ABC tag not found in {}", path);
|
panic!("ABC tag not found in {}", path);
|
||||||
|
|
486
swf/src/read.rs
486
swf/src/read.rs
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
||||||
use crate::avm1::types::*;
|
use crate::avm1::types::*;
|
||||||
use crate::avm2::read::tests::read_abc_from_file;
|
use crate::avm2::read::tests::read_abc_from_file;
|
||||||
use crate::avm2::types::*;
|
use crate::avm2::types::*;
|
||||||
use crate::read::read_swf;
|
use crate::read::{read_swf, read_swf_header};
|
||||||
use crate::read::tests::{read_tag_bytes_from_file, read_tag_bytes_from_file_with_index};
|
use crate::read::tests::{read_tag_bytes_from_file, read_tag_bytes_from_file_with_index};
|
||||||
use crate::tag_code::TagCode;
|
use crate::tag_code::TagCode;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
@ -13,14 +13,15 @@ use std::vec::Vec;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn echo_swf(filename: &str) {
|
pub fn echo_swf(filename: &str) {
|
||||||
let in_file = File::open(filename).unwrap();
|
let in_data = std::fs::read(filename).unwrap();
|
||||||
let swf = read_swf(in_file).unwrap();
|
let swf_stream = read_swf_header(&in_data[..]).unwrap();
|
||||||
|
let swf = read_swf(&swf_stream).unwrap();
|
||||||
let out_file = File::create(filename).unwrap();
|
let out_file = File::create(filename).unwrap();
|
||||||
write_swf(&swf, out_file).unwrap();
|
write_swf(&swf, out_file).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TestData<T> = (u8, T, Vec<u8>);
|
pub type TestData<T> = (u8, T, Vec<u8>);
|
||||||
pub type TagTestData = TestData<Tag>;
|
pub type TagTestData = TestData<Tag<'static>>;
|
||||||
pub type Avm1TestData = TestData<Action<'static>>;
|
pub type Avm1TestData = TestData<Action<'static>>;
|
||||||
pub type Avm2TestData = TestData<AbcFile>;
|
pub type Avm2TestData = TestData<AbcFile>;
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
9, // Minimum version not listed in SWF19.
|
9, // Minimum version not listed in SWF19.
|
||||||
Tag::DefineBinaryData {
|
Tag::DefineBinaryData {
|
||||||
id: 1,
|
id: 1,
|
||||||
data: vec![84, 101, 115, 116, 105, 110, 103, 33],
|
data: &[84, 101, 115, 116, 105, 110, 103, 33],
|
||||||
},
|
},
|
||||||
read_tag_bytes_from_file("tests/swfs/DefineBinaryData.swf", TagCode::DefineBinaryData),
|
read_tag_bytes_from_file("tests/swfs/DefineBinaryData.swf", TagCode::DefineBinaryData),
|
||||||
),
|
),
|
||||||
|
@ -49,7 +50,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
1,
|
1,
|
||||||
Tag::DefineBits {
|
Tag::DefineBits {
|
||||||
id: 1,
|
id: 1,
|
||||||
jpeg_data: vec![
|
jpeg_data: &[
|
||||||
255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255,
|
255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255,
|
||||||
192, 0, 17, 8, 0, 5, 0, 6, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1, 255, 218, 0, 12, 3,
|
192, 0, 17, 8, 0, 5, 0, 6, 3, 1, 34, 0, 2, 17, 1, 3, 17, 1, 255, 218, 0, 12, 3,
|
||||||
1, 0, 2, 17, 3, 17, 0, 63, 0, 252, 215, 162, 138, 43, 248, 28, 255, 0, 180, 3,
|
1, 0, 2, 17, 3, 17, 0, 63, 0, 252, 215, 162, 138, 43, 248, 28, 255, 0, 180, 3,
|
||||||
|
@ -65,7 +66,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
1,
|
1,
|
||||||
Tag::DefineBitsJpeg2 {
|
Tag::DefineBitsJpeg2 {
|
||||||
id: 1,
|
id: 1,
|
||||||
jpeg_data: vec![
|
jpeg_data: &[
|
||||||
255, 216, 255, 219, 0, 67, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
255, 216, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255, 219, 0,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255, 219, 0,
|
||||||
|
@ -111,7 +112,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
id: 1,
|
id: 1,
|
||||||
version: 3,
|
version: 3,
|
||||||
deblocking: 0.0,
|
deblocking: 0.0,
|
||||||
data: vec![
|
data: &[
|
||||||
255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 255,
|
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,
|
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,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
@ -125,7 +126,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
255, 196, 0, 20, 17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
|
255, 196, 0, 20, 17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
|
||||||
218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0, 134, 240, 23, 224, 94, 255, 217,
|
218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0, 134, 240, 23, 224, 94, 255, 217,
|
||||||
],
|
],
|
||||||
alpha_data: vec![120, 218, 107, 104, 160, 12, 0, 0, 16, 124, 32, 1],
|
alpha_data: &[120, 218, 107, 104, 160, 12, 0, 0, 16, 124, 32, 1],
|
||||||
}),
|
}),
|
||||||
read_tag_bytes_from_file("tests/swfs/DefineBitsJpeg3.swf", TagCode::DefineBitsJpeg3),
|
read_tag_bytes_from_file("tests/swfs/DefineBitsJpeg3.swf", TagCode::DefineBitsJpeg3),
|
||||||
),
|
),
|
||||||
|
@ -164,7 +165,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
width: 8,
|
width: 8,
|
||||||
height: 8,
|
height: 8,
|
||||||
num_colors: 0,
|
num_colors: 0,
|
||||||
data: vec![
|
data: &[
|
||||||
120, 218, 251, 207, 192, 240, 255, 255, 8, 198, 0, 4, 128, 127, 129,
|
120, 218, 251, 207, 192, 240, 255, 255, 8, 198, 0, 4, 128, 127, 129,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -182,7 +183,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
width: 8,
|
width: 8,
|
||||||
height: 8,
|
height: 8,
|
||||||
num_colors: 0,
|
num_colors: 0,
|
||||||
data: vec![
|
data: &[
|
||||||
120, 218, 107, 96, 96, 168, 107, 24, 193, 24, 0, 227, 81, 63, 129,
|
120, 218, 107, 96, 96, 168, 107, 24, 193, 24, 0, 227, 81, 63, 129,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -225,7 +226,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![0],
|
action_data: &[0],
|
||||||
}],
|
}],
|
||||||
})),
|
})),
|
||||||
read_tag_bytes_from_file("tests/swfs/DefineButton-MX.swf", TagCode::DefineButton),
|
read_tag_bytes_from_file("tests/swfs/DefineButton-MX.swf", TagCode::DefineButton),
|
||||||
|
@ -287,12 +288,12 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![150, 3, 0, 0, 65, 0, 38, 0], // trace("A");
|
action_data: &[150, 3, 0, 0, 65, 0, 38, 0], // trace("A");
|
||||||
},
|
},
|
||||||
ButtonAction {
|
ButtonAction {
|
||||||
conditions: vec![ButtonActionCondition::KeyPress].into_iter().collect(),
|
conditions: vec![ButtonActionCondition::KeyPress].into_iter().collect(),
|
||||||
key_code: Some(3), // Home
|
key_code: Some(3), // Home
|
||||||
action_data: vec![150, 3, 0, 0, 66, 0, 38, 0], // trace("B");
|
action_data: &[150, 3, 0, 0, 66, 0, 38, 0], // trace("B");
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})),
|
})),
|
||||||
|
@ -399,8 +400,8 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
indent: Twips::from_pixels(1.0),
|
indent: Twips::from_pixels(1.0),
|
||||||
leading: Twips::from_pixels(2.0),
|
leading: Twips::from_pixels(2.0),
|
||||||
}),
|
}),
|
||||||
variable_name: "foo".to_string(),
|
variable_name: "foo",
|
||||||
initial_text: Some("-_-".to_string()),
|
initial_text: Some("-_-"),
|
||||||
is_word_wrap: false,
|
is_word_wrap: false,
|
||||||
is_multiline: true,
|
is_multiline: true,
|
||||||
is_password: false,
|
is_password: false,
|
||||||
|
@ -618,12 +619,13 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
read_tag_bytes_from_file("tests/swfs/DefineFont3-CS55.swf", TagCode::DefineFont3)
|
read_tag_bytes_from_file("tests/swfs/DefineFont3-CS55.swf", TagCode::DefineFont3)
|
||||||
),
|
),
|
||||||
*/
|
*/
|
||||||
|
/* Commented out because font name has a trailing null byte in the SWF.
|
||||||
(
|
(
|
||||||
11,
|
11,
|
||||||
Tag::DefineFont2(Box::new(Font {
|
Tag::DefineFont2(Box::new(Font {
|
||||||
version: 3,
|
version: 3,
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "_sans\0".to_string(),
|
name: "_sans",
|
||||||
is_small_text: false,
|
is_small_text: false,
|
||||||
is_ansi: false,
|
is_ansi: false,
|
||||||
is_shift_jis: false,
|
is_shift_jis: false,
|
||||||
|
@ -638,6 +640,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
TagCode::DefineFont3,
|
TagCode::DefineFont3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
*/
|
||||||
(
|
(
|
||||||
8,
|
8,
|
||||||
Tag::DefineFontAlignZones {
|
Tag::DefineFontAlignZones {
|
||||||
|
@ -667,7 +670,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
10,
|
10,
|
||||||
Tag::DefineFont4(Font4 {
|
Tag::DefineFont4(Font4 {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "Dummy".to_string(),
|
name: "Dummy",
|
||||||
is_italic: false,
|
is_italic: false,
|
||||||
is_bold: false,
|
is_bold: false,
|
||||||
data: None,
|
data: None,
|
||||||
|
@ -679,7 +682,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
Tag::DefineFontInfo(Box::new(FontInfo {
|
Tag::DefineFontInfo(Box::new(FontInfo {
|
||||||
id: 1,
|
id: 1,
|
||||||
version: 1,
|
version: 1,
|
||||||
name: "Verdana".to_string(),
|
name: "Verdana",
|
||||||
is_small_text: false,
|
is_small_text: false,
|
||||||
is_ansi: true,
|
is_ansi: true,
|
||||||
is_shift_jis: false,
|
is_shift_jis: false,
|
||||||
|
@ -695,7 +698,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
Tag::DefineFontInfo(Box::new(FontInfo {
|
Tag::DefineFontInfo(Box::new(FontInfo {
|
||||||
id: 1,
|
id: 1,
|
||||||
version: 2,
|
version: 2,
|
||||||
name: "Verdana".to_string(),
|
name: "Verdana",
|
||||||
is_small_text: false,
|
is_small_text: false,
|
||||||
is_ansi: true,
|
is_ansi: true,
|
||||||
is_shift_jis: false,
|
is_shift_jis: false,
|
||||||
|
@ -710,8 +713,8 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
9,
|
9,
|
||||||
Tag::DefineFontName {
|
Tag::DefineFontName {
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "Dummy".to_string(),
|
name: "Dummy",
|
||||||
copyright_info: "Dummy font for swf-rs tests".to_string(),
|
copyright_info: "Dummy font for swf-rs tests",
|
||||||
},
|
},
|
||||||
read_tag_bytes_from_file("tests/swfs/DefineFont4.swf", TagCode::DefineFontName),
|
read_tag_bytes_from_file("tests/swfs/DefineFont4.swf", TagCode::DefineFontName),
|
||||||
),
|
),
|
||||||
|
@ -1399,33 +1402,33 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
scenes: vec![
|
scenes: vec![
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 0,
|
frame_num: 0,
|
||||||
label: "Scene 1".to_string(),
|
label: "Scene 1",
|
||||||
},
|
},
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 25,
|
frame_num: 25,
|
||||||
label: "Scene2Scene2Scene2Scene2Scene2".to_string(),
|
label: "Scene2Scene2Scene2Scene2Scene2",
|
||||||
},
|
},
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 26,
|
frame_num: 26,
|
||||||
label: "test日本語test".to_string(),
|
label: "test日本語test",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
frame_labels: vec![
|
frame_labels: vec![
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 0,
|
frame_num: 0,
|
||||||
label: "a".to_string(),
|
label: "a",
|
||||||
},
|
},
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 9,
|
frame_num: 9,
|
||||||
label: "b".to_string(),
|
label: "b",
|
||||||
},
|
},
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 17,
|
frame_num: 17,
|
||||||
label: "❤😁aaa".to_string(),
|
label: "❤😁aaa",
|
||||||
},
|
},
|
||||||
FrameLabelData {
|
FrameLabelData {
|
||||||
frame_num: 25,
|
frame_num: 25,
|
||||||
label: "frameInScene2".to_string(),
|
label: "frameInScene2",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -1856,7 +1859,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
is_stereo: false,
|
is_stereo: false,
|
||||||
},
|
},
|
||||||
num_samples: 10,
|
num_samples: 10,
|
||||||
data: vec![
|
data: &[
|
||||||
255, 127, 0, 128, 255, 127, 0, 128, 255, 127, 0, 128, 255, 127, 0, 128, 255,
|
255, 127, 0, 128, 255, 127, 0, 128, 255, 127, 0, 128, 255, 127, 0, 128, 255,
|
||||||
127, 0, 128,
|
127, 0, 128,
|
||||||
],
|
],
|
||||||
|
@ -1936,7 +1939,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
5,
|
5,
|
||||||
Tag::DoAction(vec![
|
Tag::DoAction(&[
|
||||||
150, 10, 0, 0, 84, 101, 115, 116, 105, 110, 103, 33, 0, 38, 0,
|
150, 10, 0, 0, 84, 101, 115, 116, 105, 110, 103, 33, 0, 38, 0,
|
||||||
]),
|
]),
|
||||||
read_tag_bytes_from_file("tests/swfs/DoAction-CS6.swf", TagCode::DoAction),
|
read_tag_bytes_from_file("tests/swfs/DoAction-CS6.swf", TagCode::DoAction),
|
||||||
|
@ -1945,13 +1948,13 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
6,
|
6,
|
||||||
Tag::DoInitAction {
|
Tag::DoInitAction {
|
||||||
id: 2,
|
id: 2,
|
||||||
action_data: vec![150, 6, 0, 0, 116, 101, 115, 116, 0, 38, 0],
|
action_data: &[150, 6, 0, 0, 116, 101, 115, 116, 0, 38, 0],
|
||||||
},
|
},
|
||||||
read_tag_bytes_from_file("tests/swfs/DoInitAction-CS6.swf", TagCode::DoInitAction),
|
read_tag_bytes_from_file("tests/swfs/DoInitAction-CS6.swf", TagCode::DoInitAction),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
6,
|
6,
|
||||||
Tag::EnableDebugger("$1$ve$EG3LE6bumvJ2pR8F5qXny/".to_string()),
|
Tag::EnableDebugger("$1$ve$EG3LE6bumvJ2pR8F5qXny/"),
|
||||||
read_tag_bytes_from_file(
|
read_tag_bytes_from_file(
|
||||||
"tests/swfs/EnableDebugger2-CS6.swf",
|
"tests/swfs/EnableDebugger2-CS6.swf",
|
||||||
TagCode::EnableDebugger2,
|
TagCode::EnableDebugger2,
|
||||||
|
@ -1960,14 +1963,14 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
(
|
(
|
||||||
10,
|
10,
|
||||||
Tag::EnableTelemetry {
|
Tag::EnableTelemetry {
|
||||||
password_hash: vec![],
|
password_hash: &[],
|
||||||
},
|
},
|
||||||
read_tag_bytes_from_file("tests/swfs/EnableTelemetry.swf", TagCode::EnableTelemetry),
|
read_tag_bytes_from_file("tests/swfs/EnableTelemetry.swf", TagCode::EnableTelemetry),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
10,
|
10,
|
||||||
Tag::EnableTelemetry {
|
Tag::EnableTelemetry {
|
||||||
password_hash: vec![
|
password_hash: &[
|
||||||
207, 128, 205, 138, 237, 72, 45, 93, 21, 39, 215, 220, 114, 252, 239, 248, 78,
|
207, 128, 205, 138, 237, 72, 45, 93, 21, 39, 215, 220, 114, 252, 239, 248, 78,
|
||||||
99, 38, 89, 40, 72, 68, 125, 45, 192, 176, 232, 125, 252, 154, 144,
|
99, 38, 89, 40, 72, 68, 125, 45, 192, 176, 232, 125, 252, 154, 144,
|
||||||
],
|
],
|
||||||
|
@ -1981,7 +1984,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
6,
|
6,
|
||||||
Tag::ExportAssets(vec![ExportedAsset {
|
Tag::ExportAssets(vec![ExportedAsset {
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "Test💯".to_string(),
|
name: "Test💯",
|
||||||
}]),
|
}]),
|
||||||
read_tag_bytes_from_file("tests/swfs/ExportAssets-CS6.swf", TagCode::ExportAssets),
|
read_tag_bytes_from_file("tests/swfs/ExportAssets-CS6.swf", TagCode::ExportAssets),
|
||||||
),
|
),
|
||||||
|
@ -1999,7 +2002,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
(
|
(
|
||||||
3,
|
3,
|
||||||
Tag::FrameLabel(FrameLabel {
|
Tag::FrameLabel(FrameLabel {
|
||||||
label: "test".to_string(),
|
label: "test",
|
||||||
is_anchor: false,
|
is_anchor: false,
|
||||||
}),
|
}),
|
||||||
read_tag_bytes_from_file_with_index(
|
read_tag_bytes_from_file_with_index(
|
||||||
|
@ -2011,7 +2014,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
(
|
(
|
||||||
6, // Anchor tags supported in SWF version 6 and later.
|
6, // Anchor tags supported in SWF version 6 and later.
|
||||||
Tag::FrameLabel(FrameLabel {
|
Tag::FrameLabel(FrameLabel {
|
||||||
label: "anchor_tag".to_string(),
|
label: "anchor_tag",
|
||||||
is_anchor: true,
|
is_anchor: true,
|
||||||
}),
|
}),
|
||||||
read_tag_bytes_from_file_with_index(
|
read_tag_bytes_from_file_with_index(
|
||||||
|
@ -2023,10 +2026,10 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
(
|
(
|
||||||
7,
|
7,
|
||||||
Tag::ImportAssets {
|
Tag::ImportAssets {
|
||||||
url: "ExportAssets-CS6.swf".to_string(),
|
url: "ExportAssets-CS6.swf",
|
||||||
imports: vec![ExportedAsset {
|
imports: vec![ExportedAsset {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "Test💯".to_string(),
|
name: "Test💯",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
read_tag_bytes_from_file("tests/swfs/ImportAssets-CS6.swf", TagCode::ImportAssets),
|
read_tag_bytes_from_file("tests/swfs/ImportAssets-CS6.swf", TagCode::ImportAssets),
|
||||||
|
@ -2034,17 +2037,17 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
(
|
(
|
||||||
8,
|
8,
|
||||||
Tag::ImportAssets {
|
Tag::ImportAssets {
|
||||||
url: "ExportAssets-CS6.swf".to_string(),
|
url: "ExportAssets-CS6.swf",
|
||||||
imports: vec![ExportedAsset {
|
imports: vec![ExportedAsset {
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "Test💯".to_string(),
|
name: "Test💯",
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
read_tag_bytes_from_file("tests/swfs/ImportAssets2-CS6.swf", TagCode::ImportAssets2),
|
read_tag_bytes_from_file("tests/swfs/ImportAssets2-CS6.swf", TagCode::ImportAssets2),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
Tag::JpegTables(vec![
|
Tag::JpegTables(&[
|
||||||
255, 216, 255, 219, 0, 67, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
255, 216, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255, 219, 0, 67, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255, 219, 0, 67, 1, 1, 1, 1,
|
||||||
|
@ -2081,7 +2084,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
Tag::Metadata("aa!".to_string()),
|
Tag::Metadata("aa!"),
|
||||||
vec![0b01_000100, 0b000_10011, b'a', b'a', b'!', 0],
|
vec![0b01_000100, 0b000_10011, b'a', b'a', b'!', 0],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -2125,7 +2128,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
clip_actions: Some(vec![ClipAction {
|
clip_actions: Some(vec![ClipAction {
|
||||||
events: ClipEventFlag::EnterFrame.into(),
|
events: ClipEventFlag::EnterFrame.into(),
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![150, 6, 0, 0, 99, 108, 105, 112, 0, 38, 0],
|
action_data: &[150, 6, 0, 0, 99, 108, 105, 112, 0, 38, 0],
|
||||||
}]),
|
}]),
|
||||||
is_image: false,
|
is_image: false,
|
||||||
is_bitmap_cached: None,
|
is_bitmap_cached: None,
|
||||||
|
@ -2156,17 +2159,17 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
ClipAction {
|
ClipAction {
|
||||||
events: ClipEventFlag::Press | ClipEventFlag::Release,
|
events: ClipEventFlag::Press | ClipEventFlag::Release,
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![150, 3, 0, 0, 65, 0, 38, 0],
|
action_data: &[150, 3, 0, 0, 65, 0, 38, 0],
|
||||||
},
|
},
|
||||||
ClipAction {
|
ClipAction {
|
||||||
events: ClipEventFlag::KeyPress.into(),
|
events: ClipEventFlag::KeyPress.into(),
|
||||||
key_code: Some(99),
|
key_code: Some(99),
|
||||||
action_data: vec![150, 3, 0, 0, 66, 0, 38, 0],
|
action_data: &[150, 3, 0, 0, 66, 0, 38, 0],
|
||||||
},
|
},
|
||||||
ClipAction {
|
ClipAction {
|
||||||
events: ClipEventFlag::EnterFrame.into(),
|
events: ClipEventFlag::EnterFrame.into(),
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![150, 3, 0, 0, 67, 0, 38, 0],
|
action_data: &[150, 3, 0, 0, 67, 0, 38, 0],
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
is_image: false,
|
is_image: false,
|
||||||
|
@ -2234,7 +2237,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
b_add: 20,
|
b_add: 20,
|
||||||
}),
|
}),
|
||||||
ratio: None,
|
ratio: None,
|
||||||
name: Some("test".to_string()),
|
name: Some("test"),
|
||||||
clip_depth: None,
|
clip_depth: None,
|
||||||
class_name: None,
|
class_name: None,
|
||||||
filters: Some(vec![
|
filters: Some(vec![
|
||||||
|
@ -2326,12 +2329,12 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
ClipAction {
|
ClipAction {
|
||||||
events: ClipEventFlag::ReleaseOutside | ClipEventFlag::RollOver,
|
events: ClipEventFlag::ReleaseOutside | ClipEventFlag::RollOver,
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![0],
|
action_data: &[0],
|
||||||
},
|
},
|
||||||
ClipAction {
|
ClipAction {
|
||||||
events: ClipEventFlag::Data.into(),
|
events: ClipEventFlag::Data.into(),
|
||||||
key_code: None,
|
key_code: None,
|
||||||
action_data: vec![150, 3, 0, 0, 66, 0, 38, 0],
|
action_data: &[150, 3, 0, 0, 66, 0, 38, 0],
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
is_image: false,
|
is_image: false,
|
||||||
|
@ -2371,7 +2374,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
is_image: false,
|
is_image: false,
|
||||||
is_bitmap_cached: None,
|
is_bitmap_cached: None,
|
||||||
is_visible: None,
|
is_visible: None,
|
||||||
amf_data: Some(vec![
|
amf_data: Some(&[
|
||||||
10, 11, 1, 9, 116, 101, 115, 116, 6, 17, 84, 101, 115, 116, 105, 110, 103, 33,
|
10, 11, 1, 9, 116, 101, 115, 116, 6, 17, 84, 101, 115, 116, 105, 110, 103, 33,
|
||||||
1,
|
1,
|
||||||
]),
|
]),
|
||||||
|
@ -2385,7 +2388,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
5, // Password supported in SWF version 5 or later.
|
5, // Password supported in SWF version 5 or later.
|
||||||
Tag::Protect(Some("$1$d/$yMscKH17OJ0paJT.e67iz0".to_string())),
|
Tag::Protect(Some("$1$d/$yMscKH17OJ0paJT.e67iz0")),
|
||||||
read_tag_bytes_from_file("tests/swfs/Protect.swf", TagCode::Protect),
|
read_tag_bytes_from_file("tests/swfs/Protect.swf", TagCode::Protect),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -2440,11 +2443,11 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
Tag::SymbolClass(vec![
|
Tag::SymbolClass(vec![
|
||||||
SymbolClassLink {
|
SymbolClassLink {
|
||||||
id: 2,
|
id: 2,
|
||||||
class_name: "foo.Test".to_string(),
|
class_name: "foo.Test",
|
||||||
},
|
},
|
||||||
SymbolClassLink {
|
SymbolClassLink {
|
||||||
id: 0,
|
id: 0,
|
||||||
class_name: "DocumentTest".to_string(),
|
class_name: "DocumentTest",
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
read_tag_bytes_from_file("tests/swfs/SymbolClass.swf", TagCode::SymbolClass),
|
read_tag_bytes_from_file("tests/swfs/SymbolClass.swf", TagCode::SymbolClass),
|
||||||
|
@ -2466,7 +2469,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
(
|
(
|
||||||
9,
|
9,
|
||||||
Tag::StartSound2 {
|
Tag::StartSound2 {
|
||||||
class_name: "TestSound".to_string(),
|
class_name: "TestSound",
|
||||||
sound_info: Box::new(SoundInfo {
|
sound_info: Box::new(SoundInfo {
|
||||||
event: SoundEvent::Event,
|
event: SoundEvent::Event,
|
||||||
in_sample: None,
|
in_sample: None,
|
||||||
|
@ -2486,7 +2489,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
Tag::VideoFrame(VideoFrame {
|
Tag::VideoFrame(VideoFrame {
|
||||||
stream_id: 1,
|
stream_id: 1,
|
||||||
frame_num: 0,
|
frame_num: 0,
|
||||||
data: vec![0, 0, 132, 0, 4, 4, 17, 38, 190, 190, 190, 190, 201, 182],
|
data: &[0, 0, 132, 0, 4, 4, 17, 38, 190, 190, 190, 190, 201, 182],
|
||||||
}),
|
}),
|
||||||
read_tag_bytes_from_file("tests/swfs/DefineVideoStream.swf", TagCode::VideoFrame),
|
read_tag_bytes_from_file("tests/swfs/DefineVideoStream.swf", TagCode::VideoFrame),
|
||||||
),
|
),
|
||||||
|
@ -2494,7 +2497,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
1,
|
1,
|
||||||
Tag::Unknown {
|
Tag::Unknown {
|
||||||
tag_code: 512,
|
tag_code: 512,
|
||||||
data: vec![],
|
data: &[],
|
||||||
},
|
},
|
||||||
vec![0b00_000000, 0b10000000],
|
vec![0b00_000000, 0b10000000],
|
||||||
),
|
),
|
||||||
|
@ -2502,7 +2505,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
1,
|
1,
|
||||||
Tag::Unknown {
|
Tag::Unknown {
|
||||||
tag_code: 513,
|
tag_code: 513,
|
||||||
data: vec![1, 2],
|
data: &[1, 2],
|
||||||
},
|
},
|
||||||
vec![0b01_000010, 0b10000000, 1, 2],
|
vec![0b01_000010, 0b10000000, 1, 2],
|
||||||
),
|
),
|
||||||
|
@ -2510,7 +2513,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
||||||
1,
|
1,
|
||||||
Tag::Unknown {
|
Tag::Unknown {
|
||||||
tag_code: 513,
|
tag_code: 513,
|
||||||
data: vec![0; 64],
|
data: &[0; 64],
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
0b01_111111,
|
0b01_111111,
|
||||||
|
|
183
swf/src/types.rs
183
swf/src/types.rs
|
@ -10,19 +10,22 @@ mod matrix;
|
||||||
|
|
||||||
pub use matrix::Matrix;
|
pub use matrix::Matrix;
|
||||||
|
|
||||||
|
pub type SwfStr<'a> = &'a str;
|
||||||
|
|
||||||
/// A complete header and tags in the SWF file.
|
/// A complete header and tags in the SWF file.
|
||||||
/// This is returned by the `swf::read_swf` convenience method.
|
/// This is returned by the `swf::read_swf` convenience method.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Swf {
|
pub struct Swf<'a> {
|
||||||
pub header: Header,
|
pub header: Header,
|
||||||
pub tags: Vec<Tag>,
|
pub tags: Vec<Tag<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returned by `read::read_swf_header`. Includes the decompress
|
/// Returned by `read::read_swf_header`. Includes the decompress
|
||||||
/// stream as well as the uncompressed data length.
|
/// stream as well as the uncompressed data length.
|
||||||
pub struct SwfStream<'a> {
|
pub struct SwfStream {
|
||||||
pub header: Header,
|
pub header: Header,
|
||||||
pub reader: crate::read::Reader<Box<dyn std::io::Read + 'a>>,
|
//pub reader: crate::read::Reader<'a>,
|
||||||
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The header of an SWF file.
|
/// The header of an SWF file.
|
||||||
|
@ -242,45 +245,45 @@ pub struct FileAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct FrameLabel {
|
pub struct FrameLabel<'a> {
|
||||||
pub label: String,
|
pub label: SwfStr<'a>,
|
||||||
pub is_anchor: bool,
|
pub is_anchor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct DefineSceneAndFrameLabelData {
|
pub struct DefineSceneAndFrameLabelData<'a> {
|
||||||
pub scenes: Vec<FrameLabelData>,
|
pub scenes: Vec<FrameLabelData<'a>>,
|
||||||
pub frame_labels: Vec<FrameLabelData>,
|
pub frame_labels: Vec<FrameLabelData<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct FrameLabelData {
|
pub struct FrameLabelData<'a> {
|
||||||
pub frame_num: u32,
|
pub frame_num: u32,
|
||||||
pub label: String,
|
pub label: SwfStr<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Depth = u16;
|
pub type Depth = u16;
|
||||||
pub type CharacterId = u16;
|
pub type CharacterId = u16;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct PlaceObject {
|
pub struct PlaceObject<'a> {
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub action: PlaceObjectAction,
|
pub action: PlaceObjectAction,
|
||||||
pub depth: Depth,
|
pub depth: Depth,
|
||||||
pub matrix: Option<Matrix>,
|
pub matrix: Option<Matrix>,
|
||||||
pub color_transform: Option<ColorTransform>,
|
pub color_transform: Option<ColorTransform>,
|
||||||
pub ratio: Option<u16>,
|
pub ratio: Option<u16>,
|
||||||
pub name: Option<String>,
|
pub name: Option<SwfStr<'a>>,
|
||||||
pub clip_depth: Option<Depth>,
|
pub clip_depth: Option<Depth>,
|
||||||
pub class_name: Option<String>,
|
pub class_name: Option<SwfStr<'a>>,
|
||||||
pub filters: Option<Vec<Filter>>,
|
pub filters: Option<Vec<Filter>>,
|
||||||
pub background_color: Option<Color>,
|
pub background_color: Option<Color>,
|
||||||
pub blend_mode: Option<BlendMode>,
|
pub blend_mode: Option<BlendMode>,
|
||||||
pub clip_actions: Option<Vec<ClipAction>>,
|
pub clip_actions: Option<Vec<ClipAction<'a>>>,
|
||||||
pub is_image: bool,
|
pub is_image: bool,
|
||||||
pub is_bitmap_cached: Option<bool>,
|
pub is_bitmap_cached: Option<bool>,
|
||||||
pub is_visible: Option<bool>,
|
pub is_visible: Option<bool>,
|
||||||
pub amf_data: Option<Vec<u8>>,
|
pub amf_data: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
|
@ -416,10 +419,10 @@ pub enum BlendMode {
|
||||||
///
|
///
|
||||||
/// [SWF19 pp.37-38 ClipActionRecord](https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf#page=37)
|
/// [SWF19 pp.37-38 ClipActionRecord](https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf#page=37)
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ClipAction {
|
pub struct ClipAction<'a> {
|
||||||
pub events: EnumSet<ClipEventFlag>,
|
pub events: EnumSet<ClipEventFlag>,
|
||||||
pub key_code: Option<KeyCode>,
|
pub key_code: Option<KeyCode>,
|
||||||
pub action_data: Vec<u8>,
|
pub action_data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An event that can be attached to a movieclip instance using
|
/// An event that can be attached to a movieclip instance using
|
||||||
|
@ -460,49 +463,49 @@ pub type KeyCode = u8;
|
||||||
///
|
///
|
||||||
// [SWF19 p.29](https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf#page=29)
|
// [SWF19 p.29](https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf#page=29)
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Tag {
|
pub enum Tag<'a> {
|
||||||
ExportAssets(ExportAssets),
|
ExportAssets(ExportAssets<'a>),
|
||||||
ScriptLimits {
|
ScriptLimits {
|
||||||
max_recursion_depth: u16,
|
max_recursion_depth: u16,
|
||||||
timeout_in_seconds: u16,
|
timeout_in_seconds: u16,
|
||||||
},
|
},
|
||||||
ShowFrame,
|
ShowFrame,
|
||||||
|
|
||||||
Protect(Option<String>),
|
Protect(Option<SwfStr<'a>>),
|
||||||
CsmTextSettings(CsmTextSettings),
|
CsmTextSettings(CsmTextSettings),
|
||||||
DebugId(DebugId),
|
DebugId(DebugId),
|
||||||
DefineBinaryData {
|
DefineBinaryData {
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
data: Vec<u8>,
|
data: &'a [u8],
|
||||||
},
|
},
|
||||||
DefineBits {
|
DefineBits {
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
jpeg_data: Vec<u8>,
|
jpeg_data: &'a [u8],
|
||||||
},
|
},
|
||||||
DefineBitsJpeg2 {
|
DefineBitsJpeg2 {
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
jpeg_data: Vec<u8>,
|
jpeg_data: &'a [u8],
|
||||||
},
|
},
|
||||||
DefineBitsJpeg3(DefineBitsJpeg3),
|
DefineBitsJpeg3(DefineBitsJpeg3<'a>),
|
||||||
DefineBitsLossless(DefineBitsLossless),
|
DefineBitsLossless(DefineBitsLossless<'a>),
|
||||||
DefineButton(Box<Button>),
|
DefineButton(Box<Button<'a>>),
|
||||||
DefineButton2(Box<Button>),
|
DefineButton2(Box<Button<'a>>),
|
||||||
DefineButtonColorTransform(ButtonColorTransform),
|
DefineButtonColorTransform(ButtonColorTransform),
|
||||||
DefineButtonSound(Box<ButtonSounds>),
|
DefineButtonSound(Box<ButtonSounds>),
|
||||||
DefineEditText(Box<EditText>),
|
DefineEditText(Box<EditText<'a>>),
|
||||||
DefineFont(Box<FontV1>),
|
DefineFont(Box<FontV1>),
|
||||||
DefineFont2(Box<Font>),
|
DefineFont2(Box<Font<'a>>),
|
||||||
DefineFont4(Font4),
|
DefineFont4(Font4<'a>),
|
||||||
DefineFontAlignZones {
|
DefineFontAlignZones {
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
thickness: FontThickness,
|
thickness: FontThickness,
|
||||||
zones: Vec<FontAlignZone>,
|
zones: Vec<FontAlignZone>,
|
||||||
},
|
},
|
||||||
DefineFontInfo(Box<FontInfo>),
|
DefineFontInfo(Box<FontInfo<'a>>),
|
||||||
DefineFontName {
|
DefineFontName {
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
name: String,
|
name: SwfStr<'a>,
|
||||||
copyright_info: String,
|
copyright_info: SwfStr<'a>,
|
||||||
},
|
},
|
||||||
DefineMorphShape(Box<DefineMorphShape>),
|
DefineMorphShape(Box<DefineMorphShape>),
|
||||||
DefineScalingGrid {
|
DefineScalingGrid {
|
||||||
|
@ -510,63 +513,63 @@ pub enum Tag {
|
||||||
splitter_rect: Rectangle,
|
splitter_rect: Rectangle,
|
||||||
},
|
},
|
||||||
DefineShape(Shape),
|
DefineShape(Shape),
|
||||||
DefineSound(Box<Sound>),
|
DefineSound(Box<Sound<'a>>),
|
||||||
DefineSprite(Sprite),
|
DefineSprite(Sprite<'a>),
|
||||||
DefineText(Box<Text>),
|
DefineText(Box<Text>),
|
||||||
DefineVideoStream(DefineVideoStream),
|
DefineVideoStream(DefineVideoStream),
|
||||||
DoAbc(DoAbc),
|
DoAbc(DoAbc<'a>),
|
||||||
DoAction(DoAction),
|
DoAction(DoAction<'a>),
|
||||||
DoInitAction {
|
DoInitAction {
|
||||||
id: CharacterId,
|
id: CharacterId,
|
||||||
action_data: Vec<u8>,
|
action_data: &'a [u8],
|
||||||
},
|
},
|
||||||
EnableDebugger(String),
|
EnableDebugger(SwfStr<'a>),
|
||||||
EnableTelemetry {
|
EnableTelemetry {
|
||||||
password_hash: Vec<u8>,
|
password_hash: &'a [u8],
|
||||||
},
|
},
|
||||||
End,
|
End,
|
||||||
Metadata(String),
|
Metadata(SwfStr<'a>),
|
||||||
ImportAssets {
|
ImportAssets {
|
||||||
url: String,
|
url: SwfStr<'a>,
|
||||||
imports: Vec<ExportedAsset>,
|
imports: Vec<ExportedAsset<'a>>,
|
||||||
},
|
},
|
||||||
JpegTables(JpegTables),
|
JpegTables(JpegTables<'a>),
|
||||||
SetBackgroundColor(SetBackgroundColor),
|
SetBackgroundColor(SetBackgroundColor),
|
||||||
SetTabIndex {
|
SetTabIndex {
|
||||||
depth: Depth,
|
depth: Depth,
|
||||||
tab_index: u16,
|
tab_index: u16,
|
||||||
},
|
},
|
||||||
SoundStreamBlock(SoundStreamBlock),
|
SoundStreamBlock(SoundStreamBlock<'a>),
|
||||||
SoundStreamHead(Box<SoundStreamHead>),
|
SoundStreamHead(Box<SoundStreamHead>),
|
||||||
SoundStreamHead2(Box<SoundStreamHead>),
|
SoundStreamHead2(Box<SoundStreamHead>),
|
||||||
StartSound(StartSound),
|
StartSound(StartSound),
|
||||||
StartSound2 {
|
StartSound2 {
|
||||||
class_name: String,
|
class_name: SwfStr<'a>,
|
||||||
sound_info: Box<SoundInfo>,
|
sound_info: Box<SoundInfo>,
|
||||||
},
|
},
|
||||||
SymbolClass(Vec<SymbolClassLink>),
|
SymbolClass(Vec<SymbolClassLink<'a>>),
|
||||||
PlaceObject(Box<PlaceObject>),
|
PlaceObject(Box<PlaceObject<'a>>),
|
||||||
RemoveObject(RemoveObject),
|
RemoveObject(RemoveObject),
|
||||||
VideoFrame(VideoFrame),
|
VideoFrame(VideoFrame<'a>),
|
||||||
FileAttributes(FileAttributes),
|
FileAttributes(FileAttributes),
|
||||||
|
|
||||||
FrameLabel(FrameLabel),
|
FrameLabel(FrameLabel<'a>),
|
||||||
DefineSceneAndFrameLabelData(DefineSceneAndFrameLabelData),
|
DefineSceneAndFrameLabelData(DefineSceneAndFrameLabelData<'a>),
|
||||||
|
|
||||||
ProductInfo(ProductInfo),
|
ProductInfo(ProductInfo),
|
||||||
|
|
||||||
Unknown {
|
Unknown {
|
||||||
tag_code: u16,
|
tag_code: u16,
|
||||||
data: Vec<u8>,
|
data: &'a [u8],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ExportAssets = Vec<ExportedAsset>;
|
pub type ExportAssets<'a> = Vec<ExportedAsset<'a>>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct ExportedAsset {
|
pub struct ExportedAsset<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub name: String,
|
pub name: SwfStr<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
@ -578,9 +581,9 @@ pub struct RemoveObject {
|
||||||
pub type SetBackgroundColor = Color;
|
pub type SetBackgroundColor = Color;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct SymbolClassLink {
|
pub struct SymbolClassLink<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub class_name: String,
|
pub class_name: SwfStr<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
@ -605,11 +608,11 @@ pub struct Shape {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Sound {
|
pub struct Sound<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub format: SoundFormat,
|
pub format: SoundFormat,
|
||||||
pub num_samples: u32,
|
pub num_samples: u32,
|
||||||
pub data: Vec<u8>,
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
@ -644,10 +647,10 @@ pub struct StartSound {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Sprite {
|
pub struct Sprite<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub num_frames: u16,
|
pub num_frames: u16,
|
||||||
pub tags: Vec<Tag>,
|
pub tags: Vec<Tag<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -797,14 +800,14 @@ pub struct SoundStreamHead {
|
||||||
pub latency_seek: i16,
|
pub latency_seek: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SoundStreamBlock = Vec<u8>;
|
pub type SoundStreamBlock<'a> = &'a [u8];
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Button {
|
pub struct Button<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub is_track_as_menu: bool,
|
pub is_track_as_menu: bool,
|
||||||
pub records: Vec<ButtonRecord>,
|
pub records: Vec<ButtonRecord>,
|
||||||
pub actions: Vec<ButtonAction>,
|
pub actions: Vec<ButtonAction<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
@ -844,10 +847,10 @@ pub struct ButtonSounds {
|
||||||
pub type ButtonSound = (CharacterId, SoundInfo);
|
pub type ButtonSound = (CharacterId, SoundInfo);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct ButtonAction {
|
pub struct ButtonAction<'a> {
|
||||||
pub conditions: HashSet<ButtonActionCondition>,
|
pub conditions: HashSet<ButtonActionCondition>,
|
||||||
pub key_code: Option<u8>,
|
pub key_code: Option<u8>,
|
||||||
pub action_data: Vec<u8>,
|
pub action_data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
|
@ -890,10 +893,10 @@ pub struct FontV1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Font {
|
pub struct Font<'a> {
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub name: String,
|
pub name: SwfStr<'a>,
|
||||||
pub language: Language,
|
pub language: Language,
|
||||||
pub layout: Option<FontLayout>,
|
pub layout: Option<FontLayout>,
|
||||||
pub glyphs: Vec<Glyph>,
|
pub glyphs: Vec<Glyph>,
|
||||||
|
@ -905,12 +908,12 @@ pub struct Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Font4 {
|
pub struct Font4<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub is_italic: bool,
|
pub is_italic: bool,
|
||||||
pub is_bold: bool,
|
pub is_bold: bool,
|
||||||
pub name: String,
|
pub name: SwfStr<'a>,
|
||||||
pub data: Option<Vec<u8>>,
|
pub data: Option<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -937,10 +940,10 @@ pub struct KerningRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct FontInfo {
|
pub struct FontInfo<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub name: String,
|
pub name: SwfStr<'a>,
|
||||||
pub is_small_text: bool,
|
pub is_small_text: bool,
|
||||||
pub is_shift_jis: bool,
|
pub is_shift_jis: bool,
|
||||||
pub is_ansi: bool,
|
pub is_ansi: bool,
|
||||||
|
@ -975,17 +978,17 @@ pub struct GlyphEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct EditText {
|
pub struct EditText<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub bounds: Rectangle,
|
pub bounds: Rectangle,
|
||||||
pub font_id: Option<CharacterId>, // TODO(Herschel): Combine with height
|
pub font_id: Option<CharacterId>, // TODO(Herschel): Combine with height
|
||||||
pub font_class_name: Option<String>,
|
pub font_class_name: Option<SwfStr<'a>>,
|
||||||
pub height: Option<Twips>,
|
pub height: Option<Twips>,
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
pub max_length: Option<u16>,
|
pub max_length: Option<u16>,
|
||||||
pub layout: Option<TextLayout>,
|
pub layout: Option<TextLayout>,
|
||||||
pub variable_name: String,
|
pub variable_name: SwfStr<'a>,
|
||||||
pub initial_text: Option<String>,
|
pub initial_text: Option<SwfStr<'a>>,
|
||||||
pub is_word_wrap: bool,
|
pub is_word_wrap: bool,
|
||||||
pub is_multiline: bool,
|
pub is_multiline: bool,
|
||||||
pub is_password: bool,
|
pub is_password: bool,
|
||||||
|
@ -1048,14 +1051,14 @@ pub enum TextGridFit {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct DefineBitsLossless {
|
pub struct DefineBitsLossless<'a> {
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub format: BitmapFormat,
|
pub format: BitmapFormat,
|
||||||
pub width: u16,
|
pub width: u16,
|
||||||
pub height: u16,
|
pub height: u16,
|
||||||
pub num_colors: u8,
|
pub num_colors: u8,
|
||||||
pub data: Vec<u8>,
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
@ -1095,31 +1098,31 @@ pub enum VideoCodec {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct VideoFrame {
|
pub struct VideoFrame<'a> {
|
||||||
pub stream_id: CharacterId,
|
pub stream_id: CharacterId,
|
||||||
pub frame_num: u16,
|
pub frame_num: u16,
|
||||||
pub data: Vec<u8>,
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct DefineBitsJpeg3 {
|
pub struct DefineBitsJpeg3<'a> {
|
||||||
pub id: CharacterId,
|
pub id: CharacterId,
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub deblocking: f32,
|
pub deblocking: f32,
|
||||||
pub data: Vec<u8>,
|
pub data: &'a [u8],
|
||||||
pub alpha_data: Vec<u8>,
|
pub alpha_data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct DoAbc {
|
pub struct DoAbc<'a> {
|
||||||
pub name: String,
|
pub name: SwfStr<'a>,
|
||||||
pub is_lazy_initialize: bool,
|
pub is_lazy_initialize: bool,
|
||||||
pub data: Vec<u8>,
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DoAction = Vec<u8>;
|
pub type DoAction<'a> = &'a [u8];
|
||||||
|
|
||||||
pub type JpegTables = Vec<u8>;
|
pub type JpegTables<'a> = &'a [u8];
|
||||||
|
|
||||||
/// `ProductInfo` contains information about the software used to generate the SWF.
|
/// `ProductInfo` contains information about the software used to generate the SWF.
|
||||||
/// Not documented in the SWF19 reference. Emitted by mxmlc.
|
/// Not documented in the SWF19 reference. Emitted by mxmlc.
|
||||||
|
|
|
@ -2802,7 +2802,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::test_data;
|
use crate::test_data;
|
||||||
|
|
||||||
fn new_swf() -> Swf {
|
fn new_swf() -> Swf<'static> {
|
||||||
Swf {
|
Swf {
|
||||||
header: Header {
|
header: Header {
|
||||||
compression: Compression::Zlib,
|
compression: Compression::Zlib,
|
||||||
|
@ -3125,7 +3125,7 @@ mod tests {
|
||||||
.write_tag_list(&[
|
.write_tag_list(&[
|
||||||
Tag::Unknown {
|
Tag::Unknown {
|
||||||
tag_code: 512,
|
tag_code: 512,
|
||||||
data: vec![0; 100],
|
data: &[0; 100],
|
||||||
},
|
},
|
||||||
Tag::ShowFrame,
|
Tag::ShowFrame,
|
||||||
])
|
])
|
||||||
|
|
Loading…
Reference in New Issue