oxedyne/fe2o3/fe2o3_font/src/shape.rs
2.1 KiB, 20 runs
created by r1870400018:35704, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | //! Shaped text: the glyphs a string becomes, and where each one sits. |
| 2 | |
| 3 | /// The direction a run of text is written in. |
| 4 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] |
| 5 | pub enum Dir { |
| 6 | #[default] |
| 7 | Ltr, // left to right, as English is |
| 8 | Rtl, // right to left, as Arabic and Hebrew are |
| 9 | } |
| 10 | |
| 11 | impl Dir { |
| 12 | |
| 13 | /// The direction named by a style's `dir` property. |
| 14 | pub fn from_str(s: &str) -> Option<Self> { |
| 15 | match s { |
| 16 | "ltr" => Some(Self::Ltr), |
| 17 | "rtl" => Some(Self::Rtl), |
| 18 | _ => None, |
| 19 | } |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | /// An OpenType feature applied across a whole run: `smcp` for small capitals, `onum` for old-style |
| 24 | /// figures. The value is the feature's setting -- 0 switches it off, 1 on, and a higher value picks an |
| 25 | /// alternate where the feature offers several. |
| 26 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
| 27 | pub struct Feature { |
| 28 | pub tag: [u8; 4], |
| 29 | pub value: u32, |
| 30 | } |
| 31 | |
| 32 | impl Feature { |
| 33 | |
| 34 | /// The feature switched on. |
| 35 | pub const fn on(tag: &[u8; 4]) -> Self { |
| 36 | Self { tag: *tag, value: 1 } |
| 37 | } |
| 38 | |
| 39 | /// Small capitals from lower case: what Typst's `smallcaps` asks the font for. |
| 40 | pub const SMALL_CAPS: Self = Self::on(b"smcp"); |
| 41 | } |
| 42 | |
| 43 | /// One glyph, placed in pixels relative to the run's start and baseline, y up as the font has it. |
| 44 | /// Painting flips it. |
| 45 | #[derive(Clone, Copy, Debug, PartialEq)] |
| 46 | pub struct Glyph { |
| 47 | pub id: u32, // index in the font, not a character: shaping may merge or split |
| 48 | pub face: u8, // which face of the chain drew it; a glyph index means nothing without it |
| 49 | pub x: f32, // horizontal offset from the run's start, pixels |
| 50 | pub y: f32, // vertical offset from the baseline, pixels, upwards |
| 51 | pub adv: f32, // pen movement, kept not inferred: a mark's advance is nought, its x is not |
| 52 | pub cluster: usize, // byte offset into the ORIGINAL string, so a caret moves by cluster |
| 53 | } |
| 54 | |
| 55 | /// A run of shaped text: one string, one font, one size, one direction. |
| 56 | #[derive(Clone, Debug, Default)] |
| 57 | pub struct Run { |
| 58 | pub glyphs: Vec<Glyph>, // in visual order |
| 59 | pub advance: f32, // how far the pen travels over the whole run, pixels |
| 60 | pub size: f32, // the size it was shaped at, pixels per em |
| 61 | } |
| 62 | |
| 63 | impl Run { |
| 64 | |
| 65 | pub fn is_empty(&self) -> bool { |
| 66 | self.glyphs.is_empty() |
| 67 | } |
| 68 | } |