patch UFO files with WWS entries and simplify UFO generation

Patches UFO files to contain WWS entries.
Also simplify UFO generation by moving the hard-coded make rules from the makefile into a shell script.

Related to #498 and https://github.com/googlefonts/glyphsLib/issues/820
This commit is contained in:
Rasmus Andersson 2022-10-07 17:39:15 -07:00
parent c81a0abf02
commit 7cc0ab62e6
4 changed files with 118 additions and 83 deletions

View file

@ -32,84 +32,11 @@ $(UFODIR)/%.designspace: $(UFODIR)/%.glyphs $(UFODIR)/features | venv
--master-dir $(UFODIR) --instance-dir $(UFODIR)
. $(VENV) ; python misc/tools/postprocess-designspace.py $@
# master UFOs are byproducts of building Inter.designspace
$(UFODIR)/Inter-Thin.ufo: $(UFODIR)/Inter-Roman.designspace
touch $@
$(UFODIR)/Inter-Regular.ufo: $(UFODIR)/Inter-Roman.designspace
touch $@
$(UFODIR)/Inter-Black.ufo: $(UFODIR)/Inter-Roman.designspace
touch $@
$(UFODIR)/Inter-ThinItalic.ufo: $(UFODIR)/Inter-Italic.designspace
touch $@
$(UFODIR)/Inter-Italic.ufo: $(UFODIR)/Inter-Italic.designspace
touch $@
$(UFODIR)/Inter-BlackItalic.ufo: $(UFODIR)/Inter-Italic.designspace
touch $@
$(UFODIR)/Inter-DisplayThin.ufo: $(UFODIR)/Inter-Roman.designspace
touch $@
$(UFODIR)/Inter-Display.ufo: $(UFODIR)/Inter-Roman.designspace
touch $@
$(UFODIR)/Inter-DisplayBlack.ufo: $(UFODIR)/Inter-Roman.designspace
touch $@
$(UFODIR)/Inter-DisplayThinItalic.ufo: $(UFODIR)/Inter-Italic.designspace
touch $@
$(UFODIR)/Inter-DisplayItalic.ufo: $(UFODIR)/Inter-Italic.designspace
touch $@
$(UFODIR)/Inter-DisplayBlackItalic.ufo: $(UFODIR)/Inter-Italic.designspace
touch $@
# instance UFOs are generated on demand
$(UFODIR)/Inter-Light.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Light"
$(UFODIR)/Inter-ExtraLight.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Extra Light"
$(UFODIR)/Inter-Medium.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Medium"
$(UFODIR)/Inter-SemiBold.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Semi Bold"
$(UFODIR)/Inter-Bold.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Bold"
$(UFODIR)/Inter-ExtraBold.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Extra Bold"
$(UFODIR)/Inter-LightItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Light Italic"
$(UFODIR)/Inter-ExtraLightItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Extra Light Italic"
$(UFODIR)/Inter-MediumItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Medium Italic"
$(UFODIR)/Inter-SemiBoldItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Semi Bold Italic"
$(UFODIR)/Inter-BoldItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Bold Italic"
$(UFODIR)/Inter-ExtraBoldItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Extra Bold Italic"
$(UFODIR)/Inter-DisplayLight.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Light"
$(UFODIR)/Inter-DisplayExtraLight.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Extra Light"
$(UFODIR)/Inter-DisplayMedium.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Medium"
$(UFODIR)/Inter-DisplaySemiBold.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Semi Bold"
$(UFODIR)/Inter-DisplayBold.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Bold"
$(UFODIR)/Inter-DisplayExtraBold.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Extra Bold"
$(UFODIR)/Inter-DisplayLightItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Light Italic"
$(UFODIR)/Inter-DisplayExtraLightItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Extra Light Italic"
$(UFODIR)/Inter-DisplayMediumItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Medium Italic"
$(UFODIR)/Inter-DisplaySemiBoldItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Semi Bold Italic"
$(UFODIR)/Inter-DisplayBoldItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Bold Italic"
$(UFODIR)/Inter-DisplayExtraBoldItalic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; fontmake -o ufo -m $< --output-path $@ -i "Inter Display Extra Bold Italic"
# UFOs from designspace
$(UFODIR)/Inter-%Italic.ufo: $(UFODIR)/Inter-Italic.designspace | venv
. $(VENV) ; ./misc/tools/gen-instance-ufo.sh $< $@
$(UFODIR)/Inter-%.ufo: $(UFODIR)/Inter-Roman.designspace | venv
. $(VENV) ; ./misc/tools/gen-instance-ufo.sh $< $@
# make sure intermediate files are not rm'd by make
.PRECIOUS: \

69
misc/tools/gen-instance-ufo.sh Executable file
View file

@ -0,0 +1,69 @@
#!/bin/sh
set -e
PROG=${0##*/}
DESIGNSPACE=$1
UFO=$2
INSTANCE_Light="Inter Light"
INSTANCE_ExtraLight="Inter Extra Light"
INSTANCE_Medium="Inter Medium"
INSTANCE_SemiBold="Inter Semi Bold"
INSTANCE_Bold="Inter Bold"
INSTANCE_ExtraBold="Inter Extra Bold"
INSTANCE_DisplayLight="Inter Display Light"
INSTANCE_DisplayExtraLight="Inter Display Extra Light"
INSTANCE_DisplayMedium="Inter Display Medium"
INSTANCE_DisplaySemiBold="Inter Display Semi Bold"
INSTANCE_DisplayBold="Inter Display Bold"
INSTANCE_DisplayExtraBold="Inter Display Extra Bold"
INSTANCE_LightItalic="Inter Light Italic"
INSTANCE_ExtraLightItalic="Inter Extra Light Italic"
INSTANCE_MediumItalic="Inter Medium Italic"
INSTANCE_SemiBoldItalic="Inter Semi Bold Italic"
INSTANCE_BoldItalic="Inter Bold Italic"
INSTANCE_ExtraBoldItalic="Inter Extra Bold Italic"
INSTANCE_DisplayLightItalic="Inter Display Light Italic"
INSTANCE_DisplayExtraLightItalic="Inter Display Extra Light Italic"
INSTANCE_DisplayMediumItalic="Inter Display Medium Italic"
INSTANCE_DisplaySemiBoldItalic="Inter Display Semi Bold Italic"
INSTANCE_DisplayBoldItalic="Inter Display Bold Italic"
INSTANCE_DisplayExtraBoldItalic="Inter Display Extra Bold Italic"
MASTER_Thin=1
MASTER_Regular=1
MASTER_Black=1
MASTER_ThinItalic=1
MASTER_Italic=1
MASTER_BlackItalic=1
MASTER_DisplayThin=1
MASTER_Display=1
MASTER_DisplayBlack=1
MASTER_DisplayThinItalic=1
MASTER_DisplayItalic=1
MASTER_DisplayBlackItalic=1
_err() { echo "$PROG: $@" >&2; exit 1; }
# build/ufo/Inter-DisplayExtraBold.ufo -> DisplayExtraBold
UFO_NAME=$(basename "$UFO" .ufo)
case "$UFO_NAME" in Inter-*) UFO_NAME=${UFO_NAME:6} ;; esac
# DisplayExtraBold -> "Inter Display Extra Bold"
INSTANCE=INSTANCE_${UFO_NAME} ; INSTANCE=${!INSTANCE}
# If UFO is not an instance, assume that it's a master (or else error)
# master UFOs are byproducts of building Inter.designspace, so we just update mtime.
if [ -z "$INSTANCE" ]; then
MASTER=MASTER_${UFO_NAME}
[ -n "${!MASTER}" ] || _err "Failed to map UFO name \"$UFO_NAME\" to instance"
echo "touch $UFO"
touch "$UFO"
exit
fi
set -x
fontmake -o ufo -m "$DESIGNSPACE" --output-path "$UFO" -i "$INSTANCE"
exec python misc/tools/postprocess_instance_ufo.py "$UFO"

View file

@ -6,6 +6,8 @@ from datetime import datetime
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), 'tools')))
from common import getGitHash, getVersion
from postprocess_instance_ufo import ufo_set_wws
def update_version(ufo):
version = getVersion()
@ -24,6 +26,7 @@ def update_version(ufo):
ufo.info.openTypeNameUniqueID = "%s-%s:%d:%s" % (psFamily, psStyle, now.year, buildtag)
ufo.info.openTypeHeadCreated = now.strftime("%Y/%m/%d %H:%M:%S")
def fix_opsz_range(designspace):
# TODO: find extremes by looking at the source
for a in designspace.axes:
@ -33,6 +36,7 @@ def fix_opsz_range(designspace):
break
return designspace
def fix_wght_range(designspace):
for a in designspace.axes:
if a.tag == "wght":
@ -41,6 +45,7 @@ def fix_wght_range(designspace):
break
return designspace
def should_decompose_glyph(g):
# A trivial glyph is one that does not use components or where component transformation
# does not include mirroring (i.e. "flipped").
@ -58,12 +63,14 @@ def should_decompose_glyph(g):
return True
return False
def find_glyphs_to_decompose(designspace):
source = designspace.sources[int(len(designspace.sources)/2)]
print("find_glyphs_to_decompose sourcing from %r" % source.name)
ufo = defcon.Font(source.path)
return sorted([g.name for g in ufo if should_decompose_glyph(g)])
def set_ufo_filter(ufo, **filter_dict):
filters = ufo.lib.setdefault("com.github.googlei18n.ufo2ft.filters", [])
for i in range(len(filters)):
@ -72,24 +79,27 @@ def set_ufo_filter(ufo, **filter_dict):
return
filters.append(filter_dict)
def update_source_ufo(ufo_file, weight, glyphs_to_decompose):
print(f"update {os.path.basename(ufo_file)} (weight={weight})")
def update_source_ufo(ufo_file, glyphs_to_decompose):
print(f"update {os.path.basename(ufo_file)}")
ufo = defcon.Font(ufo_file)
update_version(ufo)
set_ufo_filter(ufo, name="decomposeComponents", include=glyphs_to_decompose)
ufo_set_wws(ufo) # Fix missing WWS entries for Display fonts
ufo.save(ufo_file)
def update_sources(designspace):
glyphs_to_decompose = find_glyphs_to_decompose(designspace)
#print("glyphs marked to be decomposed: %s" % ', '.join(glyphs_to_decompose))
sources = [source for source in designspace.sources]
# sources = [s for s in sources if s.name == "Inter Thin"] # DEBUG
source_files = list(set([(s.path, s.location["Weight"]) for s in sources]))
source_files = list(set([s.path for s in sources]))
with Pool(len(source_files)) as p:
p.starmap(update_source_ufo,
[(t[0], t[1], glyphs_to_decompose) for t in source_files])
p.starmap(update_source_ufo, [(path, glyphs_to_decompose) for path in source_files])
return designspace
def main(argv):
designspace_file = argv[1]
designspace = DesignSpaceDocument.fromfile(designspace_file)
@ -98,5 +108,6 @@ def main(argv):
designspace = update_sources(designspace)
designspace.write(designspace_file)
if __name__ == '__main__':
main(sys.argv)

View file

@ -0,0 +1,28 @@
import sys
import defcon
def ufo_set_wws(ufo):
# Fix missing WWS entries for Display fonts:
# See https://github.com/googlefonts/glyphsLib/issues/820
subfamily = ufo.info.styleName
if subfamily.find("Display") == -1:
return
subfamily = subfamily[len("Display"):].strip()
if subfamily == "":
# "Display" -> "Regular"
subfamily = "Regular"
ufo.info.openTypeNameWWSFamilyName = "Inter Display"
ufo.info.openTypeNameWWSSubfamilyName = subfamily
def main(argv):
ufo_file = argv[1]
if ufo_file.find("Display") == -1:
return # skip fonts of "default" family
ufo = defcon.Font(ufo_file)
ufo_set_wws(ufo)
ufo.save(ufo_file)
if __name__ == '__main__':
main(sys.argv)