googlefonts / glyphsLib

A bridge from Glyphs source files (.glyphs) to UFOs
Apache License 2.0
178 stars 51 forks source link

Traceback with AlignmentZones custom parameter #969

Open frankrolf opened 6 months ago

frankrolf commented 6 months ago

I have a .glyphs file where each master has an alignmentZones custom parameter, like this:

alignmentZones = (
"{671, 12}",
"{612, 18}",
"{574, 12}",
"{495, 16}",
"{465, 14}",
"{436, 14}",
"{416, 18}",
"{0, -18}",
"{-211, -18}"
);

This results in the following traceback:

Traceback (most recent call last):
  File "glyphs2ufo", line 8, in <module>
    sys.exit(_glyphs2ufo_entry_point())
  File "python3.10/site-packages/glyphsLib/cli.py", line 276, in _glyphs2ufo_entry_point
    return main(args)
  File "python3.10/site-packages/glyphsLib/cli.py", line 234, in main
    return options.func(options)
  File "python3.10/site-packages/glyphsLib/cli.py", line 253, in glyphs2ufo
    glyphsLib.build_masters(
  File "python3.10/site-packages/glyphsLib/__init__.py", line 155, in build_masters
    source.font.save(ufo_path)
  File "python3.10/site-packages/ufoLib2/objects/font.py", line 593, in save
    self.write(writer, saveAs=saveAs)
  File "python3.10/site-packages/ufoLib2/objects/font.py", line 520, in write
    writer.writeInfo(self.info)
  File "python3.10/site-packages/fontTools/ufoLib/__init__.py", line 1301, in writeInfo
    infoData = validateInfoVersion3Data(infoData)
  File "python3.10/site-packages/fontTools/ufoLib/__init__.py", line 1867, in validateInfoVersion3Data
    raise UFOLibError(f"Invalid value for attribute {attr} ({value!r}).")
fontTools.ufoLib.errors.UFOLibError: Invalid value for attribute postscriptBlueValues ([-18, 0, 416, 434, 436, 450, 465, 479, 495, 511, 574, 586, 612, 630, 671, 683]).

The problem here is that that’s just too many zones. ufoLib’s fontInfoPostscriptBluesValidator rejects the list of values because more than 7 pairs are supplied, which is not allowed per the CFF spec: https://github.com/fonttools/fonttools/blob/main/Lib/fontTools/ufoLib/validators.py#L305-L306

This problem could be fixed by editing to_ufo_blue_values in blue_values.py:

def to_ufo_blue_values(self, ufo, master):
    """Set postscript blue values from Glyphs alignment zones."""

    alignment_zones = master.alignmentZones
    blue_values = []
    other_blues = []
    for zone_index, zone in enumerate(sorted(alignment_zones)):
        pos = zone.position
        size = zone.size
        val_list = blue_values if pos == 0 or size >= 0 else other_blues
        if zone_index <= 7:
            val_list.extend(sorted((pos, pos + size)))
        else:
            logger.warning(f'Surplus alignment zone {pos}, {pos + size} omitted')

    if blue_values:
        ufo.info.postscriptBlueValues = blue_values
    if other_blues:
        ufo.info.postscriptOtherBlues = other_blues