Git Product home page Git Product logo

fontmake's Introduction

GitHub Actions Build Status Python Versions PyPI Version

fontmake

fontmake compiles fonts from various sources (.glyphs, .ufo, designspace) into binaries (.otf, .ttf). You can use it to create static instances and variable fonts.

Installation

Fontmake requires Python 3.8 or later.

Releases are available on PyPI and can be installed with pip.

pip3 install fontmake

Use the -U, --upgrade option to update fontmake and its dependencies to the newest available release:

pip3 install -U fontmake

Basic Usage

After installation, you will be able to use the fontmake executable.

For example, to compile a variable font from a Glyphs source file, use:

fontmake MyFont.glyphs -o variable

The most important command line arguments to the fontmake executable are the required input, specified either as positional argument or using one of -g/-u/-m flags, and the optional -o flag, which chooses the output file format.

Source file format options

There are two ways to specify the source file or files:

One can either use the following, mutually exclusive, flags:

  • -g filename.glyphs: Converts a Glyphs source file to binary.
  • -u filename.ufo ...: Converts one or more UFO(Z) files to binary.
  • -m filename.designspace: Converts a Designspace file to binary. (The -m is for mutatormath, an old Python library for handling designspaces.)

Alternatively, one can specify the input(s) as positional arguments without the flag, letting fontmake infer the source format from the file extension: e.g. fontmake MyFont.designspace, etc.

Note: if the positional arguments are preceded by an option that takes one or more arguments, you need to use the special -- separator to mark all following arguments as positional (non-options), otherwise the parser gets confused. E.g., the -i option takes zero or one arguments (see futher below for details); without --, argparse thinks you didn't provide any inputs:

fontmake -i -- MyFont.designspace

Exactly one type of input can/must be specified, using either approaches.

Output file format options

You may provide one or more output file formats after the -o option. For example, -o otf ttf creates OTF and TTF binary font files for each master in your input file.

The following output file formats are available:

  • otf: Per-master OTF (CFF-outline) binaries. Placed in the master_otf/ directory.
  • ttf: Per-master TTF (TrueType-outline) binaries. Placed in the master_ttf/ directory.
  • otf-cff2: Per-master OTF binaries with CFF2 outlines. Placed in the master_otf/ directory.
  • variable: A TrueType variable font. Placed in the variable_ttf/ directory.
  • variable-cff2: A variable font with CFF2 outlines. Placed in the variable_otf/ directory.

The following output file formats are also available, but are generally used internally by fontmake as an intermediate step to one of the above outputs:

  • otf-interpolatable: OTF binaries suitable for merging into a variable font. Placed in the master_otf_interpolatable/ directory. (These differ from otf in that the outlines are unoptimized.)
  • ttf-interpolatable: TTF binaries suitable for merging into a variable font. Placed in the master_ttf_interpolatable/ directory. (The outlines are converted to quadratic curves in an interpolation-compatible way.)
  • ufo: Glyphs sources can be converted to UFO, or to UFO zip (.ufoz) format with the flag --save-ufo-as-zip. Placed in the master_ufo/ directory.

If no format option is specified, the default is -o otf ttf.

Other important command line options

  • -i (Interpolate instances): Having per-master binaries is not always what you expect; if you have defined instances ("exports") in your Glyphs file, they will not be generated by default. To generate them, pass the -i flag, which interpolates static instances, and places them in the instance_ttf/ or instance_otf/ directory as appropriate.

  • --output-dir <some_directory>: Places all output in the given directory, instead of the per-format directories mentioned above.

  • --output-path <filename>: This is only valid if the output is a single binary file, and writes the output to the given filename.

  • -f (Flatten components): Ensures that any glyphs which contain components which themselves contain components are decomposed to a single level. This is recommended as certain rendering environments do not correctly handle nested components - see this link for more details.

Advanced Usage

See USAGE.md.

Troubleshooting

See TROUBLESHOOTING.md.

Developers

Developers can get the latest version of fontmake by cloning the git repository:

git clone https://github.com/googlefonts/fontmake
cd fontmake
pip install .

Developers who want to quickly test changes to the source code without re-installing can use the "--editable" option when installing from a local source checkout:

pip install -e .

It is recommended to install fontmake inside a virtual environment to prevent conflicts between its dependencies and other modules installed globally.

You could also use the pipx tool to automate the installation/upgrade of python apps like fontmake in isolated environments.

Releasing a New Version

  1. Commit and push your final changes for the new version.
  2. Create an annotated Git tag of the version number, with a prepended "v", like so: git tag -a v3.1.1
  3. Write the release notes into the tag message. They will show up as release notes on the release page in GitHub.
  4. Push the tag like so: git push origin v3.1.1, where origin is the name of the usual remote you want to push the version to.

fontmake's People

Contributors

adrientetar avatar anthrotype avatar behdad avatar belluzj avatar brawer avatar chibuezeonejeme avatar chrissimpkins avatar davelab6 avatar fabiangreffrath avatar felipesanches avatar jamesgk avatar justvanrossum avatar khaledhosny avatar m4rc1e avatar madig avatar marekjez86 avatar mbrukman avatar moyogo avatar nightfurysl2001 avatar pyup-bot avatar simoncozens avatar thomasrettig avatar twardoch avatar verbosus avatar yanone avatar zjusbo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fontmake's Issues

Cannot make Breite-Light

fontmake crashes when building Breite-Light from UFO:

$ git clone https://github.com/metapolator/Breite.git
$ fontmake -u Breite/Breite\ Light/Light.ufo
Traceback (most recent call last):
  File "/usr/local/bin/fontmake", line 9, in <module>
    load_entry_point('fontmake', 'console_scripts', 'fontmake')()
  File "/home/sascha/src/fontmake/Lib/fontmake/__main__.py", line 47, in main
    project.run_from_ufos(ufo_paths, **args)
  File "/home/sascha/src/fontmake/Lib/fontmake/font_project.py", line 158, in run_from_ufos
    print '>> Removing overlaps for ' + ufo.info.postscriptFullName
TypeError: cannot concatenate 'str' and 'NoneType' objects

First I thought itโ€™s the whitespace in the file names, but renaming directories did not help. Is the font borked? Or an upstream component?

ValueError: time data '2014-09-19 15:51:55 +0100' does not match format '%Y-%m-%d %H:%M:%S +0000' while building Glyphs_Sapperlot.glyphs

I built the pipeline in the morning (PDT) on 2016-02-12.
I found Glyphs_Sapperlot.glyphs in https://github.com/DrTypo/sapperlot and decided to try using it as an input to the pipeline (my mac glyphs.app can export unhinted OTF files from Glyphs_Sapperlot.glyphs).

We get the following error while running the pipeline:

==== building src/Glyphs_Sapperlot.glyphs ====

Checking Glyphs source for illegal glyph names
Interpolating master UFOs from Glyphs source

Parsing .glyphs file
Casting parsed values
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/local/lib/python2.7/dist-packages/fontmake/main.py", line 51, in
main()
File "/usr/local/lib/python2.7/dist-packages/fontmake/main.py", line 39, in main
project.run_from_glyphs(glyphs_path, **args)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 136, in run_from_glyphs
ufos = self.build_instances(glyphs_path, is_italic)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 75, in build_instances
return build_instances(glyphs_path, master_dir, instance_dir, is_italic)
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 100, in build_instances
filename, italic, include_instances=True)
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 57, in load_to_ufos
data = load(ifile)
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 38, in load
return loads(fp.read(), dict_type=dict_type)
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 49, in loads
cast_data(data)
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/casting.py", line 49, in cast_data
cast_data(cur_data, dict(cur_type))
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/casting.py", line 51, in cast_data
data[key] = cur_type(data[key])
File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/casting.py", line 249, in glyphs_datetime
return datetime.strptime(string, '%Y-%m-%d %H:%M:%S +0000')
File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
(data_string, format))
ValueError: time data '2014-09-19 15:51:55 +0100' does not match format '%Y-%m-%d %H:%M:%S +0000'

Name the designspace file after the family

Right now when I run fontmake multiple times, on different font sources, the master_ufo/mm.designspace is rewritten. Can you please add the base input name to it? Eg. "NotoSerif-RomanMM.designspace".

Thanks.

AutomatedTestReport: Glyph has intersecting components

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Of the errors listed by our test tool I mention:
Glyph has intersecting components. 407 more like this [marekjez86: this message occurs 408 times]'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

feaTools.parser.FeaToolsParserSyntaxError: u'lookupflag format B is not supported for any value other than 0'

I got this error while processing, using pipeline delivery, of Noto Serif Hebrew font.

Is this a fontmake issue or a problem with the delivered files or a compatibility issue?

< >>> Parsing .glyphs file
< >>> Casting parsed values
< >>> Loading to RFonts
< >>> Writing masters
< >>> Building instances
< >> Removing overlaps for NotoSerifHebrew-Thin
< >> Removing overlaps for NotoSerifHebrew-Light
< >> Removing overlaps for NotoSerifHebrew-Regular
< >> Removing overlaps for NotoSerifHebrew-SemiBold
< >> Removing overlaps for NotoSerifHebrew-Bold
< >> Removing overlaps for NotoSerifHebrew-ExtraBold
< >> Removing overlaps for NotoSerifHebrew-Black
< >> Removing overlaps for NotoSerifHebrewCondensed-Thin
< >> Removing overlaps for NotoSerifHebrewCondensed-Light
< >> Removing overlaps for NotoSerifHebrewCondensed-Regular
< >> Removing overlaps for NotoSerifHebrewCondensed-SemiBold
< >> Removing overlaps for NotoSerifHebrewCondensed-Bold
< >> Removing overlaps for NotoSerifHebrewCondensed-ExtraBold
< >> Removing overlaps for NotoSerifHebrewCondensed-Black
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-Thin
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-Light
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-Regular
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-SemiBold
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-Bold
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-ExtraBold
< >> Removing overlaps for NotoSerifHebrewSemiCondensed-Black
< >> Saving OTF for NotoSerifHebrew-Thin
< Traceback (most recent call last):
< File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
< "main", fname, loader, pkg_name)
< File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
< exec code in run_globals
< File "build/bdist.linux-x86_64/egg/fontmake/main.py", line 51, in
< File "build/bdist.linux-x86_64/egg/fontmake/main.py", line 39, in main
< File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 184, in run_from_glyphs
< File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 212, in run_from_ufos
< File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 120, in save_otf
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/init.py", line 29, in compileOTF
< featureCompilerClass, mtiFeaFiles, kernWriter, markWriter)
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/init.py", line 18, in _compile
< featureCompiler.compile()
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/makeotfParts.py", line 37, in compile
< self.setupFile_features()
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/makeotfParts.py", line 73, in setupFile_features
< autoFeatures["kern"] = self.writeFeatures_kern()
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/makeotfParts.py", line 97, in writeFeatures_kern
< return writer.write()
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/kernFeatureWriter.py", line 61, in write
< self._collectFeaClasses()
< File "/usr/local/lib/python2.7/dist-packages/ufo2ft/kernFeatureWriter.py", line 99, in _collectFeaClasses
< parser.parseFeatures(self, self.featxt)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 657, in parseFeatures
< _parseUnknown(writer, text)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 309, in _parseUnknown
< _parseFeature(writer, featureTag, featureText)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 438, in _parseFeature
< parsed = _parseUnknown(featureWriter, feature)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 327, in _parseUnknown
< _parseLookup(writer, lookupName, lookupText)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 442, in _parseLookup
< parsed = _parseUnknown(lookupWriter, lookup)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 339, in _parseUnknown
< text = _executeSimpleSlice(precedingMark, text, subType1And4RE, writer)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 432, in _executeSimpleSlice
< _parseUnknown(writer, precedingText)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 407, in _parseUnknown
< _parseLookupFlag(writer, lookupflagValues)
< File "/usr/local/lib/python2.7/dist-packages/feaTools/parser.py", line 621, in _parseLookupFlag
< raise FeaToolsParserSyntaxError("lookupflag format B is not supported for any value other than 0")
< feaTools.parser.FeaToolsParserSyntaxError: u'lookupflag format B is not supported for any value other than 0'

AutomatedTestReport: The usMaxContext should be 3, but is 0

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Of the errors listed by our test tool I mention:
The usMaxContext should be 3, but is 0'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

GSUB and GPOS are different from generated by other tool. GPOS decompile fails.

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Looking at the regular Ethiopic, I can confirm that the Glyphs version [...] matches the font I found that has been used for Monotypeโ€™s QA. The only difference seems to be that we tested without hints.

The โ€œpipelineโ€ font is different. [...]

[...] There are size differences of GSUB and GPOS too. The GSUB seems to be OK. The GPOS of the pipeline is significant larger and the tools that I have to decompile GPOS tables both fail to do so.'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

NotoSansArabic-Black: sample differences in generated OTF

The values below were obtained by running ttx on the OTF files and doing the diff.
< represents what's in the Glyphs generated OTF
> represents what's in the pipeline generated OTF

It's possible that all the information below is irrelevant and not important. I just want to make the differences visible.

1885,1887c1885,1887
<     <ulUnicodeRange1 value="10000000 00000000 00100000 00000011"/>
<     <ulUnicodeRange2 value="10000000 00000000 00100000 00000000"/>
<     <ulUnicodeRange3 value="00000000 00000000 00000000 00001000"/>

---
>     <ulUnicodeRange1 value="00000000 00000000 00000000 00000000"/>
>     <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
>     <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
1890c1890
<     <fsSelection value="00000000 11000000"/>

---
>     <fsSelection value="00000000 01000000"/>
1898c1898
<     <ulCodePageRange1 value="00000000 00000000 00000000 01000000"/>

---
>     <ulCodePageRange1 value="00000000 00000000 00000000 00000000"/>

Glyphs produced OTF
NotoSansArabic-Black.otf.zip

Pipeline produced OTF
NotoSansArabic-Black.otf.zip

Crash building Arima_Madurai_03.glyphs

mkdir -p ~/src/github.com/NDSICOVER/;
cd !$;
git clone https://github.com:NDSICOVER/Arima-Font;
cd Arima-Font/sources;
fontmake -g ArimaMadurai.glyphs;
>> Checking Glyphs source for illegal glyph names
Found 114 glyph names containing hyphens: a-tamil, aa-tamil, aaMatra-tamil, ai-tamil, aiMatra-tamil, ...
Replacing all hyphens with underscores.
>> Loading master UFOs from Glyphs source
>>> Parsing .glyphs file
>>> Casting parsed values
>>> Loading to RFonts
>>> Writing master_ufo/ArimaMadurai-Light.ufo
Traceback (most recent call last):
  File "/usr/local/bin/fontmake", line 9, in <module>
    load_entry_point('fontmake', 'console_scripts', 'fontmake')()
  File "/Users/dcrossland/src/github.com/googlei18n/fontmake/Lib/fontmake/__main__.py", line 39, in main
    project.run_from_glyphs(glyphs_path, **args)
  File "/Users/dcrossland/src/github.com/googlei18n/fontmake/Lib/fontmake/font_project.py", line 139, in run_from_glyphs
    ufos = self.build_masters(glyphs_path, is_italic)
  File "/Users/dcrossland/src/github.com/googlei18n/fontmake/Lib/fontmake/font_project.py", line 68, in build_masters
    return build_masters(glyphs_path, master_dir, is_italic)
  File "/usr/local/lib/python2.7/site-packages/glyphs2ufo/glyphslib.py", line 88, in build_masters
    write(ufo, master_dir)
  File "/usr/local/lib/python2.7/site-packages/glyphs2ufo/glyphslib.py", line 79, in write
    ufo.save(out_path)
  File "/usr/local/lib/python2.7/site-packages/robofab/objects/objectsRF.py", line 468, in save
    glyph._saveToGlyphSet(glyphSet, glyphName=glyphName, force=saveAs)
  File "/usr/local/lib/python2.7/site-packages/robofab/objects/objectsBase.py", line 1475, in _saveToGlyphSet
    glyphSet.writeGlyph(glyphName, self, self.drawPoints)
  File "/usr/local/lib/python2.7/site-packages/robofab/glifLib.py", line 214, in writeGlyph
    data = writeGlyphToString(glyphName, glyphObject, drawPointsFunc)
  File "/usr/local/lib/python2.7/site-packages/robofab/glifLib.py", line 411, in writeGlyphToString
    plistWriter.writeValue(lib)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 255, in writeValue
    self.writeDict(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 284, in writeDict
    self.writeValue(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 261, in writeValue
    self.writeArray(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 290, in writeArray
    self.writeValue(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 255, in writeValue
    self.writeDict(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 284, in writeDict
    self.writeValue(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 242, in writeValue
    self.simpleElement("string", value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 175, in simpleElement
    value = _escapeAndEncode(value)
  File "/usr/local/lib/python2.7/site-packages/robofab/plistlib.py", line 225, in _escapeAndEncode
    return text.encode("utf-8")             # encode as UTF-8
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)

Cannot pip3 install requirements

Cannot install fontmake requirements with pip3. In python3, print statement need parentheses around their arguments.

$ sudo pip3 install -r requirements.txt
Downloading/unpacking git+https://github.com/behdad/fonttools.git (from -r requirements.txt (line 2))
  Cloning https://github.com/behdad/fonttools.git to /tmp/pip-o_bou4fc-build
  Running setup.py (path:/tmp/pip-o_bou4fc-build/setup.py) egg_info for package from git+https://github.com/behdad/fonttools.git

    warning: no files found matching 'LICENSE.txt'
    warning: no files found matching 'Doc/ChangeLog'
    warning: no files found matching 'Doc/*.txt'
    warning: no files found matching 'Doc/*.html'
    warning: no files found matching 'Windows/mcmillan.bat'
    warning: no files found matching 'Windows/ttx.ico'
    warning: no files found matching 'Windows/README.TXT'
    warning: no files found matching 'Windows/fonttools-win-setup.iss'
    warning: no files found matching 'Windows/fonttools-win-setup.txt'
Downloading/unpacking git+https://github.com/typesupply/feaTools.git (from -r requirements.txt (line 3))
  Cloning https://github.com/typesupply/feaTools.git to /tmp/pip-1xuyjbd4-build
  Running setup.py (path:/tmp/pip-1xuyjbd4-build/setup.py) egg_info for package from git+https://github.com/typesupply/feaTools.git

Downloading/unpacking git+https://github.com/googlei18n/cu2qu.git (from -r requirements.txt (line 9))
  Cloning https://github.com/googlei18n/cu2qu.git to /tmp/pip-e58ks7m8-build
  Running setup.py (path:/tmp/pip-e58ks7m8-build/setup.py) egg_info for package from git+https://github.com/googlei18n/cu2qu.git

Downloading/unpacking git+https://github.com/googlei18n/glyphs2ufo.git (from -r requirements.txt (line 10))
  Cloning https://github.com/googlei18n/glyphs2ufo.git to /tmp/pip-6zb84hi_-build
  Running setup.py (path:/tmp/pip-6zb84hi_-build/setup.py) egg_info for package from git+https://github.com/googlei18n/glyphs2ufo.git

Downloading/unpacking git+https://github.com/googlei18n/ufo2ft.git (from -r requirements.txt (line 11))
  Cloning https://github.com/googlei18n/ufo2ft.git to /tmp/pip-ltyotyv2-build
  Running setup.py (path:/tmp/pip-ltyotyv2-build/setup.py) egg_info for package from git+https://github.com/googlei18n/ufo2ft.git
    *** Warning: ufo2ft requires FontTools, see:
        fonttools.sf.net
    *** Warning: ufo2ft requires RoboFab, see:
        robofab.com

Downloading/unpacking git+https://github.com/robofab-developers/robofab.git (from -r requirements.txt (line 12))
  Cloning https://github.com/robofab-developers/robofab.git to /tmp/pip-_zdncxqh-build
  Running setup.py (path:/tmp/pip-_zdncxqh-build/setup.py) egg_info for package from git+https://github.com/robofab-developers/robofab.git
    Traceback (most recent call last):
      File "<string>", line 17, in <module>
      File "/tmp/pip-_zdncxqh-build/setup.py", line 15
        print "*** Warning: FontTools needs the numpy library for some operations, see:"
                                                                                       ^
    SyntaxError: Missing parentheses in call to 'print'
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 17, in <module>

  File "/tmp/pip-_zdncxqh-build/setup.py", line 15

    print "*** Warning: FontTools needs the numpy library for some operations, see:"

                                                                                   ^

SyntaxError: Missing parentheses in call to 'print'

----------------------------------------
Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip-_zdncxqh-build
Storing debug log for failure in /root/.pip/pip.log

fontmake/Lib/fontmake/font_project.py : after we started checking for correct names we cannot process directories

The font sources can have one of the two formats:

  • a glyphs file; for example:
    NotoSansGeorgian-MM.glyphs, testNotoSansOlChiki-Regular.glyphs, mzjNotoSansCham-Bold.glyphs,NotoSansHebrew-MM.glyphs ...
  • a directory which contains a glyphs file and all other input files; for example

marekj@yol-worjdp:~/src/noto-source$ ls src/NotoSansDevanagari

Noto Sans Devanagari Black Condensed GPOS.txt Noto Sans Devanagari Regular GPOS.txt Noto Sans Devanagari UI Bold GSUB w122-171.txt
Noto Sans Devanagari Black GPOS.txt Noto Sans Devanagari Regular GSUB w59-121.txt NotoSansDevanagariUI.cmap.txt
Noto Sans Devanagari Black GSUB w172-190.txt Noto Sans Devanagari Thin Condensed GPOS.txt Noto Sans Devanagari UI Condensed GPOS.txt
Noto Sans Devanagari Bold Condensed GPOS.txt Noto Sans Devanagari Thin GPOS.txt Noto Sans Devanagari UI GDEF.txt
Noto Sans Devanagari Bold GPOS.txt Noto Sans Devanagari Thin GSUB w26-58.txt NotoSansDevanagariUI.plist
Noto Sans Devanagari Bold GSUB w122-171.txt Noto Sans Devanagari UI Black Condensed GPOS.txt Noto Sans Devanagari UI Regular GPOS.txt
Noto Sans Devanagari Condensed GPOS.txt Noto Sans Devanagari UI Black GPOS.txt Noto Sans Devanagari UI regular GSUB w59-121.txt
Noto Sans Devanagari GDEF.txt Noto Sans Devanagari UI Black GSUB w172-190.txt Noto Sans Devanagari UI Thin Condensed GPOS.txt
NotoSansDevanagari.glyphs Noto Sans Devanagari UI Bold Condensed GPOS.txt Noto Sans Devanagari UI Thin GPOS.txt
NotoSansDevanagari.plist Noto Sans Devanagari UI Bold GPOS.txt Noto Sans Devanagari UI Thin GSUB w26-58.txt

Ever since we introduced checking for the proper names we "lost" the ability to process glyphs that required additional (GSUB, GPOS, GDEF) data.

I finally managed to figure out how to force make to print more information, hence the traceback below:

Making src/NotoSansDevanagari' due to always-make flag. Must remake targetsrc/NotoSansDevanagari'.
bash build.sh build_one src/NotoSansDevanagari
Putting child 0x02020b30 (src/NotoSansDevanagari) PID 28657 on the chain.
Live child 0x02020b30 (src/NotoSansDevanagari) PID 28657

Checking Glyphs source for illegal glyph names
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/local/lib/python2.7/dist-packages/fontmake/main.py", line 51, in
main()
File "/usr/local/lib/python2.7/dist-packages/fontmake/main.py", line 39, in main
project.run_from_glyphs(glyphs_path, *args)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 129, in run_from_glyphs
glyphs_source = self.preprocess(glyphs_path)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 46, in preprocess
with open(glyphs_path) as fp:
IOError: [Errno 21] Is a directory: 'src/NotoSansDevanagari'
Reaping losing child 0x02020b30 PID 28657
make: *
* [src/NotoSansDevanagari] Error 1
Removing child 0x02020b30 PID 28657 from chain.

defcon.errors.DefconError: The kerning data is not valid.

Newest pipeline as of 2016-03-09 afternoon PST produces a new error:

============ src/NotoSansEthiopic-MM.glyphs.201603091451.txt ==============
    project.run_from_glyphs(glyphs_path, **args)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 178, in run_from_glyphs
    ufos = self.build_instances(glyphs_path, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 77, in build_instances
    return build_instances(glyphs_path, master_dir, instance_dir, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 107, in build_instances
    instance_data)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/interpolation.py", line 59, in interpolate
    raise e
defcon.errors.DefconError: The kerning data is not valid.

======================================

=========== src/NotoSerif-RomanMM.glyphs.201603091451.txt ==============
    project.run_from_glyphs(glyphs_path, **args)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 178, in run_from_glyphs
    ufos = self.build_instances(glyphs_path, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 77, in build_instances
    return build_instances(glyphs_path, master_dir, instance_dir, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 107, in build_instances
    instance_data)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/interpolation.py", line 59, in interpolate
    raise e
defcon.errors.DefconError: The kerning data is not valid.
======================================
============ src/NotoSerif-ItalicMM.glyphs.201603091451.txt ==============
    project.run_from_glyphs(glyphs_path, **args)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 178, in run_from_glyphs
    ufos = self.build_instances(glyphs_path, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 77, in build_instances
    return build_instances(glyphs_path, master_dir, instance_dir, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 107, in build_instances
    instance_data)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/interpolation.py", line 59, in interpolate
    raise e
defcon.errors.DefconError: The kerning data is not valid.

======================================

OffendingGlyphs.zip

possibly incorrect 'Duplicate kerning rules found for glyph pair "hhaa_ethiopic, ggwa_ethiopic" (-63 vs -63)'

pipeline as of 2016-03-11 processing NotoSansEthiopic-MM.glyphs.zip
produces many warnings

produces the following warnings. My guess that -63 vs -63 represent real numbers rounded/truncated to -63 so maybe these are real

WARNING: Duplicate kerning rules found for glyph pair "hhaa_ethiopic, ggwaa_ethiopic" (-63 vs -63), removing from rule "hhaa_ethiopic, public.kern2.ge_ethiopic"
WARNING: Duplicate kerning rules found for glyph pair "hhaa_ethiopic, ggwa_ethiopic" (-63 vs -63), removing from rule "hhaa_ethiopic, public.kern2.ge_ethiopic"
WARNING: Duplicate kerning rules found for glyph pair "hhaa_ethiopic, ggwi_ethiopic" (-63 vs -63), removing from rule "hhaa_ethiopic, public.kern2.ge_ethiopic"
WARNING: Duplicate kerning rules found for glyph pair "hhaa_ethiopic, ggwe_ethiopic" (-63 vs -63), removing from rule "hhaa_ethiopic, public.kern2.ge_ethiopic"

NotoSansArabic-Black: for NotoSansArabic-Black we produce <Weight value="Bold"/>

I do not know how important this info is in the file but for NotoSansArabic-Black we produce and Glyphs app creates which appears to be more correct (but maybe both are OK, I do not know).

4541c4298,4300
<       <Weight value="Black"/>

---
>       <FontName value="NotoSansArabic-Black"/>
>       <FamilyName value="Noto Sans Arabic"/>
>       <Weight value="Bold"/>

Glyphs produced OTF
NotoSansArabic-Black.otf.zip

Pipeline produced OTF
NotoSansArabic-Black.otf.zip

AutomatedTestReport: hmtxThe left sidebearing 34 does not match the glyph's xMin 35 (glyph 418)

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Of the errors listed by our test tool I mention:
hmtxThe left sidebearing 34 does not match the glyph's xMin 35 (glyph 418)
13 more like this'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

ontTools.feaLib.error.FeatureLibError: /tmp/tmp6Uhht3:5:24: Unknown glyph class @MMK_R_period.right

Newest pipeline as of 2016-03-09 afternoon PST produces a new error:

============ src/NotoSansDisplayItalic-MM.glyphs.201603091451.txt ==============
self.parse_block_(block, vertical)
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 867, in parse_block_
self.parse_position_(enumerated=False, vertical=vertical))
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 448, in parse_position_
self.parse_glyph_pattern_(vertical)
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 246, in parse_glyph_pattern_
gc = self.parse_glyphclass_(accept_glyphname=True)
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 181, in parse_glyphclass_
self.cur_token_location_)
fontTools.feaLib.error.FeatureLibError: /tmp/tmp6Uhht3:5:24: Unknown glyph class @MMK_R_period.right

============ src/NotoSansUIItalic-MM.glyphs.201603091451.txt ==============
self.parse_block_(block, vertical)
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 867, in parse_block_
self.parse_position_(enumerated=False, vertical=vertical))
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 448, in parse_position_
self.parse_glyph_pattern_(vertical)
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 246, in parse_glyph_pattern_
gc = self.parse_glyphclass_(accept_glyphname=True)
File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/parser.py", line 181, in parse_glyphclass_
self.cur_token_location_)
fontTools.feaLib.error.FeatureLibError: /tmp/tmpgMhHRH:5:24: Unknown glyph class @MMK_R_period.right

here are the glyph offending files

NotoSans-star-Italic.zip

AutomatedTestReport: CFFContours do not have correct winding direction

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Of the errors listed by our test tool I mention:
CFFContours do not have correct winding direction. 32 more like this [marekjez86: repeats 32 times]'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

Add yml-based config files

It's painful to pass many arguments on the command-line. We should have a way to pass a yml file, similar to fontbakery:

https://github.com/googlefonts/fontbakery

We probably should have sections for sources (.glyphs, UFO, .fea, mti, ...), outputs to generate, and for each output (or globally), options like "remove overlap", "optimize", "fix outline directions", "autohint", etc.

In some distant future, this will become pluggable plugins / modules, and the optimizations in pyftsubset, as well as fixes that @DCrossland needs ala fontbakery, they all become part of fontmake configurable pipeline.

In some even more distant future, we'll configure pipelines using a data-flow graph...

Missing typographic names

Is it intentional that only one of the emitted instances has โ€œtypographicโ€ names?

To reproduce:

$ git clone https://github.com/Microsoft/Selawik.git
$ fontmake -g Selawik/Source\ files/Glyphs/selawik.glyphs 
$ for STYLE in Light Regular Bold ; do ttx -t name -o - master_ttf/Selawik-$STYLE.ttf ; done

As expected, Selawik-Light has typographic family and style names:

    <namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
      Selawik
    </namerecord>
    <namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
      Light
    </namerecord>

However, the Regular and Bold fonts currently do not have any typographic names.

AutomatedTestReport: Postscript name not present for both Mac and Windows

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Of the errors listed by our test tool I mention:
Postscript name not present for both Mac and Windows'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

CFF table is too large because pipeline ignores much of the data in the Glyphs file

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Looking at the regular Ethiopic, I can confirm that the Glyphs version [...] matches the font I found that has been used for Monotypeโ€™s QA. The only difference seems to be that we tested without hints.

The โ€œpipelineโ€ font is different. [...]

The most profound difference is the CFF table, which for the pipeline font
is more than twice as large. It contains more glyphs, 714 versus 561, but
that cannot explain the size difference alone. The explanation for the
different glyph count is that the Pipeline ignores much of the data in the
Glyphs file. It contains Ascii characters and component glyphs that have
been set not to export. The Pipeline exports them anyway: in alphabetical
order of glyph name with NULL between N and O. Glyphs exports the intended
glyph set, using production names in uniXXXX format, in what appears to be
based on Unicode order.'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

AutomatedTestReport: GPOSThe Class1Count does not match the values in ClassDef1

I copied the text below from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

'Of the errors listed by our test tool I mention:
GPOSThe Class1Count does not match the values in ClassDef1. (lookuplist
lookup 1 lookup subtable 29 pair pairclasses)
The following glyphs explicitly mapped to class zero in the second
ClassDefโ€ฆ.
(lookuplist lookup 1 lookup subtable 5 pair pairclasses) Vxxxx'

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

Dot of ยฟ in Selawik-Regular is shifted

When building Microsoftโ€™s Selawik font from the glyphs source, fontmake moves the dot of the ยฟ character. To reproduce:

$ wget https://raw.githubusercontent.com/Microsoft/Selawik/master/Source%20files/Glyphs/selawik.glyphs
$ fontmake -g selawik.glyphs
$ hb-view master_otf/Selawik-Regular.otf "ยฟHuh?"

selawik_bug

Or open the font in Glyphs.app:
questiondown

The original glyphs source places the dot at the expected location. So this looks like a problem in the fontmake pipeline, probably related to composite glyphs.

"ValueError: need more than 3 values to unpack" while processing Glyphs_Sapperlot.glyphs

I built the pipeline in the evening (PDT) on 2016-02-16.
I used Glyphs_Sapperlot.glyphs from https://github.com/DrTypo/sapperlot and decided to try using it as an input to the pipeline (my mac glyphs.app can export unhinted OTF files from Glyphs_Sapperlot.glyphs).

Note that while #14 appears to be fixed we get the following error while running the pipeline:

==== building src/Glyphs_Sapperlot.glyphs ====
....
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 144, in run_from_glyphs
< self.run_from_ufos(ufos, is_instance=interpolate, **kwargs)
< File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 159, in run_from_ufos
< self.remove_overlaps(ufo)
< File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 85, in remove_overlaps
< manager.union(contours, glyph.getPointPen())
< File "/usr/local/lib/python2.7/dist-packages/booleanOperations/booleanOperationManager.py", line 56, in union
< return self._performOperation("union", contours, [], outPen)
< File "/usr/local/lib/python2.7/dist-packages/booleanOperations/booleanOperationManager.py", line 20, in _performOperation
< subjectInputContours = [InputContour(contour) for contour in subjectContours if contour and len(contour) > 1]
< File "/usr/local/lib/python2.7/dist-packages/booleanOperations/flatten.py", line 71, in init
< self.segments = _convertPointsToSegments(points)
< File "/usr/local/lib/python2.7/dist-packages/booleanOperations/flatten.py", line 436, in _convertPointsToSegments
< willBeReversed=willBeReversed
< File "/usr/local/lib/python2.7/dist-packages/booleanOperations/flatten.py", line 194, in init
< self.flat = _flattenSegment(pointsToFlatten)
< File "/usr/local/lib/python2.7/dist-packages/booleanOperations/flatten.py", line 1157, in _flattenSegment
< onCurve1, offCurve1, offCurve2, onCurve2 = segment
< ValueError: need more than 3 values to unpack

pipeline regression: allmost of all my test runs produce stack trace AttributeError: 'str' object has no attribute 'getReverseGlyphMap'

The last time I updated and ran pipeline was about 2 days ago. At that time I had no problems like this one.

Here's the input file that causes the problem below
mzjArimo-Regular.glyphs.zip

I can submit many more input files.

This is the stack trace:

==== building src/mzjArimo-Regular.glyphs ====
/usr/local/lib/python2.7/dist-packages/mutatorMath/ufo/instance.py:199: UserWarning: MathInfo object missing round() method.
  warnings.warn("MathInfo object missing round() method.")
>> Checking Glyphs source for illegal glyph names
>> Interpolating master UFOs from Glyphs source
>>> Parsing .glyphs file
>>> Casting parsed values
>>> Loading to RFonts
>>> Writing masters
>>> Building instances
>> Removing overlaps for Arimo-Regular
>> Saving OTF for Arimo-Regular
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "build/bdist.linux-x86_64/egg/fontmake/__main__.py", line 51, in <module>
  File "build/bdist.linux-x86_64/egg/fontmake/__main__.py", line 39, in main
  File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 184, in run_from_glyphs
  File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 212, in run_from_ufos
  File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 120, in save_otf
  File "build/bdist.linux-x86_64/egg/ufo2ft/__init__.py", line 29, in compileOTF
  File "build/bdist.linux-x86_64/egg/ufo2ft/__init__.py", line 18, in _compile
  File "build/bdist.linux-x86_64/egg/ufo2ft/makeotfParts.py", line 40, in compile
  File "build/bdist.linux-x86_64/egg/ufo2ft/makeotfParts.py", line 188, in setupFile_featureTables
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/builder.py", line 15, in addOpenTypeFeatures
    builder = Builder(font, featurefile)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/feaLib/builder.py", line 32, in __init__
    self.glyphMap = font.getReverseGlyphMap()
AttributeError: 'str' object has no attribute 'getReverseGlyphMap'

make it possible to scale glyphs (and other metrics) when generating fonts from the source

It'd be handy to scale up or down glyphs and other metrics when the source scale (e.g. 1000/em) is different from the desired target scale (e.g. 2048/em).

I came across this issue when I tried to transplant a few glyphs (U+2032 .. U+2034) from the source generated TTF to v2 Noto fonts in googlei18n/noto-fonts#510. The former (source) is 1000/em while the latter is 2048/em.

@roozbehp @dougfelt @xiangyexiao

glyphs file compatibility issue: unescaped quote in license string causes traceback

NotoSansThaiUI-MM.Glyphs.zip

I'm not certain how the above input file was produced, but Glyphs.app handles it.
The issue is with the unescaped " in the license attribute.

The file above has:
_This Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.
_where "AS IS" is not presented as "AS IS" like in the previous inputs.

We produce a traceback. Glyphs.app does not.

~/rel/noto-source$ make -B src/NotoSansThaiUI-MM.glyphs
bash build.sh build_one src/NotoSansThaiUI-MM.glyphs
>> Checking Glyphs source for illegal glyph names
Found 123 glyph names containing hyphens: angkhankhu-thai, boBaimai-thai, choChan-thai, choChang-thai, choChing-thai, ...
Replacing all hyphens with underscores.
>> Interpolating master UFOs from Glyphs source
>>> Parsing .glyphs file
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "build/bdist.linux-x86_64/egg/fontmake/__main__.py", line 51, in <module>
  File "build/bdist.linux-x86_64/egg/fontmake/__main__.py", line 39, in main
  File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 179, in run_from_glyphs
  File "build/bdist.linux-x86_64/egg/fontmake/font_project.py", line 77, in build_instances
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/glyphslib.py", line 101, in build_instances
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/glyphslib.py", line 57, in load_to_ufos
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/glyphslib.py", line 38, in load
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/glyphslib.py", line 47, in loads
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 39, in parse
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 51, in _parse
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 79, in _parse_dict
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 57, in _parse
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 100, in _parse_list
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 51, in _parse
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 84, in _parse_dict
  File "build/bdist.linux-x86_64/egg/glyphs2ufo/parser.py", line 130, in _fail
ValueError: Missing delimiter in dictionary before content:
AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or i
make: *** [src/NotoSansThaiUI-MM.glyphs] Error 1

Invalid value for macintoshFONDFamilyID

Fontmake crashes when building the attached Raleway-Medium.glyphs. The file was converted from UFO with Glyphs, and Glyphs can open it without hiccups. Within that file, customParameters contains:

{
name = macintoshFONDFamilyID;
value = 128;
},

Apparently, somewhere in the fontmake pipeline, the value becomes a string instead of an int:

$ fontmake -g Raleway-Medium.glyphs
>> Checking Glyphs source for illegal glyph names
>> Loading master UFOs from Glyphs source
>>> Parsing .glyphs file
>>> Casting parsed values
>>> Loading to RFonts
Traceback (most recent call last):
  File "/usr/local/bin/fontmake", line 9, in <module>
    load_entry_point('fontmake', 'console_scripts', 'fontmake')()
  File "/home/sascha/src/fontmake/Lib/fontmake/__main__.py", line 39, in main
    project.run_from_glyphs(glyphs_path, **args)
  File "/home/sascha/src/fontmake/Lib/fontmake/font_project.py", line 139, in run_from_glyphs
    ufos = self.build_masters(glyphs_path, is_italic)
  File "/home/sascha/src/fontmake/Lib/fontmake/font_project.py", line 68, in build_masters
    return build_masters(glyphs_path, master_dir, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 85, in build_masters
    ufos = load_to_ufos(filename, italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 60, in load_to_ufos
    debug=debug)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/torf.py", line 93, in to_robofab
    rfonts, master_id_order = generate_base_fonts(data, italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/torf.py", line 261, in generate_base_fonts
    setattr(rfont.info, name, value)
  File "/usr/local/lib/python2.7/dist-packages/robofab/objects/objectsBase.py", line 2920, in __setattr__
    raise RoboFabError("Invalid value (%s) for attribute (%s)." % (repr(value), attr))
robofab.RoboFabError: Invalid value ('128') for attribute (macintoshFONDFamilyID).

Panose numbers and ascender/descender values defined for the instances are ignored

I copied from an email by Jelle.B who looked at regular Ethiopic font (see the otf file in the attached zip) generated by the pipeline from the glyphs file (see the attached zip) on about 1/Feb/2016. The comments pertain to that version of the pipeline. See the bottom of this message for the reason why I cannot generate a new version of the fonts.

[...] ignored are Panose numbers and ascender/descender values defined for
the instances.

NotoSansEthiopicCondensed-Regular-km-error.zip

Note that NotoSansEthiopic-MM.glyphs generates as of 12/Feb/2016 "defcon.errors.DefconError: The kerning data is not valid" so I cannot check what the newest version of pipeline generates (see #13 )

noto_lint.py error: E <head/os2/windescent>

I don't know if this is a big issue or not (cc @dougfelt ) but noto_lint.py produces the following error on our pipeline generated OTF font for the following fonts. It doesn't happen when otf is produced by the glyphs app.

NotoSansArmenian-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenian-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenianCondensed-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenian-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenian-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenian-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenian-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansArmenian-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-BlackItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-BoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-BlackItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-BoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-ExtraBoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-ExtraBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Italic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-LightItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-MediumItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-ThinItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplayCondensed-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-ExtraBoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-ExtraBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-LightItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-MediumItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-ThinItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansDisplay-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgianCondensed-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansGeorgian-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSansHebrewCondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (242) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansHebrewCondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (241) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansHebrew-ExtraBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (252) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansHebrew-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (246) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansHebrew-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (252) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-BlackItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-BoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-BlackItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-BoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-ExtraBoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-ExtraBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Italic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-LightItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-236), but they should be opposites.
NotoSansUICondensed-MediumItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-ThinItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUICondensed-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-232), but they should be opposites.
NotoSansUI-ExtraBoldItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-ExtraBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-LightItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-MediumItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-ThinItalic.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSansUI-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (389) is different from the opposite of value of Descent in 'hhea' table (-240), but they should be opposites.
NotoSerifArmenian-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenian-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenianCondensed-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenian-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenian-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenian-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (553) is different from the opposite of value of Descent in 'hhea' table (-600), but they should be opposites.
NotoSerifArmenian-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifArmenian-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgian-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgian-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-Black.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-Bold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgianCondensed-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgian-Light.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgian-Medium.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgian-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (502) is different from the opposite of value of Descent in 'hhea' table (-600), but they should be opposites.
NotoSerifGeorgian-SemiBold.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifGeorgian-Thin.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (292) is different from the opposite of value of Descent in 'hhea' table (292), but they should be opposites.
NotoSerifThai-Regular.otf:E <head/os2/windescent> Value of usWinDescent in 'OS/2' table (534) is different from the opposite of value of Descent in 'hhea' table (-524), but they should be opposites.

Dependency hell

We need to work with maintainers of modules we depend on and clean-up the "dependency hell" we are in right now. In particular, I'm now stuck with no way to fully utilize the pipeline because of ufolib dep in defcon. But we all know what problems I'm talking about. So let's streamline and clean up this together. Here's my thoughts on how to do it:

  • Switch all libraries away from robofab and to defcon and ufolib. Remove robofab dependency from defcon. For robofab pens, either move them to fonttools and switch everyone, or make libraries that use robofab pens just make a copy for now. Deprecate robofab and don't update it anymore and advise everyone to move away from it.

  • Switch all uses of plistlib to Python's builtin plistlib. Defcon master currently seems to do from ufoLib.plistlib import writePlistToString, which fails badly if the standalone ufoLib is installed (it doesn't have plistlib).

  • Merge all py23 fixes that are outstanding. Is there any of that left or we're good? In particular, add the following to every Python source in every library:

    from __future__ import print_function, division, absolute_import

possibly also:

from fontTools.misc.py23 import *

  • Add requirements.txt to all libraries. Right now fonttools, fontmake, cu2qu, etc have, but since MutatorMath, defcon, etc do NOT, pip install -U -r requirements.txt is not as useful as it can be.

If we do the above, it leaves us with just one uncertainty: UFO 2 vs 3. For that, I suggest that individual modules decided to either support both (in the same branch), or only support UFO 3. Old versions of libraries that support UFO 2 can live in a branch forever.

So, what do people think? Can we clean this up please? If we agree on the action plan?

CC @jamesgk @brawer @adrientetar @anthrotype @typesupply @typemytype @LettError @justvanrossum @moyogo @benkiel

difference between the hb-view outputs for font generated by pipeline and by the Glyphs app

I used NotoSerifThai-MM.glyphs.zip as input to both pipeline and to the Glyphs.app on Mac.

The pipeline produced the following OTF font
NotoSerifThai-Regular.otf.zip

The Glyphs.app on Mac produced the following OTF font
NotoSerifThai-Regular.otf.zip

Then I ran
hb-view NotoSerifThai-Regular.otf --output-format=png --text-file=../thai-sample2.txt > ts.png
for each of the fonts.

Pipeline font produced the following image
ts2

The Glyphs.app on Mac font produced the following image
ts

please advise: bad or good :-)

I took an intermediate (early, for review) delivery of NotoSansArabic-MM.glyphs
NotoSansArabic-MM.glyphs.zip
and ran through the pipeline creating 4 OTF fonts.

I took a sample Arabic text and created png files using hb-view.
I have no idea if what we generated is bad or good :-)
Please advise.

NotoSansArabic-Black.otf
NotoSansArabic-Black.otf 2.zip
notosansarabic-black otf

NotoSansArabic-Bold.otf
NotoSansArabic-Bold.otf.zip
notosansarabic-bold otf

NotoSansArabic-Regular.otf
NotoSansArabic-Regular.otf.zip
notosansarabic-regular otf

NotoSansArabic-Thin.otf
NotoSansArabic-Thin.otf.zip
notosansarabic-thin otf

File "/usr/local/lib/python2.7/dist-packages/robofab/glifLib.py", line 297, in _getXMLTree raise KeyError, glyphName KeyError: 'uni000D'

I built the pipeline in the evening (PDT) on 2016-02-16.

==== building src/NotoSerifArmenian-MM.glyphs ====
NotoSerifArmenian-MM.glyphs.zip
WARNING: Non-existent glyph class @MMK_L_uni0533 found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_uni0532 found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_uni0535 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0553 found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_uni0539 found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_uni057C found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_uni0575 found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_uni056A found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0584 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0575 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0553 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0562 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0573 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0565 found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_uni0561 found in kerning rules.
[... many more ...]
WARNING: Non-existent glyph class @MMK_R_uni0575 found in kerning rules.

Checking Glyphs source for illegal glyph names
Loading master UFOs from Glyphs source

Parsing .glyphs file
Casting parsed values
Loading to RFonts
Writing master_ufo/NotoSerifArmenian-Light.ufo
Writing master_ufo/NotoSerifArmenian-SemiLight.ufo
Writing master_ufo/NotoSerifArmenian-Regular.ufo
Writing master_ufo/NotoSerifArmenian-SemiBold.ufo
Writing master_ufo/NotoSerifArmenian-Bold.ufo
Writing master_ufo/NotoSerifArmenianCondensed-Light.ufo
Writing master_ufo/NotoSerifArmenianCondensed-Regular.ufo
Writing master_ufo/NotoSerifArmenianCondensed-Bold.ufo
Removing overlaps for NotoSerifArmenian-Light
Removing overlaps for NotoSerifArmenian-SemiLight
Removing overlaps for NotoSerifArmenian-Regular
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/usr/local/lib/python2.7/dist-packages/fontmake/main.py", line 51, in
main()
File "/usr/local/lib/python2.7/dist-packages/fontmake/main.py", line 39, in main
project.run_from_glyphs(glyphs_path, *_args)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 144, in run_from_glyphs
self.run_from_ufos(ufos, is_instance=interpolate, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 159, in run_from_ufos
self.remove_overlaps(ufo)
File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 80, in remove_overlaps
for glyph in ufo:
File "/usr/local/lib/python2.7/dist-packages/robofab/objects/objectsBase.py", line 696, in iter
yield self.getGlyph(glyphName)
File "/usr/local/lib/python2.7/dist-packages/robofab/objects/objectsRF.py", line 556, in getGlyph
n = self._loadGlyph(glyphName)
File "/usr/local/lib/python2.7/dist-packages/robofab/objects/objectsRF.py", line 213, in _loadGlyph
self._glyphSet.readGlyph(glyphName=glyphName, glyphObject=g, pointPen=pen)
File "/usr/local/lib/python2.7/dist-packages/robofab/glifLib.py", line 192, in readGlyph
tree = self._getXMLTree(glyphName)
File "/usr/local/lib/python2.7/dist-packages/robofab/glifLib.py", line 297, in _getXMLTree
raise KeyError, glyphName
KeyError: 'uni000D'

defcon.errors.DefconError: The kerning data is not valid while processing NotoSansEthiopic-MM.glyphs

The pipeline built on both 10/Feb and 12/Feb fails to build NotoSansEthiopic fonts.
I have attached the input file used for the pipeline.
NotoSansEthiopic-MM.glyphs.zip

==== building src/NotoSansEthiopic-MM.glyphs ====
WARNING: Illegal glyph name "geminationandvowellengthcomb_ethiopic". If this is used in the font's feature syntax, it could cause errors.
WARNING: Non-existent glyph class @MMK_R_ddhe_ethiopic found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_ddho_ethiopic found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_ddo_ethiopic found in kerning rules.
[... deleted hundreds of similar WARNINGs ...]
WARNING: Non-existent glyph class @MMK_R_ddo_ethiopic found in kerning rules.
WARNING: Non-existent glyph class @MMK_R_de_ethiopic found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_qyu_ethiopic found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_lo_ethiopic found in kerning rules.
WARNING: Non-existent glyph class @MMK_L_qho_ethiopic found in kerning rules.
>> Checking Glyphs source for illegal glyph names
Found 555 glyph names containing hyphens: aGlottal-ethiopic, aPharyngeal-ethiopic, aaGlottal-ethiopic, aaPharyngeal-ethiopic, ba-ethiopic, ...
Replacing all hyphens with underscores.
>> Interpolating master UFOs from Glyphs source
>>> Parsing .glyphs file
>>> Casting parsed values
>>> Loading to RFonts
>>> Writing masters
>>> Building instances
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/local/lib/python2.7/dist-packages/fontmake/__main__.py", line 34, in <module>
    main()
  File "/usr/local/lib/python2.7/dist-packages/fontmake/__main__.py", line 30, in main
    project.run_all(glyphs_path, **args)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 139, in run_all
    ufos = self.build_instances(glyphs_path, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 64, in build_instances
    return build_instances(glyphs_path, master_dir, instance_dir, is_italic)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/glyphslib.py", line 102, in build_instances
    master_ufos, master_dir, instance_dir, designspace_path, instance_data)
  File "/usr/local/lib/python2.7/dist-packages/glyphs2ufo/interpolation.py", line 49, in interpolate
    build(designspace_path)
  File "/usr/local/lib/python2.7/dist-packages/mutatorMath/ufo/__init__.py", line 56, in build
    reader.process()
  File "/usr/local/lib/python2.7/dist-packages/mutatorMath/ufo/document.py", line 369, in process
    self.readSources()
  File "/usr/local/lib/python2.7/dist-packages/mutatorMath/ufo/document.py", line 403, in readSources
    sourceObject = self._fontClass(sourcePath)
  File "/usr/local/lib/python2.7/dist-packages/defcon/objects/font.py", line 161, in __init__
    k = self.kerning
  File "/usr/local/lib/python2.7/dist-packages/defcon/objects/font.py", line 430, in _get_kerning
    self._loadKerningAndGroups()
  File "/usr/local/lib/python2.7/dist-packages/defcon/objects/font.py", line 403, in _loadKerningAndGroups
    raise error
defcon.errors.DefconError: The kerning data is not valid.

Skip over missing components?

When fontmake builds from UFO, what should happen when a glyph refers to an undefined component? Apparently, other build chains are silently skipping over the problem; see metapolator/Breite#1. Instead of crashing, should fontmake perhaps emit a warning and proceed building? Although, nobody looks at warnings, so maybe crashing is fine.

fontmake passes incomplete feature files to fonttools

When building Raleway-Medium.ufo, fontmake crashes with the following error:

$ fontmake -u src/Raleway-Medium.ufo
>> Removing overlaps for Raleway Medium
>> Saving OTF for Raleway Medium
Traceback (most recent call last):
  File "/usr/local/bin/fontmake", line 9, in <module>
    load_entry_point('fontmake', 'console_scripts', 'fontmake')()
  File "/home/sascha/src/fontmake/Lib/fontmake/__main__.py", line 47, in main
    project.run_from_ufos(ufo_paths, **args)
  File "/home/sascha/src/fontmake/Lib/fontmake/font_project.py", line 174, in run_from_ufos
    mti_feafiles=mti_paths.get(name), kern_writer=GlyphsKernWriter)
  File "/home/sascha/src/fontmake/Lib/fontmake/font_project.py", line 118, in save_otf
    kernWriter=kern_writer, mtiFeaFiles=mti_feafiles)
  File "/usr/local/lib/python2.7/dist-packages/ufo2ft/__init__.py", line 29, in compileOTF
    featureCompilerClass, mtiFeaFiles, kernWriter, markWriter)
  File "/usr/local/lib/python2.7/dist-packages/ufo2ft/__init__.py", line 18, in _compile
    featureCompiler.compile()
  File "/usr/local/lib/python2.7/dist-packages/ufo2ft/makeotfParts.py", line 38, in compile
    self.setupFile_featureTables()
  File "/usr/local/lib/python2.7/dist-packages/ufo2ft/makeotfParts.py", line 183, in setupFile_featureTables
    addOpenTypeFeatures(fea_path, self.outline)
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/builder.py", line 13, in addOpenTypeFeatures
    builder.build()
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/builder.py", line 50, in build
    self.parseTree = Parser(self.featurefile_path).parse()
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/parser.py", line 40, in parse
    statements.append(self.parse_feature_block_())
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/parser.py", line 820, in parse_feature_block_
    self.parse_block_(block, vertical)
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/parser.py", line 872, in parse_block_
    statements.append(self.parse_substitute_())
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/parser.py", line 543, in parse_substitute_
    self.parse_glyph_pattern_(vertical=False)
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/parser.py", line 246, in parse_glyph_pattern_
    gc = self.parse_glyphclass_(accept_glyphname=True)
  File "/usr/local/lib/python2.7/dist-packages/FontTools/fontTools/feaLib/parser.py", line 181, in parse_glyphclass_
    self.cur_token_location_)
fontTools.feaLib.error.FeatureLibError: /tmp/tmpOwId86:13:9: Unknown glyph class @smcp1

However, the file in /tmp/tmpOwId86 has no definition of glyph class smcp1. fontTools.feaLib is therefore correct when it rejects this input. When passing that same file to AFDKO, it equally rejects it with the same error message.

Now, the command fontmake -u src/Raleway-Medium.ufo --use-afdko does not fail in feature file parsing but barfs on #10. This is extremely surprising, because the content of the tmpOwId86 feature file would also have been rejected by AFDKO. Does AFDKO receive a different input feature file than feaLib? Or does fontmake not check for makeotf errors? (Actually, when running fontmake under strace, I could not find any exec calls to makeotf; perhaps makeotf does not get run at all, despite passing --use-afdko?)

KeyError: u'.notdef' with the newest pipeline (as of 9/Mar/2016 afternoon PST)

processing Glyphs_Sapperlot.glyphs.zip

>> Saving TTF for GlyphsSapperlot-Regular
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/local/lib/python2.7/dist-packages/fontmake/__main__.py", line 51, in <module>
    main()
  File "/usr/local/lib/python2.7/dist-packages/fontmake/__main__.py", line 39, in main
    project.run_from_glyphs(glyphs_path, **args)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 187, in run_from_glyphs
    kern_writer=GlyphsKernWriter, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 232, in run_from_ufos
    ufo, ttf=True, mti_feafiles=mti_paths.get(name), **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/fontmake/font_project.py", line 121, in save_otf
    otf.save(otf_path)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 216, in save
    self._writeTable(tag, writer, done)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 645, in _writeTable
    self._writeTable(masterTable, writer, done)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 645, in _writeTable
    self._writeTable(masterTable, writer, done)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 648, in _writeTable
    tabledata = self.getTableData(tag)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/__init__.py", line 659, in getTableData
    return self.tables[tag].compile(self)
  File "/usr/local/lib/python2.7/dist-packages/fonttools-3.0-py2.7.egg/fontTools/ttLib/tables/_g_l_y_f.py", line 81, in compile
    glyph = self.glyphs[glyphName]
KeyError: u'.notdef'

Build color fonts

It would be nice if fontmake could build color fonts.

Glyphs already supports color fonts, both as vectors and images. Therefore, a glyphs file should contain all information needed to build color fonts in various formats.

Sadly, color font formats are very fragmented. As a general tool chain, I think fontmake should be agnostic about formats and try to support them all. (Of course, it would be nice if the industry could converge eventually). As an intermediate format, SVG might work because it can be easily converted into PDF, PNG, and JPEG images. Later in the pipeline, those images can then be packaged into sbix, CBDT, COLR, CBDT/CBLC, and similar tables depending on what format was requested.

Support building UFOs

README says,

This library provides a wrapper for several other Python libraries which together compile fonts from various sources (.glyphs, .ufo) into binaries (.otf, .ttf).

but it seems to only accept .glyphs files atm,

https://github.com/googlei18n/fontmake/blob/master/Lib/fontmake/__main__.py#L22

In reading https://github.com/googlei18n/fontmake/blob/master/Lib/fontmake/font_project.py then I suppose there needs to be a default assumption that an input UFO is a master or an instance, and an arg to declare this I propose that assuming UFOs are masters makes more sense.

noto_lint.py <name/*> errors

I'm not sure if these <name/ attributes are generated or just passed from the glyphs input file (cc @dougfelt ), but noto_lint.py generates errors (the following were from linting NotoSansArmenianCondensed-Bold.otf )

E <name/family> The family is 'Noto Sans Armenian Condensed' but was expecting 'Noto Sans Armenian Condensed Bold'
E <name/postscript_name> The postscript name is 'NotoSansArmenianCondensed-Bold' but was expecting 'NotoSansArmenian-CondensedBold'
E <name/preferred_family> The preferred family is not set, but was expecting 'Noto Sans Armenian'
E <name/preferred_subfamily> The preferred subfamily is not set, but was expecting 'Condensed Bold'
E <name/subfamily> The subfamily is 'Bold' but was expecting 'Regular'
E <name/trademark> The trademark is 'Noto is a trademark of Google Inc. and may be registered in certain jurisdictions.' but was expecting 'Noto is a trademark of Google Inc.'
E <name/vendor_url> The vendor url is 'http://code.google.com/p/noto/' but was expecting 'http://www.google.com/get/noto/'

Process one instance at a time

Right now fontmake generates and saves UFO for all instances, then removeoverlaps them all, then save them. Will be much more memory-efficient and as such probably even faster, if we process one instance completely, then the next, then the next...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.