ttf_view/tables/glyf/
composite.rs1use 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 }
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}