adobe-type-tools / afdko

Adobe Font Development Kit for OpenType
https://adobe-type-tools.github.io/afdko/
Other
1.01k stars 166 forks source link

[checkoutlinesufo] XMLSyntaxError reading fontinfo.plist of temp UFO font #1743

Open vitorsr opened 1 month ago

vitorsr commented 1 month ago

I think because of unescaped XML reserved markup characters.

MWE:

curl -O https://raw.githubusercontent.com/ArtifexSoftware/urw-base35-fonts/20200910/fonts/NimbusSans-Regular.otf
python3 -c 'from afdko import checkoutlinesufo; checkoutlinesufo.run(["-e", "NimbusSans-Regular.otf"])'

Traceback:

Converting to temp UFO font...
.notdef has no contours
Rfraktur Colinear line at (309, 385). Colinear line at (309, 375).
germandbls Colinear line at (268, 62).
notsubset Colinear line at (476, 62).
section Colinear line at (464, 532). Colinear line at (381, 533).
three Colinear line at (232, 333).
threeeighths Colinear line at (163, 476).
threequarters Colinear line at (153, 476).
threesuperior Colinear line at (135, 476).
uni20AF Colinear line at (316, 577). Colinear line at (321, 577).
uni2285 Colinear line at (524, 62).
uniEFC6 Colinear line at (676, 354).
uniEFC7 Colinear line at (45, 169).
uniEFCE Colinear line at (387, -192).
uniEFD3 There is an overlap.
uniEFD9 Colinear line at (906, 493).
Finished checkoutlinesufo: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 855/855 [00:03<00:00, 224.95it/s]
Traceback (most recent call last):
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/fontTools/ufoLib/__init__.py", line 145, in _getPlist
    return plistlib.load(f)
           ^^^^^^^^^^^^^^^^
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/fontTools/misc/plistlib/__init__.py", line 548, in load
    result = etree.parse(fp, parser=parser)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "src/lxml/etree.pyx", line 3590, in lxml.etree.parse
  File "src/lxml/parser.pxi", line 1973, in lxml.etree._parseDocument
  File "src/lxml/parser.pxi", line 1993, in lxml.etree._parseFilelikeDocument
  File "src/lxml/parser.pxi", line 1887, in lxml.etree._parseDocFromFilelike
  File "src/lxml/parser.pxi", line 1224, in lxml.etree._BaseParser._parseDocFromFilelike
  File "src/lxml/parsertarget.pxi", line 178, in lxml.etree._TargetParserContext._handleParseResultDoc
  File "src/lxml/parsertarget.pxi", line 175, in lxml.etree._TargetParserContext._handleParseResultDoc
  File "src/lxml/parser.pxi", line 672, in lxml.etree._raiseParseError
  File "/tmp/tmpm0gs8peg/font.ufo/fontinfo.plist", line 16
lxml.etree.XMLSyntaxError: xmlParseEntityRef: no name, line 16, column 62

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/afdko/checkoutlinesufo.py", line 1141, in run
    font_file.save()
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/afdko/checkoutlinesufo.py", line 112, in save
    self.defcon_font.save()
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/defcon/objects/font.py", line 896, in save
    self._saveInfo(writer=writer, saveAs=saveAs, progressBar=progressBar)
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/defcon/objects/font.py", line 933, in _saveInfo
    self.saveInfo(writer)
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/defcon/objects/font.py", line 944, in saveInfo
    writer.writeInfo(self.info, validate=self.info.ufoLibWriteValidate)
                     ^^^^^^^^^
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/defcon/objects/font.py", line 425, in _get_info
    reader.readInfo(self._info, validate=self._info.ufoLibReadValidate)
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/fontTools/ufoLib/__init__.py", line 544, in readInfo
    infoDict = self._readInfo(validate)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/fontTools/ufoLib/__init__.py", line 527, in _readInfo
    data = self._getPlist(FONTINFO_FILENAME, {})
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vitor/.local/pipx/venvs/afdko/lib/python3.11/site-packages/fontTools/ufoLib/__init__.py", line 155, in _getPlist
    raise UFOLibError(f"'{fileName}' could not be read on {self.fs}: {e}")
fontTools.ufoLib.errors.UFOLibError: 'fontinfo.plist' could not be read on <osfs '/tmp/tmpm0gs8peg/font.ufo'>: xmlParseEntityRef: no name, line 16, column 62 (fontinfo.plist, line 16)

Here is /tmp/tmpm0gs8peg/font.ufo/fontinfo.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>postscriptFontName</key>
        <string>NimbusSans-Regular</string>
        <key>styleName</key>
        <string>Regular</string>
        <key>familyName</key>
        <string>Nimbus Sans</string>
        <key>versionMajor</key>
        <integer>1</integer>
        <key>versionMinor</key>
        <integer>0</integer>
        <key>copyright</key>
        <string>Copyright (URW)++,Copyright 2014 by (URW)++ Design & Development</string>
        <key>trademark</key>
        <string>(URW)++,Copyright 2014 by (URW)++ Design & Development</string>
        <key>unitsPerEm</key>
        <integer>1000</integer>
        <key>postscriptFullName</key>
        <string>Nimbus Sans</string>
        <key>postscriptWeightName</key>
        <string>Regular</string>
        <key>postscriptUnderlinePosition</key>
        <integer>-151</integer>
        <key>postscriptBlueValues</key>
        <array>
                <integer>-23</integer>
                <integer>0</integer>
                <integer>524</integer>
                <integer>539</integer>
                <integer>729</integer>
                <integer>741</integer>
                <integer>709</integer>
                <integer>724</integer>
        </array>
        <key>postscriptStemSnapH</key>
        <array>
                <integer>43</integer>
                <integer>46</integer>
                <integer>53</integer>
                <integer>57</integer>
                <integer>61</integer>
                <integer>68</integer>
                <integer>73</integer>
                <integer>78</integer>
                <integer>81</integer>
                <integer>91</integer>
                <integer>101</integer>
                <integer>104</integer>
        </array>
        <key>postscriptStdHW</key>
        <array>
                <integer>81</integer>
        </array>
        <key>postscriptStemSnapV</key>
        <array>
                <integer>41</integer>
                <integer>53</integer>
                <integer>59</integer>
                <integer>63</integer>
                <integer>68</integer>
                <integer>76</integer>
                <integer>79</integer>
                <integer>83</integer>
                <integer>88</integer>
                <integer>93</integer>
                <integer>103</integer>
                <integer>168</integer>
        </array>
        <key>postscriptStdVW</key>
        <array>
                <integer>93</integer>
        </array>
        <key>postscriptBlueScale</key>
        <real>0.039625</real>
        <key>postscriptBlueShift</key>
        <integer>7</integer>
        <key>postscriptBlueFuzz</key>
        <integer>1</integer>
        <key>ExpansionFactor</key>
        <real>0.06</real>
</dict>
</plist>
frankrolf commented 1 month ago

Reproduced the error. The problem is the UFO conversion in tx.

In the OTF’s name table, nameID 0 is

    <namerecord nameID="0" platformID="1" platEncID="0" langID="0x0" unicode="True">
      (URW)++,Copyright 2014 by (URW)++ Design &amp; Development
    </namerecord>

tx converts that to

    <key>copyright</key>
    <string>Copyright (URW)++,Copyright 2014 by (URW)++ Design & Development</string>
    <key>trademark</key>
    <string>(URW)++,Copyright 2014 by (URW)++ Design & Development</string>

which is invalid XML 🤦‍♂️ – that ampersand needs to stay &amp;

To reproduce: tx -ufo NimbusSans-Regular.otf open NimbusSans-Regular.otf/fontinfo.plist

vitorsr commented 1 month ago

Thanks, @frankrolf.

Yes, reserved characters have to be replaced by their respective entity references.

This also affects Bigelow & Holmes fonts:

        <key>copyright</key>
        <string>Copyright (C) 1993 Bigelow & Holmes Inc. All rights reserved.</string>
        <key>trademark</key>
        <string>Lucida is a registered trademark of Bigelow & Holmes Inc.</string>
punchcutter commented 4 weeks ago

I made a local fix that handles these, but it's not a real solution right now because it doesn't cover all possible situations. Maybe we can throw it in anyway and go from there.