Skip to main content

ttf_view/tables/glyf/
composite.rs

1use crate::{
2    tables::glyf::Glyph,
3    types::{Affine2x2, BigEndian, F2Dot14, int16, uint16},
4};
5
6#[repr(C)]
7pub struct CompositeGlyph {
8    base: Glyph,
9}
10
11const impl std::ops::Deref for CompositeGlyph {
12    type Target = Glyph;
13    fn deref(&self) -> &Self::Target {
14        &self.base
15    }
16}
17
18#[repr(C)]
19pub struct Component {
20    pub flags: ComponentFlags,
21    pub glyph_index: uint16,
22    data: [uint16; 0],
23    // : if ( flags & ARG_1_AND_2_ARE_WORDS ) {
24    // :     (int16 or FWORD) argument1;
25    // :     (int16 or FWORD) argument2;
26    // : } else {
27    // :     uint16 arg1and2; /* (arg1 << 8) | arg2 */
28    // : }
29    // : if ( flags & WE_HAVE_A_SCALE ) {
30    // :     F2Dot14  scale;
31    // : } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) {
32    // :     F2Dot14  xscale;
33    // :     F2Dot14  yscale;
34    // : } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) {
35    // :     F2Dot14  xscale;
36    // :     F2Dot14  scale01;
37    // :     F2Dot14  scale10;
38    // :     F2Dot14  yscale;
39    // : }
40}
41
42impl Component {
43    pub const fn arguments(&self) -> (i16, i16) {
44        if self.flags.intersects(ComponentFlags::ARG_1_AND_2_ARE_WORDS) {
45            let [a1, a2] = unsafe { *self.data.as_ptr().cast::<[int16; 2]>() };
46            (a1.get(), a2.get())
47        } else {
48            let [a1, a2] = unsafe { *self.data.as_ptr().cast::<[u8; 2]>() };
49            (a1.into(), a2.into())
50        }
51    }
52    pub const fn trabsform(&self) -> Option<Affine2x2> {
53        let long_args = self.flags.intersects(ComponentFlags::ARG_1_AND_2_ARE_WORDS);
54        let ptr = unsafe { self.data.as_ptr().byte_add(if long_args { 4 } else { 2 }) };
55
56        Some(unsafe {
57            if self.flags.intersects(ComponentFlags::WE_HAVE_A_SCALE) {
58                let scale = (&*ptr.cast::<BigEndian<F2Dot14>>()).get();
59                Affine2x2::scale(scale)
60            } else if self.flags.intersects(ComponentFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
61                let [x, y] = *ptr.cast::<[BigEndian<F2Dot14>; 2]>();
62                Affine2x2::scale_xy(x.get(), y.get())
63            } else if self.flags.intersects(ComponentFlags::WE_HAVE_A_TWO_BY_TWO) {
64                (&*ptr.cast::<BigEndian<Affine2x2>>()).get()
65            } else {
66                return None;
67            }
68        })
69    }
70}
71
72bitflags::bitflags! {
73    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
74    pub struct ComponentFlags: u16 {
75        const ARG_1_AND_2_ARE_WORDS = 0x0001_u16.to_be();
76        const ARGS_ARE_XY_VALUES = 0x0002_u16.to_be();
77        const ROUND_XY_TO_GRID = 0x0004_u16.to_be();
78        const WE_HAVE_A_SCALE = 0x0008_u16.to_be();
79        const MORE_COMPONENTS = 0x0020_u16.to_be();
80        const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040_u16.to_be();
81        const WE_HAVE_A_TWO_BY_TWO = 0x0080_u16.to_be();
82        const WE_HAVE_INSTRUCTIONS = 0x0100_u16.to_be();
83        const USE_MY_METRICS = 0x0200_u16.to_be();
84        const OVERLAP_COMPOUND = 0x0400_u16.to_be();
85        const SCALED_COMPONENT_OFFSET = 0x0800_u16.to_be();
86        const UNSCALED_COMPONENT_OFFSET = 0x1000_u16.to_be();
87        const RESERVED = 0xE010_u16.to_be();
88    }
89}