tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }