Skip to content

Instantly share code, notes, and snippets.

@joshhunt
Created February 14, 2024 14:08
Show Gist options
  • Save joshhunt/2d3240c0d6ff722b9abebae09f23df75 to your computer and use it in GitHub Desktop.
Save joshhunt/2d3240c0d6ff722b9abebae09f23df75 to your computer and use it in GitHub Desktop.
Subsetting fonts

This summarises an experiment in attempting to subset a font (Inter) into multiple unicode ranges for smaller files if the UI only uses a subset of the supported characters. It's kind code splitting but for fonts :)

Background:

  • Inter used to publish 'official' subsetted fonts, but they disabled it as it broke certain type feature substitutions like ccmp. I don't think that's that much of an issue, but useful to know

To run:

cd grafana/public/fonts
docker build . --tag grafana-font-subset
docker run --rm -v (pwd):/fonts grafana-font-subset -u $(whoami)
FROM python:3.7-alpine
RUN apk add --no-cache bash
RUN pip install fonttools brotli zopfli
ADD ./subset-fonts.sh /subset-fonts.sh
ENTRYPOINT [ "bash", "/subset-fonts.sh", "/fonts", "#{$font-file-path}/" ]
#!/bin/bash
# This script uses the python fonttools package to generate subsets of fonts to reduce file size.
# It's designed to run in the docker included in this same directory.
fonts_dir=$1
public_dir=$2
# Maps a font name to a CSS font-style value for the CSS output
get_css_font_style() {
if [[ $1 == *"Italic"* ]]; then
echo "italic"
else
echo "normal"
fi
}
# Maps a font name to a CSS font-weight value for the CSS output
get_css_font_weight() {
if [[ $1 == *"Medium"* ]]; then
echo "500"
else
echo "400"
fi
}
subset_inter() {
subset_name=$1
unicode_range=$2
for font in "${inter_font_files[@]}"; do
echo "Subsetting $font with $subset_name..."
output="inter/generated-subsets/$font-$subset_name.woff2"
pyftsubset "$fonts_dir/inter/$font.woff2" \
--unicodes="$unicode_range" \
--layout-features="*" \
--flavor="woff2" \
--output-file="$fonts_dir/$output"
css=$(cat <<EOF
@font-face {
font-family: 'Inter';
font-style: $(get_css_font_style "$font");
font-weight: 400 500;
font-display: swap;
src: url('$public_dir$output') format('woff2');
unicode-range: $unicode_range;
}
EOF
)
echo "$css" >> /tmp/_temp_inter.css
done
}
# Each font file that we want to subset. If adding additional weights or styles, remember to update
# the get_css_font_style and get_css_font_weight functions
inter_font_files=(
"InterVariable"
"InterVariable-Italic"
)
# Each subset we want to generate. First value is the subset name, second value is the unicode range to subset
subset_inter "cyrillic-ext" "U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F"
subset_inter "cyrillic" "U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116"
subset_inter "greek-ext" "U+1F00-1FFF"
subset_inter "greek" "U+0370-03FF"
subset_inter "vietnamese" "U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB"
subset_inter "latin-ext" "U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF"
subset_inter "latin" "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
echo ""
echo ""
echo "Here's the CSS to copy into inter.css. Remember to make sure the font file paths are correct!"
echo ""
cat /tmp/_temp_inter.css
rm /tmp/_temp_inter.css
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment