Skip to content

Commit

Permalink
Be more clever about subsetting:
Browse files Browse the repository at this point in the history
* Find appropriate master from subset font by matching source location to subset location
* Write changed files in a temporary directory
  • Loading branch information
simoncozens committed Apr 6, 2022
1 parent 163846c commit 2b21786
Showing 1 changed file with 64 additions and 21 deletions.
85 changes: 64 additions & 21 deletions Lib/gftools/actions/notobuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import os
import re
import sys
import shutil
import tempfile
from pathlib import Path

import pygit2
Expand Down Expand Up @@ -118,20 +120,39 @@ def build(self):
for key in ["vfDir", "otDir", "ttDir"]:
self.config[key] = self.config[key].replace("unhinted", "full")

new_builder_sources = []
temporaries = []

for ds_file in self.config["sources"]:
new_ds_file_dir = tempfile.TemporaryDirectory()
temporaries.append(new_ds_file_dir)
ds = designspaceLib.DesignSpaceDocument.fromfile(ds_file)
for subset in self.config["includeSubsets"]:
if len(ds.sources) == 1:
self.add_subset(ds.sources[0], subset, mapping="Regular")
else:
for master in ds.sources:
self.add_subset(ds.sources[0], subset)
for master in ds.sources:
# Save a copy to temporary UFO
newpath = os.path.join(new_ds_file_dir.name, os.path.basename(master.path))
original_ufo = ufoLib2.Font.open(master.path)
original_ufo.save(newpath, overwrite=True)

master.path = newpath

for subset in self.config["includeSubsets"]:
self.add_subset(master, subset)
# # Set instance filenames to temporary
for instance in ds.instances:
instance.filename = instance.path = os.path.join(new_ds_file_dir.name, os.path.basename(instance.filename))

# Save new designspace to temporary
new_ds_file = os.path.join(new_ds_file_dir.name, os.path.basename(ds_file))
ds.write(new_ds_file)

new_builder_sources.append(new_ds_file)

self.config["sources"] = new_builder_sources

super().build()
# Temporaries should get cleaned here.

def add_subset(self, ds_source, subset, mapping=None):
if mapping is None:
raise NotImplementedError
def add_subset(self, ds_source, subset):
if "name" in subset:
# Resolve to glyphset
unicodes = CodepointsInSubset(subset["name"])
Expand All @@ -140,33 +161,55 @@ def add_subset(self, ds_source, subset, mapping=None):
for r in subset["ranges"]:
for cp in range(r["start"], r["end"] + 1):
unicodes.append(cp)
source_ufo = self.obtain_noto_ufo(subset["from"], mapping)
source_ufo = self.obtain_noto_ufo(subset["from"], ds_source.location)
target_ufo = ufoLib2.Font.open(ds_source.path)
merge_ufos(
target_ufo, source_ufo, codepoints=unicodes, existing_handling="skip",
)
target_ufo.save(ds_source.path, overwrite=True)

def obtain_noto_ufo(self, font_name, mapping):
def obtain_noto_ufo(self, font_name, location):
if font_name == "Noto Sans":
self.clone_for_subsetting("latin-greek-cyrillic")
path = "../subset-files/latin-greek-cyrillic/sources/NotoSans-MM.glyphs"
if font_name == "Noto Serif":
self.clone_for_subsetting("latin-greek-cyrillic")
path = "../subset-files/latin-greek-cyrillic/sources/NotoSerif-MM.glyphs"
if font_name == "Noto Sans Devanagari":
self.clone_for_subsetting("devanagari")
path = "../subset-files/devanagari/sources/NotoSansDevanagari.glyphs"

if path.endswith(".glyphs"):
# Check if UFO already exists
path = self.glyphs_to_ufo(path)
ds_path = path.replace(".glyphs", ".designspace")
if os.path.exists(ds_path):
path = ds_path
else:
self.logger.info("Building UFO file for subset font "+font_name)
path = self.glyphs_to_ufo(path)
source_ds = designspaceLib.DesignSpaceDocument.fromfile(path)
regs = [
source.path
for source in source_ds.sources
if source.name.endswith("Regular")
]
if not regs:
regs = [source_ds.sources[0].path]
return ufoLib2.Font.open(regs[0])

# Find a source for this location
return ufoLib2.Font.open(self.find_source(source_ds, location, font_name).path)

def find_source(self, source_ds, location, font_name):
source_mappings = {
ax.name: ax.map_forward for ax in source_ds.axes
}
target = None
for source in source_ds.sources:
match = True
for axis, loc in location.items():
if axis in source.location and axis in source_mappings and source.location[axis] != source_mappings[axis](loc):
match = False
if match:
target = source
break
if target:
self.logger.info(f"Adding subset from {target} for location {location}")
return target
self.logger.error(f"Could not find master in {font_name} for location {location}")
import IPython;IPython.embed()
raise ValueError("Could not add subset")

def clone_for_subsetting(self, repo):
dest = "../subset-files/" + repo
Expand Down

0 comments on commit 2b21786

Please sign in to comment.