diff --git a/fontbe/src/features.rs b/fontbe/src/features.rs index 16d1f606..fdc829f2 100644 --- a/fontbe/src/features.rs +++ b/fontbe/src/features.rs @@ -35,7 +35,11 @@ use fontdrasil::{ orchestration::{Access, AccessBuilder, Work}, types::Axis, }; -use write_fonts::{tables::variations::VariationRegion, types::Tag, OtRound}; +use write_fonts::{ + tables::{layout::ClassDef, variations::VariationRegion}, + types::Tag, + OtRound, +}; use crate::{ error::Error, @@ -526,6 +530,7 @@ impl Work for FeatureCompilationWork { fn read_access(&self) -> Access { AccessBuilder::new() + .variant(FeWorkId::GlyphOrder) .variant(WorkId::FeaturesAst) .variant(WorkId::GatherBeKerning) .variant(WorkId::Marks) @@ -543,10 +548,29 @@ impl Work for FeatureCompilationWork { fn exec(&self, context: &Context) -> Result<(), Error> { let static_metadata = context.ir.static_metadata.get(); let ast = context.fea_ast.get(); + let glyph_order = context.ir.glyph_order.get(); let kerns = context.fea_rs_kerns.get(); let marks = context.fea_rs_marks.get(); - let result = self.compile(&static_metadata, &ast, kerns.as_ref(), marks.as_ref())?; + let mut result = self.compile(&static_metadata, &ast, kerns.as_ref(), marks.as_ref())?; + if result.gdef_classes.is_none() { + // there were no explicit gdef categories, so let's use the ones + // that were in public.openTypeCatgories or which we computed from + // GlyphData.xml + + if let Some(gdef) = result.gdef.as_mut() { + let class_def: ClassDef = static_metadata + .gdef_categories + .categories + .iter() + .filter_map(|(name, cls)| { + glyph_order.glyph_id(name).map(|id| (id, *cls as u16)) + }) + .collect(); + + gdef.glyph_class_def.set(class_def); + } + } debug!( "Built features, gpos? {} gsub? {} gdef? {}", diff --git a/glyphs2fontir/src/source.rs b/glyphs2fontir/src/source.rs index 6f0b8c59..68ca9228 100644 --- a/glyphs2fontir/src/source.rs +++ b/glyphs2fontir/src/source.rs @@ -17,9 +17,9 @@ use fontdrasil::{ use fontir::{ error::{BadGlyph, BadGlyphKind, BadSource, Error}, ir::{ - self, AnchorBuilder, AnchorKind, GdefCategories, GlobalMetric, GlobalMetrics, - GlyphInstance, GlyphOrder, KernGroup, KernSide, KerningGroups, KerningInstance, - NameBuilder, NameKey, NamedInstance, StaticMetadata, DEFAULT_VENDOR_ID, + self, AnchorBuilder, GdefCategories, GlobalMetric, GlobalMetrics, GlyphInstance, + GlyphOrder, KernGroup, KernSide, KerningGroups, KerningInstance, NameBuilder, NameKey, + NamedInstance, StaticMetadata, DEFAULT_VENDOR_ID, }, orchestration::{Context, IrWork, WorkId}, source::{Input, Source}, @@ -475,11 +475,9 @@ fn category_for_glyph(glyph: &glyphs_reader::Glyph) -> Option { .layers .iter() .flat_map(|layer| layer.anchors.iter()) - .any(|anchor| { - AnchorKind::new(&anchor.name) - .map(|a| a.is_attaching()) - .unwrap_or(false) - }); + // glyphsLib considers any anchor that does not start with '_' as an + // 'attaching anchor'; see https://github.com/googlefonts/glyphsLib/issues/1024 + .any(|anchor| !anchor.name.starts_with('_')); match (glyph.category, glyph.sub_category) { (_, Subcategory::Ligature) if has_attaching_anchor => Some(GlyphClassDef::Ligature), (Some(Category::Mark), Subcategory::Nonspacing | Subcategory::SpacingCombining) => {