diff --git a/fontbe/src/os2.rs b/fontbe/src/os2.rs index 2e406d16..74b664e2 100644 --- a/fontbe/src/os2.rs +++ b/fontbe/src/os2.rs @@ -306,11 +306,18 @@ fn add_unicode_range_bits(add_to: &mut HashSet, codepoint: u32) { } /// -fn apply_unicode_range(os2: &mut Os2, codepoints: &HashSet) { - let mut bits = HashSet::new(); - for codepoint in codepoints { - add_unicode_range_bits(&mut bits, *codepoint); - } +fn apply_unicode_range( + os2: &mut Os2, + assigned_bits: Option>, + codepoints: &HashSet, +) { + let bits = assigned_bits.unwrap_or_else(|| { + let mut bits = HashSet::new(); + for codepoint in codepoints { + add_unicode_range_bits(&mut bits, *codepoint); + } + bits + }); let mut unicode_range = [0u32; 4]; for bit in bits { @@ -331,7 +338,7 @@ fn apply_unicode_range(os2: &mut Os2, codepoints: &HashSet) { /// This is a direct translation from FontTools /// /// FontTools is in turn a translation of -fn codepage_range_bits(codepoints: &HashSet) -> HashSet { +fn codepage_range_bits(codepoints: &HashSet) -> HashSet { let mut bits = HashSet::new(); let chars = codepoints @@ -459,14 +466,18 @@ fn codepage_range_bits(codepoints: &HashSet) -> HashSet { bits } -fn apply_codepage_range(os2: &mut Os2, codepoints: &HashSet) { - let bits = codepage_range_bits(codepoints); +fn apply_codepage_range( + os2: &mut Os2, + assigned_bits: Option>, + codepoints: &HashSet, +) { + let bits = assigned_bits.unwrap_or_else(|| codepage_range_bits(codepoints)); let mut codepage_range = [0u32; 2]; for bit in bits { let idx = bit / 32; let bit = bit - idx * 32; assert!(bit <= 32, "{bit}"); - codepage_range[idx] |= 1 << bit; + codepage_range[idx as usize] |= 1 << bit; } os2.ul_code_page_range_1 = Some(codepage_range[0]); os2.ul_code_page_range_2 = Some(codepage_range[1]); @@ -573,8 +584,16 @@ impl Work for Os2Work { }; apply_panose(&mut os2, static_metadata.misc.panose.as_ref()); apply_metrics(&mut os2, &metrics); - apply_unicode_range(&mut os2, &codepoints); - apply_codepage_range(&mut os2, &codepoints); + apply_unicode_range( + &mut os2, + static_metadata.misc.unicode_range_bits.clone(), + &codepoints, + ); + apply_codepage_range( + &mut os2, + static_metadata.misc.codepage_range_bits.clone(), + &codepoints, + ); apply_min_max_char_index(&mut os2, &codepoints); apply_max_context(&mut os2, context); diff --git a/fontc/src/lib.rs b/fontc/src/lib.rs index 432e92f1..bb8d5786 100644 --- a/fontc/src/lib.rs +++ b/fontc/src/lib.rs @@ -3217,4 +3217,51 @@ mod tests { ) ); } + + fn assert_expected_unicode_ranges(source: &str) { + let compile = TestCompile::compile_source(source); + let font = compile.font(); + let os2 = font.os2().unwrap(); + + assert_eq!( + [1 | 1 << 28, 1 << 20 | 1 << 24, 0, 1 << 26], + [ + os2.ul_unicode_range_1(), + os2.ul_unicode_range_2(), + os2.ul_unicode_range_3(), + os2.ul_unicode_range_4() + ] + ); + } + + #[test] + fn obeys_source_unicode_ranges_glyphs() { + assert_expected_unicode_ranges("glyphs3/WghtVar_OS2.glyphs"); + } + + #[test] + fn obeys_source_unicode_ranges_designspace() { + assert_expected_unicode_ranges("designspace_from_glyphs/WghtVarOS2.designspace"); + } + + fn assert_expected_codepage_ranges(source: &str) { + let compile = TestCompile::compile_source(source); + let font = compile.font(); + let os2 = font.os2().unwrap(); + + assert_eq!( + [Some(1 | 1 << 1 | 1 << 19), Some(1 << 31)], + [os2.ul_code_page_range_1(), os2.ul_code_page_range_2(),] + ); + } + + #[test] + fn obeys_source_codepage_ranges_glyphs() { + assert_expected_codepage_ranges("glyphs3/WghtVar_OS2.glyphs"); + } + + #[test] + fn obeys_source_codepage_ranges_designspace() { + assert_expected_codepage_ranges("designspace_from_glyphs/WghtVarOS2.designspace"); + } } diff --git a/fontir/src/ir.rs b/fontir/src/ir.rs index a6db62ec..e2abb859 100644 --- a/fontir/src/ir.rs +++ b/fontir/src/ir.rs @@ -124,6 +124,12 @@ pub struct MiscMetadata { pub created: Option>, pub panose: Option, + + // Allows source to explicitly control bits. + pub unicode_range_bits: Option>, + + // Allows source to explicitly control bits. + pub codepage_range_bits: Option>, } /// PANOSE bytes @@ -464,6 +470,8 @@ impl StaticMetadata { head_flags: 3, created: None, panose: None, + unicode_range_bits: None, + codepage_range_bits: None, }, }) } @@ -2124,6 +2132,8 @@ mod tests { lowest_rec_ppm: 42, created: None, panose: None, + unicode_range_bits: None, + codepage_range_bits: None, }, number_values: Default::default(), } diff --git a/glyphs-reader/src/error.rs b/glyphs-reader/src/error.rs index f7e80aa0..e211fff3 100644 --- a/glyphs-reader/src/error.rs +++ b/glyphs-reader/src/error.rs @@ -20,4 +20,6 @@ pub enum Error { NotAGlyphsPackage(PathBuf), #[error("Invalid plist")] WorstPlistEver(#[from] crate::plist::Error), + #[error("Invalid code page {0}")] + InvalidCodePage(u32), } diff --git a/glyphs-reader/src/font.rs b/glyphs-reader/src/font.rs index 1d7106c2..569f8476 100644 --- a/glyphs-reader/src/font.rs +++ b/glyphs-reader/src/font.rs @@ -86,6 +86,8 @@ pub struct Font { pub superscript_y_offset: Option, pub superscript_y_size: Option, + pub unicode_range_bits: Option>, + pub codepage_range_bits: Option>, pub panose: Option>, } @@ -420,6 +422,20 @@ impl CustomParameters { Some(bits) } + fn unicode_range(&self) -> Option<&Vec> { + let Some(CustomParameterValue::UnicodeRange(bits)) = self.get("unicodeRanges") else { + return None; + }; + Some(bits) + } + + fn codepage_range(&self) -> Option<&Vec> { + let Some(CustomParameterValue::CodepageRange(bits)) = self.get("codePageRanges") else { + return None; + }; + Some(bits) + } + fn panose(&self) -> Option<&Vec> { let Some(CustomParameterValue::Panose(values)) = self.get("panose") else { return None; @@ -439,6 +455,8 @@ enum CustomParameterValue { GlyphOrder(Vec), VirtualMaster(Vec), FsType(Vec), + UnicodeRange(Vec), + CodepageRange(Vec), Panose(Vec), } @@ -537,6 +555,20 @@ impl FromPlist for CustomParameters { }; value = Some(CustomParameterValue::FsType(tokenizer.parse()?)); } + _ if name == Some(String::from("unicodeRanges")) => { + let Token::OpenParen = peek else { + return Err(Error::UnexpectedChar('(')); + }; + value = + Some(CustomParameterValue::UnicodeRange(tokenizer.parse()?)); + } + _ if name == Some(String::from("codePageRanges")) => { + let Token::OpenParen = peek else { + return Err(Error::UnexpectedChar('(')); + }; + value = + Some(CustomParameterValue::CodepageRange(tokenizer.parse()?)); + } _ if name == Some(String::from("panose")) => { let Token::OpenParen = peek else { return Err(Error::UnexpectedChar('(')); @@ -2154,6 +2186,48 @@ impl Instance { } } +/// Glyphs appears to use code page identifiers rather than bits +/// +/// +fn codepage_range_bit(codepage: u32) -> Result { + Ok(match codepage { + 1252 => 0, // Latin 1 + 1250 => 1, // Latin 2: Eastern Europe + 1251 => 2, // Cyrillic + 1253 => 3, // Greek + 1254 => 4, // Turkish + 1255 => 5, // Hebrew + 1256 => 6, // Arabic + 1257 => 7, // Windows Baltic + 1258 => 8, // Vietnamese + 874 => 16, // Thai + 932 => 17, // JIS/Japan + 936 => 18, // Chinese: Simplified PRC and Singapore + 949 => 19, // Korean Wansung + 950 => 20, // Chinese: Traditional Taiwan and Hong Kong SAR + 1361 => 21, // Korean Johab + 869 => 48, // IBM Greek + 866 => 49, // MS-DOS Russian + 865 => 50, // MS-DOS Nordic + 864 => 51, // Arabic + 863 => 52, // MS-DOS Canadian French + 862 => 53, // Hebrew + 861 => 54, // MS-DOS Icelandic + 860 => 55, // MS-DOS Portuguese + 857 => 56, // IBM Turkish + 855 => 57, // IBM Cyrillic; primarily Russian + 852 => 58, // Latin 2 + 775 => 59, // MS-DOS Baltic + 737 => 60, // Greek; former 437 G + 708 => 61, // Arabic; ASMO 708 + 850 => 62, // WE/Latin 1 + 437 => 63, // US + + v if v < 64 => v, // an actual bit + _ => return Err(Error::InvalidCodePage(codepage)), + }) +} + impl TryFrom for Font { type Error = Error; @@ -2227,6 +2301,21 @@ impl TryFrom for Font { .fs_type() .map(|bits| bits.iter().map(|bit| 1 << bit).sum()); + let unicode_range_bits = from + .custom_parameters + .unicode_range() + .map(|bits| bits.iter().map(|b| *b as u32).collect()); + + let codepage_range_bits = from + .custom_parameters + .codepage_range() + .map(|bits| { + bits.iter() + .map(|b| codepage_range_bit(*b as u32)) + .collect::>() + }) + .transpose()?; + let panose = from.custom_parameters.panose().cloned(); let mut names = BTreeMap::new(); @@ -2372,6 +2461,8 @@ impl TryFrom for Font { superscript_x_size, superscript_y_offset, superscript_y_size, + unicode_range_bits, + codepage_range_bits, panose, }) } @@ -2651,19 +2742,21 @@ mod tests { let _ = env_logger::builder().is_test(true).try_init(); let filename = format!("{name}.glyphs"); let pkgname = format!("{name}.glyphspackage"); - let g2 = Font::load(&glyphs2_dir().join(filename.clone())).unwrap(); - let g3 = Font::load(&glyphs3_dir().join(filename.clone())).unwrap(); + let g2_file = glyphs2_dir().join(filename.clone()); + let g3_file = glyphs3_dir().join(filename.clone()); + let g2 = Font::load(&g2_file).unwrap(); + let g3 = Font::load(&g3_file).unwrap(); // Handy if troubleshooting std::fs::write("/tmp/g2.glyphs.txt", format!("{g2:#?}")).unwrap(); std::fs::write("/tmp/g3.glyphs.txt", format!("{g3:#?}")).unwrap(); // Assert fields that often don't match individually before doing the whole struct for nicer diffs - assert_eq!(g2.axes, g3.axes); + assert_eq!(g2.axes, g3.axes, "axes mismatch {g2_file:?} vs {g3_file:?}"); for (g2m, g3m) in g2.masters.iter().zip(g3.masters.iter()) { - assert_eq!(g2m, g3m); + assert_eq!(g2m, g3m, "master mismatch {g2_file:?} vs {g3_file:?}"); } - assert_eq!(g2, g3, "g2 should match g3"); + assert_eq!(g2, g3, "g2 should match g3 {g2_file:?} vs {g3_file:?}"); if has_package { let g2_pkg = Font::load(&glyphs2_dir().join(pkgname.clone())).unwrap(); diff --git a/glyphs2fontir/src/source.rs b/glyphs2fontir/src/source.rs index c7cf3ce1..62031118 100644 --- a/glyphs2fontir/src/source.rs +++ b/glyphs2fontir/src/source.rs @@ -127,6 +127,8 @@ impl GlyphsIrSource { superscript_x_size: font.superscript_x_size, superscript_y_offset: font.superscript_y_offset, superscript_y_size: font.superscript_y_size, + unicode_range_bits: font.unicode_range_bits.clone(), + codepage_range_bits: font.codepage_range_bits.clone(), panose: font.panose.clone(), }; state.track_memory("/font_master".to_string(), &font)?; @@ -177,6 +179,8 @@ impl GlyphsIrSource { superscript_x_size: font.superscript_x_size, superscript_y_offset: font.superscript_y_offset, superscript_y_size: font.superscript_y_size, + unicode_range_bits: None, + codepage_range_bits: None, panose: None, }; state.track_memory("/font_master".to_string(), &font)?; @@ -453,6 +457,15 @@ impl Work for StaticMetadataWork { // Default per static_metadata.misc.fs_type = font.fs_type.or(Some(1 << 3)); + static_metadata.misc.unicode_range_bits = font + .unicode_range_bits + .as_ref() + .map(|bits| bits.iter().copied().collect()); + static_metadata.misc.codepage_range_bits = font + .codepage_range_bits + .as_ref() + .map(|bits| bits.iter().copied().collect()); + if let Some(raw_panose) = font.panose.as_ref() { let mut bytes = [0u8; 10]; bytes diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/fontinfo.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/fontinfo.plist new file mode 100644 index 00000000..2cb4f42b --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/fontinfo.plist @@ -0,0 +1,63 @@ + + + + + ascender + 800 + capHeight + 700 + copyright + Copy! + descender + -200 + familyName + WghtVarOS2 + italicAngle + 0 + openTypeHeadCreated + 2022/12/01 04:52:20 + openTypeNameDescription + The greatest weight var + openTypeNameLicenseURL + https://example.com/my/font/license + openTypeNameVersion + New Value + openTypeOS2Type + + 3 + + openTypeOS2UnicodeRanges + + 0 + 28 + 52 + 56 + 122 + + openTypeOS2CodePageRanges + + 0 + 1 + 19 + 63 + + postscriptUnderlinePosition + -100 + postscriptUnderlineThickness + 50 + styleMapFamilyName + WghtVarOS2 + styleMapStyleName + bold + styleName + Bold + unitsPerEm + 1000 + versionMajor + 42 + versionMinor + 42 + xHeight + 500 + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/contents.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/contents.plist new file mode 100644 index 00000000..310df9a4 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/contents.plist @@ -0,0 +1,14 @@ + + + + + exclam + exclam.glif + hyphen + hyphen.glif + manual-component + manual-component.glif + space + space.glif + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/exclam.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/exclam.glif new file mode 100644 index 00000000..c1677122 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/exclam.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/hyphen.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/hyphen.glif new file mode 100644 index 00000000..4bc2c734 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/hyphen.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/manual-component.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/manual-component.glif new file mode 100644 index 00000000..cd1d614c --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/manual-component.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/space.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/space.glif new file mode 100644 index 00000000..98334812 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/glyphs/space.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/layercontents.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/layercontents.plist new file mode 100644 index 00000000..b9c1a4f2 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/layercontents.plist @@ -0,0 +1,10 @@ + + + + + + public.default + glyphs + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/lib.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/lib.plist new file mode 100644 index 00000000..95372af3 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/lib.plist @@ -0,0 +1,72 @@ + + + + + com.github.googlei18n.ufo2ft.featureWriters + + + class + CursFeatureWriter + + + class + KernFeatureWriter + + + class + MarkFeatureWriter + + + class + GdefFeatureWriter + + + com.github.googlei18n.ufo2ft.filters + + + name + eraseOpenCorners + namespace + glyphsLib.filters + pre + + + + com.schriftgestaltung.customParameter.GSFont.disablesAutomaticAlignment + + com.schriftgestaltung.customParameter.GSFont.useNiceNames + 1 + com.schriftgestaltung.customParameter.GSFontMaster.customValue + 0 + com.schriftgestaltung.customParameter.GSFontMaster.customValue1 + 0 + com.schriftgestaltung.customParameter.GSFontMaster.customValue2 + 0 + com.schriftgestaltung.customParameter.GSFontMaster.customValue3 + 0 + com.schriftgestaltung.customParameter.GSFontMaster.iconName + Bold + com.schriftgestaltung.customParameter.GSFontMaster.weightValue + 700 + com.schriftgestaltung.customParameter.GSFontMaster.widthValue + 100 + com.schriftgestaltung.fontMasterOrder + 1 + com.schriftgestaltung.weightValue + 700 + com.schriftgestaltung.widthValue + 100 + public.glyphOrder + + space + exclam + hyphen + manual-component + + public.postscriptNames + + manual-component + manualcomponent + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/metainfo.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/metainfo.plist new file mode 100644 index 00000000..7b8b34ac --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Bold.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + com.github.fonttools.ufoLib + formatVersion + 3 + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/fontinfo.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/fontinfo.plist new file mode 100644 index 00000000..9edf23a7 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/fontinfo.plist @@ -0,0 +1,91 @@ + + + + + ascender + 737 + capHeight + 702 + copyright + Copy! + descender + -42 + familyName + WghtVarOS2 + italicAngle + 0 + openTypeHeadCreated + 2022/12/01 04:52:20 + openTypeHheaAscender + 1194 + openTypeHheaDescender + -290 + openTypeHheaLineGap + 43 + openTypeNameDescription + The greatest weight var + openTypeNameLicenseURL + https://example.com/my/font/license + openTypeNameVersion + New Value + openTypeOS2Type + + 3 + + openTypeOS2TypoAscender + 1193 + openTypeOS2TypoDescender + -289 + openTypeOS2TypoLineGap + 42 + openTypeOS2UnicodeRanges + + 0 + 28 + 52 + 56 + 122 + + openTypeOS2CodePageRanges + + 0 + 1 + 19 + 63 + + openTypeOS2WinAscent + 1325 + openTypeOS2WinDescent + 377 + postscriptBlueValues + + -16 + 0 + 737 + 753 + + postscriptOtherBlues + + -58 + -42 + + postscriptUnderlinePosition + -100 + postscriptUnderlineThickness + 50 + styleMapFamilyName + WghtVarOS2 + styleMapStyleName + regular + styleName + Regular + unitsPerEm + 1000 + versionMajor + 42 + versionMinor + 42 + xHeight + 501 + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/contents.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/contents.plist new file mode 100644 index 00000000..310df9a4 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/contents.plist @@ -0,0 +1,14 @@ + + + + + exclam + exclam.glif + hyphen + hyphen.glif + manual-component + manual-component.glif + space + space.glif + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/exclam.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/exclam.glif new file mode 100644 index 00000000..5bc6d8c7 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/exclam.glif @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/hyphen.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/hyphen.glif new file mode 100644 index 00000000..8b2d57e9 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/hyphen.glif @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/manual-component.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/manual-component.glif new file mode 100644 index 00000000..1da63bcd --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/manual-component.glif @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/space.glif b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/space.glif new file mode 100644 index 00000000..c05cd73f --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/glyphs/space.glif @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/layercontents.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/layercontents.plist new file mode 100644 index 00000000..b9c1a4f2 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/layercontents.plist @@ -0,0 +1,10 @@ + + + + + + public.default + glyphs + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/lib.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/lib.plist new file mode 100644 index 00000000..b7c2428e --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/lib.plist @@ -0,0 +1,72 @@ + + + + + com.github.googlei18n.ufo2ft.featureWriters + + + class + CursFeatureWriter + + + class + KernFeatureWriter + + + class + MarkFeatureWriter + + + class + GdefFeatureWriter + + + com.github.googlei18n.ufo2ft.filters + + + name + eraseOpenCorners + namespace + glyphsLib.filters + pre + + + + com.schriftgestaltung.customParameter.GSFont.disablesAutomaticAlignment + + com.schriftgestaltung.customParameter.GSFont.useNiceNames + 1 + com.schriftgestaltung.customParameter.GSFontMaster.customValue + 0 + com.schriftgestaltung.customParameter.GSFontMaster.customValue1 + 0 + com.schriftgestaltung.customParameter.GSFontMaster.customValue2 + 0 + com.schriftgestaltung.customParameter.GSFontMaster.customValue3 + 0 + com.schriftgestaltung.customParameter.GSFontMaster.iconName + + com.schriftgestaltung.customParameter.GSFontMaster.weightValue + 400 + com.schriftgestaltung.customParameter.GSFontMaster.widthValue + 100 + com.schriftgestaltung.fontMasterOrder + 0 + com.schriftgestaltung.weightValue + 400 + com.schriftgestaltung.widthValue + 100 + public.glyphOrder + + space + exclam + hyphen + manual-component + + public.postscriptNames + + manual-component + manualcomponent + + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/metainfo.plist b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/metainfo.plist new file mode 100644 index 00000000..7b8b34ac --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2-Regular.ufo/metainfo.plist @@ -0,0 +1,10 @@ + + + + + creator + com.github.fonttools.ufoLib + formatVersion + 3 + + diff --git a/resources/testdata/designspace_from_glyphs/WghtVarOS2.designspace b/resources/testdata/designspace_from_glyphs/WghtVarOS2.designspace new file mode 100644 index 00000000..a7474be7 --- /dev/null +++ b/resources/testdata/designspace_from_glyphs/WghtVarOS2.designspace @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/testdata/designspace_from_glyphs/make_designspace.sh b/resources/testdata/designspace_from_glyphs/make_designspace.sh index 72c759bd..e4b4b344 100755 --- a/resources/testdata/designspace_from_glyphs/make_designspace.sh +++ b/resources/testdata/designspace_from_glyphs/make_designspace.sh @@ -19,3 +19,4 @@ generate_designspace resources/testdata/glyphs3/WghtVar.glyphs generate_designspace resources/testdata/glyphs3/WghtVar_Anchors.glyphs generate_designspace resources/testdata/glyphs3/WghtVar_NoExport.glyphs generate_designspace resources/testdata/glyphs3/SlantedFont.glyphs +generate_designspace resources/testdata/glyphs3/WghtVar_OS2.glyphs diff --git a/resources/testdata/glyphs2/WghtVar_OS2.glyphs b/resources/testdata/glyphs2/WghtVar_OS2.glyphs index 336f1207..92ea99d0 100644 --- a/resources/testdata/glyphs2/WghtVar_OS2.glyphs +++ b/resources/testdata/glyphs2/WghtVar_OS2.glyphs @@ -30,10 +30,29 @@ Name = Weight; Tag = wght; } ); +}, +{ +name = unicodeRanges; +value = ( +0, +28, +52, +56, +122 +); +}, +{ +name = codePageRanges; +value = ( +"1252", +"1250", +"949", +"437" +); } ); date = "2022-12-01 04:52:20 +0000"; -familyName = WghtVar; +familyName = WghtVarOS2; fontMaster = ( { alignmentZones = ( diff --git a/resources/testdata/glyphs2/WghtVar_OS2.glyphspackage/fontinfo.plist b/resources/testdata/glyphs2/WghtVar_OS2.glyphspackage/fontinfo.plist index 89cb9f64..6a339a56 100644 --- a/resources/testdata/glyphs2/WghtVar_OS2.glyphspackage/fontinfo.plist +++ b/resources/testdata/glyphs2/WghtVar_OS2.glyphspackage/fontinfo.plist @@ -26,10 +26,29 @@ Name = Weight; Tag = wght; } ); +}, +{ +name = unicodeRanges; +value = ( +0, +28, +52, +56, +122 +); +}, +{ +name = codePageRanges; +value = ( +"1252", +"1250", +"949", +"437" +); } ); date = "2022-12-01 04:52:20 +0000"; -familyName = WghtVar; +familyName = WghtVarOS2; fontMaster = ( { alignmentZones = ( diff --git a/resources/testdata/glyphs3/WghtVar_OS2.glyphs b/resources/testdata/glyphs3/WghtVar_OS2.glyphs index 2027e00f..d1645795 100644 --- a/resources/testdata/glyphs3/WghtVar_OS2.glyphs +++ b/resources/testdata/glyphs3/WghtVar_OS2.glyphs @@ -11,8 +11,29 @@ name = Weight; tag = wght; } ); +customParameters = ( +{ +name = unicodeRanges; +value = ( +0, +28, +52, +56, +122 +); +}, +{ +name = codePageRanges; +value = ( +"1252", +"1250", +"949", +"437" +); +} +); date = "2022-12-01 04:52:20 +0000"; -familyName = WghtVar; +familyName = WghtVarOS2; fontMaster = ( { axesValues = ( diff --git a/resources/testdata/glyphs3/WghtVar_OS2.glyphspackage/fontinfo.plist b/resources/testdata/glyphs3/WghtVar_OS2.glyphspackage/fontinfo.plist index 0025e275..f4da25aa 100644 --- a/resources/testdata/glyphs3/WghtVar_OS2.glyphspackage/fontinfo.plist +++ b/resources/testdata/glyphs3/WghtVar_OS2.glyphspackage/fontinfo.plist @@ -7,8 +7,29 @@ name = Weight; tag = wght; } ); +customParameters = ( +{ +name = unicodeRanges; +value = ( +0, +28, +52, +56, +122 +); +}, +{ +name = codePageRanges; +value = ( +"1252", +"1250", +"949", +"437" +); +} +); date = "2022-12-01 04:52:20 +0000"; -familyName = WghtVar; +familyName = WghtVarOS2; fontMaster = ( { axesValues = ( diff --git a/ufo2fontir/src/source.rs b/ufo2fontir/src/source.rs index 06aa37eb..1ed893b0 100644 --- a/ufo2fontir/src/source.rs +++ b/ufo2fontir/src/source.rs @@ -964,6 +964,15 @@ impl Work for StaticMetadataWork { .unwrap_or(1_u16 << 2), ); + static_metadata.misc.unicode_range_bits = font_info_at_default + .open_type_os2_unicode_ranges + .as_ref() + .map(|bits| bits.iter().map(|b| *b as u32).collect()); + static_metadata.misc.codepage_range_bits = font_info_at_default + .open_type_os2_code_page_ranges + .as_ref() + .map(|bits| bits.iter().map(|b| *b as u32).collect()); + if let Some(ot_panose) = &font_info_at_default.open_type_os2_panose { static_metadata.misc.panose = Some(Panose { family_type: ot_panose.family_type as u8,