diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/wr/webrender_api/src/font.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/wr/webrender_api/src/font.rs')
-rw-r--r-- | gfx/wr/webrender_api/src/font.rs | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/gfx/wr/webrender_api/src/font.rs b/gfx/wr/webrender_api/src/font.rs new file mode 100644 index 0000000000..286742bff6 --- /dev/null +++ b/gfx/wr/webrender_api/src/font.rs @@ -0,0 +1,435 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use peek_poke::PeekPoke; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; +#[cfg(not(target_os = "macos"))] +use std::path::PathBuf; +use std::sync::Arc; +// local imports +use crate::IdNamespace; +use crate::channel::Sender; +use crate::color::ColorU; +use crate::units::LayoutPoint; + +/// Hashable floating-point storage for font size. +#[repr(C)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, Deserialize, Serialize)] +pub struct FontSize(pub f32); + +impl Ord for FontSize { + fn cmp(&self, other: &FontSize) -> Ordering { + self.partial_cmp(other).unwrap_or(Ordering::Equal) + } +} + +impl Eq for FontSize {} + +impl Hash for FontSize { + fn hash<H: Hasher>(&self, state: &mut H) { + self.0.to_bits().hash(state); + } +} + +impl From<f32> for FontSize { + fn from(size: f32) -> Self { FontSize(size) } +} + +impl From<FontSize> for f32 { + fn from(size: FontSize) -> Self { size.0 } +} + +impl FontSize { + pub fn zero() -> Self { FontSize(0.0) } + + pub fn from_f32_px(size: f32) -> Self { FontSize(size) } + + pub fn to_f32_px(&self) -> f32 { self.0 } + + pub fn from_f64_px(size: f64) -> Self { FontSize(size as f32) } + + pub fn to_f64_px(&self) -> f64 { self.0 as f64 } +} + +#[cfg(not(target_os = "macos"))] +#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct NativeFontHandle { + pub path: PathBuf, + pub index: u32, +} + +#[cfg(target_os = "macos")] +#[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct NativeFontHandle { + pub name: String, +} + +#[repr(C)] +#[derive(Copy, Clone, Deserialize, Serialize, Debug)] +pub struct GlyphDimensions { + pub left: i32, + pub top: i32, + pub width: i32, + pub height: i32, + pub advance: f32, +} + +pub struct GlyphDimensionRequest { + pub key: FontInstanceKey, + pub glyph_indices: Vec<GlyphIndex>, + pub sender: Sender<Vec<Option<GlyphDimensions>>>, +} + +pub struct GlyphIndexRequest { + pub key: FontKey, + pub text: String, + pub sender: Sender<Vec<Option<u32>>>, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)] +pub struct FontKey(pub IdNamespace, pub u32); + +impl FontKey { + pub fn new(namespace: IdNamespace, key: u32) -> FontKey { + FontKey(namespace, key) + } +} + +/// Container for the raw data describing a font. This might be a stream of +/// bytes corresponding to a downloaded font, or a handle to a native font from +/// the operating system. +/// +/// Note that fonts need to be instantiated before being used, which involves +/// assigning size and various other options. The word 'template' here is +/// intended to distinguish this data from instance-specific data. +#[derive(Debug, Clone, Hash, Eq, PartialEq)] +pub enum FontTemplate { + Raw(Arc<Vec<u8>>, u32), + Native(NativeFontHandle), +} + +#[repr(u8)] +#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)] +pub enum FontRenderMode { + Mono = 0, + Alpha, + Subpixel, +} + +impl Default for FontRenderMode { + fn default() -> Self { + FontRenderMode::Mono + } +} + +impl FontRenderMode { + // Combine two font render modes such that the lesser amount of AA limits the AA of the result. + pub fn limit_by(self, other: FontRenderMode) -> FontRenderMode { + match (self, other) { + (FontRenderMode::Subpixel, _) | (_, FontRenderMode::Mono) => other, + _ => self, + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)] +pub struct FontVariation { + pub tag: u32, + pub value: f32, +} + +impl Ord for FontVariation { + fn cmp(&self, other: &FontVariation) -> Ordering { + self.tag.cmp(&other.tag) + .then(self.value.to_bits().cmp(&other.value.to_bits())) + } +} + +impl PartialEq for FontVariation { + fn eq(&self, other: &FontVariation) -> bool { + self.tag == other.tag && + self.value.to_bits() == other.value.to_bits() + } +} + +impl Eq for FontVariation {} + +impl Hash for FontVariation { + fn hash<H: Hasher>(&self, state: &mut H) { + self.tag.hash(state); + self.value.to_bits().hash(state); + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, PeekPoke)] +pub struct GlyphOptions { + pub render_mode: FontRenderMode, + pub flags: FontInstanceFlags, +} + +impl Default for GlyphOptions { + fn default() -> Self { + GlyphOptions { + render_mode: FontRenderMode::Subpixel, + flags: FontInstanceFlags::empty(), + } + } +} + +bitflags! { + #[repr(C)] + #[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)] + pub struct FontInstanceFlags: u32 { + // Common flags + // Use native synthetic bold, if supported. + const SYNTHETIC_BOLD = 1 << 1; + const EMBEDDED_BITMAPS = 1 << 2; + const SUBPIXEL_BGR = 1 << 3; + const TRANSPOSE = 1 << 4; + const FLIP_X = 1 << 5; + const FLIP_Y = 1 << 6; + const SUBPIXEL_POSITION = 1 << 7; + const VERTICAL = 1 << 8; + // Explicitly use multi-strike bold emulation. + const MULTISTRIKE_BOLD = 1 << 9; + + // Internal flags + const TRANSFORM_GLYPHS = 1 << 12; + const TEXTURE_PADDING = 1 << 13; + + // Windows flags + const FORCE_GDI = 1 << 16; + const FORCE_SYMMETRIC = 1 << 17; + const NO_SYMMETRIC = 1 << 18; + + // Mac flags + const FONT_SMOOTHING = 1 << 16; + + // FreeType flags + const FORCE_AUTOHINT = 1 << 16; + const NO_AUTOHINT = 1 << 17; + const VERTICAL_LAYOUT = 1 << 18; + const LCD_VERTICAL = 1 << 19; + } +} + +impl Default for FontInstanceFlags { + #[cfg(target_os = "windows")] + fn default() -> FontInstanceFlags { + FontInstanceFlags::SUBPIXEL_POSITION + } + + #[cfg(target_os = "macos")] + fn default() -> FontInstanceFlags { + FontInstanceFlags::SUBPIXEL_POSITION | + FontInstanceFlags::FONT_SMOOTHING + } + + #[cfg(not(any(target_os = "macos", target_os = "windows")))] + fn default() -> FontInstanceFlags { + FontInstanceFlags::SUBPIXEL_POSITION + } +} + + +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub struct SyntheticItalics { + // Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point. + pub angle: i16, +} + +impl SyntheticItalics { + pub const ANGLE_SCALE: f32 = 256.0; + + pub fn from_degrees(degrees: f32) -> Self { + SyntheticItalics { angle: (degrees.max(-89.0).min(89.0) * Self::ANGLE_SCALE) as i16 } + } + + pub fn to_degrees(self) -> f32 { + self.angle as f32 / Self::ANGLE_SCALE + } + + pub fn to_radians(self) -> f32 { + self.to_degrees().to_radians() + } + + pub fn to_skew(self) -> f32 { + self.to_radians().tan() + } + + pub fn enabled() -> Self { + Self::from_degrees(14.0) + } + + pub fn disabled() -> Self { + SyntheticItalics { angle: 0 } + } + + pub fn is_enabled(self) -> bool { + self.angle != 0 + } +} + +impl Default for SyntheticItalics { + fn default() -> Self { + SyntheticItalics::disabled() + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub struct FontInstanceOptions { + pub render_mode: FontRenderMode, + pub flags: FontInstanceFlags, + /// When bg_color.a is != 0 and render_mode is FontRenderMode::Subpixel, + /// the text will be rendered with bg_color.r/g/b as an opaque estimated + /// background color. + pub bg_color: ColorU, + pub synthetic_italics: SyntheticItalics, +} + +impl Default for FontInstanceOptions { + fn default() -> FontInstanceOptions { + FontInstanceOptions { + render_mode: FontRenderMode::Subpixel, + flags: Default::default(), + bg_color: ColorU::new(0, 0, 0, 0), + synthetic_italics: SyntheticItalics::disabled(), + } + } +} + +#[cfg(target_os = "windows")] +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub struct FontInstancePlatformOptions { + pub gamma: u16, // percent + pub contrast: u8, // percent + pub cleartype_level: u8, // percent +} + +#[cfg(target_os = "windows")] +impl Default for FontInstancePlatformOptions { + fn default() -> FontInstancePlatformOptions { + FontInstancePlatformOptions { + gamma: 180, // Default DWrite gamma + contrast: 100, + cleartype_level: 100, + } + } +} + +#[cfg(target_os = "macos")] +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub struct FontInstancePlatformOptions { + pub unused: u32, +} + +#[cfg(target_os = "macos")] +impl Default for FontInstancePlatformOptions { + fn default() -> FontInstancePlatformOptions { + FontInstancePlatformOptions { + unused: 0, + } + } +} + +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[repr(u8)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub enum FontLCDFilter { + None, + Default, + Light, + Legacy, +} + +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[repr(u8)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub enum FontHinting { + None, + Mono, + Light, + Normal, + LCD, +} + +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] +pub struct FontInstancePlatformOptions { + pub lcd_filter: FontLCDFilter, + pub hinting: FontHinting, +} + +#[cfg(not(any(target_os = "macos", target_os = "windows")))] +impl Default for FontInstancePlatformOptions { + fn default() -> FontInstancePlatformOptions { + FontInstancePlatformOptions { + lcd_filter: FontLCDFilter::Default, + hinting: FontHinting::LCD, + } + } +} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, MallocSizeOf, PeekPoke)] +#[derive(Deserialize, Serialize)] +pub struct FontInstanceKey(pub IdNamespace, pub u32); + +impl FontInstanceKey { + pub fn new(namespace: IdNamespace, key: u32) -> FontInstanceKey { + FontInstanceKey(namespace, key) + } +} + +/// Data corresponding to an instantiation of a font, with size and +/// other options specified. +/// +/// Note that the actual font is stored out-of-band in `FontTemplate`. +#[derive(Clone)] +pub struct FontInstanceData { + pub font_key: FontKey, + pub size: f32, + pub options: Option<FontInstanceOptions>, + pub platform_options: Option<FontInstancePlatformOptions>, + pub variations: Vec<FontVariation>, +} + +pub type GlyphIndex = u32; + +#[repr(C)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)] +pub struct GlyphInstance { + pub index: GlyphIndex, + pub point: LayoutPoint, +} + +impl Default for GlyphInstance { + fn default() -> Self { + GlyphInstance { + index: 0, + point: LayoutPoint::zero(), + } + } +} + +impl Eq for GlyphInstance {} + +#[cfg_attr(feature = "cargo-clippy", allow(clippy::derive_hash_xor_eq))] +impl Hash for GlyphInstance { + fn hash<H: Hasher>(&self, state: &mut H) { + // Note: this is inconsistent with the Eq impl for -0.0 (don't care). + self.index.hash(state); + self.point.x.to_bits().hash(state); + self.point.y.to_bits().hash(state); + } +} |