aseprite_loader/binary/chunks/
slice.rs

1use bitflags::bitflags;
2use nom::{combinator::cond, multi::count};
3
4use crate::binary::{
5    errors::ParseResult,
6    scalars::{dword, long, parse_dword_as_usize, parse_string, Dword, Long},
7};
8
9#[derive(Debug)]
10pub struct SliceChunk<'a> {
11    pub name: &'a str,
12    pub flags: SliceFlags,
13    pub slice_keys: Vec<SliceKey>,
14}
15
16bitflags! {
17    #[derive(Debug, Copy, Clone)]
18    pub struct SliceFlags: Dword {
19        const NINE_PATCH = 0x01;
20        const PIVOT = 0x02;
21    }
22}
23
24#[derive(Debug, Copy, Clone)]
25pub struct SliceKey {
26    pub frame_number: Dword,
27    pub x: Long,
28    pub y: Long,
29    pub width: Dword,
30    pub height: Dword,
31    pub nine_patch: Option<NinePatch>,
32    pub pivot: Option<Pivot>,
33}
34
35#[derive(Debug, Copy, Clone)]
36pub struct NinePatch {
37    pub x: Long,
38    pub y: Long,
39    pub width: Dword,
40    pub height: Dword,
41}
42
43#[derive(Debug, Copy, Clone)]
44pub struct Pivot {
45    pub x: Long,
46    pub y: Long,
47}
48
49pub fn parse_slice_chunk(input: &[u8]) -> ParseResult<'_, SliceChunk<'_>> {
50    let (input, number_of_keys) = parse_dword_as_usize(input)?;
51    let (input, flags) = dword(input)?;
52    let flags = SliceFlags::from_bits_truncate(flags);
53    let (input, _) = dword(input)?;
54    let (input, name) = parse_string(input)?;
55    let (input, slice_keys) = count(|input| parse_slice_key(input, flags), number_of_keys)(input)?;
56    Ok((
57        input,
58        SliceChunk {
59            name,
60            flags,
61            slice_keys,
62        },
63    ))
64}
65
66pub fn parse_slice_key(input: &[u8], flags: SliceFlags) -> ParseResult<'_, SliceKey> {
67    let (input, frame_number) = dword(input)?;
68    let (input, x) = long(input)?;
69    let (input, y) = long(input)?;
70    let (input, width) = dword(input)?;
71    let (input, height) = dword(input)?;
72    let (input, nine_patch) =
73        cond(flags.contains(SliceFlags::NINE_PATCH), parse_nine_patch)(input)?;
74    let (input, pivot) = cond(flags.contains(SliceFlags::PIVOT), parse_pivot)(input)?;
75    Ok((
76        input,
77        SliceKey {
78            frame_number,
79            x,
80            y,
81            width,
82            height,
83            nine_patch,
84            pivot,
85        },
86    ))
87}
88
89pub fn parse_nine_patch(input: &[u8]) -> ParseResult<'_, NinePatch> {
90    let (input, x) = long(input)?;
91    let (input, y) = long(input)?;
92    let (input, width) = dword(input)?;
93    let (input, height) = dword(input)?;
94    Ok((
95        input,
96        NinePatch {
97            x,
98            y,
99            width,
100            height,
101        },
102    ))
103}
104
105pub fn parse_pivot(input: &[u8]) -> ParseResult<'_, Pivot> {
106    let (input, x) = long(input)?;
107    let (input, y) = long(input)?;
108    Ok((input, Pivot { x, y }))
109}