DEV Community

loading...
Cover image for Converting my OTF font into multiple web fonts with this bash script

Converting my OTF font into multiple web fonts with this bash script

Jan Küster
Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
・4 min read

I came across this use-case where we had to use a specific custom font but it was only available in .otf. However, we want to support multiple formats to ensure even deprecated browsers can load the font. Otf has a global coverage of 97.89% but we didn't want to take any chances of the font not loading as it's a crucial feature in our app.

I wanted to convert the font to support the following browsers:

  • woff2 - Latest browsers 🚀
  • woff - Modern browsers 👍
  • ttf - Apple and mobile OS 🍎📱
  • svg - older safari and ios support 😢
  • eot - older IE support 😢

I am skipping svg as I found no converter package, fulfilling the same requirements as the others (available from Ubuntu repositories without additional sources).

The goal

Consider my font being custom.otf then the font face should look like the following:

@font-face {
  font-family: 'Custom';
  src: url('custom.woff2') format('woff2'),
       url('custom.woff') format('woff'), 
       url('custom.ttf')  format('truetype'),
       url('custom.otf')  format('truetype'),
       url('custom.eot') format('embedded-opentype');
}
Enter fullscreen mode Exit fullscreen mode

The loading order is from latest to oldest so the majority should get the woff2/woff files.

Why not using an online converter?

Now I know there are many converters out there but I have some issues with them

  • I can't upload the font, since the license forbids it
  • I don't know what I download with the font into my system
  • I don't have the time to check each of them

Let's see what Ubuntu provides out of the box

I immediatley thought I should check my Ubuntu repositories and do some research on tools to convert into all the required types:

package command description
eot-utils mkeot convert otf to eot
eot2ttf eot2ttf convert eot to ttf
woff-tools sfnt2woff convert otf to woff
woff2 woff2_compress convert ttf to woff2
- - convert any of them to svg

Let's create a simple bash script

The script should take in a single otf file and convert it to separate oet, ttf, woff and woff2 files on a given destination folder.

It should furthermore check, if the inputs are correct and the packages are installed.

The next parts are showing the script from top to bottom, split by some comments. If you combine all the parts into one file you will get the final script.

First of all, we create a new file

$ touch convertOtf.sh
Enter fullscreen mode Exit fullscreen mode

Then we open it with our editor of choice, add the shebang and set the script to exit on the first error:

#!/usr/bin/env bash

set -e
Enter fullscreen mode Exit fullscreen mode

Now check the parameters and create local variables from them:

SOURCE=$1
DESTINATION=$2
FILENAME=$(basename "${SOURCE%.otf}")

# we omit mime check since we use this script only locally and assume it's otf
if [[ ${SOURCE: -4} != ".otf" ]]; then
  echo "usage: convertOtf input.otf /path/to/output/"
  exit 1
fi

# check the destination is a folder
if [[ ! -d "$DESTINATION" ]]; then
  echo "usage: convertOtf input.otf /path/to/output/"
  exit 1
fi
Enter fullscreen mode Exit fullscreen mode

We could directly add installing the commands into the script but it should be kept simple so we just warn of missing packages and exit:

ALLCOMMANDS=(
  mkeot
  eot2ttf
  sfnt2woff
  woff2_compress
)

# iterate the ALLCOMMANDS list to check for each required command
# skip as soon as a command is not found
for CMD in "${ALLCOMMANDS[@]}"
do
   :
   if [[ ! -f $(command -v "$CMD") ]];then
        echo "Cannot convert ($CMD). The following packages are required: eot-utils eot2ttf woff-tools woff2"
        exit 1
    fi
done
Enter fullscreen mode Exit fullscreen mode

Now that we've covered the requirements to convert our file we can now run the tools. Note, that they have to be in the right order, because some depend on the ouput of one another:

EOT_PATH="$DESTINATION/$FILENAME.eot"
echo "[OTF ---> EOT]: (over-)write to $EOT_PATH"
mkeot ${SOURCE} > ${EOT_PATH}

TTF_PATH="$DESTINATION/$FILENAME.ttf"
echo "[EOT ---> TTF]: (over-)write to $TTF_PATH"
eot2ttf ${EOT_PATH} ${TTF_PATH}

WOFF_PATH="$DESTINATION/$FILENAME.woff"
echo "[OTF --> WOFF]: (over-)write to $WOFF_PATH"
sfnt2woff ${SOURCE} > ${WOFF_PATH}

WOFF2_PATH="$DESTINATION/$FILENAME.woff2"
echo "[TTF -> WOFF2]: (over-)write to $WOFF2_PATH"
woff2_compress ${TTF_PATH} > ${WOFF2_PATH}

exit 0
Enter fullscreen mode Exit fullscreen mode

Running the script

First, make the script executable, then run it with our otf font as first input and a destination folder as second input:

$ chmod +x ./convertOtf.sh
$ ./convertOtf.sh custom.otf ./out
[OTF ---> EOT]: (over-)write to ./out/custom.eot
[EOT ---> TTF]: (over-)write to ./out/custom.ttf
[OTF --> WOFF]: (over-)write to ./out/custom.woff
[TTF -> WOFF2]: (over-)write to ./out/custom.woff2
Compressed 25698 to 16389.
Enter fullscreen mode Exit fullscreen mode

Summary

The script is a simple way to convert an otf to multiple webfont formats using only tools that Ubuntu brings with it's default repositories.

I am no bash guru, so please comment if you think there are parts in the code (or in the article in general) that can be improved 🙇

Resources used for this article

https://caniuse.com/
https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face
https://css-tricks.com/snippets/css/using-font-face/
https://github.com/ikatyang/emoji-cheat-sheet
https://stackoverflow.com/
https://help.ubuntu.com/stable/ubuntu-help/addremove-install-synaptic.html.en

Discussion (0)