Skip to content

Commit

Permalink
Use JSON format UFOs for intermediaries, fixes googlefonts#731
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncozens committed Sep 27, 2023
1 parent cfc004c commit f8e9df3
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Lib/gftools/builder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ def glyphs_to_ufo(self, source):
FontProject().run_from_glyphs(
str(source.resolve()),
**{
"format": ["ufo"],
"output": ["ufo"],
"output_dir": directory,
"master_dir": directory,
"designspace_path": output,
"ufo_structure": "json"
},
)
return source.with_suffix(".designspace").name
Expand Down
6 changes: 4 additions & 2 deletions Lib/gftools/builder/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from fontTools.designspaceLib import InstanceDescriptor
from glyphsLib.builder import UFOBuilder

from gftools.utils import open_ufo


@dataclass
class File:
Expand Down Expand Up @@ -35,7 +37,7 @@ def is_glyphs(self):

@property
def is_ufo(self):
return self.extension == "ufo"
return self.extension == "ufo" or ".ufo.json" in self.path

@property
def is_designspace(self):
Expand Down Expand Up @@ -79,7 +81,7 @@ def family_name(self):
elif self.designspace.sources[0].familyName:
return self.designspace.sources[0].familyName
else:
self.designspace.loadSourceFonts(ufoLib2.Font.open)
self.designspace.loadSourceFonts(open_ufo)
self.designspace.sources[0].font.info.familyName
return name

2 changes: 1 addition & 1 deletion Lib/gftools/builder/operations/addSubset.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class AddSubset(OperationBase):
description = "Add a subset from another font"
rule = "gftools-add-ds-subsets -y $yaml -o $out $in"
rule = "gftools-add-ds-subsets -j -y $yaml -o $out $in"

def validate(self):
# Ensure there is a new name
Expand Down
3 changes: 2 additions & 1 deletion Lib/gftools/builder/operations/instantiateUfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ def targets(self):
assert instance is not None
assert instance.filename is not None
# if self.first_source.is_glyphs:
return [ File(str(self.instance_dir / os.path.basename(instance.filename))) ]
return [ File(str(self.instance_dir / (os.path.basename(instance.filename)+".json"))) ]
# return [ File(instance.filename) ]

@property
def variables(self):
vars = super().variables
vars["fontmake_args"] += " --ufo-structure=json "
if self.first_source.is_glyphs:
vars["fontmake_args"] += f"--instance-dir {escape_path(str(self.instance_dir))}"
else:
Expand Down
2 changes: 1 addition & 1 deletion Lib/gftools/builder/recipeproviders/noto.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def build_a_static(self, source, instance, output):
"operation": "instantiateUfo",
"instance_name": instance.name,
"target": "full-designspace/instance_ufos/"
+ os.path.basename(instance.filename),
+ os.path.basename(instance.filename)+".json",
},
{"operation": "buildTTF" if output == "ttf" else "buildOTF"},
]
Expand Down
5 changes: 4 additions & 1 deletion Lib/gftools/scripts/add_ds_subsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def main(args=None):
parser.add_argument("--file", "-f", help="Source file within GitHub repository")
parser.add_argument("--name", "-n", help="Name of subset to use from glyphset")
parser.add_argument("--codepoints", "-c", help="Range of codepoints to subset")
parser.add_argument(
"--json", "-j", action="store_true", help="Use JSON structured UFOs"
)

parser.add_argument("--output", "-o", help="Output designspace file")

Expand Down Expand Up @@ -122,7 +125,7 @@ def main(args=None):
}
)
SubsetMerger(
args.input, args.output, subsets, googlefonts=args.googlefonts
args.input, args.output, subsets, googlefonts=args.googlefonts, json=args.json
).add_subsets()


Expand Down
25 changes: 13 additions & 12 deletions Lib/gftools/subsetmerger.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from ufomerge import merge_ufos

from gftools.util.styles import STYLE_NAMES
from gftools.utils import download_file
from gftools.utils import download_file, open_ufo

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
Expand Down Expand Up @@ -92,12 +92,13 @@ def prepare_minimal_subsets(subsets):

class SubsetMerger:
def __init__(
self, input_ds, output_ds, subsets, googlefonts=False, cache="../subset-files"
self, input_ds, output_ds, subsets, googlefonts=False, cache="../subset-files", json=False
):
self.input = input_ds
self.output = output_ds
self.subsets = prepare_minimal_subsets(subsets)
self.googlefonts = googlefonts
self.json = json
self.cache_dir = cache
self.subset_instances = {}

Expand All @@ -107,13 +108,6 @@ def add_subsets(self):
outpath = Path(self.output).parent
added_subsets = False
for master in ds.sources:
# Clone the UFO before doing anything clever with it.
newpath = os.path.join(outpath, 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.subsets:
added_subsets |= self.add_subset(ds, master, subset)
if not added_subsets:
Expand All @@ -137,7 +131,7 @@ def add_subset(self, ds, ds_source, subset):
return False

# Open it up and send it to ufomerge, using the options supplied.
target_ufo = ufoLib2.Font.open(ds_source.path)
target_ufo = open_ufo(ds_source.path)
existing_handling = "skip"
if subset.get("force"):
existing_handling = "replace"
Expand All @@ -152,7 +146,14 @@ def add_subset(self, ds, ds_source, subset):
existing_handling=existing_handling,
layout_handling=layout_handling,
)
target_ufo.save(ds_source.path, overwrite=True)
if self.json:
if not ds_source.path.endswith(".json"):
ds_source.path += ".json"
if ds_source.filename:
ds_source.filename += ".json"
target_ufo.json_dump(open(ds_source.path+".json", "wb"))
else:
target_ufo.save(ds_source.path, overwrite=True)
return True

def obtain_upstream(self, upstream, location):
Expand Down Expand Up @@ -187,7 +188,7 @@ def obtain_upstream(self, upstream, location):
source_ds = DesignSpaceDocument.fromfile(path)
source_ufo = self.find_source_for_location(source_ds, location, font_name)
if source_ufo:
return ufoLib2.Font.open(source_ufo.path)
return open_ufo(source_ufo.path)
return None

def glyphs_to_ufo(self, source, directory=None):
Expand Down
10 changes: 10 additions & 0 deletions Lib/gftools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import sys
import os
import shutil
import ufoLib2
import unicodedata
from unidecode import unidecode
from collections import namedtuple
Expand Down Expand Up @@ -536,3 +537,12 @@ def primary_script(ttFont, ignore_latin=True):
most_common = script_count.most_common(1)
if most_common:
return most_common[0][0]


def open_ufo(path):
if os.path.isdir(path):
return ufoLib2.Font.open(path)
elif path.endswith(".json"):
return ufoLib2.Font.json_load(open(path, "rb"))
else: # Maybe a .ufoz
return ufoLib2.Font.open(path)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ dependencies = [
'vttlib',
'pygit2',
'strictyaml',
'fontmake>=3.3.0',
'fontmake[json]>=3.3.0',
'skia-pathops',
'statmake',
'PyYAML',
Expand Down

0 comments on commit f8e9df3

Please sign in to comment.