pict 0.1.0

Half-baked PICT resource rendering in rust
Documentation
use binrw::BinRead;

pub mod drawing_context;
pub mod shared;
pub mod v1;
pub mod v2;

pub use drawing_context::{DrawingContext, decode_bitmap};

#[derive(BinRead, Debug)]
#[br(big)]
pub enum PictVersion {
    #[br(magic(0x11u8))]
    Version1(u8),
    #[br(magic(0x0011u16))]
    Version2,

    Unknown(u16),
}

#[derive(BinRead, Debug)]
#[br(big)]
pub struct PictHeader {
    pub size: u16,
    pub bounds: shared::Rect,

    pub version: PictVersion,
}

use binrw::BinReaderExt;
use resource_fork::Resource;

#[derive(Debug, Resource)]
#[resource(code = "PICT")]
pub struct Pict(pub image::ImageBuffer<image::Rgba<u8>, Vec<u8>>);

impl BinRead for Pict {
    type Args<'a> = ();

    fn read_options<R: std::io::Read + std::io::Seek>(
        reader: &mut R,
        _: binrw::Endian,
        (): Self::Args<'_>,
    ) -> binrw::BinResult<Self> {
        let header: PictHeader = reader.read_be()?;
        let mut context = DrawingContext::new(header.bounds);

        match header.version {
            PictVersion::Version1(..) => loop {
                let opcode: v1::Opcode = reader.read_be()?;
                if context.command_v1(opcode) {
                    break;
                }
            },
            PictVersion::Version2 => loop {
                let opcode: v2::Opcode = reader.read_be()?;
                if context.command_v2(opcode) {
                    break;
                }

                // align reader to word boundary
                if reader.stream_position()? % 2 == 1 {
                    let _: u8 = reader.read_le()?;
                }
            },
            PictVersion::Unknown(_) => {
                panic!("Unknown pict version encountered!");
            }
        }

        Ok(Self(context.into_image()))
    }
}