Skip to content

Compiling FreeType

metafloor edited this page Aug 29, 2016 · 2 revisions
  • Any version of linux should work, although I have only tested this on 32-bit lubuntu.

  • From Windows, use a pre-built VMware Player for 32-bit lubuntu. I would not recommend trying to compile freetype directly from Windows. There are too many unix-y things about the freetype compilation process that emscripten will likely have trouble with.

  • Update linux with the required build dependencies:

    $ sudo apt-get install git
    $ sudo apt-get install default-jre
    $ sudo apt-get install cmake
    $ sudo apt-get install g++
    
  • Goto the node.js web site and download, build, and install node.

  • Download and unpack emscripten. I used emsdk-portable for linux and installed to ~/emsdk.

  • Follow the install instructions on the emsdk page. At the time of writing:

    $ cd ~/emsdk
    $ ./emsdk update
    $ ./emsdk install latest
    $ # Get a cup of coffee or two....
    $ ./emsdk activate latest
    $ . emsdk_env.sh
    
  • Goto the freetype web site and download and unpack the latest freetype source. I installed to ~/freetype-2.5.5.

  • cd ~/freetype-2.5.5

  • Customize modules.cfg. For bwip-js, I commented out everything that was not needed to render OpenType and TrueType fonts. This was done to make the resulting JavaScript module as small as possible.

    View file modules.cfg

    Comment lines beginning #MRW were added by the author.

  • Next, you must empty the file builds/exports.mk:

    #
    # FreeType 2 exports sub-Makefile
    #
    
    # EOF 
    
  • Emscripten maintains tables of function pointers which are indexed both by return type and their parameter types. The FreeType hinting code casts functions returning int to functions returning void, which causes a function-not-found exception when working with certain fonts. You must make the following change to src/autofit/aftypes.h:

    typedef int
    (*AF_WritingSystem_ApplyHintsFunc)( AF_GlyphHints    hints,
                                        FT_Outline*      outline,
                                        AF_StyleMetrics  metrics );
    

    The void return type must be changed to int as shown above.

  • By default, FreeType links in zlib and gzip to handle fonts compressed for the X-Windows system. Those dependencies cause link-time issues for Emscripten. Disable by commenting out the following directives in include/config/ftoption.h:

    /* #define FT_CONFIG_OPTION_USE_LZW */
    /* #define FT_CONFIG_OPTION_USE_ZLIB */
    
  • There are the glyph metrics plus the bitmap that we need to move between the freetype module and bwip-js. Due to emscripten's architecture, this is not straightforward. The best approach I have found is to create a main.c which initializes the freetype library and defines functions we can call directly from JavaScript.

    View file main.c

  • From bwip.js, this is what the freetype interface looks like:

    BWIPJS.ft_lookup = Module.cwrap("find_font", 'number', ['string']);
    BWIPJS.ft_bitmap = Module.cwrap("get_bitmap", 'number', ['number','number','number']);
    BWIPJS.ft_width  = Module.cwrap("get_width", 'number', []);
    BWIPJS.ft_height = Module.cwrap("get_height", 'number', []);
    BWIPJS.ft_left   = Module.cwrap("get_left", 'number', []);
    BWIPJS.ft_top    = Module.cwrap("get_top", 'number', []);
    BWIPJS.ft_advance= Module.cwrap("get_advance", 'number', []);
    
  • Separate functions are provided to get the glyph bitmap (which initializes the glyph slot struct with its corresponding metrics) and each glyph metric.

  • Another issue to consider is how to include the OCR font files so freetype has access to them. emscripten provides two options, either embedding the files in the compiled JavaScript, or demand loading them using XHR. For this initial release, I chose to embed them.

  • Build freetype with emscripten and compile in main.c:

    $ emconfigure ./configure
    $ emmake make
    $ emcc -I ./include -o main.o main.c
    $ emcc -O3 --embed-file OCRA.otf --embed-file OCRB.otf -s NO_EXIT_RUNTIME=1 \
      -s EXPORTED_FUNCTIONS='["_main","_load_font","_find_font","_get_bitmap",\
      "_get_left","_get_top","_get_width","_get_height","_get_pitch","_get_advance"]' \
      main.o objs/.libs/libfreetype.so -o freetype.js
    
  • You should now have two files in your working directory:

    freetype.js
    freetype.js.mem
    
  • To use in a browser, include only freetype.js in a <script> tag. The mem-file will be demand loaded. The test file freetype.html shows how to use the library:

    View file freetype.html

    The files freetype.js and freetype.js.mem are also available in the repository.