Skip to content

Commit

Permalink
🔨 generate fonts/embedded.css with data-uri faces
Browse files Browse the repository at this point in the history
  • Loading branch information
samizdatco committed Oct 19, 2023
1 parent 7c79bac commit d73814e
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 5 deletions.
10 changes: 8 additions & 2 deletions devTools/fonts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ BUILD_DIR := $(VENV)/build
FONTS_DIR := ../../public/fonts
FONTS_CSS := ../../public/fonts.css
FACES = $(BUILD_DIR)/fonts.css
EMBEDS = $(BUILD_DIR)/embedded.css

LATO_WOFFS = $(wildcard $(LATO)/Lato-*.woff2)
LATO_LATIN_WOFFS = $(subst Lato-,LatoLatin-,$(LATO_WOFFS))
Expand All @@ -35,7 +36,7 @@ LatoLatin-%: Lato-%
PLAYFAIR := $(BUILD_DIR)/playfair
PLAYFAIR_URL := https://fonts.google.com/download/list?family=Playfair%20Display
$(PLAYFAIR).tsv:
curl -sL $(PLAYFAIR_URL) | tail -n +2 | \
curl -sL $(PLAYFAIR_URL) | tail -n +2 | \
jq -r '.manifest.fileRefs[] | select(.filename | contains("Variable") | not) | [.url, .filename] | @tsv' \
> $@
$(PLAYFAIR): $(PLAYFAIR).tsv
Expand All @@ -58,9 +59,13 @@ $(VENV):
$(FACES): $(VENV) $(FONTS)
@$(PYTHON) make-faces.py $(FONTS) | $(PRETTIER) --parser css > $@

$(EMBEDS): $(VENV) $(FONTS)
@$(PYTHON) make-faces.py --embed $(FONTS) | $(PRETTIER) --parser css > $@

all: $(VENV) $(LATO) $(PLAYFAIR)
rm -f $(FACES)
rm -f $(FACES) $(EMBEDS)
$(MAKE) -j8 $(FACES)
$(MAKE) -j8 $(EMBEDS)
@for font in $(LATO)/*.woff2 $(PLAYFAIR)/*.woff2; do \
diff -q "$$font" $(FONTS_DIR)/`basename "$$font"` || true; \
done
Expand All @@ -84,6 +89,7 @@ test:
install: $(FONTS) $(FACES)
mkdir -p $(FONTS_DIR)
cp $(FONTS) $(FONTS_DIR)
cp $(EMBEDS) $(FONTS_DIR)
cp $(FACES) $(FONTS_CSS)

clean:
Expand Down
1 change: 1 addition & 0 deletions devTools/fonts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ You can also run `make report` to display the current division of characters bet

- Python3 (in order to use the [`fontTools.ttLib`](https://pypi.org/project/fonttools/) module for converting otf to woff2, creating the LatoLatin & PlayfairLatin fonts with its [subset](https://fonttools.readthedocs.io/en/latest/subset/index.html) tool, and unpacking the `cmap` table to calculate `unicode-range` settings for switching between the subset and full version in the browser)
- the repo's copies of prettier and express in `../../node_modules`
- the `jq` command line tool

## Typefaces

Expand Down
46 changes: 43 additions & 3 deletions devTools/fonts/make-faces.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from more_itertools import consecutive_groups
from operator import itemgetter
from os.path import basename, splitext
from base64 import b64encode
import sys
import re

Expand Down Expand Up @@ -52,7 +53,8 @@ def inspect_font(path):
italic = italic,
style = "italic" if italic else "normal",
codepoints = codepoints,
url = f'/fonts/{basename(path)}'
url = f'/fonts/{basename(path)}',
path = path,
)

def find_ranges(iterable):
Expand Down Expand Up @@ -90,7 +92,7 @@ def make_face(font, subset=None, singleton=False):

return "\n".join(css)

def main(woff_files):
def main_stylesheet(woff_files):
fonts = sorted([inspect_font(f) for f in woff_files], key=itemgetter('weight', 'italic'))
lato = [f for f in fonts if f['family']=='Lato' and not f['subset']]
lato_latin = [f for f in fonts if f['family']=='Lato' and f['subset']]
Expand All @@ -111,6 +113,44 @@ def main(woff_files):
]
print("\n\n".join(faces))

def make_embedded_face(font):
font_data = open(font['path'], 'rb').read()
font_uri = 'data:font/woff2;base64,' + b64encode(font_data).decode('utf-8')
family = font['family']
weight = font['weight']
style = font['style']

css = [
'@font-face {',
f'font-family: "{family}";',
f'font-weight: {weight};',
f'font-style: {style};',
f'src: url({font_uri}) format("woff2");',
"}",
]
return " ".join(css)

def embedded_stylesheet(woff_files):
font_info = [inspect_font(f) for f in woff_files]

# include just the fonts known to be used in static chart exports
embeddable_fonts =[
'Lato-Regular',
'Lato-Italic',
'Lato-Bold',
'PlayfairDisplay-SemiBold',
]

# use the latin subsets to keep the size down
faces = [make_embedded_face(f) for f in font_info if f['subset'] and f['ps_name'] in embeddable_fonts]
print("\n".join(faces))

if __name__ == "__main__":
main(sys.argv[1:])
args = sys.argv[1:]
if '--embed' in args[:1]:
embedded_stylesheet(args[1:])
elif args:
main_stylesheet(args)
else:
print("Usage: make-faces.py [--embed] woff2-files...")

28 changes: 28 additions & 0 deletions public/fonts/embedded.css

Large diffs are not rendered by default.

0 comments on commit d73814e

Please sign in to comment.