//! Text shaping and styling. use std::borrow::Cow; use std::fmt::{self, Debug, Formatter}; use std::ops::{BitXor, Range}; use kurbo::{BezPath, Line, ParamCurve}; use rustybuzz::{Feature, UnicodeBuffer}; use ttf_parser::{GlyphId, OutlineBuilder, Tag}; use super::prelude::*; use super::Decoration; use crate::font::{ Face, FaceId, FontStore, FontStretch, FontStyle, FontVariant, FontWeight, VerticalFontMetric, }; use crate::geom::{Dir, Em, Length, Point, Size}; use crate::util::{EcoString, SliceExt}; /// A single run of text with the same style. #[derive(Hash)] pub struct TextNode; #[class] impl TextNode { /// A prioritized sequence of font families. #[variadic] pub const FAMILY: Vec = vec![FontFamily::SansSerif]; /// The serif font family/families. pub const SERIF: Vec = vec![NamedFamily::new("IBM Plex Serif")]; /// The sans-serif font family/families. pub const SANS_SERIF: Vec = vec![NamedFamily::new("IBM Plex Sans")]; /// The monospace font family/families. pub const MONOSPACE: Vec = vec![NamedFamily::new("IBM Plex Mono")]; /// Whether to allow font fallback when the primary font list contains no /// match. pub const FALLBACK: bool = true; /// How the font is styled. pub const STYLE: FontStyle = FontStyle::Normal; /// The boldness / thickness of the font's glyphs. pub const WEIGHT: FontWeight = FontWeight::REGULAR; /// The width of the glyphs. pub const STRETCH: FontStretch = FontStretch::NORMAL; /// The glyph fill color. #[shorthand] pub const FILL: Paint = Color::BLACK.into(); /// The size of the glyphs. #[shorthand] #[fold(Linear::compose)] pub const SIZE: Linear = Length::pt(11.0).into(); /// The amount of space that should be added between characters. pub const TRACKING: Em = Em::zero(); /// The top end of the text bounding box. pub const TOP_EDGE: VerticalFontMetric = VerticalFontMetric::CapHeight; /// The bottom end of the text bounding box. pub const BOTTOM_EDGE: VerticalFontMetric = VerticalFontMetric::Baseline; /// Whether to apply kerning ("kern"). pub const KERNING: bool = true; /// Whether small capital glyphs should be used. ("smcp") pub const SMALLCAPS: bool = false; /// Whether to apply stylistic alternates. ("salt") pub const ALTERNATES: bool = false; /// Which stylistic set to apply. ("ss01" - "ss20") pub const STYLISTIC_SET: Option = None; /// Whether standard ligatures are active. ("liga", "clig") pub const LIGATURES: bool = true; /// Whether ligatures that should be used sparingly are active. ("dlig") pub const DISCRETIONARY_LIGATURES: bool = false; /// Whether historical ligatures are active. ("hlig") pub const HISTORICAL_LIGATURES: bool = false; /// Which kind of numbers / figures to select. pub const NUMBER_TYPE: Smart = Smart::Auto; /// The width of numbers / figures. pub const NUMBER_WIDTH: Smart = Smart::Auto; /// How to position numbers. pub const NUMBER_POSITION: NumberPosition = NumberPosition::Normal; /// Whether to have a slash through the zero glyph. ("zero") pub const SLASHED_ZERO: bool = false; /// Whether to convert fractions. ("frac") pub const FRACTIONS: bool = false; /// Raw OpenType features to apply. pub const FEATURES: Vec<(Tag, u32)> = vec![]; /// Whether the font weight should be increased by 300. #[skip] #[fold(bool::bitxor)] pub const STRONG: bool = false; /// Whether the the font style should be inverted. #[skip] #[fold(bool::bitxor)] pub const EMPH: bool = false; /// Whether a monospace font should be preferred. #[skip] pub const MONOSPACED: bool = false; /// Decorative lines. #[skip] #[fold(|a, b| a.into_iter().chain(b).collect())] pub const LINES: Vec = vec![]; /// An URL the text should link to. #[skip] pub const LINK: Option = None; fn construct(_: &mut Vm, args: &mut Args) -> TypResult