use binrw::{BinRead, BinReaderExt, BinResult, binread};
use packbits_rle::PackBitsReaderExt;
use super::shared::*;
#[derive(BinRead, Debug)]
#[br(big)]
pub struct FixedRect {
pub left: Fixed,
pub top: Fixed,
pub right: Fixed,
pub bottom: Fixed,
}
#[derive(BinRead, Debug)]
#[br(big)]
pub enum MinorVersion {
#[br(magic(-1i32))]
Normal,
#[br(magic(-2i32))]
Extended,
}
#[binread]
#[derive(Debug)]
#[br(big)]
pub struct Header {
pub version: MinorVersion,
pub bounds: FixedRect,
#[br(temp, assert(reserved == 0x00000000u32))]
pub reserved: u32,
}
#[derive(BinRead, Debug)]
#[br(big)]
pub enum Opcode {
#[br(magic(0x0000u16))]
NOP,
#[br(magic(0x0001u16))]
Clip(Region),
#[br(magic(0x0002u16))]
BkPat(Pattern),
#[br(magic(0x0003u16))]
TxFont(Integer),
#[br(magic(0x0004u16))]
TxFace(u8),
#[br(magic(0x0005u16))]
TxMode(u16),
#[br(magic(0x0006u16))]
SpExtra(Fixed),
#[br(magic(0x0007u16))]
PnSize(Point),
#[br(magic(0x0008u16))]
PnMode(Integer),
#[br(magic(0x0009u16))]
PnPat(Pattern),
#[br(magic(0x000Au16))]
FillPat(Pattern),
#[br(magic(0x000Bu16))]
OvSize(Point),
#[br(magic(0x000Cu16))]
Origin(Integer, Integer),
#[br(magic(0x000Du16))]
TxSize(Integer),
#[br(magic(0x000Eu16))]
FgColor(Long),
#[br(magic(0x000Fu16))]
BkColor(Long),
#[br(magic(0x0010u16))]
TxRatio(Point, Point),
#[br(magic(0x0011u16))]
VersionOp,
#[br(magic(0x0012u16))]
BkPixPat,
#[br(magic(0x0013u16))]
PnPixPat,
#[br(magic(0x0014u16))]
FillPixPat,
#[br(magic(0x0015u16))]
PnLocHFrac,
#[br(magic(0x0016u16))]
ChExtra(Integer),
#[br(magic(0x0017u16))]
ReservedForAppleUse,
#[br(magic(0x0018u16))]
ReservedForAppleUse1,
#[br(magic(0x0019u16))]
ReservedForAppleUse2,
#[br(magic(0x001Au16))]
RGBFgColor(RGBColor),
#[br(magic(0x001Bu16))]
RGBBkCol(RGBColor),
#[br(magic(0x001Cu16))]
HiliteMode,
#[br(magic(0x001Du16))]
HiliteColor(RGBColor),
#[br(magic(0x001Eu16))]
DefHilite,
#[br(magic(0x001Fu16))]
OpColor(RGBColor),
#[br(magic(0x0020u16))]
Line(Point, Point),
#[br(magic(0x0021u16))]
LineFrom(Point),
#[br(magic(0x0022u16))]
ShortLine(Point, i8, i8),
#[br(magic(0x0023u16))]
ShortLineFrom(i8, i8),
#[br(magic(0x0024u16))]
ReservedForAppleUse3(u16, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0025u16))]
ReservedForAppleUse4(u16, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0026u16))]
ReservedForAppleUse5(u16, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0027u16))]
ReservedForAppleUse6(u16, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0028u16))]
LongText(Point, ShortString),
#[br(magic(0x0029u16))]
DHText(u8, ShortString),
#[br(magic(0x002Au16))]
DVText(u8, ShortString),
#[br(magic(0x002Bu16))]
DHDVText(u8, u8, ShortString),
#[br(magic(0x002Cu16))]
FontName(Integer, Integer, ShortString),
#[br(magic(0x002Du16))]
LineJustify(Integer, Fixed, Fixed),
#[br(magic(0x002Eu16))]
GlyphState(Word, u8, u8, u8, u8),
#[br(magic(0x002Fu16))]
ReservedForAppleUse7(u16, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0030u16))]
FrameRect(Rect),
#[br(magic(0x0031u16))]
PaintRect(Rect),
#[br(magic(0x0032u16))]
EraseRect(Rect),
#[br(magic(0x0033u16))]
InvertRect(Rect),
#[br(magic(0x0034u16))]
FillRect(Rect),
#[br(magic(0x0035u16))]
ReservedForAppleUse8(Rect),
#[br(magic(0x0036u16))]
ReservedForAppleUse9(Rect),
#[br(magic(0x0037u16))]
ReservedForAppleUse10(Rect),
#[br(magic(0x0038u16))]
FrameSameRect,
#[br(magic(0x0039u16))]
PaintSameRect,
#[br(magic(0x003Au16))]
EraseSameRect,
#[br(magic(0x003Bu16))]
InvertSameRect,
#[br(magic(0x003Cu16))]
FillSameRect,
#[br(magic(0x003Du16))]
ReservedForAppleUse11,
#[br(magic(0x003Eu16))]
ReservedForAppleUse12,
#[br(magic(0x003Fu16))]
ReservedForAppleUse13,
#[br(magic(0x0040u16))]
FrameRRect(Rect),
#[br(magic(0x0041u16))]
PaintRRect(Rect),
#[br(magic(0x0042u16))]
EraseRRect(Rect),
#[br(magic(0x0043u16))]
InvertRRect(Rect),
#[br(magic(0x0044u16))]
FillRRect(Rect),
#[br(magic(0x0045u16))]
ReservedForAppleUse14(Rect),
#[br(magic(0x0046u16))]
ReservedForAppleUse15(Rect),
#[br(magic(0x0047u16))]
ReservedForAppleUse16(Rect),
#[br(magic(0x0048u16))]
FrameSameRRect,
#[br(magic(0x0049u16))]
PaintSameRRect,
#[br(magic(0x004Au16))]
EraseSameRRect,
#[br(magic(0x004Bu16))]
InvertSameRRect,
#[br(magic(0x004Cu16))]
FillSameRRect,
#[br(magic(0x004Du16))]
ReservedForAppleUse17,
#[br(magic(0x004Eu16))]
ReservedForAppleUse18,
#[br(magic(0x004Fu16))]
ReservedForAppleUse19,
#[br(magic(0x0050u16))]
FrameOval(Rect),
#[br(magic(0x0051u16))]
PaintOval(Rect),
#[br(magic(0x0052u16))]
EraseOval(Rect),
#[br(magic(0x0053u16))]
InvertOval(Rect),
#[br(magic(0x0054u16))]
FillOval(Rect),
#[br(magic(0x0055u16))]
ReservedForAppleUse20(Rect),
#[br(magic(0x0056u16))]
ReservedForAppleUse21(Rect),
#[br(magic(0x0057u16))]
ReservedForAppleUse22(Rect),
#[br(magic(0x0058u16))]
FrameSameOval,
#[br(magic(0x0059u16))]
PaintSameOval,
#[br(magic(0x005Au16))]
EraseSameOval,
#[br(magic(0x005Bu16))]
InvertSameOval,
#[br(magic(0x005Cu16))]
FillSameOval,
#[br(magic(0x005Du16))]
ReservedForAppleUse23,
#[br(magic(0x005Eu16))]
ReservedForAppleUse24,
#[br(magic(0x005Fu16))]
ReservedForAppleUse25,
#[br(magic(0x0060u16))]
FrameArc(Rect, u16, u16),
#[br(magic(0x0061u16))]
PaintArc(Rect, u16, u16),
#[br(magic(0x0062u16))]
EraseArc(Rect, u16, u16),
#[br(magic(0x0063u16))]
InvertArc(Rect, u16, u16),
#[br(magic(0x0064u16))]
FillArc(Rect, u16, u16),
#[br(magic(0x0065u16))]
ReservedForAppleUse26(Rect, u16, u16),
#[br(magic(0x0066u16))]
ReservedForAppleUse27(Rect, u16, u16),
#[br(magic(0x0067u16))]
ReservedForAppleUse28(Rect, u16, u16),
#[br(magic(0x0068u16))]
FrameSameArc(u16, u16),
#[br(magic(0x0069u16))]
PaintSameArc(u16, u16),
#[br(magic(0x006Au16))]
EraseSameArc(u16, u16),
#[br(magic(0x006Bu16))]
InvertSameArc(u16, u16),
#[br(magic(0x006Cu16))]
FillSameArc(u16, u16),
#[br(magic(0x006Du16))]
ReservedForAppleUse29(u16, u16),
#[br(magic(0x006Eu16))]
ReservedForAppleUse30(u16, u16),
#[br(magic(0x006Fu16))]
ReservedForAppleUse31(u16, u16),
#[br(magic(0x0070u16))]
FramePoly(Polygon),
#[br(magic(0x0071u16))]
PaintPoly(Polygon),
#[br(magic(0x0072u16))]
ErasePoly(Polygon),
#[br(magic(0x0073u16))]
InvertPoly(Polygon),
#[br(magic(0x0074u16))]
FillPoly(Polygon),
#[br(magic(0x0075u16))]
ReservedForAppleUse32(Polygon),
#[br(magic(0x0076u16))]
ReservedForAppleUse33(Polygon),
#[br(magic(0x0077u16))]
ReservedForAppleUse34(Polygon),
#[br(magic(0x0078u16))]
FrameSamePoly,
#[br(magic(0x0079u16))]
PaintSamePoly,
#[br(magic(0x007Au16))]
EraseSamePoly,
#[br(magic(0x007Bu16))]
InvertSamePoly,
#[br(magic(0x007Cu16))]
FillSamePoly,
#[br(magic(0x007Du16))]
ReservedForAppleUse35,
#[br(magic(0x007Eu16))]
ReservedForAppleUse36,
#[br(magic(0x007Fu16))]
ReservedForAppleUse37,
#[br(magic(0x0080u16))]
FrameRgn(Region),
#[br(magic(0x0081u16))]
PaintRgn(Region),
#[br(magic(0x0082u16))]
EraseRgn(Region),
#[br(magic(0x0083u16))]
InvertRgn(Region),
#[br(magic(0x0084u16))]
FillRgn(Region),
#[br(magic(0x0085u16))]
ReservedForAppleUse38(Region),
#[br(magic(0x0086u16))]
ReservedForAppleUse39(Region),
#[br(magic(0x0087u16))]
ReservedForAppleUse40(Region),
#[br(magic(0x0088u16))]
FrameSameRgn,
#[br(magic(0x0089u16))]
PaintSameRgn,
#[br(magic(0x008Au16))]
EraseSameRgn,
#[br(magic(0x008Bu16))]
InvertSameRgn,
#[br(magic(0x008Cu16))]
FillSameRgn,
#[br(magic(0x008Du16))]
ReservedForAppleUse41,
#[br(magic(0x008Eu16))]
ReservedForAppleUse42,
#[br(magic(0x008Fu16))]
ReservedForAppleUse43,
#[br(magic(0x0090u16))]
BitsRect(#[br(args(true, false))] CopyBits),
#[br(magic(0x0091u16))]
BitsRgn(#[br(args(false, false))] CopyBits),
#[br(magic(0x0092u16))]
ReservedForAppleUse44(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0093u16))]
ReservedForAppleUse45(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0094u16))]
ReservedForAppleUse46(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0095u16))]
ReservedForAppleUse47(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0096u16))]
ReservedForAppleUse48(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0097u16))]
ReservedForAppleUse49(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x0098u16))]
PackBitsRect(#[br(args(true, false))] CopyBits),
#[br(magic(0x0099u16))]
PackBitsRgn(#[br(args(true, true))] CopyBits),
#[br(magic(0x009Au16))]
DirectBitsRect(#[br(args(false))] DirectBits),
#[br(magic(0x009Bu16))]
DirectBitsRgn(#[br(args(true))] DirectBits),
#[br(magic(0x009Cu16))]
ReservedForAppleUse50(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x009Du16))]
ReservedForAppleUse51(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x009Eu16))]
ReservedForAppleUse52(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x009Fu16))]
ReservedForAppleUse53(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x00A0u16))]
ShortComment(CommentKind),
#[br(magic(0x00A1u16))]
LongComment(CommentKind, Integer, #[br(count(self_1))] Vec<u8>),
#[br(magic(0x00A2u16))]
ReservedForAppleUse54(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x00AFu16))]
ReservedForAppleUse55(Integer, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x00B0u16))]
ReservedForAppleUse56,
#[br(magic(0x00CFu16))]
ReservedForAppleUse57,
#[br(magic(0x00D0u16))]
ReservedForAppleUse58(Long, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x00FEu16))]
ReservedForAppleUse59(Long, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x00FFu16))]
OpEndPic,
#[br(magic(0x0100u16))]
ReservedForAppleUse60(u16),
#[br(magic(0x01FFu16))]
ReservedForAppleUse61(u16),
#[br(magic(0x0200u16))]
ReservedForAppleUse62(u32),
#[br(magic(0x02FFu16))]
Version,
#[br(magic(0x0BFFu16))]
ReservedForAppleUse63([u8; 22]),
#[br(magic(0x0C00u16))]
HeaderOp(Header),
#[br(magic(0x0C01u16))]
ReservedForAppleUse64([u8; 24]),
#[br(magic(0x7F00u16))]
ReservedForAppleUse65([u8; 254]),
#[br(magic(0x7FFFu16))]
ReservedForAppleUse66([u8; 254]),
#[br(magic(0x8000u16))]
ReservedForAppleUse67,
#[br(magic(0x80FFu16))]
ReservedForAppleUse68,
#[br(magic(0x8100u16))]
ReservedForAppleUse69(Long, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x8200u16))]
CompressedQuickTime(Long, #[br(count(self_0))] Vec<u8>),
#[br(magic(0x8201u16))]
UncompressedQuickTime(Long, #[br(count(self_0))] Vec<u8>),
#[br(magic(0xFFFFu16))]
ReservedForAppleUse70(Long, #[br(count(self_0))] Vec<u8>),
Unknown(u16),
}
#[derive(Debug)]
pub struct DirectBits {
pub pix_map: PixMap,
pub src_rect: Rect,
pub dst_rect: Rect,
pub mode: Short,
pub mask: Option<Region>,
pub data: Vec<u8>,
}
impl BinRead for DirectBits {
type Args<'a> = (bool,);
fn read_options<R: std::io::Read + std::io::Seek>(
reader: &mut R,
_endian: binrw::Endian,
(masked,): Self::Args<'_>,
) -> BinResult<Self> {
let _base_address: u32 = reader.read_be()?;
let row_bytes_and_flags_hi: u8 = reader.read_be()?;
let result: BinResult<PixMap> = reader.read_be_args((row_bytes_and_flags_hi,));
let pix_map: PixMap = result?;
let src_rect = reader.read_be()?;
let dst_rect = reader.read_be()?;
let mode = reader.read_be()?;
let mask = if masked {
Some(reader.read_be()?)
} else {
None
};
let scanline_count = pix_map.bounds.height() as usize;
let scanline_size = pix_map.component_count as usize * pix_map.bounds.width() as usize;
let unpacked_size = scanline_count * scanline_size;
let mut data = vec![0u8; unpacked_size];
for y in 0..scanline_count {
#[allow(unused)]
let packed_scanline_size: usize = if scanline_size > 250 {
reader.read_be::<u16>()?.into()
} else {
reader.read_be::<u8>()?.into()
};
let unpacked_scanline_range = (y * scanline_size)..((y + 1) * scanline_size);
reader.read_packbits(&mut data[unpacked_scanline_range])?;
}
Ok(DirectBits {
pix_map,
src_rect,
dst_rect,
mode,
mask,
data,
})
}
}