diff --git a/resources/codegen_inputs/post.rs b/resources/codegen_inputs/post.rs index b511c7abd..1c730d55b 100644 --- a/resources/codegen_inputs/post.rs +++ b/resources/codegen_inputs/post.rs @@ -7,8 +7,6 @@ table Post { /// 0x00025000 for version 2.5 (deprecated) 0x00030000 for version /// 3.0 #[version] - // NOTE: we will need some sort of builder to compile post tables, and that - // builder should set the version. This attribute is a placeholder. #[default(Version16Dot16::VERSION_1_0)] version: Version16Dot16, /// Italic angle in counter-clockwise degrees from the vertical. @@ -32,18 +30,23 @@ table Post { /// font is not proportionally spaced (i.e. monospaced). is_fixed_pitch: u32, /// Minimum memory usage when an OpenType font is downloaded. + #[default(0)] min_mem_type42: u32, /// Maximum memory usage when an OpenType font is downloaded. + #[default(0)] max_mem_type42: u32, /// Minimum memory usage when an OpenType font is downloaded as a /// Type 1 font. + #[default(0)] min_mem_type1: u32, /// Maximum memory usage when an OpenType font is downloaded as a /// Type 1 font. + #[default(0)] max_mem_type1: u32, /// Number of glyphs (this should be the same as numGlyphs in /// 'maxp' table). #[since_version(2,0)] + #[compile(self.compute_num_glyphs())] num_glyphs: u16, /// Array of indices into the string data. See below for details. #[count($num_glyphs)] diff --git a/write-fonts/generated/generated_post.rs b/write-fonts/generated/generated_post.rs index 1b56a376b..444372649 100644 --- a/write-fonts/generated/generated_post.rs +++ b/write-fonts/generated/generated_post.rs @@ -42,9 +42,6 @@ pub struct Post { /// Maximum memory usage when an OpenType font is downloaded as a /// Type 1 font. pub max_mem_type1: u32, - /// Number of glyphs (this should be the same as numGlyphs in - /// 'maxp' table). - pub num_glyphs: Option, /// Array of indices into the string data. See below for details. pub glyph_name_index: Option>, /// Storage for the string data. @@ -59,11 +56,10 @@ impl Default for Post { underline_position: Default::default(), underline_thickness: Default::default(), is_fixed_pitch: Default::default(), - min_mem_type42: Default::default(), - max_mem_type42: Default::default(), - min_mem_type1: Default::default(), - max_mem_type1: Default::default(), - num_glyphs: Default::default(), + min_mem_type42: 0, + max_mem_type42: 0, + min_mem_type1: 0, + max_mem_type1: 0, glyph_name_index: Default::default(), string_data: Default::default(), } @@ -72,32 +68,24 @@ impl Default for Post { impl Post { /// Construct a new `Post` - #[allow(clippy::too_many_arguments)] pub fn new( italic_angle: Fixed, underline_position: FWord, underline_thickness: FWord, is_fixed_pitch: u32, - min_mem_type42: u32, - max_mem_type42: u32, - min_mem_type1: u32, - max_mem_type1: u32, ) -> Self { Self { italic_angle, underline_position, underline_thickness, is_fixed_pitch, - min_mem_type42, - max_mem_type42, - min_mem_type1, - max_mem_type1, ..Default::default() } } } impl FontWrite for Post { + #[allow(clippy::unnecessary_cast)] fn write_into(&self, writer: &mut TableWriter) { let version = self.version; version.write_into(writer); @@ -109,12 +97,9 @@ impl FontWrite for Post { self.max_mem_type42.write_into(writer); self.min_mem_type1.write_into(writer); self.max_mem_type1.write_into(writer); - version.compatible((2, 0)).then(|| { - self.num_glyphs - .as_ref() - .expect("missing versioned field should have failed validation") - .write_into(writer) - }); + version + .compatible((2, 0)) + .then(|| (self.compute_num_glyphs() as u16).write_into(writer)); version.compatible((2, 0)).then(|| { self.glyph_name_index .as_ref() @@ -137,11 +122,6 @@ impl Validate for Post { fn validate_impl(&self, ctx: &mut ValidationCtx) { ctx.in_table("Post", |ctx| { let version = self.version; - ctx.in_field("num_glyphs", |ctx| { - if version.compatible((2, 0)) && self.num_glyphs.is_none() { - ctx.report(format!("field must be present for version {version}")); - } - }); ctx.in_field("glyph_name_index", |ctx| { if version.compatible((2, 0)) && self.glyph_name_index.is_none() { ctx.report(format!("field must be present for version {version}")); @@ -173,7 +153,6 @@ impl<'a> FromObjRef> for Post { max_mem_type42: obj.max_mem_type42(), min_mem_type1: obj.min_mem_type1(), max_mem_type1: obj.max_mem_type1(), - num_glyphs: obj.num_glyphs(), glyph_name_index: obj.glyph_name_index().to_owned_obj(offset_data), string_data: obj.string_data().map(|obj| { obj.iter() diff --git a/write-fonts/src/tables/post.rs b/write-fonts/src/tables/post.rs index b0ed72a0d..265b216fd 100644 --- a/write-fonts/src/tables/post.rs +++ b/write-fonts/src/tables/post.rs @@ -11,8 +11,24 @@ include!("../../generated/generated_post.rs"); pub struct PString(String); impl Post { - /// Construct a new version 2.0 table from a glyph order. - pub fn new_v2<'a>(order: impl IntoIterator) -> Self { + /// Builder-style method to add glyph names to the table. + /// + /// See [`set_glyph_names`] for more information. + /// + /// [`set_glyph_names`]: Self::set_glyph_names + pub fn with_glyph_names<'a>(mut self, order: impl IntoIterator) -> Self { + self.set_glyph_names(order); + self + } + + /// Set the glyph names for this table. + /// + /// The provided order is an iterator of the names of glyphs, in the order + /// that they appear in the `glyf` table. + /// + /// This replaces any previously set glyph names, and sets the table version + /// to 2.0. + pub fn set_glyph_names<'a>(&mut self, order: impl IntoIterator) { let known_glyphs = read_fonts::tables::post::DEFAULT_GLYPH_NAMES .iter() .enumerate() @@ -31,14 +47,16 @@ impl Post { } } } + self.glyph_name_index = Some(name_index); + self.string_data = Some(storage); + self.version = Version16Dot16::VERSION_2_0; + } - Post { - version: Version16Dot16::VERSION_2_0, - num_glyphs: Some(name_index.len() as u16), - glyph_name_index: Some(name_index), - string_data: Some(storage), - ..Default::default() - } + fn compute_num_glyphs(&self) -> u16 { + self.glyph_name_index + .as_ref() + .map(Vec::len) + .unwrap_or_default() as u16 } } @@ -90,7 +108,7 @@ mod tests { #[test] fn compilev2() { - let post = Post::new_v2([".dotdef", "A", "B", "one", "flarb", "C"]); + let post = Post::default().with_glyph_names([".dotdef", "A", "B", "one", "flarb", "C"]); let dumped = crate::dump_table(&post).unwrap(); let loaded = read_fonts::tables::post::Post::read(FontData::new(&dumped)).unwrap(); assert_eq!(loaded.version(), Version16Dot16::VERSION_2_0);