googlefonts / glyphsLib

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

MTI features plist as custom parameter, exported to UFO data/ #326

Open anthrotype opened 6 years ago

anthrotype commented 6 years ago

fontmake has an --mti-source option to load Monotype feature files from a plist file containing a mapping of OpenType table tags (GSUB, GPOS, GDEF) to text files containing feature specifications in MTI feature file format. http://monotype.github.io/OpenType_Table_Source/otl_source.html When building the master UFOs from a glyphs source, if that command line option is provided, fontmake reads the plist and copies the content of the referenced text files inside each master UFO's data directory, prefixed with a private reverse-domain prefix that ufo2ft uses to load these data files and pass them on to fontTools.mtiLib for compilation.

I would like that we could store the filenames of these external MTI feature files inside the Glyphs source file itself, in the form of masters custom parameters, and the glyphsLib could read these upon building the UFO masters and store them in the data folder, just like fontmake does.

This way, the fontmake command line to build from a glyphs source file with MTI features would not contain the extra option and its output determined only by the content of the single input glyphs file.

This is how this plist files currently look like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NotoSansCham-Light</key>
    <dict>
        <key>GDEF</key>
        <string>Noto Sans Cham GDEF.txt</string>
        <key>GPOS</key>
        <string>Noto Sans Cham 26-100 GPOS.txt</string>
        <key>GSUB</key>
        <string>Noto Sans Cham GSUB.txt</string>
    </dict>

    <key>NotoSansCham-Regular</key>
    <dict>
        <key>GDEF</key>
        <string>Noto Sans Cham GDEF.txt</string>
        <key>GPOS</key>
        <string>Noto Sans Cham 90-100 GPOS.txt</string>
        <key>GSUB</key>
        <string>Noto Sans Cham GSUB.txt</string>
    </dict>

    <key>NotoSansCham-SemiBold</key>
    <dict>
        <key>GDEF</key>
        <string>Noto Sans Cham GDEF.txt</string>
        <key>GPOS</key>
        <string>Noto Sans Cham 151-100 GPOS.txt</string>
        <key>GSUB</key>
        <string>Noto Sans Cham GSUB.txt</string>
    </dict>

    <key>NotoSansCham-Bold</key>
    <dict>
        <key>GDEF</key>
        <string>Noto Sans Cham GDEF.txt</string>
        <key>GPOS</key>
        <string>Noto Sans Cham 190-100 GPOS.txt</string>
        <key>GSUB</key>
        <string>Noto Sans Cham GSUB.txt</string>
    </dict>

</dict>
</plist>
belluzj commented 6 years ago

It's not exactly what you want, but in order to roundtrip UFO -> Glyphs -> UFO, I store all the contents of the data folder in base64 in the Glyphs file's userData, and restore the data files when going back to UFO. If you were to put your MTI files in that same key as base64, they would be copied to the data folder.

https://github.com/googlei18n/glyphsLib/blob/0a86327a93b3f324f200e35a23f639db4ae58280/Lib/glyphsLib/builder/user_data.py#L112-L121

https://github.com/googlei18n/glyphsLib/blob/0a86327a93b3f324f200e35a23f639db4ae58280/Lib/glyphsLib/builder/user_data.py#L50-L54

anthrotype commented 6 years ago

I am not sure whether a Glyphs.app user can define one's own "private" custom parameters for one's own tools' consumption, not for the Glyphs.app core to use. I don't think there is a reverse-domain prefix convention in place like there is for the UFO lib elements, to avoid that multiple users' private parameters overwrite each other.

Another problem with self-defined custom parameters is that only strings seems to be allowed, so if want to store a structured data like this one (a dictionary keyed by table tags, with values the respective text file names) I would have to resort to some special formatting like <key>=<value>, [...] (which maybe it's fine).

Maybe I'm abusing the concept of custom parameters, and I should rather use the userData dictionary for this use case?

The problem with userData is that is not user friendly to input and requires one to write some python code for it.

anthrotype commented 6 years ago

thanks jany, but I think it would be best to keep those files as external files, as they may be edited from an external editor I guess. so you're basically suggesting that we use the userData with some private key to store the mapping of tags to features filenames. Not ideal but maybe it's fine...

schriftgestalt commented 6 years ago

I’m thinking on adding support for MTI sources somehow to Glyphs. As a similar case, if you add a featurePrefix with the name "morx" this will be used to compile AAT tables (of you have the apple font tools installed). Something similar could be done for MIT sources. I can’t compile those, yet, but that shouldn’t be to complicated.

The plist contains OT data for each instances, so I would put it there. Glyphs is fine with "custom" custom parameters (they are just shown grey to signal that Glyphs doesn’t know/use them.

schriftgestalt commented 6 years ago

I look into the possibility to store dicts in the custom custom parameters.

For now, we could defined three keys, like: MTI-GDEF-filePath, MTI-GPOS-filePath ...

anthrotype commented 6 years ago

The plist contains OT data for each instances, so I would put it there

in the case of Noto, they refer to the masters actually, and the instance GPOS is interpolated with fonttools.varLib.interpolate_layout. But I guess that's an implementation detail. I'd like to be able to decide whether to store these either in the masters or in the instances.

anthrotype commented 6 years ago

I look into the possibility to store dicts in the custom custom parameters.

thanks!

For now, we could defined three keys, like: MTI-GDEF-filePath, MTI-GPOS-filePath ...

yeah, maybe that's good enough for now.

Glyphs is fine with "custom" custom parameters (they are just shown grey to signal that Glyphs doesn’t know/use them

but if two users define the same private name to mean different things then there could be problems. Or you the app developer could decide to reserve that name in a subsequent version of the app, breaking other people's workflows, etc. That's why in UFO they use that thing com.schriftgestaltung.* -- thanks to which I am now even able to correctly spell your nickname.

schriftgestalt commented 6 years ago

I recommend the reverse name keys in userData but for custom parameter I prefer shorter and more readable keys.

anthrotype commented 6 years ago

I prefer shorter and more readable keys

that's a good point, but the risk of clashing still persists.

moyogo commented 6 years ago

It wouldn’t be that hard to write a userData editor as a plugin/extension for Glyphs.app.

anthrotype commented 6 years ago

@moyogo you volunteering? 😛

schriftgestalt commented 6 years ago

True. But there is a UI for user facing data already ;)

anthrotype commented 6 years ago

there is a UI for user facing data already?

then I missed it. Where can I find it?

schriftgestalt commented 6 years ago

The custom parameter list

anthrotype commented 6 years ago

oh, I thought you meant the userData dicts.

schriftgestalt commented 6 years ago

I had a look at the dict in custom parameters. It works fine.

I improved the display/handling a bit. Manually editing is possible, now, too.

screenshot
anthrotype commented 6 years ago

that was fast, thanks :) I think our glyphsLib parser and writer should already be able to serialize/deserialize those ascii plist dicts and arrays to/from string. However, having the user edit those manually (taking into account the quote escaping rules) is not that great.

schriftgestalt commented 6 years ago

However, having the user edit those manually (taking into account the quote escaping rules) is not that great.

Yes. Thats why I suggested three entry in this particular use case.

anthrotype commented 6 years ago

I've been thinking.. even if we were able to store the paths to these MTI feature files as master's custom parameters in the .glyphs source, instead of in the external .plist files, this would not solve the problem for a group of Noto sources (i.e. Devanagari, Bengali, Malayalam and Tamil) that have two MTI plists, one for the normal fonts and the other for the UI variant, but only one .glyphs source file shared by both.

These .glyphs sources needs to be built twice: once with one set of MTI sources, then again for the UI variants with the corresponding UI .plist, and using the weird --family-name option (this selects the instances with that familyName, and also renames the generated UFO masters, I presume to avoid overwriting the non-UI ones).

I am tempted to simply duplicate the .glyphs sources in the noto-source repo, and enforce a one-to-one relation between .glyphs and MTI .plist sources: e.g. so there would be NotoSansDevanagariUI-MM.glyphs which is the same as NotoSansDevanagari-MM.glyphs, but its masters uses different MTI sources.

For Noto Sans Myanmar and Khmer, the UI variants are in different *UI-MM.glyphs sources, each with its own set of MTI features (probably because for those two it was necessary to also make adjustment to the outlines instead of only to the opentype layout features).

schriftgestalt commented 6 years ago

I would add a second set of instances on for the normal and one for the UI fonts. Then you can add all specific settings like family name and feature files.

anthrotype commented 6 years ago

That is already the case. The Devanagari glyphs source contains both the non UI and the UI instances. However for the MTI features we need to associate them to the masters, as the instances’s GPOS is interpolated at the binary level using fontTools.varLib.interpolate_layout. So we need to build the masters twice with different set of features, then interpolate the instances from them.

schriftgestalt commented 6 years ago

I see. I still would try to control that by instances settings. Maybe add a suffix to the UI-MTI sources and define the suffix in the instances. So the masters have "Mastername.mti" and the instance can add a suffix that the file "Mastername-UI.mti" will be used instead? It is a bit of a hack but better than duplicating the file.