Skip to content

Commit

Permalink
swf: Introduce ShapeRecordFlag
Browse files Browse the repository at this point in the history
No functionality change.
  • Loading branch information
relrelb committed May 2, 2023
1 parent fe56f8d commit 182ae6c
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 33 deletions.
65 changes: 37 additions & 28 deletions swf/src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1762,49 +1762,58 @@ impl<'a> Reader<'a> {
})
}
} else {
let flags = bits.read_ubits(5)?;
if flags != 0 {
let flags = ShapeRecordFlag::from_bits_truncate(bits.read_ubits(5)? as u8);
if !flags.is_empty() {
// StyleChange
let num_fill_bits = context.num_fill_bits as u32;
let num_line_bits = context.num_line_bits as u32;
let mut new_style = StyleChangeData {
move_to: None,
fill_style_0: None,
fill_style_1: None,
line_style: None,
new_styles: None,
};
if (flags & 0b1) != 0 {
// move
let move_to = if flags.contains(ShapeRecordFlag::MOVE_TO) {
let num_bits = bits.read_ubits(5)?;
new_style.move_to = Some((
Some((
bits.read_sbits_twips(num_bits)?,
bits.read_sbits_twips(num_bits)?,
));
}
if (flags & 0b10) != 0 {
new_style.fill_style_0 = Some(bits.read_ubits(num_fill_bits)?);
}
if (flags & 0b100) != 0 {
new_style.fill_style_1 = Some(bits.read_ubits(num_fill_bits)?);
}
if (flags & 0b1000) != 0 {
new_style.line_style = Some(bits.read_ubits(num_line_bits)?);
}
))
} else {
None
};
let fill_style_0 = if flags.contains(ShapeRecordFlag::FILL_STYLE_0) {
Some(bits.read_ubits(num_fill_bits)?)
} else {
None
};
let fill_style_1 = if flags.contains(ShapeRecordFlag::FILL_STYLE_1) {
Some(bits.read_ubits(num_fill_bits)?)
} else {
None
};
let line_style = if flags.contains(ShapeRecordFlag::LINE_STYLE) {
Some(bits.read_ubits(num_line_bits)?)
} else {
None
};
// The spec says that StyleChangeRecord can only occur in DefineShape2+,
// but SWFs in the wild exist with them in DefineShape1 (generated by third party tools),
// and these run correctly in the Flash Player.
if (flags & 0b10000) != 0 {
let new_styles = if flags.contains(ShapeRecordFlag::NEW_STYLES) {
let mut reader = Reader::new(bits.reader(), context.swf_version);
let (new_styles, num_fill_bits, num_line_bits) =
reader.read_shape_styles(context.shape_version)?;
*bits.reader() = reader.input;
context.num_fill_bits = num_fill_bits;
context.num_line_bits = num_line_bits;
new_style.new_styles = Some(new_styles);
*bits.reader() = reader.input;
}
Some(ShapeRecord::StyleChange(Box::new(new_style)))
Some(new_styles)
} else {
None
};
Some(ShapeRecord::StyleChange(Box::new(StyleChangeData {
move_to,
fill_style_0,
fill_style_1,
line_style,
new_styles,
})))
} else {
// EndShapeRecord
None
}
};
Expand Down
11 changes: 11 additions & 0 deletions swf/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,17 @@ pub enum ShapeRecord {
},
}

bitflags! {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ShapeRecordFlag: u8 {
const MOVE_TO = 1 << 0;
const FILL_STYLE_0 = 1 << 1;
const FILL_STYLE_1 = 1 << 2;
const LINE_STYLE = 1 << 3;
const NEW_STYLES = 1 << 4;
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StyleChangeData {
pub move_to: Option<(Twips, Twips)>,
Expand Down
24 changes: 19 additions & 5 deletions swf/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1460,11 +1460,25 @@ impl<W: Write> Writer<W> {
bits.write_bit(false)?; // Style change
let num_fill_bits = context.num_fill_bits.into();
let num_line_bits = context.num_line_bits.into();
bits.write_bit(style_change.new_styles.is_some())?;
bits.write_bit(style_change.line_style.is_some())?;
bits.write_bit(style_change.fill_style_1.is_some())?;
bits.write_bit(style_change.fill_style_0.is_some())?;
bits.write_bit(style_change.move_to.is_some())?;
let mut flags = ShapeRecordFlag::empty();
flags.set(ShapeRecordFlag::MOVE_TO, style_change.move_to.is_some());
flags.set(
ShapeRecordFlag::FILL_STYLE_0,
style_change.fill_style_0.is_some(),
);
flags.set(
ShapeRecordFlag::FILL_STYLE_1,
style_change.fill_style_1.is_some(),
);
flags.set(
ShapeRecordFlag::LINE_STYLE,
style_change.line_style.is_some(),
);
flags.set(
ShapeRecordFlag::NEW_STYLES,
style_change.new_styles.is_some(),
);
bits.write_ubits(5, flags.bits().into())?;
if let Some((move_x, move_y)) = style_change.move_to {
let num_bits = max(count_sbits_twips(move_x), count_sbits_twips(move_y));
bits.write_ubits(5, num_bits)?;
Expand Down

0 comments on commit 182ae6c

Please sign in to comment.