1use peek_poke::PeekPoke;
6use std::cmp::Ordering;
7use std::hash::{Hash, Hasher};
8#[cfg(not(any(target_os = "macos", target_os = "ios")))]
9use std::path::PathBuf;
10use std::sync::Arc;
11use crate::IdNamespace;
13use crate::channel::Sender;
14use crate::units::LayoutPoint;
15
16#[repr(C)]
18#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, Deserialize, Serialize)]
19pub struct FontSize(pub f32);
20
21impl Ord for FontSize {
22 fn cmp(&self, other: &FontSize) -> Ordering {
23 self.partial_cmp(other).unwrap_or(Ordering::Equal)
24 }
25}
26
27impl Eq for FontSize {}
28
29impl Hash for FontSize {
30 fn hash<H: Hasher>(&self, state: &mut H) {
31 self.0.to_bits().hash(state);
32 }
33}
34
35impl From<f32> for FontSize {
36 fn from(size: f32) -> Self { FontSize(size) }
37}
38
39impl From<FontSize> for f32 {
40 fn from(size: FontSize) -> Self { size.0 }
41}
42
43impl FontSize {
44 pub fn zero() -> Self { FontSize(0.0) }
45
46 pub fn from_f32_px(size: f32) -> Self { FontSize(size) }
47
48 pub fn to_f32_px(&self) -> f32 { self.0 }
49
50 pub fn from_f64_px(size: f64) -> Self { FontSize(size as f32) }
51
52 pub fn to_f64_px(&self) -> f64 { self.0 as f64 }
53}
54
55#[cfg(not(any(target_os = "macos", target_os = "ios")))]
56#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
57pub struct NativeFontHandle {
58 pub path: PathBuf,
59 pub index: u32,
60}
61
62#[cfg(any(target_os = "macos", target_os = "ios"))]
63#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
64pub struct NativeFontHandle {
65 pub name: String,
66 pub path: String,
67}
68
69#[repr(C)]
70#[derive(Copy, Clone, Deserialize, Serialize, Debug)]
71pub struct GlyphDimensions {
72 pub left: i32,
73 pub top: i32,
74 pub width: i32,
75 pub height: i32,
76 pub advance: f32,
77}
78
79pub struct GlyphDimensionRequest {
80 pub key: FontInstanceKey,
81 pub glyph_indices: Vec<GlyphIndex>,
82 pub sender: Sender<Vec<Option<GlyphDimensions>>>,
83}
84
85pub struct GlyphIndexRequest {
86 pub key: FontKey,
87 pub text: String,
88 pub sender: Sender<Vec<Option<u32>>>,
89}
90
91#[repr(C)]
92#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)]
93pub struct FontKey(pub IdNamespace, pub u32);
94
95impl FontKey {
96 pub fn new(namespace: IdNamespace, key: u32) -> FontKey {
97 FontKey(namespace, key)
98 }
99}
100
101#[derive(Debug, Clone, Hash, Eq, PartialEq)]
109pub enum FontTemplate {
110 Raw(Arc<Vec<u8>>, u32),
111 Native(NativeFontHandle),
112}
113
114#[repr(u8)]
115#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
116pub enum FontRenderMode {
117 Mono = 0,
118 Alpha,
119 Subpixel,
120}
121
122impl Default for FontRenderMode {
123 fn default() -> Self {
124 FontRenderMode::Mono
125 }
126}
127
128impl FontRenderMode {
129 pub fn limit_by(self, other: FontRenderMode) -> FontRenderMode {
131 match (self, other) {
132 (FontRenderMode::Subpixel, _) | (_, FontRenderMode::Mono) => other,
133 _ => self,
134 }
135 }
136}
137
138#[repr(C)]
139#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)]
140pub struct FontVariation {
141 pub tag: u32,
142 pub value: f32,
143}
144
145impl Ord for FontVariation {
146 fn cmp(&self, other: &FontVariation) -> Ordering {
147 self.tag.cmp(&other.tag)
148 .then(self.value.to_bits().cmp(&other.value.to_bits()))
149 }
150}
151
152impl PartialEq for FontVariation {
153 fn eq(&self, other: &FontVariation) -> bool {
154 self.tag == other.tag &&
155 self.value.to_bits() == other.value.to_bits()
156 }
157}
158
159impl Eq for FontVariation {}
160
161impl Hash for FontVariation {
162 fn hash<H: Hasher>(&self, state: &mut H) {
163 self.tag.hash(state);
164 self.value.to_bits().hash(state);
165 }
166}
167
168#[repr(C)]
169#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, PeekPoke)]
170pub struct GlyphOptions {
171 pub render_mode: FontRenderMode,
172 pub flags: FontInstanceFlags,
173}
174
175impl Default for GlyphOptions {
176 fn default() -> Self {
177 GlyphOptions {
178 render_mode: FontRenderMode::Subpixel,
179 flags: FontInstanceFlags::empty(),
180 }
181 }
182}
183
184#[repr(C)]
185#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
186pub struct FontInstanceFlags(u32);
187
188bitflags! {
189 impl FontInstanceFlags: u32 {
190 const SYNTHETIC_BOLD = 1 << 1;
193 const EMBEDDED_BITMAPS = 1 << 2;
194 const SUBPIXEL_BGR = 1 << 3;
195 const TRANSPOSE = 1 << 4;
196 const FLIP_X = 1 << 5;
197 const FLIP_Y = 1 << 6;
198 const SUBPIXEL_POSITION = 1 << 7;
199 const VERTICAL = 1 << 8;
200 const MULTISTRIKE_BOLD = 1 << 9;
202
203 const TRANSFORM_GLYPHS = 1 << 12;
205 const TEXTURE_PADDING = 1 << 13;
206
207 const FORCE_GDI = 1 << 16;
209 const FORCE_SYMMETRIC = 1 << 17;
210 const NO_SYMMETRIC = 1 << 18;
211
212 const FONT_SMOOTHING = 1 << 16;
214
215 const FORCE_AUTOHINT = 1 << 16;
217 const NO_AUTOHINT = 1 << 17;
218 const VERTICAL_LAYOUT = 1 << 18;
219 const LCD_VERTICAL = 1 << 19;
220 }
221}
222
223impl core::fmt::Debug for FontInstanceFlags {
224 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
225 if self.is_empty() {
226 write!(f, "{:#x}", Self::empty().bits())
227 } else {
228 bitflags::parser::to_writer(self, f)
229 }
230 }
231}
232
233impl Default for FontInstanceFlags {
234 #[cfg(target_os = "windows")]
235 fn default() -> FontInstanceFlags {
236 FontInstanceFlags::SUBPIXEL_POSITION
237 }
238
239 #[cfg(any(target_os = "macos", target_os = "ios"))]
240 fn default() -> FontInstanceFlags {
241 FontInstanceFlags::SUBPIXEL_POSITION |
242 FontInstanceFlags::FONT_SMOOTHING
243 }
244
245 #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
246 fn default() -> FontInstanceFlags {
247 FontInstanceFlags::SUBPIXEL_POSITION
248 }
249}
250
251
252#[repr(C)]
253#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
254pub struct SyntheticItalics {
255 pub angle: i16,
257}
258
259impl SyntheticItalics {
260 pub const ANGLE_SCALE: f32 = 256.0;
261
262 pub fn from_degrees(degrees: f32) -> Self {
263 SyntheticItalics { angle: (degrees.clamp(-89.0, 89.0) * Self::ANGLE_SCALE) as i16 }
264 }
265
266 pub fn to_degrees(self) -> f32 {
267 self.angle as f32 / Self::ANGLE_SCALE
268 }
269
270 pub fn to_radians(self) -> f32 {
271 self.to_degrees().to_radians()
272 }
273
274 pub fn to_skew(self) -> f32 {
275 self.to_radians().tan()
276 }
277
278 pub fn enabled() -> Self {
279 Self::from_degrees(14.0)
280 }
281
282 pub fn disabled() -> Self {
283 SyntheticItalics { angle: 0 }
284 }
285
286 pub fn is_enabled(self) -> bool {
287 self.angle != 0
288 }
289}
290
291impl Default for SyntheticItalics {
292 fn default() -> Self {
293 SyntheticItalics::disabled()
294 }
295}
296
297#[repr(C)]
298#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
299pub struct FontInstanceOptions {
300 pub flags: FontInstanceFlags,
301 pub synthetic_italics: SyntheticItalics,
302 pub render_mode: FontRenderMode,
303 pub _padding: u8,
308}
309
310impl Default for FontInstanceOptions {
311 fn default() -> FontInstanceOptions {
312 FontInstanceOptions {
313 render_mode: FontRenderMode::Subpixel,
314 flags: Default::default(),
315 synthetic_italics: SyntheticItalics::disabled(),
316 _padding: 0,
317 }
318 }
319}
320
321#[cfg(target_os = "windows")]
322#[repr(C)]
323#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
324pub struct FontInstancePlatformOptions {
325 pub gamma: u16, pub contrast: u8, pub cleartype_level: u8, }
329
330#[cfg(target_os = "windows")]
331impl Default for FontInstancePlatformOptions {
332 fn default() -> FontInstancePlatformOptions {
333 FontInstancePlatformOptions {
334 gamma: 180, contrast: 100,
336 cleartype_level: 100,
337 }
338 }
339}
340
341#[cfg(any(target_os = "macos", target_os = "ios"))]
342#[repr(C)]
343#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
344pub struct FontInstancePlatformOptions {
345 pub unused: u32,
346}
347
348#[cfg(any(target_os = "macos", target_os = "ios"))]
349impl Default for FontInstancePlatformOptions {
350 fn default() -> FontInstancePlatformOptions {
351 FontInstancePlatformOptions {
352 unused: 0,
353 }
354 }
355}
356
357#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
358#[repr(u8)]
359#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
360pub enum FontLCDFilter {
361 None,
362 Default,
363 Light,
364 Legacy,
365}
366
367#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
368#[repr(u8)]
369#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
370pub enum FontHinting {
371 None,
372 Mono,
373 Light,
374 Normal,
375 LCD,
376}
377
378#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
379#[repr(C)]
380#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
381pub struct FontInstancePlatformOptions {
382 pub lcd_filter: FontLCDFilter,
383 pub hinting: FontHinting,
384}
385
386#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
387impl Default for FontInstancePlatformOptions {
388 fn default() -> FontInstancePlatformOptions {
389 FontInstancePlatformOptions {
390 lcd_filter: FontLCDFilter::Default,
391 hinting: FontHinting::LCD,
392 }
393 }
394}
395
396#[repr(C)]
397#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, MallocSizeOf, PeekPoke)]
398#[derive(Deserialize, Serialize)]
399pub struct FontInstanceKey(pub IdNamespace, pub u32);
400
401impl FontInstanceKey {
402 pub fn new(namespace: IdNamespace, key: u32) -> FontInstanceKey {
403 FontInstanceKey(namespace, key)
404 }
405}
406
407#[derive(Clone)]
412pub struct FontInstanceData {
413 pub font_key: FontKey,
414 pub size: f32,
415 pub options: Option<FontInstanceOptions>,
416 pub platform_options: Option<FontInstancePlatformOptions>,
417 pub variations: Vec<FontVariation>,
418}
419
420pub type GlyphIndex = u32;
421
422#[repr(C)]
423#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
424pub struct GlyphInstance {
425 pub index: GlyphIndex,
426 pub point: LayoutPoint,
427}
428
429impl Default for GlyphInstance {
430 fn default() -> Self {
431 GlyphInstance {
432 index: 0,
433 point: LayoutPoint::zero(),
434 }
435 }
436}
437
438impl Eq for GlyphInstance {}
439
440#[allow(clippy::derived_hash_with_manual_eq)]
441impl Hash for GlyphInstance {
442 fn hash<H: Hasher>(&self, state: &mut H) {
443 self.index.hash(state);
445 self.point.x.to_bits().hash(state);
446 self.point.y.to_bits().hash(state);
447 }
448}