1 //! The [MVAR (Metrics Variation)](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar) table 2 3 use super::variations::{DeltaSetIndex, ItemVariationStore}; 4 5 /// Four-byte tags used to represent particular metric or other values. 6 pub mod tags { 7 use font_types::Tag; 8 9 /// Horizontal ascender. 10 pub const HASC: Tag = Tag::new(b"hasc"); 11 /// Horizontal descender. 12 pub const HDSC: Tag = Tag::new(b"hdsc"); 13 /// Horizontal line gap. 14 pub const HLGP: Tag = Tag::new(b"hlgp"); 15 16 /// Horizontal clipping ascent. 17 pub const HCLA: Tag = Tag::new(b"hcla"); 18 /// Horizontal clipping descent. 19 pub const HCLD: Tag = Tag::new(b"hcld"); 20 21 /// Vertical ascender. 22 pub const VASC: Tag = Tag::new(b"vasc"); 23 /// Vertical descender. 24 pub const VDSC: Tag = Tag::new(b"vdsc"); 25 /// Vertical line gap. 26 pub const VLGP: Tag = Tag::new(b"vlgp"); 27 28 /// Horizontal caret rise. 29 pub const HCRS: Tag = Tag::new(b"hcrs"); 30 /// Horizontal caret run. 31 pub const HCRN: Tag = Tag::new(b"hcrn"); 32 /// Horizontal caret offset. 33 pub const HCOF: Tag = Tag::new(b"hcof"); 34 35 /// Vertical caret rise. 36 pub const VCRS: Tag = Tag::new(b"vcrs"); 37 /// Vertical caret run. 38 pub const VCRN: Tag = Tag::new(b"vcrn"); 39 /// Vertical caret offset. 40 pub const VCOF: Tag = Tag::new(b"vcof"); 41 42 /// X-height. 43 pub const XHGT: Tag = Tag::new(b"xhgt"); 44 /// Cap height. 45 pub const CPHT: Tag = Tag::new(b"cpht"); 46 47 /// Subscript em x-offset. 48 pub const SBXO: Tag = Tag::new(b"sbxo"); 49 /// Subscript em y-offset. 50 pub const SBYO: Tag = Tag::new(b"sbyo"); 51 /// Subscript em x-size. 52 pub const SBXS: Tag = Tag::new(b"sbxs"); 53 /// Subscript em y-size. 54 pub const SBYS: Tag = Tag::new(b"sbys"); 55 56 /// Superscript em x-offset. 57 pub const SPXO: Tag = Tag::new(b"spxo"); 58 /// Superscript em y-offset. 59 pub const SPYO: Tag = Tag::new(b"spyo"); 60 /// Superscript em x-size. 61 pub const SPXS: Tag = Tag::new(b"spxs"); 62 /// Superscript em y-size. 63 pub const SPYS: Tag = Tag::new(b"spys"); 64 65 /// Strikeout size. 66 pub const STRS: Tag = Tag::new(b"strs"); 67 /// Strikeout offset. 68 pub const STRO: Tag = Tag::new(b"stro"); 69 70 /// Underline size. 71 pub const UNDS: Tag = Tag::new(b"unds"); 72 /// Underline offset. 73 pub const UNDO: Tag = Tag::new(b"undo"); 74 75 /// GaspRange\[0\] 76 pub const GSP0: Tag = Tag::new(b"gsp0"); 77 /// GaspRange\[1\] 78 pub const GSP1: Tag = Tag::new(b"gsp1"); 79 /// GaspRange\[2\] 80 pub const GSP2: Tag = Tag::new(b"gsp2"); 81 /// GaspRange\[3\] 82 pub const GSP3: Tag = Tag::new(b"gsp3"); 83 /// GaspRange\[4\] 84 pub const GSP4: Tag = Tag::new(b"gsp4"); 85 /// GaspRange\[5\] 86 pub const GSP5: Tag = Tag::new(b"gsp5"); 87 /// GaspRange\[6\] 88 pub const GSP6: Tag = Tag::new(b"gsp6"); 89 /// GaspRange\[7\] 90 pub const GSP7: Tag = Tag::new(b"gsp7"); 91 /// GaspRange\[8\] 92 pub const GSP8: Tag = Tag::new(b"gsp8"); 93 /// GaspRange\[9\] 94 pub const GSP9: Tag = Tag::new(b"gsp9"); 95 } 96 97 include!("../../generated/generated_mvar.rs"); 98 99 impl<'a> Mvar<'a> { 100 /// Returns the metric delta for the specified tag and normalized 101 /// variation coordinates. Possible tags are found in the [tags] 102 /// module. metric_delta(&self, tag: Tag, coords: &[F2Dot14]) -> Result<Fixed, ReadError>103 pub fn metric_delta(&self, tag: Tag, coords: &[F2Dot14]) -> Result<Fixed, ReadError> { 104 use std::cmp::Ordering; 105 let records = self.value_records(); 106 let mut lo = 0; 107 let mut hi = records.len(); 108 while lo < hi { 109 let i = (lo + hi) / 2; 110 let record = &records[i]; 111 match tag.cmp(&record.value_tag()) { 112 Ordering::Less => { 113 hi = i; 114 } 115 Ordering::Greater => { 116 lo = i + 1; 117 } 118 Ordering::Equal => { 119 let ivs = self.item_variation_store().ok_or(ReadError::NullOffset)??; 120 return Ok(Fixed::from_i32(ivs.compute_delta( 121 DeltaSetIndex { 122 outer: record.delta_set_outer_index(), 123 inner: record.delta_set_inner_index(), 124 }, 125 coords, 126 )?)); 127 } 128 } 129 } 130 Err(ReadError::MetricIsMissing(tag)) 131 } 132 } 133