From a9708a25f25ff2b26296e1f3ec1819f33b1cbe70 Mon Sep 17 00:00:00 2001 From: Martin von Gagern Date: Sun, 20 Aug 2017 06:45:34 +0100 Subject: [PATCH] Modernize font creation (#624) * Modernize font creation * Automate the build process, instead of writing a complicated manual * Update sources used by the docker image away from google code * Exclude MathJax-dev checkout from docker image, to allow image reuse * Try to keep the individual image layers small by combining RUN commands and removing temporary files used only during each individual step * Allow creating fonts from local directory Also use hash of Dockerfile to compute image tag, in order to ensure creation of a new image if the Dockerfile changes. * make glob syntax work on MacOS --- dockers/MathJaxFonts/Dockerfile | 59 ++++++------ dockers/MathJaxFonts/README.md | 65 ++++--------- dockers/MathJaxFonts/buildFonts.sh | 148 +++++++++++++++++++++++++++++ dockers/MathJaxFonts/copy_fonts.sh | 47 --------- 4 files changed, 196 insertions(+), 123 deletions(-) create mode 100755 dockers/MathJaxFonts/buildFonts.sh delete mode 100755 dockers/MathJaxFonts/copy_fonts.sh diff --git a/dockers/MathJaxFonts/Dockerfile b/dockers/MathJaxFonts/Dockerfile index dc5b4e5c..d23a0752 100644 --- a/dockers/MathJaxFonts/Dockerfile +++ b/dockers/MathJaxFonts/Dockerfile @@ -2,7 +2,10 @@ FROM ubuntu:14.04 MAINTAINER xymostech # Install things -RUN apt-get -qq update && apt-get -qqy install \ +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get -y upgrade \ + && DEBIAN_FRONTEND=noninteractive apt-get -y install \ + --no-install-recommends --auto-remove \ git \ dvipng \ default-jre \ @@ -23,39 +26,41 @@ RUN apt-get -qq update && apt-get -qqy install \ woff-tools \ pkg-config \ libharfbuzz-dev \ - libfreetype6-dev || true -RUN gem install ttfunk --version 1.1.1 + libfreetype6-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && gem install ttfunk --version 1.1.1 # Download yuicompressor -RUN mkdir /usr/share/yui-compressor/ -RUN wget "https://github.com/yui/yuicompressor/releases/download/v2.4.8/yuicompressor-2.4.8.jar" -O /usr/share/yui-compressor/yui-compressor.jar +ADD https://github.com/yui/yuicompressor/releases/download/v2.4.8/yuicompressor-2.4.8.jar /usr/share/yui-compressor/yui-compressor.jar # Download batik-ttf2svg.jar -RUN wget "https://archive.apache.org/dist/xmlgraphics/batik/batik-1.7.zip" -RUN unzip -qq batik-1.7.zip -RUN mv batik-1.7/batik-ttf2svg.jar /usr/share/java/ +RUN wget "https://archive.apache.org/dist/xmlgraphics/batik/batik-1.7.zip" \ + && unzip batik-*.zip batik-*/batik-ttf2svg.jar \ + && mv batik-*/batik-ttf2svg.jar /usr/share/java/ \ + && rm -r batik-* # Download and compile ttf2eof (note we add a patch to make it compile) -RUN wget "https://ttf2eot.googlecode.com/files/ttf2eot-0.0.2-2.tar.gz" -RUN tar -xzf ttf2eot-0.0.2-2.tar.gz -RUN sed -i "1s/^/#include /" ttf2eot-0.0.2-2/OpenTypeUtilities.h -RUN make -C ttf2eot-0.0.2-2/ -RUN mv ttf2eot-0.0.2-2/ttf2eot /usr/bin/ +RUN wget "https://github.com/wget/ttf2eot/archive/v0.0.2-2.tar.gz" -O ttf2eot.tar.gz\ + && tar -xzf ttf2eot.tar.gz \ + && sed -i "1s/^/#include /" ttf2eot-*/OpenTypeUtilities.h \ + && make -C ttf2eot-*/ \ + && mv ttf2eot-*/ttf2eot /usr/bin/ \ + && rm -r ttf2eot* # Download and compile ttfautohint -RUN wget "http://download.savannah.gnu.org/releases/freetype/ttfautohint-1.3.tar.gz" -RUN tar -xzf ttfautohint-1.3.tar.gz -RUN cd ttfautohint-1.3/ && ./configure --without-qt -RUN make -C ttfautohint-1.3/ -RUN mv ttfautohint-1.3/frontend/ttfautohint /usr/bin +RUN wget "http://download.savannah.gnu.org/releases/freetype/ttfautohint-1.3.tar.gz" \ + && tar -xzf ttfautohint-*.tar.gz \ + && cd ttfautohint-*/ \ + && ./configure --without-qt \ + && make \ + && mv frontend/ttfautohint /usr/bin \ + && cd .. \ + && rm -r ttfautohint-* # Download and compile woff2_compress -RUN git clone "https://code.google.com/p/font-compression-reference/" woff2_compress -RUN make -C woff2_compress/woff2/ -RUN mv woff2_compress/woff2/woff2_compress /usr/bin/ - -# Download and setup MathJax-dev -RUN git clone "https://github.com/khan/MathJax-dev.git" -RUN cp MathJax-dev/default.cfg MathJax-dev/custom.cfg -RUN make -C MathJax-dev custom.cfg.pl - +RUN wget "https://github.com/google/woff2/archive/d9a74803fa884559879e3205cfe6f257a2d85519.tar.gz" -O woff2.tar.gz \ + && tar -xzf woff2.tar.gz \ + && make -C woff2-*/woff2/ \ + && mv woff2-*/woff2/woff2_compress /usr/bin \ + && rm -r woff2* diff --git a/dockers/MathJaxFonts/README.md b/dockers/MathJaxFonts/README.md index 1451bdc0..01e0c475 100644 --- a/dockers/MathJaxFonts/README.md +++ b/dockers/MathJaxFonts/README.md @@ -1,55 +1,22 @@ ### How to generate MathJax fonts --------------------------------- -It's really simple (now)! Just make a docker image from the included Dockerfile -using a command like +The `buildFonts.sh` script should do everything automatically, +as long as Docker is installed. - sudo docker build --tag=mathjaxfonts . +If you want to try out a change +to [the MathJax-dev repository](https://github.com/Khan/MathJax-dev), +create a local clone (or download and unpack the ZIP file) +and specify the path to this directory as an arument to `buildFonts.sh`. +You can also specify a local or remote tarball, +e.g. a GitHub download of your own personal feature branch. -from within this directory (note you need to have docker installed and running -for this to work). This will build a docker image with the mathjaxfonts tag, -which you can then use to run dockers based on them. Then, run a mathjaxfonts -docker with +The script `buildFonts.sh` automatically creates Docker images +from the supplied `Dockerfile`. +It uses the hash of the file to tag the image, so a change to the file +will result in the creation of a new image. +If you want to see all created images, run `docker images katex/fonts`. +To remove all generated images, you can run +`docker rmi $(docker images --format '{{.Repository}}:{{.Tag}}' katex/fonts)`. - sudo docker run --interactive --tty --name mjf mathjaxfonts /bin/bash - -We name this docker "mjf" so we can reference it later when we want to copy the -files off. (If you get an error about the name being in use, perhaps because you -are trying to create another docker, you can either delete the old docker with - - sudo docker rm mjf - -or use a different name.) This will get you into the docker in the root -directory. From there, cd into the `/MathJax-dev/fonts/OTF/TeX` directory, and -run - - make ttf eot woff woff2 - -to build all of the fonts that we need. Finally, leave the docker and copy all -the files off with the `copy_fonts.sh` script: - - ./copy_fonts.sh mjf - -And you're good to go! Don't forget to update the font metrics with `make -metrics`. - -### General Docker Help ------------------------ - -When you quit the docker, it will stop the docker from running. If you want to -reattach to the docker, you can start it again with - - sudo docker start mjf - -and then attach with - - sudo docker attach mjf - -Alternatively, if you want to detach from the docker when you're done instead of -quitting and stopping it, you can detach with `C-p C-q`, and then re-attach with - - sudo docker attach mjf - -To see a list of your current dockers, you can run - - docker ps +If there is a problem, file a bug report. diff --git a/dockers/MathJaxFonts/buildFonts.sh b/dockers/MathJaxFonts/buildFonts.sh new file mode 100755 index 00000000..e62b0e61 --- /dev/null +++ b/dockers/MathJaxFonts/buildFonts.sh @@ -0,0 +1,148 @@ +#!/usr/bin/env bash +shopt -s extglob + +usage() { + while [[ $# -gt 1 ]]; do + echo "$1" >&2 + shift + done + echo "Usage: ${0##*/} [OPTIONS] [SOURCE]" + echo "" + echo "SOURCE may be" + echo " - a URL for a tarball, or" + echo " - a local tarball file, or" + echo " - a local directory" + echo "with a layout compatible to MathJax-dev." + echo "It defaults to ${URL}" + echo "" + echo "OPTIONS:" + echo " -h|--help display this help" + echo " --image NAME:TAG use the named docker image [$IMAGE]" + exit $1 +} + +used_fonts=( + KaTeX_AMS-Regular + KaTeX_Caligraphic-Bold + KaTeX_Caligraphic-Regular + KaTeX_Fraktur-Bold + KaTeX_Fraktur-Regular + KaTeX_Main-Bold + KaTeX_Main-Italic + KaTeX_Main-Regular + KaTeX_Math-BoldItalic + KaTeX_Math-Italic + KaTeX_Math-Regular + KaTeX_SansSerif-Bold + KaTeX_SansSerif-Italic + KaTeX_SansSerif-Regular + KaTeX_Script-Regular + KaTeX_Size1-Regular + KaTeX_Size2-Regular + KaTeX_Size3-Regular + KaTeX_Size4-Regular + KaTeX_Typewriter-Regular +) + +filetypes=( ttf eot woff woff2 ) + +set -e +cd "$(dirname "$0")" + +cleanup() { + [[ "${CONTAINER}" ]] \ + && docker stop "${CONTAINER}" >/dev/null \ + && docker rm "${CONTAINER}" >/dev/null + CONTAINER= + [[ -f "${TMPFILE}" ]] && rm "${TMPFILE}" + TMPFILE= +} +CONTAINER= +trap cleanup EXIT + +IMAGE="katex/fonts:DF-$(openssl sha1 Dockerfile | tail -c 9)" +URL=https://github.com/Khan/MathJax-dev/archive/master.tar.gz +TMPFILE= +FILE= +NARGS=0 +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + usage 0 + ;; + --image=*) + IMAGE="${1#*=}" + ;; + --image) + shift + IMAGE="$1" + ;; + -*) + usage "Invalid option: $1" "" 1 + ;; + *) + case $NARGS in + 0) + if [[ -d "$1" ]]; then + TMPFILE="$(mktemp "${TMPDIR:-/tmp}/mjf.XXXXXXXX")" + FILE="$TMPFILE" + pushd "$1" + if [[ ! -f fonts/OTF/TeX/Makefile ]]; then + echo "$1 does not look like MathJax-dev" >&2 + exit 1 + fi + tar cf "$FILE" Makefile default.cfg fonts/OTF/TeX + popd + elif [[ -f "$1" ]]; then + FILE="$1" + elif [[ "$1" = http?(s)://* ]]; then + URL="$1" + else + echo "'$1' is not a valid source" >&2 + exit 1 + fi + NARGS=1 + ;; + *) + usage "Too many arguments: $1" "" 1 + ;; + esac + ;; + esac + shift +done + +# build image if missing +if [[ $(docker images "$IMAGE" | wc -l) -lt 2 ]]; then + echo "Need to build docker image $IMAGE" + docker build --tag "$IMAGE" . +fi + +CMDS="set -ex +test -f MathJax-dev.tar.gz || wget -O MathJax-dev.tar.gz '${URL}' +mk=\$(tar tf MathJax-dev.tar.gz | grep 'fonts/OTF/TeX/Makefile\$') +tar xf MathJax-dev.tar.gz +cd \"\${mk%fonts/*}\" +cp default.cfg custom.cfg +make custom.cfg.pl +make -C fonts/OTF/TeX ${filetypes[*]} +tar cf /fonts.tar ${filetypes[*]/#/fonts/OTF/TeX/}" + +echo "Creating and starting docker container from image $IMAGE" +CONTAINER=$(docker create "$IMAGE" /bin/sh -c "${CMDS}") +if [[ ${FILE} ]]; then + docker cp "${FILE}" $CONTAINER:/MathJax-dev.tar.gz +fi +docker start --attach $CONTAINER +docker cp $CONTAINER:/fonts.tar . +cleanup +echo "Docker executed successfully, will now unpack the fonts" + +tar xf fonts.tar +for filetype in "${filetypes[@]}"; do + for font in "${used_fonts[@]}"; do + echo "$filetype/$font" + mv "fonts/OTF/TeX/$filetype/$font".* ../../static/fonts/ + done +done +rm -rf fonts fonts.tar diff --git a/dockers/MathJaxFonts/copy_fonts.sh b/dockers/MathJaxFonts/copy_fonts.sh deleted file mode 100755 index d1cc0824..00000000 --- a/dockers/MathJaxFonts/copy_fonts.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [ -z "$1" ]; then - echo "Usage: $(basename $0) " - echo " If you followed the README, the docker name would be 'mjf'" - exit 1 -else - DOCKER_NAME="$1" -fi - -mkdir fonts - -used_fonts=( - KaTeX_AMS-Regular - KaTeX_Caligraphic-Bold - KaTeX_Caligraphic-Regular - KaTeX_Fraktur-Bold - KaTeX_Fraktur-Regular - KaTeX_Main-Bold - KaTeX_Main-Italic - KaTeX_Main-Regular - KaTeX_Math-BoldItalic - KaTeX_Math-Italic - KaTeX_Math-Regular - KaTeX_SansSerif-Bold - KaTeX_SansSerif-Italic - KaTeX_SansSerif-Regular - KaTeX_Script-Regular - KaTeX_Size1-Regular - KaTeX_Size2-Regular - KaTeX_Size3-Regular - KaTeX_Size4-Regular - KaTeX_Typewriter-Regular -) - -for filetype in ttf eot woff woff2; do - echo "Copying $filetype" - docker cp "$DOCKER_NAME":/MathJax-dev/fonts/OTF/TeX/"$filetype" fonts - - for font in ${used_fonts[*]}; do - mv fonts/"$filetype"/"$font"* fonts/ - done - - rm -rf fonts/"$filetype" -done