diff --git a/NOTICE b/NOTICE index 80a9cdc0..1f058ed1 100644 --- a/NOTICE +++ b/NOTICE @@ -72,6 +72,7 @@ The SIL OPEN FONT LICENSE Version 1.1 applies to the following fonts: - fonts/NotoSansCJKsc-Bold-subset1.otf - fonts/NotoSansCJKsc-Regular.otf - fonts/Syne-Regular_subset.oft (Copyright 2017 The Syne Project Authors (https://gitlab.com/bonjour-monde/fonderie/syne-typeface)) +- fonts/Astrolabe_subset.ttf (Copyright 2024 The Astrolabe Project Authors (github.com/aliftype/astrolabe)) ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 diff --git a/fonts/Astrolabe_subset.ttf b/fonts/Astrolabe_subset.ttf new file mode 100644 index 00000000..b5329a00 Binary files /dev/null and b/fonts/Astrolabe_subset.ttf differ diff --git a/src/glyf.rs b/src/glyf.rs index 2c2a6c6d..1bfb1cec 100644 --- a/src/glyf.rs +++ b/src/glyf.rs @@ -83,6 +83,10 @@ pub(crate) fn subset_with<'a>( glyph_data_fn: impl FnMut(u16, &Context<'a>) -> Result>, ) -> Result<()> { let subsetted_entries = subset_glyf_entries(ctx, glyph_data_fn)?; + ctx.font_bbox = subsetted_entries + .iter() + .filter_map(|entry| glyph_bbox(entry)) + .reduce(|a, b| [a[0].min(b[0]), a[1].min(b[1]), a[2].max(b[2]), a[3].max(b[3])]); let mut sub_glyf = Writer::new(); let mut sub_loca = Writer::new(); @@ -187,6 +191,11 @@ fn subset_glyf_entries<'a>( Ok(glyf_entries) } +fn glyph_bbox(glyph_data: &[u8]) -> Option<[i16; 4]> { + let mut r = Reader::new_at(glyph_data, 2); + Some([r.read()?, r.read()?, r.read()?, r.read()?]) +} + fn remap_component_glyph(mapper: &GlyphRemapper, data: &[u8]) -> Result> { let mut r = Reader::new(data); let mut w = Writer::with_capacity(data.len()); diff --git a/src/head.rs b/src/head.rs index 9814af83..78b5045e 100644 --- a/src/head.rs +++ b/src/head.rs @@ -1,6 +1,7 @@ //! The `head` table mostly contains information that can be reused from the //! old table, except for the `loca` format, which depends on the size of the -//! glyph data. The checksum will be recalculated in the very end. +//! glyph data, and the bounds which can change when instancing. The checksum +//! will be recalculated in the very end. use super::*; @@ -9,6 +10,17 @@ pub fn subset(ctx: &mut Context) -> Result<()> { let index_to_loc = head.get_mut(50..52).ok_or(MalformedFont)?; index_to_loc[0] = 0; index_to_loc[1] = ctx.long_loca as u8; + + // We are (potentially) instancing a variable font, recalculate the font bounds. + if ctx.interjector.is_skrifa() { + let [x_min, y_min, x_max, y_max] = ctx.font_bbox.unwrap_or_default(); + let bbox = head.get_mut(36..44).ok_or(MalformedFont)?; + bbox[0..2].copy_from_slice(&x_min.to_be_bytes()); + bbox[2..4].copy_from_slice(&y_min.to_be_bytes()); + bbox[4..6].copy_from_slice(&x_max.to_be_bytes()); + bbox[6..8].copy_from_slice(&y_max.to_be_bytes()); + } + ctx.push(Tag::HEAD, head); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index fa9568f5..32f5ded7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -203,6 +203,7 @@ fn prepare_context<'a>( flavor, tables: vec![], long_loca: false, + font_bbox: None, }) } @@ -390,6 +391,9 @@ struct Context<'a> { pub(crate) custom_hmtx_data: Option>, /// Whether the long loca format was chosen. long_loca: bool, + /// The font bounding box (xMin, yMin, xMax, yMax), or `None` if there are + /// no glyphs with outlines. + font_bbox: Option<[i16; 4]>, } impl<'a> Context<'a> { diff --git a/tests/data/fonttools.tests b/tests/data/fonttools.tests index 7dba3823..55e41ea3 100644 --- a/tests/data/fonttools.tests +++ b/tests/data/fonttools.tests @@ -17,4 +17,6 @@ NotoSans-Regular_var.ttf;10,40,58,201-205;wght=800,wdth=70.0 // Note that the lsb values currently doesn't match fonttools Cantarell-VF.otf;1,15,30-35,40,103-105;wght=400 Cantarell-VF.otf;1,15,30-35,40,103-105;wght=800 +// Glyph 1 at MSHQ=200 is outside the head bounds of the font. +Astrolabe_subset.ttf;1;MSHQ=200 diff --git a/tests/src/font_tools.rs b/tests/src/font_tools.rs index d71d1ac0..b8c338b3 100644 --- a/tests/src/font_tools.rs +++ b/tests/src/font_tools.rs @@ -19,3 +19,4 @@ use crate::*; #[test] #[cfg(feature = "variable-fonts")] fn noto_sans_regular_var_3() {test_font_tools("NotoSans-Regular_var.ttf", "10,40,58,201-205", "wght=800,wdth=70.0", 3)} #[test] #[cfg(feature = "variable-fonts")] fn cantarell_v_f_1() {test_font_tools("Cantarell-VF.otf", "1,15,30-35,40,103-105", "wght=400", 1)} #[test] #[cfg(feature = "variable-fonts")] fn cantarell_v_f_2() {test_font_tools("Cantarell-VF.otf", "1,15,30-35,40,103-105", "wght=800", 2)} +#[test] #[cfg(feature = "variable-fonts")] fn astrolabe_subset_1() {test_font_tools("Astrolabe_subset.ttf", "1", "MSHQ=200", 1)} diff --git a/tests/ttx/Astrolabe_subset_1.ttx b/tests/ttx/Astrolabe_subset_1.ttx new file mode 100644 index 00000000..b458a8a4 --- /dev/null +++ b/tests/ttx/Astrolabe_subset_1.ttx @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copyright 2024 The Astrolabe Project Authors (github.com/aliftype/astrolabe) + + + Astrolabe + + + Regular + + + 1.000;ALIF;Astrolabe-Regular + + + Astrolabe Regular + + + Version 1.000 + + + Astrolabe-Regular + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/ttx/Cantarell-VF_1.ttx b/tests/ttx/Cantarell-VF_1.ttx index 5008c186..ec26a802 100644 --- a/tests/ttx/Cantarell-VF_1.ttx +++ b/tests/ttx/Cantarell-VF_1.ttx @@ -22,16 +22,16 @@ - + - + - - + + diff --git a/tests/ttx/Cantarell-VF_2.ttx b/tests/ttx/Cantarell-VF_2.ttx index 146b1c60..a46695e6 100644 --- a/tests/ttx/Cantarell-VF_2.ttx +++ b/tests/ttx/Cantarell-VF_2.ttx @@ -22,16 +22,16 @@ - + - - - - + + + + diff --git a/tests/ttx/NotoSans-Regular_var_2.ttx b/tests/ttx/NotoSans-Regular_var_2.ttx index b0a9199a..38e19394 100644 --- a/tests/ttx/NotoSans-Regular_var_2.ttx +++ b/tests/ttx/NotoSans-Regular_var_2.ttx @@ -23,16 +23,16 @@ - + - - - - + + + + diff --git a/tests/ttx/NotoSans-Regular_var_3.ttx b/tests/ttx/NotoSans-Regular_var_3.ttx index 70a97a48..329a5402 100644 --- a/tests/ttx/NotoSans-Regular_var_3.ttx +++ b/tests/ttx/NotoSans-Regular_var_3.ttx @@ -23,16 +23,16 @@ - + - - - - + + + +