aseprite_loader/binary/chunks/
slice.rs

1use bitflags::bitflags;
2use nom::{combinator::cond, multi::count, Parser};
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) =
56        count(|input| parse_slice_key(input, flags), number_of_keys).parse(input)?;
57    Ok((
58        input,
59        SliceChunk {
60            name,
61            flags,
62            slice_keys,
63        },
64    ))
65}
66
67pub fn parse_slice_key(input: &[u8], flags: SliceFlags) -> ParseResult<'_, SliceKey> {
68    let (input, frame_number) = dword(input)?;
69    let (input, x) = long(input)?;
70    let (input, y) = long(input)?;
71    let (input, width) = dword(input)?;
72    let (input, height) = dword(input)?;
73    let (input, nine_patch) =
74        cond(flags.contains(SliceFlags::NINE_PATCH), parse_nine_patch).parse(input)?;
75    let (input, pivot) = cond(flags.contains(SliceFlags::PIVOT), parse_pivot).parse(input)?;
76    Ok((
77        input,
78        SliceKey {
79            frame_number,
80            x,
81            y,
82            width,
83            height,
84            nine_patch,
85            pivot,
86        },
87    ))
88}
89
90pub fn parse_nine_patch(input: &[u8]) -> ParseResult<'_, NinePatch> {
91    let (input, x) = long(input)?;
92    let (input, y) = long(input)?;
93    let (input, width) = dword(input)?;
94    let (input, height) = dword(input)?;
95    Ok((
96        input,
97        NinePatch {
98            x,
99            y,
100            width,
101            height,
102        },
103    ))
104}
105
106pub fn parse_pivot(input: &[u8]) -> ParseResult<'_, Pivot> {
107    let (input, x) = long(input)?;
108    let (input, y) = long(input)?;
109    Ok((input, Pivot { x, y }))
110}