font.rs (12603B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use peek_poke::PeekPoke; 6 use std::cmp::Ordering; 7 use std::hash::{Hash, Hasher}; 8 #[cfg(not(any(target_os = "macos", target_os = "ios")))] 9 use std::path::PathBuf; 10 use std::sync::Arc; 11 // local imports 12 use crate::IdNamespace; 13 use crate::channel::Sender; 14 use crate::units::LayoutPoint; 15 16 /// Hashable floating-point storage for font size. 17 #[repr(C)] 18 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, Deserialize, Serialize)] 19 pub struct FontSize(pub f32); 20 21 impl Ord for FontSize { 22 fn cmp(&self, other: &FontSize) -> Ordering { 23 self.partial_cmp(other).unwrap_or(Ordering::Equal) 24 } 25 } 26 27 impl Eq for FontSize {} 28 29 impl Hash for FontSize { 30 fn hash<H: Hasher>(&self, state: &mut H) { 31 self.0.to_bits().hash(state); 32 } 33 } 34 35 impl From<f32> for FontSize { 36 fn from(size: f32) -> Self { FontSize(size) } 37 } 38 39 impl From<FontSize> for f32 { 40 fn from(size: FontSize) -> Self { size.0 } 41 } 42 43 impl 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)] 57 pub 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)] 64 pub struct NativeFontHandle { 65 pub name: String, 66 pub path: String, 67 } 68 69 #[repr(C)] 70 #[derive(Copy, Clone, Deserialize, Serialize, Debug)] 71 pub struct GlyphDimensions { 72 pub left: i32, 73 pub top: i32, 74 pub width: i32, 75 pub height: i32, 76 pub advance: f32, 77 } 78 79 pub struct GlyphDimensionRequest { 80 pub key: FontInstanceKey, 81 pub glyph_indices: Vec<GlyphIndex>, 82 pub sender: Sender<Vec<Option<GlyphDimensions>>>, 83 } 84 85 pub 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)] 93 pub struct FontKey(pub IdNamespace, pub u32); 94 95 impl FontKey { 96 pub fn new(namespace: IdNamespace, key: u32) -> FontKey { 97 FontKey(namespace, key) 98 } 99 } 100 101 /// Container for the raw data describing a font. This might be a stream of 102 /// bytes corresponding to a downloaded font, or a handle to a native font from 103 /// the operating system. 104 /// 105 /// Note that fonts need to be instantiated before being used, which involves 106 /// assigning size and various other options. The word 'template' here is 107 /// intended to distinguish this data from instance-specific data. 108 #[derive(Debug, Clone, Hash, Eq, PartialEq)] 109 pub 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)] 116 pub enum FontRenderMode { 117 Mono = 0, 118 Alpha, 119 Subpixel, 120 } 121 122 impl Default for FontRenderMode { 123 fn default() -> Self { 124 FontRenderMode::Mono 125 } 126 } 127 128 impl FontRenderMode { 129 // Combine two font render modes such that the lesser amount of AA limits the AA of the result. 130 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)] 140 pub struct FontVariation { 141 pub tag: u32, 142 pub value: f32, 143 } 144 145 impl 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 152 impl 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 159 impl Eq for FontVariation {} 160 161 impl 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)] 170 pub struct GlyphOptions { 171 pub render_mode: FontRenderMode, 172 pub flags: FontInstanceFlags, 173 } 174 175 impl 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)] 186 pub struct FontInstanceFlags(u32); 187 188 bitflags! { 189 impl FontInstanceFlags: u32 { 190 // Common flags 191 // Use native synthetic bold, if supported. 192 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 // Explicitly use multi-strike bold emulation. 201 const MULTISTRIKE_BOLD = 1 << 9; 202 203 // Internal flags 204 const TRANSFORM_GLYPHS = 1 << 12; 205 const TEXTURE_PADDING = 1 << 13; 206 207 // Windows flags 208 const FORCE_GDI = 1 << 16; 209 const FORCE_SYMMETRIC = 1 << 17; 210 const NO_SYMMETRIC = 1 << 18; 211 212 // Mac flags 213 const FONT_SMOOTHING = 1 << 16; 214 215 // FreeType flags 216 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 223 impl 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 233 impl 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)] 254 pub struct SyntheticItalics { 255 // Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point. 256 pub angle: i16, 257 } 258 259 impl 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 291 impl 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)] 299 pub struct FontInstanceOptions { 300 pub flags: FontInstanceFlags, 301 pub synthetic_italics: SyntheticItalics, 302 pub render_mode: FontRenderMode, 303 // We need to pad this struct out so that all bytes are part of fields, in 304 // order to satisfy the robustness requirements (and static_asserts) of 305 // ParamTraits_TiedFields. 306 // The sizeof(T) must be equal to the sum of the sizeof each field in T. 307 pub _padding: u8, 308 } 309 310 impl 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)] 324 pub struct FontInstancePlatformOptions { 325 pub gamma: u16, // percent 326 pub contrast: u8, // percent 327 pub cleartype_level: u8, // percent 328 } 329 330 #[cfg(target_os = "windows")] 331 impl Default for FontInstancePlatformOptions { 332 fn default() -> FontInstancePlatformOptions { 333 FontInstancePlatformOptions { 334 gamma: 180, // Default DWrite gamma 335 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)] 344 pub struct FontInstancePlatformOptions { 345 pub unused: u32, 346 } 347 348 #[cfg(any(target_os = "macos", target_os = "ios"))] 349 impl 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)] 360 pub 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)] 370 pub 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)] 381 pub 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")))] 387 impl 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)] 399 pub struct FontInstanceKey(pub IdNamespace, pub u32); 400 401 impl FontInstanceKey { 402 pub fn new(namespace: IdNamespace, key: u32) -> FontInstanceKey { 403 FontInstanceKey(namespace, key) 404 } 405 } 406 407 /// Data corresponding to an instantiation of a font, with size and 408 /// other options specified. 409 /// 410 /// Note that the actual font is stored out-of-band in `FontTemplate`. 411 #[derive(Clone)] 412 pub 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 420 pub type GlyphIndex = u32; 421 422 #[repr(C)] 423 #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)] 424 pub struct GlyphInstance { 425 pub index: GlyphIndex, 426 pub point: LayoutPoint, 427 } 428 429 impl Default for GlyphInstance { 430 fn default() -> Self { 431 GlyphInstance { 432 index: 0, 433 point: LayoutPoint::zero(), 434 } 435 } 436 } 437 438 impl Eq for GlyphInstance {} 439 440 #[allow(clippy::derived_hash_with_manual_eq)] 441 impl Hash for GlyphInstance { 442 fn hash<H: Hasher>(&self, state: &mut H) { 443 // Note: this is inconsistent with the Eq impl for -0.0 (don't care). 444 self.index.hash(state); 445 self.point.x.to_bits().hash(state); 446 self.point.y.to_bits().hash(state); 447 } 448 }