ttf_view/tables/cmap/
mod.rs1use crate::{
2 types::{Offset32, Tag, tags, uint16, uint32},
3 util::iterator_map,
4};
5use std::mem::ManuallyDrop;
6
7mod codepoint;
8mod glyph_id;
9
10pub use codepoint::*;
11pub use glyph_id::*;
12
13pub mod format0;
14pub mod format2;
15pub mod format4;
16pub mod format6;
17pub mod format8;
18
19pub mod format10;
20pub mod format12;
21pub mod format13;
22pub mod format14;
23
24#[repr(C)]
25#[non_exhaustive]
26pub struct CmapTableRepr {
27 pub version: uint16,
28 pub num_tables: uint16,
29 encoding_records: [EncodingRecordRepr; 0],
30}
31#[repr(C)]
32pub struct EncodingRecordRepr {
33 pub platform_id: uint16,
34 pub encoding_id: uint16,
35 pub subtable_offset: Offset32,
36}
37
38impl super::Table for CmapTableRepr {
39 const TAG: Tag = tags::cmap;
40 type Handle<'a> = &'a Self;
41}
42
43impl CmapTableRepr {
44 pub const fn encoding_records(&self) -> &[EncodingRecordRepr] {
45 let len = self.num_tables.get() as usize;
46 unsafe { std::slice::from_raw_parts(self.encoding_records.as_ptr(), len) }
47 }
48 pub const fn encodings(&self) -> EncodingsIter<'_> {
49 EncodingsIter::new(self)
50 }
51}
52
53#[derive(Copy)]
54#[derive_const(Clone)]
55pub struct EncodingHandle<'a>(&'a CmapTableRepr, &'a EncodingRecordRepr);
56
57const impl std::ops::Deref for EncodingHandle<'_> {
58 type Target = EncodingRecordRepr;
59 fn deref(&self) -> &Self::Target {
60 self.1
61 }
62}
63impl<'a> EncodingHandle<'a> {
64 pub const fn subtable(&self) -> &'a CmapSubtableRepr {
65 let offset = self.1.subtable_offset.get() as _;
66 unsafe { &*std::ptr::from_ref(self.0).cast::<u8>().byte_add(offset).cast() }
67 }
68}
69
70pub struct EncodingsIter<'a> {
72 cmap: &'a CmapTableRepr,
73 inner: std::slice::Iter<'a, EncodingRecordRepr>,
74}
75impl<'a> EncodingsIter<'a> {
76 pub const fn new(cmap: &'a CmapTableRepr) -> Self {
77 Self { cmap, inner: cmap.encoding_records().iter() }
78 }
79 pub fn as_records(&self) -> &'a [EncodingRecordRepr] {
81 self.inner.as_slice()
82 }
83}
84iterator_map!(EncodingsIter<'a> {
85 type Item = EncodingHandle<'a>;
86 |this, x| EncodingHandle(this.cmap, x)
87});
88
89#[repr(C)]
90#[non_exhaustive]
91pub struct CmapSubtableRepr {
92 meta: SubtableMeta,
93 }
95
96#[repr(C)]
115union SubtableMeta {
116 short: ManuallyDrop<ShortMeta>,
117 long: ManuallyDrop<LongMeta>,
118 len_only: ManuallyDrop<LenOnlyMeta>,
119}
120
121#[repr(C)]
122#[non_exhaustive]
123struct ShortMeta {
124 format: uint16,
125 length: uint16,
126 language: uint16,
127 data: [u8; 0],
128}
129#[repr(C)]
130#[non_exhaustive]
131struct LongMeta {
132 format: uint16,
133 reserved: uint16,
134 length: uint32,
135 language: uint32,
136 data: [u8; 0],
137}
138#[repr(C)]
139#[non_exhaustive]
140struct LenOnlyMeta {
141 format: uint16,
142 length: uint32,
143 data: [u8; 0],
144}
145
146impl CmapSubtableRepr {
147 pub const fn format(&self) -> u16 {
148 unsafe { self.meta.short.format.get() }
149 }
150 pub const fn length(&self) -> Option<u32> {
151 Some(match self.format() {
152 0 | 2 | 4 | 6 => unsafe { self.meta.short.length.get() as _ },
153 8 | 10 | 12 | 13 => unsafe { self.meta.long.length.get() },
154 14 => unsafe { self.meta.len_only.length.get() },
155 _ => return None,
156 })
157 }
158 pub const fn language(&self) -> Option<u32> {
159 Some(match self.format() {
160 0 | 2 | 4 | 6 => unsafe { self.meta.short.language.get() as _ },
161 8 | 10 | 12 | 13 => unsafe { self.meta.long.language.get() },
162 _ => return None,
163 })
164 }
165 const fn data_ptr(&self) -> Option<&u8> {
166 Some(match self.format() {
167 0 | 2 | 4 | 6 => unsafe { &*self.meta.short.data.as_ptr() },
168 8 | 10 | 12 | 13 => unsafe { &*self.meta.long.data.as_ptr() },
169 14 => unsafe { &*self.meta.len_only.data.as_ptr() },
170 _ => return None,
171 })
172 }
173
174 pub const fn get_as_bytes(&self) -> Option<&[u8]> {
175 match self.format() {
176 0 | 2 | 4 | 6 => unsafe {
177 let size = self.meta.short.length.get() as usize - size_of::<ShortMeta>();
178 Some(std::slice::from_raw_parts(self.meta.short.data.as_ptr(), size))
179 },
180 8 | 10 | 12 | 13 => unsafe {
181 let size = self.meta.long.length.get() as usize - size_of::<LongMeta>();
182 Some(std::slice::from_raw_parts(self.meta.long.data.as_ptr(), size))
183 },
184 14 => unsafe {
185 let size = self.meta.len_only.length.get() as usize - size_of::<LenOnlyMeta>();
186 Some(std::slice::from_raw_parts(self.meta.len_only.data.as_ptr(), size))
187 },
188 _ => None,
189 }
190 }
191 pub const fn get_as<T: CmapSubtableTrait>(&self) -> Option<&T> {
192 if self.format() == T::FORMAT { Some(unsafe { self.get_as_unchecked() }) } else { None }
193 }
194 pub const unsafe fn get_as_unchecked<T: CmapSubtableTrait>(&self) -> &T {
195 debug_assert!(self.format() == T::FORMAT);
196 unsafe { &*std::ptr::from_ref(self.data_ptr().unwrap()).cast() }
197 }
198
199 pub const fn as_format0(&self) -> Option<&format0::CmapSubtableFormat0Repr> {
200 self.get_as()
201 }
202 pub const fn as_format2(&self) -> Option<&format2::CmapSubtableFormat2Repr> {
203 self.get_as()
204 }
205 pub const fn as_format4(&self) -> Option<&format4::CmapSubtableFormat4Repr> {
206 self.get_as()
207 }
208 pub const fn as_format6(&self) -> Option<&format6::CmapSubtableFormat6Repr> {
209 self.get_as()
210 }
211 pub const fn as_format8(&self) -> Option<&format8::CmapSubtableFormat8Repr> {
212 self.get_as()
213 }
214 pub const fn as_format10(&self) -> Option<&format10::CmapSubtableFormat10Repr> {
215 self.get_as()
216 }
217 pub const fn as_format12(&self) -> Option<&format12::CmapSubtableFormat12Repr> {
218 self.get_as()
219 }
220 pub const fn as_format13(&self) -> Option<&format13::CmapSubtableFormat13Repr> {
221 self.get_as()
222 }
223 pub const fn as_format14(&self) -> Option<&format14::CmapSubtableFormat14Repr> {
224 self.get_as()
225 }
226}
227
228pub trait CmapSubtableTrait {
229 const FORMAT: u16;
230}