glyphhanger

repository·master·Indexed 22 days ago

https://github.com/filamentgroup/glyphhanger

A web font utility tool for subsetting web fonts and analyzing unicode ranges used on websites to optimize font delivery. It provides a CLI to audit web pages for character usage, generate optimized font subsets, and create @font-face CSS rules. The tool can automate subsetting or be used to generate unicode lists for manual subsetting via pyftsubset.

Tokens
6.6K
Snippets
18
Records
30
Agent score
77%

What's inside glyphhanger

  1. Overview of glyphhanger

    master

    glyphhanger is a web font utility belt designed to optimize font usage on websites. Its primary capabilities include:

    • Subsetting web fonts: Creating smaller font files containing only the characters you need.
    • Analyzing unicode-ranges: Identifying which unicode ranges are actually used on a specific website (with optional per-font-family analysis).
    • Automated subsetting: Automatically subsetting web fonts based on the unicode ranges discovered during site analysis.
  2. Subset fonts manually using `pyftsubset`

    master

    While GlyphHanger can automate subsetting using the --subset option (available since v1.0.5), you can perform the process manually by piping GlyphHanger's output to pyftsubset.

    Note: Do not use DEBUG mode when performing this manual workflow, as the output must be saved to a file to be used as a unicode list for pyftsubset.

    # 1. Generate the unicode list from your HTML
    glyphhanger ./test.html > glyphhanger_output
    
    # 2. Use pyftsubset to create the subset font
    pyftsubset FONTFILENAME.ttf --unicodes-file=glyphhanger_output --flavor=woff
    
    # 3. Clean up the temporary unicode list
    rm glyphhanger_output
  3. How to use pyftsubset for font subsetting

    master

    pyftsubset is a command-line tool used to subset and optimize OpenType fonts (.otf, .ttf, .woff). Subsetting reduces font file size by including only the specific glyphs or characters required for a project.

    To use it, you must provide an input font file and at least one method of specifying which glyphs to keep (e.g., via Unicode codepoints, specific text, or glyph IDs).

    Basic Syntax:

    pyftsubset font-file [glyph...] [--option=value]...
    pyftsubset font.ttf --unicodes="U+0020-0025"
  4. Configure `pyftsubset` output flavors

    master

    When manually subsetting fonts with pyftsubset, you can specify the output format using the --flavor flag. Common configurations include:

    • WOFF: Use --flavor=woff.
    • WOFF2: Use --flavor=woff2 (requires additional installation steps).
    • TTF: For compatibility with older Android devices, omit the --flavor flag entirely to output a subsetted .ttf file.

    To achieve additional byte savings for WOFF files, you can install py-zopfli and use the --with-zopfli flag. Note that --with-zopfli is ignored for WOFF2.

    # Output WOFF with Zopfli compression (requires py-zopfli)
    pyftsubset FONTFILENAME.ttf --unicodes-file=glyphhanger_output --flavor=woff --with-zopfli
    
    # Output WOFF2
    pyftsubset FONTFILENAME.ttf --unicodes-file=glyphhanger_output --flavor=woff2
    
    # Output TTF (for old Android compatibility)
    pyftsubset FONTFILENAME.ttf --unicodes-file=glyphhanger_output
  5. Choose between JSDOM and Puppeteer environments

    master

    GlyphHanger supports two execution environments for analyzing web content:

    1. JSDOM: A lightweight, pure JavaScript implementation of the DOM. It is faster and does not require a full browser, but it may not execute complex JavaScript or handle CSS as accurately as a real browser.
    2. Puppeteer: A headless Chrome/Chromium browser. This is the more robust option and is required if your target content relies heavily on complex JavaScript execution or specific browser behaviors. Puppeteer environments require a web server to be running if you are accessing content via a URL.

    You can switch between them by setting the environment type in the GlyphHangerEnvironment class.

  6. Use the GlyphHanger CLI

    master

    GlyphHanger is a command-line tool used to audit web pages for character usage and generate optimized font subsets. You can run it by passing URLs as arguments or by piping text into it via standard input. It can identify which characters are actually used on your site and then create subsetted font files (e.g., .ttf) and corresponding @font-face CSS rules to reduce font file size.

    # Basic usage with a URL
    glyphhanger http://localhost/
    
    # Using a whitelist of characters
    glyphhanger http://localhost/ --whitelist=ABCD
    
    # Subsetting specific font files
    glyphhanger http://localhost/ --subset=*.ttf
  7. Example: Create a highly compatible subset font

    master

    This example demonstrates how to produce a subset containing specific characters while preserving maximum compatibility and metadata (useful for complex typography or PDF generation):

    $ pyftsubset font.ttf --unicodes="U+0020-0025" \
        --layout-features='*' --glyph-names --symbol-cmap --legacy-cmap \
        --notdef-glyph --notdef-outline --recommended-glyphs \
        --name-IDs='*' --name-legacy --name-languages='*'
    pyftsubset font.ttf --unicodes="U+0020-0025" \
        --layout-features='*' --glyph-names --symbol-cmap --legacy-cmap \
        --notdef-glyph --notdef-outline --recommended-glyphs \
        --name-IDs='*' --name-legacy --name-languages='*'
  8. Manage OpenType layout features in pyftsubset

    master

    You can control which OpenType layout features are preserved in the subset. This is critical for maintaining correct typography (like kerning or ligatures).

    Use the following syntax with --layout-features:

    • =: Set the exact set of features.
    • +=: Add features to the existing set.
    • -=: Exclude specific features from the set.

    Examples:

    • --layout-features+=onum,pnum,ss01: Keep defaults and add onum, pnum, and ss01.
    • --layout-features-='mark','mkmk': Keep defaults but drop mark and mkmk.
    • --layout-features='kern': Keep only the kern feature; drop all others.
    • --layout-features='*': Keep all features.

    By default, pyftsubset preserves a standard set including calt, ccmp, clig, curs, kern, liga, locl, mark, mkmk, rclt, and rlig.

    To see the full list of default features, run: pyftsubset --layout-features=?.

  9. Specify glyphs for subsetting in pyftsubset

    master

    You can populate the initial glyph set using several different methods. These options are cumulative; you can use multiple options to build your set.

    OptionDescription
    --gids=<NNN>[,<NNN>...]Comma/whitespace-separated list of decimal glyph IDs or ranges (e.g., 10-12,14).
    --gids-file=<path>Reads glyph IDs from a file. Lines starting with # are ignored.
    --glyphs=<name>[,<name>...]Comma/whitespace-separated PostScript glyph names. Use * to keep the entire set.
    --glyphs-file=<path>Reads PS glyph names from a file. Lines starting with # are ignored.
    --text=<text>A UTF-8 string of characters to include.
    --text-file=<path>Reads characters from a file. Newlines are not added to the subset.
    --unicodes=<XXXX>[,<XXXX>...]Comma/whitespace-separated hex Unicode codepoints or ranges (e.g., 41-5a or U+0041-005A). Use * for all mapped characters.
    --unicodes-file=<path>Reads Unicode codepoints from a file. Lines starting with # are ignored.

    Error Handling:

    • --ignore-missing-glyphs: Do not fail if requested glyphs/gids are missing.
    • --no-ignore-missing-glyphs: Stop and fail if requested glyphs/gids are missing (default).
    • --ignore-missing-unicodes: Do not fail if requested Unicode characters are missing (default).
    • --no-ignore-missing-unicodes: Stop and fail if requested Unicode characters are missing.
  10. Optimize font size by stripping hinting and tables

    master

    To create extremely small webfonts for high-resolution displays, you can strip metadata and hinting:

    Hinting:

    • --no-hinting: Drops glyph-specific and font-wide hinting tables. This can reduce size by up to 30%.
      • Warning: Stripping hints from CFF fonts can sometimes make them unusable in browsers. Use --desubroutinize to mitigate this.

    Tables:

    • --drop-tables[+|-]=<table>...: Specify tables to remove. By default, several tables like DSIG, SVG, and color tables are dropped.
    • --passthrough-tables: Prevents the tool from dropping tables it doesn't know how to subset.
    • --no-subset-tables+=<table>...: Prevents specific tables from being subsetted (they are kept as-is).
  11. Reference: GlyphHangerSubset subset methods

    master

    The GlyphHangerSubset class exposes two primary methods for executing the subsetting command via pyftsubset.

    subsetAll(unicodes, formats)
    
    subset(inputFile, unicodes, format, useZopfli)