Implement DefineSprite

This commit is contained in:
Mike Welsh 2016-09-07 22:08:24 -07:00
parent 7dde55e8a4
commit 95c3e12c4f
6 changed files with 71 additions and 0 deletions

View File

@ -308,6 +308,7 @@ impl<R: Read> Reader<R> {
let (tag_code, length) = try!(self.read_tag_code_and_length());
let mut tag_reader = Reader::new(self.input.by_ref().take(length as u64), self.version);
//let mut tag_reader = Reader::new(Box::new(self.input.by_ref().take(length as u64)) as Box<Read>, self.version);
use tag_codes::TagCode;
let tag = match TagCode::from_u16(tag_code) {
Some(TagCode::End) => return Ok(None),
@ -333,6 +334,17 @@ impl<R: Read> Reader<R> {
try!(tag_reader.read_define_scene_and_frame_label_data())
}
Some(TagCode::DefineSprite) => {
// TODO: There's probably a better way to prevent the infinite type recursion.
// Tags can only be nested one level deep, so perhaps I can implement
// read_tag_list for Reader<Take<R>> to enforce this.
let mut sprite_reader = Reader::new(
&mut tag_reader.input as &mut Read,
self.version
);
try!(sprite_reader.read_define_sprite())
},
Some(TagCode::PlaceObject) => try!(tag_reader.read_place_object()),
Some(TagCode::PlaceObject2) => try!(tag_reader.read_place_object_2()),
//Some(TagCode::PlaceObject3) => try!(tag_reader.read_place_object_3()),
@ -596,6 +608,14 @@ impl<R: Read> Reader<R> {
Ok(shape_record)
}
fn read_define_sprite(&mut self) -> Result<Tag> {
Ok(Tag::DefineSprite(Sprite {
id: try!(self.read_u16()),
num_frames: try!(self.read_u16()),
tags: try!(self.read_tag_list()),
}))
}
fn read_place_object(&mut self) -> Result<Tag> {
// TODO: What's a best way to know if the tag has a color transform?
Ok(Tag::PlaceObject(Box::new(PlaceObject {
@ -972,6 +992,12 @@ pub mod tests {
assert_eq!(reader(&tag_bytes).read_tag().unwrap().unwrap(), tag);
}
#[test]
fn read_define_sprite() {
let (tag, tag_bytes) = test_data::define_sprite();
assert_eq!(reader(&tag_bytes).read_tag().unwrap().unwrap(), tag);
}
#[test]
fn read_place_object_2() {
let (tag, tag_bytes) = test_data::place_object_2();

View File

@ -85,6 +85,23 @@ pub fn define_shape() -> TagTestData {
)
}
pub fn define_sprite() -> TagTestData {
(
Tag::DefineSprite(Sprite {
id: 1,
num_frames: 5,
tags: vec![
Tag::ShowFrame,
Tag::ShowFrame,
Tag::ShowFrame,
Tag::ShowFrame,
Tag::ShowFrame,
],
}),
read_tag_bytes_from_file("tests/swfs/define_sprite.swf", TagCode::DefineSprite)
)
}
pub fn place_object_2() -> TagTestData {
(
Tag::PlaceObject(Box::new(PlaceObject {

View File

@ -175,6 +175,7 @@ pub enum Tag {
ShowFrame,
DefineShape(Shape),
DefineSprite(Sprite),
SetBackgroundColor(Color),
@ -200,6 +201,13 @@ pub struct Shape {
pub shape: Vec<ShapeRecord>,
}
#[derive(Debug,PartialEq)]
pub struct Sprite {
pub id: CharacterId,
pub num_frames: u16,
pub tags: Vec<Tag>,
}
#[derive(Debug,PartialEq)]
pub struct ShapeStyles {
pub fill_styles: Vec<FillStyle>,

View File

@ -302,6 +302,7 @@ impl<W: Write> Writer<W> {
&Tag::ShowFrame => try!(self.write_tag_header(TagCode::ShowFrame, 0)),
&Tag::DefineShape(ref shape) => try!(self.write_define_shape(shape)),
&Tag::DefineSprite(ref sprite) => try!(self.write_define_sprite(sprite)),
// TODO: Allow clone of color.
&Tag::SetBackgroundColor(ref color) => {
@ -401,6 +402,19 @@ impl<W: Write> Writer<W> {
Ok(())
}
fn write_define_sprite(&mut self, sprite: &Sprite) -> Result<()> {
let mut buf = Vec::new();
{
let mut writer = Writer::new(&mut buf, self.version);
try!(writer.write_u16(sprite.id));
try!(writer.write_u16(sprite.num_frames));
try!(writer.write_tag_list(&sprite.tags));
};
try!(self.write_tag_header(TagCode::DefineSprite, buf.len() as u32));
try!(self.output.write_all(&buf));
Ok(())
}
fn write_shape_styles(&mut self, styles: &ShapeStyles, shape_version: u8) -> Result<()> {
// TODO: Check shape_version.
if styles.fill_styles.len() >= 0xff {
@ -1084,6 +1098,12 @@ mod tests {
assert_eq!(write_tag_to_buf(&tag, 1), tag_bytes);
}
#[test]
fn write_define_sprite() {
let (tag, tag_bytes) = test_data::define_sprite();
assert_eq!(write_tag_to_buf(&tag, 1), tag_bytes);
}
#[test]
fn write_place_object_2() {
let (tag, tag_bytes) = test_data::place_object_2();

Binary file not shown.

Binary file not shown.