Skip to main content

car/model/
rendition.rs

1use std::io::{Read, Seek, SeekFrom};
2
3use bom::{BOMBlock, BOMEror, BOMResult};
4use deku::{ctx::Order, prelude::*, reader::Reader};
5
6use super::ColorSpace;
7use crate::PayloadBytes;
8
9#[derive(Debug, DekuRead)]
10#[deku(magic = b"tmfk", endian = "little")]
11pub struct KeyFmt {
12    pub version: u32,
13    pub max_count: u32,
14    #[deku(reader = "KeyFmt::read_attr_types(deku::reader, *max_count)")]
15    pub attribute_types: Vec<AttributeType>,
16}
17
18impl KeyFmt {
19    fn read_attr_types<R: Read + Seek>(
20        reader: &mut Reader<R>,
21        count: u32,
22    ) -> Result<Vec<AttributeType>, DekuError> {
23        let mut attr_types: Vec<AttributeType> = vec![];
24        for _ in 0..count {
25            attr_types.push(AttributeType::from_reader_with_ctx(
26                reader,
27                deku::ctx::Endian::Little,
28            )?);
29            reader.seek(SeekFrom::Current(2))?;
30        }
31        Ok(attr_types)
32    }
33}
34
35#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, DekuRead)]
36#[deku(endian = "little")]
37pub struct KeyToken {
38    pub x: u16,
39    pub y: u16,
40    count: u16,
41    #[deku(count = "count")]
42    pub attrs: Vec<Attribute>,
43}
44
45#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, DekuRead)]
46#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
47pub struct Attribute {
48    pub name: AttributeType,
49    pub val: u16,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, DekuRead)]
53#[deku(id_type = "u16", endian = "little", ctx = "endian: deku::ctx::Endian")]
54pub enum AttributeType {
55    #[deku(id = 0)]
56    ThemeLook,
57    #[deku(id = 1)]
58    Element,
59    #[deku(id = 2)]
60    Part,
61    #[deku(id = 3)]
62    Size,
63    #[deku(id = 4)]
64    Direction,
65    #[deku(id = 5)]
66    Placeholder,
67    #[deku(id = 6)]
68    Value,
69    #[deku(id = 7)]
70    ThemeAppearance,
71    #[deku(id = 8)]
72    Dimension1,
73    #[deku(id = 9)]
74    Dimension2,
75    #[deku(id = 10)]
76    State,
77    #[deku(id = 11)]
78    Layer,
79    #[deku(id = 12)]
80    Scale,
81    #[deku(id = 13)]
82    Localization,
83    #[deku(id = 14)]
84    PresentationState,
85    #[deku(id = 15)]
86    Idiom,
87    #[deku(id = 16)]
88    Subtype,
89    #[deku(id = 17)]
90    Identifier,
91    #[deku(id = 18)]
92    PreviousValue,
93    #[deku(id = 19)]
94    PreviousState,
95    #[deku(id = 20)]
96    HorizontalSizeClass,
97    #[deku(id = 21)]
98    VerticalSizeClass,
99    #[deku(id = 22)]
100    MemoryLevelClass,
101    #[deku(id = 23)]
102    GraphicsFeatureSetClass,
103    #[deku(id = 24)]
104    DisplayGamut,
105    #[deku(id = 25)]
106    DeploymentTarget,
107    #[deku(id = 26)]
108    GlyphWeight,
109    #[deku(id = 27)]
110    GlyphSize,
111
112    #[deku(id_pat = "_")]
113    Unknown { tag: u16 },
114}
115
116#[derive(Debug, Clone)]
117pub enum Rendition {
118    Color(RenditionColor),
119    RawData(RenditionRawData),
120    ThemeCBCK(RenditionThemeCBCK),
121    MultisizeImageSet(RenditionMultisizeImageSet),
122    Unknown {
123        tag: [u8; 4],
124        data: RenditionUnknown,
125    },
126}
127
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum RenditionKind {
130    None,
131    Color,
132    RawData,
133    ThemeCBCK,
134    MultisizeImageSet,
135    Unknown,
136}
137
138#[derive(Debug, Clone, DekuRead)]
139#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
140pub struct RenditionColor {
141    pub version: u32,
142    pub color_space: ColorSpace,
143    _component_count: u32,
144    #[deku(count = "_component_count")]
145    pub components: Vec<f64>,
146}
147
148#[derive(Debug, Clone)]
149pub struct RenditionRawData {
150    pub version: u32,
151    _raw_data_length: u32,
152    pub raw_data: PayloadBytes,
153}
154
155#[derive(Debug, Clone)]
156pub struct RenditionThemeCBCK {
157    pub version: u32,
158    pub compression_type: CompressionType,
159    _raw_data_length: u32,
160    pub chunks: Vec<ThemeChunk>,
161}
162
163impl RenditionThemeCBCK {
164    pub fn raw_datas(&self) -> impl Iterator<Item = &[u8]> {
165        self.chunks.iter().map(|chunk| chunk.raw_data.as_slice())
166    }
167}
168
169#[derive(Debug, Clone, DekuRead)]
170#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
171pub struct RenditionMultisizeImageSet {
172    pub version: u32,
173    _count: u32,
174    #[deku(count = "_count")]
175    pub entries: Vec<MultisizeImageSetEntry>,
176}
177
178#[derive(Debug, Clone)]
179pub struct RenditionUnknown {
180    // pub tag: [u8; 4],
181    pub version: u32,
182    _raw_data_length: u32,
183    pub raw_data: PayloadBytes,
184}
185
186#[derive(Debug, Clone, DekuRead)]
187#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
188pub struct CBCK {
189    pub idk: u32,
190    pub tag: u32,
191    pub a: u32,
192    pub b: u32,
193}
194
195#[derive(Debug, Clone, DekuRead)]
196#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
197pub struct MultisizeImageSetEntry {
198    pub width: u32,
199    pub height: u32,
200    pub index: u16,
201    pub idiom: Idiom,
202}
203
204#[derive(Debug, Clone, DekuRead)]
205#[deku(endian = "little")]
206pub struct ThemePartHeader {
207    pub tag: [u8; 4],
208    pub arg2: u32,
209    pub arg3: u32,
210    pub height: u32,
211    pub raw_len: u32,
212}
213
214#[derive(Debug, Clone)]
215pub struct ThemeChunk {
216    pub part_header: Option<ThemePartHeader>,
217    pub raw_data: PayloadBytes,
218}
219
220pub(crate) fn parse_rendition_payload(payload: PayloadBytes) -> BOMResult<Rendition> {
221    let mut reader = Reader::new(BOMBlock::new(payload));
222    let mut tag = [0_u8; 4];
223    reader.read_bytes(4, &mut tag, Order::default())?;
224
225    match &tag {
226        b"RLOC" => {
227            let data =
228                RenditionColor::from_reader_with_ctx(&mut reader, deku::ctx::Endian::Little)?;
229            Ok(Rendition::Color(data))
230        }
231        b"DWAR" => {
232            let version = read_u32(&mut reader)?;
233            let raw_data_length = read_u32(&mut reader)?;
234            let raw_data = payload_slice(&mut reader, raw_data_length)?;
235            Ok(Rendition::RawData(RenditionRawData {
236                version,
237                _raw_data_length: raw_data_length,
238                raw_data,
239            }))
240        }
241        b"MLEC" => {
242            let version = read_u32(&mut reader)?;
243            let compression_type =
244                CompressionType::from_reader_with_ctx(&mut reader, deku::ctx::Endian::Little)?;
245            let raw_data_length = read_u32(&mut reader)?;
246            let chunks = read_theme_chunks(&mut reader, version, raw_data_length)?;
247            Ok(Rendition::ThemeCBCK(RenditionThemeCBCK {
248                version,
249                compression_type,
250                _raw_data_length: raw_data_length,
251                chunks,
252            }))
253        }
254        b"SISM" => {
255            let data = RenditionMultisizeImageSet::from_reader_with_ctx(
256                &mut reader,
257                deku::ctx::Endian::Little,
258            )?;
259            Ok(Rendition::MultisizeImageSet(data))
260        }
261        _ => {
262            let version = read_u32(&mut reader)?;
263            let raw_data_length = read_u32(&mut reader)?;
264            let raw_data = payload_slice(&mut reader, raw_data_length)?;
265            Ok(Rendition::Unknown {
266                tag,
267                data: RenditionUnknown {
268                    version,
269                    _raw_data_length: raw_data_length,
270                    raw_data,
271                },
272            })
273        }
274    }
275}
276
277fn read_u32(reader: &mut Reader<BOMBlock>) -> Result<u32, DekuError> {
278    u32::from_reader_with_ctx(reader, deku::ctx::Endian::Little)
279}
280
281fn payload_slice(reader: &mut Reader<BOMBlock>, len: u32) -> BOMResult<PayloadBytes> {
282    let len = len as usize;
283    let slice = reader.as_mut().slice_at_current(len)?;
284    reader.bits_read = reader.bits_read.saturating_add(len.saturating_mul(8));
285    reader.leftover = None;
286    Ok(slice)
287}
288
289fn read_theme_chunks(
290    reader: &mut Reader<BOMBlock>,
291    version: u32,
292    raw_len: u32,
293) -> BOMResult<Vec<ThemeChunk>> {
294    match version {
295        0 | 2 => {
296            let raw_data = payload_slice(reader, raw_len)?;
297            Ok(vec![ThemeChunk {
298                part_header: None,
299                raw_data,
300            }])
301        }
302        1 | 3 => {
303            let mut result = vec![];
304            for _ in 0..raw_len {
305                let part_header = ThemePartHeader::from_reader_with_ctx(reader, ())?;
306                let raw_data = payload_slice(reader, part_header.raw_len)?;
307                result.push(ThemeChunk {
308                    part_header: Some(part_header),
309                    raw_data,
310                });
311            }
312            Ok(result)
313        }
314        _ => Err(BOMEror::ParseStruct(DekuError::Parse(
315            format!("Not support version {}", version).into(),
316        ))),
317    }
318}
319
320#[derive(Debug, Clone, Copy, PartialEq, Eq, DekuRead)]
321#[deku(id_type = "u32", endian = "little", ctx = "endian: deku::ctx::Endian")]
322pub enum CompressionType {
323    #[deku(id = 0)]
324    Uncompressed,
325    #[deku(id = 1)]
326    Rle,
327    #[deku(id = 2)]
328    Zip,
329    #[deku(id = 3)]
330    Lzvn,
331    #[deku(id = 4)]
332    Lzfse,
333    #[deku(id = 5)]
334    JpegLzfse,
335    #[deku(id = 6)]
336    Blurred,
337    #[deku(id = 7)]
338    Astc,
339    #[deku(id = 8)]
340    PaletteImg,
341    #[deku(id = 9)]
342    HEVC, // ?
343    #[deku(id = 10)]
344    DeepmapLzfse,
345    // Unknow,
346    #[deku(id = 11)]
347    Deepmap2,
348
349    #[deku(id_pat = "_")]
350    Unknown { tag: u32 },
351}
352
353#[derive(Debug, Clone, DekuRead)]
354#[deku(id_type = "u16", endian = "little", ctx = "endian: deku::ctx::Endian")]
355pub enum Idiom {
356    #[deku(id = 0)]
357    Universal,
358    #[deku(id = 1)]
359    Phone,
360    #[deku(id = 2)]
361    Pad,
362    #[deku(id = 3)]
363    TV,
364    #[deku(id = 4)]
365    Car,
366    #[deku(id = 5)]
367    Watch,
368    #[deku(id = 6)]
369    Marketing,
370
371    #[deku(id_pat = "_")]
372    Unknown { tag: u16 },
373}
374
375#[derive(Debug, DekuRead)]
376#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
377pub struct BitmapList {
378    pub bitmap_count: u32, // usually 1?
379    pub zero: u32,         // usually 0?
380    pub rendition_length: u32,
381}
382
383#[derive(Debug, Clone, Copy, PartialEq, Eq, DekuRead)]
384#[deku(id_type = "u32", endian = "little", ctx = "endian: deku::ctx::Endian")]
385pub enum LayoutType {
386    #[deku(id = 6)]
387    Gradient,
388    #[deku(id = 7)]
389    Effect,
390    #[deku(id = 9)]
391    Vector,
392    #[deku(id = 10)]
393    OnePartFixedSize,
394    #[deku(id = 11)]
395    OnePartTile,
396    #[deku(id = 12)]
397    OnePartScale,
398    #[deku(id = 20)]
399    ThreePartHorizontalTile,
400    #[deku(id = 21)]
401    ThreePartHorizontalScale,
402    #[deku(id = 22)]
403    ThreePartHorizontalUniform,
404    #[deku(id = 23)]
405    ThreePartVerticalTile,
406    #[deku(id = 24)]
407    ThreePartVerticalScale,
408    #[deku(id = 25)]
409    ThreePartVerticalUniform,
410    #[deku(id = 30)]
411    NinePartTile,
412    #[deku(id = 31)]
413    NinePartScale,
414    #[deku(id = 32)]
415    NinePartHorizontalUniformVerticalScale,
416    #[deku(id = 33)]
417    NinePartHorizontalScaleVerticalUniform,
418    #[deku(id = 34)]
419    NinePartEdgesOnly,
420    #[deku(id = 40)]
421    SixPart,
422    #[deku(id = 50)]
423    AnimationFilmstrip,
424
425    #[deku(id = 1000)]
426    Data,
427    #[deku(id = 1001)]
428    ExternalLink,
429    #[deku(id = 1002)]
430    LayerStack,
431    #[deku(id = 1003)]
432    InternalReference,
433    #[deku(id = 1004)]
434    PackedImage,
435    #[deku(id = 1005)]
436    NameList,
437    #[deku(id = 1006)]
438    UnknownAddObject,
439    #[deku(id = 1007)]
440    Texture,
441    #[deku(id = 1008)]
442    TextureImage,
443    #[deku(id = 1009)]
444    Color,
445    #[deku(id = 1010)]
446    MultisizeImage,
447    #[deku(id = 1012)]
448    LayerReference,
449    #[deku(id = 1013)]
450    ContentRendition,
451    #[deku(id = 1014)]
452    RecognitionObject,
453
454    #[deku(id_pat = "_")]
455    Unknown { tag: u32 },
456}
457
458#[derive(Debug, DekuRead)]
459#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
460pub struct Flags {
461    #[deku(bits = 1)]
462    pub is_header_flagged_fpo: bool,
463    #[deku(bits = 1)]
464    pub is_excluded_from_contrast_filter: bool,
465    #[deku(bits = 1)]
466    pub is_vector_based: bool,
467    #[deku(bits = 1)]
468    pub is_opaque: bool,
469    #[deku(bits = 4)]
470    pub bitmap_encoding: u8,
471    #[deku(bits = 1)]
472    pub opt_out_of_thinning: bool,
473    #[deku(bits = 1)]
474    pub is_flippable: bool,
475    #[deku(bits = 1)]
476    pub is_tintable: bool,
477    #[deku(bits = 1)]
478    pub preserved_vector_representation: bool,
479    #[deku(bits = 20)]
480    _reserved: u32,
481}
482
483#[derive(Debug, DekuRead)]
484#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
485pub struct Slice {
486    pub x: u32,
487    pub y: u32,
488    pub width: u32,
489    pub height: u32,
490}
491
492#[derive(Debug, DekuRead)]
493#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
494pub struct Metric {
495    pub width: u32,
496    pub height: u32,
497}
498
499#[derive(Debug, DekuRead)]
500#[deku(id_type = "u32", endian = "little", ctx = "endian: deku::ctx::Endian")]
501pub enum RenditionType {
502    #[deku(id = 1001)]
503    Slices(RenditionTypeSlice),
504    #[deku(id = 1003)]
505    Metrics(RenditionTypeMetric),
506    #[deku(id = 1004)]
507    BlendModeAndOpacity(RenditionTypeBlendModeAndOpacity),
508    #[deku(id = 1005)]
509    UTI(RenditionTypeUTI),
510    #[deku(id = 1006)]
511    EXIFOrientation(RenditionTypeEXIFOrientation),
512    #[deku(id = 1007)]
513    BytesPerRow { length: u32, bytes_per_row: u32 },
514    #[deku(id = 1010)]
515    Reference(RenditionTypeReference),
516    #[deku(id_pat = "_")]
517    Unknown {
518        tag: u32,
519        data: RenditionTypeUnknown,
520    },
521}
522
523#[derive(Debug, DekuRead)]
524#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
525pub struct RenditionTypeSlice {
526    _length: u32,
527    _count: u32,
528    #[deku(count = "_count")]
529    pub data: Vec<Slice>,
530}
531
532#[derive(Debug, DekuRead)]
533#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
534pub struct RenditionTypeMetric {
535    _length: u32,
536    _count: u32,
537    pub top_right_inset: Metric,
538    pub bottom_left_inset: Metric,
539    pub image_size: Metric,
540}
541
542#[derive(Debug, DekuRead)]
543#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
544pub struct RenditionTypeBlendModeAndOpacity {
545    _length: u32,
546    pub blend_mode: u32,
547    pub opacity: f32,
548}
549
550#[derive(Debug, DekuRead)]
551#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
552pub struct RenditionTypeUTI {
553    _length: u32,
554    pub string_length: u32,
555    pub padding: u32,
556    #[deku(count = "string_length")]
557    pub string: Vec<u8>,
558}
559
560#[derive(Debug, DekuRead)]
561#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
562pub struct RenditionTypeEXIFOrientation {
563    _length: u32,
564    pub orientation: EXIFOrientationValue,
565}
566
567#[derive(Debug, DekuRead)]
568#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
569pub struct RenditionTypeBytesPerRow {
570    _length: u32,
571    pub bytes_per_row: u32,
572}
573
574#[derive(Debug, DekuRead)]
575#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
576pub struct RenditionTypeReference {
577    _length: u32,
578    _magic: [u8; 4], // INLK
579    _padding: u32,   // always 0?
580    pub x: u32,
581    pub y: u32,
582    pub width: u32,
583    pub height: u32,
584    pub layout: u16, // since rendition header says internal link
585    _key_length: u32,
586    #[deku(count = "_key_length")]
587    pub keys: Vec<u8>, // rendition containing data
588}
589#[derive(Debug, DekuRead)]
590#[deku(endian = "little", ctx = "endian: deku::ctx::Endian")]
591pub struct RenditionTypeUnknown {
592    _length: u32,
593    #[deku(count = "_length")]
594    pub data: Vec<u8>,
595}
596
597#[derive(Debug, DekuRead)]
598#[deku(id_type = "u32", endian = "little", ctx = "endian: deku::ctx::Endian")]
599pub enum EXIFOrientationValue {
600    #[deku(id = 0)]
601    None,
602    #[deku(id = 1)]
603    Normal,
604    #[deku(id = 2)]
605    Mirrored,
606    #[deku(id = 3)]
607    Rotated180,
608    #[deku(id = 4)]
609    Rotated180Mirrored,
610    #[deku(id = 5)]
611    Rotated90,
612    #[deku(id = 6)]
613    Rotated90Mirrored,
614    #[deku(id = 7)]
615    Rotated270,
616    #[deku(id = 8)]
617    Rotated270Mirrored,
618
619    #[deku(id_pat = "_")]
620    Unknown { tag: u32 },
621}