swf: Use EnumSet for ClipEventFlag
This commit is contained in:
parent
174426856f
commit
da13b36e47
|
@ -1842,6 +1842,7 @@ name = "swf"
|
|||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"enumset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libflate 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -11,6 +11,7 @@ description = "Read and write the Adobe Flash SWF file format."
|
|||
|
||||
[dependencies]
|
||||
byteorder = "1.0"
|
||||
enumset = "0.4.2"
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
libflate = {version = "0.1", optional = true}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
use crate::error::{Error, Result};
|
||||
use crate::types::*;
|
||||
use byteorder::{LittleEndian, ReadBytesExt};
|
||||
use enumset::EnumSet;
|
||||
use std::collections::HashSet;
|
||||
use std::convert::TryInto;
|
||||
use std::io::{self, Read};
|
||||
|
@ -2234,7 +2235,7 @@ impl<R: Read> Reader<R> {
|
|||
Ok(None)
|
||||
} else {
|
||||
let mut length = self.read_u32()?;
|
||||
let key_code = if events.contains(&ClipEvent::KeyPress) {
|
||||
let key_code = if events.contains(ClipEventFlag::KeyPress) {
|
||||
// ActionData length includes the 1 byte key code.
|
||||
length -= 1;
|
||||
Some(self.read_u8()?)
|
||||
|
@ -2253,32 +2254,32 @@ impl<R: Read> Reader<R> {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_clip_event_flags(&mut self) -> Result<HashSet<ClipEvent>> {
|
||||
fn read_clip_event_flags(&mut self) -> Result<EnumSet<ClipEventFlag>> {
|
||||
// TODO: Switch to a bitset.
|
||||
let mut event_list = HashSet::with_capacity(32);
|
||||
let mut event_list = EnumSet::new();
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::KeyUp);
|
||||
event_list.insert(ClipEventFlag::KeyUp);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::KeyDown);
|
||||
event_list.insert(ClipEventFlag::KeyDown);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::MouseUp);
|
||||
event_list.insert(ClipEventFlag::MouseUp);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::MouseDown);
|
||||
event_list.insert(ClipEventFlag::MouseDown);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::MouseMove);
|
||||
event_list.insert(ClipEventFlag::MouseMove);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::Unload);
|
||||
event_list.insert(ClipEventFlag::Unload);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::EnterFrame);
|
||||
event_list.insert(ClipEventFlag::EnterFrame);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::Load);
|
||||
event_list.insert(ClipEventFlag::Load);
|
||||
}
|
||||
if self.version < 6 {
|
||||
// SWF19 pp. 48-50: For SWFv5, the ClipEventFlags only had 2 bytes of flags,
|
||||
|
@ -2287,41 +2288,41 @@ impl<R: Read> Reader<R> {
|
|||
self.read_u8()?;
|
||||
} else {
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::DragOver);
|
||||
event_list.insert(ClipEventFlag::DragOver);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::RollOut);
|
||||
event_list.insert(ClipEventFlag::RollOut);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::RollOver);
|
||||
event_list.insert(ClipEventFlag::RollOver);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::ReleaseOutside);
|
||||
event_list.insert(ClipEventFlag::ReleaseOutside);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::Release);
|
||||
event_list.insert(ClipEventFlag::Release);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::Press);
|
||||
event_list.insert(ClipEventFlag::Press);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::Initialize);
|
||||
event_list.insert(ClipEventFlag::Initialize);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::Data);
|
||||
event_list.insert(ClipEventFlag::Data);
|
||||
}
|
||||
if self.version < 6 {
|
||||
self.read_u16()?;
|
||||
} else {
|
||||
self.read_ubits(5)?;
|
||||
if self.read_bit()? && self.version >= 7 {
|
||||
event_list.insert(ClipEvent::Construct);
|
||||
event_list.insert(ClipEventFlag::Construct);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::KeyPress);
|
||||
event_list.insert(ClipEventFlag::KeyPress);
|
||||
}
|
||||
if self.read_bit()? {
|
||||
event_list.insert(ClipEvent::DragOut);
|
||||
event_list.insert(ClipEventFlag::DragOut);
|
||||
}
|
||||
self.read_u8()?;
|
||||
}
|
||||
|
|
|
@ -2123,7 +2123,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
background_color: None,
|
||||
blend_mode: BlendMode::Normal,
|
||||
clip_actions: vec![ClipAction {
|
||||
events: vec![ClipEvent::EnterFrame].into_iter().collect(),
|
||||
events: ClipEventFlag::EnterFrame.into(),
|
||||
key_code: None,
|
||||
action_data: vec![150, 6, 0, 0, 99, 108, 105, 112, 0, 38, 0],
|
||||
}],
|
||||
|
@ -2154,19 +2154,17 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
blend_mode: BlendMode::Normal,
|
||||
clip_actions: vec![
|
||||
ClipAction {
|
||||
events: vec![ClipEvent::Press, ClipEvent::Release]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
events: ClipEventFlag::Press | ClipEventFlag::Release,
|
||||
key_code: None,
|
||||
action_data: vec![150, 3, 0, 0, 65, 0, 38, 0],
|
||||
},
|
||||
ClipAction {
|
||||
events: vec![ClipEvent::KeyPress].into_iter().collect(),
|
||||
events: ClipEventFlag::KeyPress.into(),
|
||||
key_code: Some(99),
|
||||
action_data: vec![150, 3, 0, 0, 66, 0, 38, 0],
|
||||
},
|
||||
ClipAction {
|
||||
events: vec![ClipEvent::EnterFrame].into_iter().collect(),
|
||||
events: ClipEventFlag::EnterFrame.into(),
|
||||
key_code: None,
|
||||
action_data: vec![150, 3, 0, 0, 67, 0, 38, 0],
|
||||
},
|
||||
|
@ -2326,14 +2324,12 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
blend_mode: BlendMode::Difference,
|
||||
clip_actions: vec![
|
||||
ClipAction {
|
||||
events: vec![ClipEvent::ReleaseOutside, ClipEvent::RollOver]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
events: ClipEventFlag::ReleaseOutside | ClipEventFlag::RollOver,
|
||||
key_code: None,
|
||||
action_data: vec![0],
|
||||
},
|
||||
ClipAction {
|
||||
events: vec![ClipEvent::Data].into_iter().collect(),
|
||||
events: ClipEventFlag::Data.into(),
|
||||
key_code: None,
|
||||
action_data: vec![150, 3, 0, 0, 66, 0, 38, 0],
|
||||
},
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//! These structures are documented in the Adobe SWF File Foramt Specification
|
||||
//! version 19 (henceforth SWF19):
|
||||
//! https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf
|
||||
use enumset::{EnumSet, EnumSetType};
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// A complete header and tags in the SWF file.
|
||||
|
@ -412,37 +413,46 @@ pub enum BlendMode {
|
|||
HardLight,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
/// An clip action (a.k.a. clip event) placed on a movieclip instance.
|
||||
/// Created in the Flash IDE using `onClipEvent` or `on` blocks.
|
||||
///
|
||||
/// [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)]
|
||||
pub struct ClipAction {
|
||||
pub events: HashSet<ClipEvent>,
|
||||
pub key_code: Option<u8>,
|
||||
pub events: EnumSet<ClipEventFlag>,
|
||||
pub key_code: Option<KeyCode>,
|
||||
pub action_data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum ClipEvent {
|
||||
/// An event that can be attached to a movieclip instance using
|
||||
/// an `onClipEvent` or `on` block.
|
||||
///
|
||||
/// [SWF19 pp.48-50 ClipEvent](https://www.adobe.com/content/dam/acom/en/devnet/pdf/swf-file-format-spec.pdf#page=38)
|
||||
#[derive(Debug, EnumSetType)]
|
||||
pub enum ClipEventFlag {
|
||||
Construct,
|
||||
Data,
|
||||
DragOut,
|
||||
DragOver,
|
||||
EnterFrame,
|
||||
Initialize,
|
||||
KeyUp,
|
||||
KeyDown,
|
||||
KeyPress,
|
||||
Load,
|
||||
MouseUp,
|
||||
MouseDown,
|
||||
MouseMove,
|
||||
Unload,
|
||||
EnterFrame,
|
||||
Load,
|
||||
DragOver,
|
||||
Press,
|
||||
RollOut,
|
||||
RollOver,
|
||||
ReleaseOutside,
|
||||
Release,
|
||||
Press,
|
||||
Initialize,
|
||||
Data,
|
||||
Construct,
|
||||
KeyPress,
|
||||
DragOut,
|
||||
ReleaseOutside,
|
||||
Unload,
|
||||
}
|
||||
|
||||
pub type ClipEventFlags = HashSet<ClipEvent>;
|
||||
/// A key code used in `ButtonAction` and `ClipAction` key press events.
|
||||
pub type KeyCode = u8;
|
||||
|
||||
/// Represents a tag in an SWF file.
|
||||
///
|
||||
|
|
|
@ -9,8 +9,8 @@ use crate::error::{Error, Result};
|
|||
use crate::tag_code::TagCode;
|
||||
use crate::types::*;
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use enumset::EnumSet;
|
||||
use std::cmp::max;
|
||||
use std::collections::HashSet;
|
||||
use std::io::{self, Write};
|
||||
|
||||
/// Writes an SWF file to an output stream.
|
||||
|
@ -2195,14 +2195,14 @@ impl<W: Write> Writer<W> {
|
|||
fn write_clip_actions(&mut self, clip_actions: &[ClipAction]) -> Result<()> {
|
||||
self.write_u16(0)?; // Reserved
|
||||
{
|
||||
let mut all_events = HashSet::with_capacity(32);
|
||||
let mut all_events = EnumSet::new();
|
||||
for action in clip_actions {
|
||||
all_events = &all_events | &action.events;
|
||||
all_events |= action.events;
|
||||
}
|
||||
self.write_clip_event_flags(&all_events)?;
|
||||
self.write_clip_event_flags(all_events)?;
|
||||
}
|
||||
for action in clip_actions {
|
||||
self.write_clip_event_flags(&action.events)?;
|
||||
self.write_clip_event_flags(action.events)?;
|
||||
let action_length =
|
||||
action.action_data.len() as u32 + if action.key_code.is_some() { 1 } else { 0 };
|
||||
self.write_u32(action_length)?;
|
||||
|
@ -2219,30 +2219,30 @@ impl<W: Write> Writer<W> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_clip_event_flags(&mut self, clip_events: &HashSet<ClipEvent>) -> Result<()> {
|
||||
fn write_clip_event_flags(&mut self, clip_events: EnumSet<ClipEventFlag>) -> Result<()> {
|
||||
// TODO: Assert proper version.
|
||||
self.write_bit(clip_events.contains(&ClipEvent::KeyUp))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::KeyDown))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::MouseUp))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::MouseDown))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::MouseMove))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::Unload))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::EnterFrame))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::Load))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::DragOver))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::RollOut))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::RollOver))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::ReleaseOutside))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::Release))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::Press))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::Initialize))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::Data))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::KeyUp))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::KeyDown))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::MouseUp))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::MouseDown))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::MouseMove))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::Unload))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::EnterFrame))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::Load))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::DragOver))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::RollOut))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::RollOver))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::ReleaseOutside))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::Release))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::Press))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::Initialize))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::Data))?;
|
||||
if self.version >= 6 {
|
||||
self.write_ubits(5, 0)?;
|
||||
let has_construct = self.version >= 7 && clip_events.contains(&ClipEvent::Construct);
|
||||
let has_construct = self.version >= 7 && clip_events.contains(ClipEventFlag::Construct);
|
||||
self.write_bit(has_construct)?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::KeyPress))?;
|
||||
self.write_bit(clip_events.contains(&ClipEvent::DragOut))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::KeyPress))?;
|
||||
self.write_bit(clip_events.contains(ClipEventFlag::DragOut))?;
|
||||
self.write_u8(0)?;
|
||||
}
|
||||
self.flush_bits()?;
|
||||
|
|
Loading…
Reference in New Issue