#!/bin/sh set -e # # This script subsets our variable fonts, # converts them to woff2 files and puts them in the # fonts folder. # # We do have to update the font paths in the @font-face # definitions manually since we use a checksum to make # # We use fonttools to create a partial instance of the # variable font where we keep only our needed features. # See more at: # https://fonttools.readthedocs.io/en/latest/varLib/instancer.html # # fonttools requires python > 3.7. For up-to-date # instructions see https://github.com/fonttools/fonttools#installation # # Lot's of info was gathered from: # https://markoskon.com/creating-font-subsets/ # https://barrd.dev/article/create-a-variable-font-subset-for-smaller-file-size/ # ORIGINAL_FONTS="./originalMedia/fonts" TEMP_FOLDER="./.subset-fonts-temp" FONT_FOLDER="./src/assets/fonts" err_report() { echo "Error on line $(caller)" >&2 } trap err_report ERR mkdir -p $TEMP_FOLDER # the latin subset that google uses on GoogleFonts # this is the same as the latin subset range that google uses on GoogleFonts # see for examle the unicode-range definition here: # https://fonts.googleapis.com/css2?family=Open+Sans UNICODE_LATIN_SUBSET="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" get_filename_without_type() { filename=$1 dirname=$(dirname $filename) # Extract the file type using parameter expansion filetype=${filename##*.} basename=$(basename $filename .$filetype) echo $basename } # This function takes a font file and creates a subset of it using a specified set of unicode characters. instance_and_subset () { # Define default arguments for the subsetter. DEFAULT_SUBSETTER_ARGS="--layout-features=* --unicodes=${UNICODE_LATIN_SUBSET}" # Assign function arguments to variables with more descriptive names. INPUT_FONT_FILE=$1 INSTANCER_ARGS=$2 OUTPUT_FONT_BASENAME=$3 OUTPUT_FOLDER=$FONT_FOLDER # If the output font basename is not provided, use the input font file's basename as the output font basename. if [ -z "$OUTPUT_FONT_BASENAME" ]; then INPUT_FONT_BASENAME=$(get_filename_without_type $INPUT_FONT_FILE) OUTPUT_FONT_BASENAME=$INPUT_FONT_BASENAME fi # Use the default subsetter arguments if no custom arguments are provided. SUBSETTER_ARGS="${4:-$DEFAULT_SUBSETTER_ARGS}" CHECKSUM=$( # Concatenate the contents of the input font file, the instancer arguments, and the subsetter arguments printf "%s%s" "$(cat $INPUT_FONT_FILE)" "$INSTANCER_ARGS" "$SUBSETTER_ARGS" | # Calculate the Blake2b checksum of the concatenated string b2sum | # Extract the checksum from the output of b2sum (it's the first field) awk '{print $1}' ) # Limit the checksum to 8 characters. CHECKSUM=$(echo "${CHECKSUM:0:8}") # Construct the output font's filename OUTPUT_FONT_BASENAME="${OUTPUT_FONT_BASENAME}_${CHECKSUM}" OUTPUT_FONT_FILE="${OUTPUT_FOLDER}/${OUTPUT_FONT_BASENAME}.woff2" # Check if the output font file already exists if test -f $OUTPUT_FONT_FILE; then echo "${OUTPUT_FONT_FILE} exists" return 0 fi FONT_INSTANCE="${TEMP_FOLDER}/${OUTPUT_FONT_BASENAME}.ttf" if [ -n "$INSTANCER_ARGS" ]; then # If the INSTANCER_ARGS variable is set, use fonttools to create a font instance fonttools varLib.instancer --output $FONT_INSTANCE $INPUT_FONT_FILE $INSTANCER_ARGS else # Otherwise, just copy the input font file to the font instance file cp $INPUT_FONT_FILE $FONT_INSTANCE fi # Use pyftsubset to create a subset of the font instance and save it to the output font file pyftsubset $FONT_INSTANCE --output-file=$OUTPUT_FONT_FILE --flavor=woff2 $SUBSETTER_ARGS echo "${OUTPUT_FONT_BASENAME} subsetted." } echo "" echo "###################################################" echo "# Install required libs" echo "###################################################" echo "" pip install fonttools brotli echo "" echo "###################################################" echo "# Create a partial instance of the variable font" echo "# where we keep only our needed features and then" echo "# subset fonts with latin unicode range and export" echo "# as woff2 file" echo "###################################################" echo "" mkdir -p $TEMP_FOLDER echo "\nOpen Sans" # we drop the wdth axis for all instance_and_subset "${ORIGINAL_FONTS}/OpenSans[wdth,wght].ttf" "wdth=drop wght=400:700" "OpenSans[wght]" # we restrict the wght range instance_and_subset "${ORIGINAL_FONTS}/OpenSans[wdth,wght].ttf" "wdth=drop wght=400" "OpenSans-Regular" instance_and_subset "${ORIGINAL_FONTS}/OpenSans[wdth,wght].ttf" "wdth=drop wght=700" "OpenSans-Bold" echo "\nOpen Sans Italic" # we drop the wdth axis for all instance_and_subset "${ORIGINAL_FONTS}/OpenSans-Italic[wdth,wght].ttf" "wdth=drop wght=400:700" "OpenSans-Italic[wght]" # we restrict the wght range instance_and_subset "${ORIGINAL_FONTS}/OpenSans-Italic[wdth,wght].ttf" "wdth=drop wght=400" "OpenSans-RegularItalic" instance_and_subset "${ORIGINAL_FONTS}/OpenSans-Italic[wdth,wght].ttf" "wdth=drop wght=700" "OpenSans-BoldItalic" echo "\nQuicksand" instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=400:700" # we restrict the wght range instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=400" "Quicksand-Regular" instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=600" "Quicksand-SemiBold" instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=700" "Quicksand-Bold" echo "\nSubsetting files complete" # remove temp folder rm -r $TEMP_FOLDER