swf: Use bitflags for `PlaceFlag`
This commit is contained in:
parent
6d2005c2fe
commit
e88c7102f5
|
@ -1918,61 +1918,68 @@ impl<'a> Reader<'a> {
|
|||
place_object_version: u8,
|
||||
) -> Result<PlaceObject<'a>> {
|
||||
let flags = if place_object_version >= 3 {
|
||||
self.read_u16()?
|
||||
PlaceFlag::from_bits_truncate(self.read_u16()?)
|
||||
} else {
|
||||
self.read_u8()?.into()
|
||||
PlaceFlag::from_bits_truncate(self.read_u8()?.into())
|
||||
};
|
||||
|
||||
let depth = self.read_u16()?;
|
||||
|
||||
// PlaceObject3
|
||||
let is_image = (flags & 0b10000_00000000) != 0;
|
||||
// SWF19 p.40 incorrectly says class name if (HasClassNameFlag || (HasImage && HasCharacterID))
|
||||
// I think this should be if (HasClassNameFlag || (HasImage && !HasCharacterID)),
|
||||
// you use the class name only if a character ID isn't present.
|
||||
// But what is the case where we'd have an image without either HasCharacterID or HasClassName set?
|
||||
let has_character_id = (flags & 0b10) != 0;
|
||||
let has_class_name = (flags & 0b1000_00000000) != 0 || (is_image && !has_character_id);
|
||||
let is_image = flags.contains(PlaceFlag::IS_IMAGE);
|
||||
let has_character_id = flags.contains(PlaceFlag::HAS_CHARACTER);
|
||||
let has_class_name =
|
||||
flags.contains(PlaceFlag::HAS_CLASS_NAME) || (is_image && !has_character_id);
|
||||
let class_name = if has_class_name {
|
||||
Some(self.read_str()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let action = match flags & 0b11 {
|
||||
0b01 => PlaceObjectAction::Modify,
|
||||
0b10 => PlaceObjectAction::Place(self.read_u16()?),
|
||||
0b11 => PlaceObjectAction::Replace(self.read_u16()?),
|
||||
let action = match (flags.contains(PlaceFlag::MOVE), has_character_id) {
|
||||
(true, false) => PlaceObjectAction::Modify,
|
||||
(false, true) => {
|
||||
let id = self.read_u16()?;
|
||||
PlaceObjectAction::Place(id)
|
||||
}
|
||||
(true, true) => {
|
||||
let id = self.read_u16()?;
|
||||
PlaceObjectAction::Replace(id)
|
||||
}
|
||||
_ => return Err(Error::invalid_data("Invalid PlaceObject type")),
|
||||
};
|
||||
let matrix = if (flags & 0b100) != 0 {
|
||||
let matrix = if flags.contains(PlaceFlag::HAS_MATRIX) {
|
||||
Some(self.read_matrix()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let color_transform = if (flags & 0b1000) != 0 {
|
||||
let color_transform = if flags.contains(PlaceFlag::HAS_COLOR_TRANSFORM) {
|
||||
Some(self.read_color_transform()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ratio = if (flags & 0b1_0000) != 0 {
|
||||
let ratio = if flags.contains(PlaceFlag::HAS_RATIO) {
|
||||
Some(self.read_u16()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let name = if (flags & 0b10_0000) != 0 {
|
||||
let name = if flags.contains(PlaceFlag::HAS_NAME) {
|
||||
Some(self.read_str()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let clip_depth = if (flags & 0b100_0000) != 0 {
|
||||
let clip_depth = if flags.contains(PlaceFlag::HAS_CLIP_DEPTH) {
|
||||
Some(self.read_u16()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// PlaceObject3
|
||||
let filters = if (flags & 0b1_00000000) != 0 {
|
||||
let filters = if flags.contains(PlaceFlag::HAS_FILTER_LIST) {
|
||||
let num_filters = self.read_u8()?;
|
||||
let mut filters = Vec::with_capacity(num_filters as usize);
|
||||
for _ in 0..num_filters {
|
||||
|
@ -1982,37 +1989,39 @@ impl<'a> Reader<'a> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let blend_mode = if (flags & 0b10_00000000) != 0 {
|
||||
let blend_mode = if flags.contains(PlaceFlag::HAS_BLEND_MODE) {
|
||||
Some(self.read_blend_mode()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let is_bitmap_cached = if (flags & 0b100_00000000) != 0 {
|
||||
let is_bitmap_cached = if flags.contains(PlaceFlag::HAS_CACHE_AS_BITMAP) {
|
||||
Some(self.read_u8()? != 0)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let is_visible = if (flags & 0b100000_00000000) != 0 {
|
||||
let is_visible = if flags.contains(PlaceFlag::HAS_VISIBLE) {
|
||||
Some(self.read_u8()? != 0)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let background_color = if (flags & 0b1000000_00000000) != 0 {
|
||||
let background_color = if flags.contains(PlaceFlag::OPAQUE_BACKGROUND) {
|
||||
Some(self.read_rgba()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let clip_actions = if (flags & 0b1000_0000) != 0 {
|
||||
let clip_actions = if flags.contains(PlaceFlag::HAS_CLIP_ACTIONS) {
|
||||
Some(self.read_clip_actions()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// PlaceObject4
|
||||
let amf_data = if place_object_version >= 4 {
|
||||
Some(self.read_slice_to_end())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(PlaceObject {
|
||||
version: place_object_version,
|
||||
action,
|
||||
|
|
|
@ -608,6 +608,28 @@ pub struct PlaceObject<'a> {
|
|||
pub amf_data: Option<&'a [u8]>,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct PlaceFlag: u16 {
|
||||
const MOVE = 1 << 0;
|
||||
const HAS_CHARACTER = 1 << 1;
|
||||
const HAS_MATRIX = 1 << 2;
|
||||
const HAS_COLOR_TRANSFORM = 1 << 3;
|
||||
const HAS_RATIO = 1 << 4;
|
||||
const HAS_NAME = 1 << 5;
|
||||
const HAS_CLIP_DEPTH = 1 << 6;
|
||||
const HAS_CLIP_ACTIONS = 1 << 7;
|
||||
|
||||
// PlaceObject3
|
||||
const HAS_FILTER_LIST = 1 << 8;
|
||||
const HAS_BLEND_MODE = 1 << 9;
|
||||
const HAS_CACHE_AS_BITMAP = 1 << 10;
|
||||
const HAS_CLASS_NAME = 1 << 11;
|
||||
const IS_IMAGE = 1 << 12;
|
||||
const HAS_VISIBLE = 1 << 13;
|
||||
const OPAQUE_BACKGROUND = 1 << 14;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum PlaceObjectAction {
|
||||
Place(CharacterId),
|
||||
|
|
108
swf/src/write.rs
108
swf/src/write.rs
|
@ -1716,70 +1716,54 @@ impl<W: Write> Writer<W> {
|
|||
{
|
||||
// TODO: Assert version.
|
||||
let mut writer = Writer::new(&mut buf, self.version);
|
||||
writer.write_u8(
|
||||
if place_object.clip_actions.is_some() {
|
||||
0b1000_0000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.clip_depth.is_some() {
|
||||
0b0100_0000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.name.is_some() {
|
||||
0b0010_0000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.ratio.is_some() {
|
||||
0b0001_0000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.color_transform.is_some() {
|
||||
0b0000_1000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.matrix.is_some() {
|
||||
0b0000_0100
|
||||
} else {
|
||||
0
|
||||
} | match place_object.action {
|
||||
PlaceObjectAction::Place(_) => 0b10,
|
||||
PlaceObjectAction::Modify => 0b01,
|
||||
PlaceObjectAction::Replace(_) => 0b11,
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut flags = PlaceFlag::empty();
|
||||
flags.set(
|
||||
PlaceFlag::MOVE,
|
||||
matches!(
|
||||
place_object.action,
|
||||
PlaceObjectAction::Modify | PlaceObjectAction::Replace(_)
|
||||
),
|
||||
);
|
||||
flags.set(
|
||||
PlaceFlag::HAS_CHARACTER,
|
||||
matches!(
|
||||
place_object.action,
|
||||
PlaceObjectAction::Place(_) | PlaceObjectAction::Replace(_)
|
||||
),
|
||||
);
|
||||
flags.set(PlaceFlag::HAS_MATRIX, place_object.matrix.is_some());
|
||||
flags.set(
|
||||
PlaceFlag::HAS_COLOR_TRANSFORM,
|
||||
place_object.color_transform.is_some(),
|
||||
);
|
||||
flags.set(PlaceFlag::HAS_RATIO, place_object.ratio.is_some());
|
||||
flags.set(PlaceFlag::HAS_NAME, place_object.name.is_some());
|
||||
flags.set(PlaceFlag::HAS_CLIP_DEPTH, place_object.clip_depth.is_some());
|
||||
flags.set(
|
||||
PlaceFlag::HAS_CLIP_ACTIONS,
|
||||
place_object.clip_actions.is_some(),
|
||||
);
|
||||
|
||||
if place_object_version >= 3 {
|
||||
writer.write_u8(
|
||||
if place_object.background_color.is_some() {
|
||||
0b100_0000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.is_visible.is_some() {
|
||||
0b10_0000
|
||||
} else {
|
||||
0
|
||||
} | if place_object.is_image { 0b1_0000 } else { 0 }
|
||||
| if place_object.class_name.is_some() {
|
||||
0b1000
|
||||
} else {
|
||||
0
|
||||
}
|
||||
| if place_object.is_bitmap_cached.is_some() {
|
||||
0b100
|
||||
} else {
|
||||
0
|
||||
}
|
||||
| if place_object.blend_mode.is_some() {
|
||||
0b10
|
||||
} else {
|
||||
0
|
||||
}
|
||||
| if place_object.filters.is_some() {
|
||||
0b1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)?;
|
||||
flags.set(PlaceFlag::HAS_FILTER_LIST, place_object.filters.is_some());
|
||||
flags.set(PlaceFlag::HAS_BLEND_MODE, place_object.blend_mode.is_some());
|
||||
flags.set(
|
||||
PlaceFlag::HAS_CACHE_AS_BITMAP,
|
||||
place_object.is_bitmap_cached.is_some(),
|
||||
);
|
||||
flags.set(PlaceFlag::HAS_CLASS_NAME, place_object.class_name.is_some());
|
||||
flags.set(PlaceFlag::IS_IMAGE, place_object.is_image);
|
||||
flags.set(PlaceFlag::HAS_VISIBLE, place_object.is_visible.is_some());
|
||||
flags.set(
|
||||
PlaceFlag::OPAQUE_BACKGROUND,
|
||||
place_object.background_color.is_some(),
|
||||
);
|
||||
writer.write_u16(flags.bits())?;
|
||||
} else {
|
||||
writer.write_u8(flags.bits() as u8)?;
|
||||
}
|
||||
|
||||
writer.write_u16(place_object.depth)?;
|
||||
|
||||
if place_object_version >= 3 {
|
||||
|
|
Loading…
Reference in New Issue