msdfgen

repository·master·Indexed 26 days ago

https://github.com/chlumsky/msdfgen

A utility and C++ library for generating multi-channel signed distance fields (MSDF) from vector shapes, SVG files, and font glyphs. It enables high-quality, sharp-edged shape rendering in real-time graphics with minimal texture memory. The tool supports multiple modes including SDF, PSDF, MSDF, and MTSDF, and provides a command-line interface for generation and a C++ API for integration.

Tokens
3.9K
Snippets
4
Records
17
Agent score
39%

What's inside msdfgen

  1. Install msdfgen via vcpkg or CMake

    master

    You can use msdfgen as a library in your C++ projects. The easiest way to install it is via the vcpkg package manager:

    vcpkg install msdfgen

    Alternatively, you can build from source using the included CMake script. By default, CMake uses vcpkg to provide third-party dependencies. If you set the VCPKG_ROOT environment variable to your vcpkg directory, CMake will automatically fetch the required packages.

  2. Render MSDF in GLSL shaders

    master

    To use a multi-channel signed distance field (MSDF) in a fragment shader, sample the texture and compute the median of the three color channels.

    Important: Interpret MSDF color channels in linear space, not sRGB.

    Basic Implementation

    in vec2 texCoord;
    out vec4 color;
    uniform sampler2D msdf;
    uniform vec4 bgColor;
    uniform vec4 fgColor;
    
    float median(float r, float g, float b) {
        return max(min(r, g), min(max(r, g), b));
    }
    
    void main() {
        vec3 msd = texture(msdf, texCoord).rgb;
        float sd = median(msd.r, msd.g, msd.b);
        float screenPxDistance = screenPxRange()*(sd - 0.5);
        float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);
        color = mix(bgColor, fgColor, opacity);
    }

    Calculating screenPxRange()

    screenPxRange() represents the distance field range in output screen pixels.

    For 2D rendering: Use a precomputed uniform value. If the pixel range was set to 2 for a 32x32 field drawn on a 72x72 quad, the value is (72/32) * 2 = 4.5.

    For 3D perspective: Use fragment derivatives to handle varying texture scales:

    uniform float pxRange; // set to distance field's pixel range
    
    vec2 sqr(vec2 x) { return x*x; }
    
    float screenPxRange() {
        vec2 unitRange = vec2(pxRange)/vec2(textureSize(msdf, 0));
        vec2 screenTexSize = inversesqrt(sqr(dFdx(texCoord))+sqr(dFdy(texCoord)));
        return max(0.5*dot(unitRange, screenTexSize), 1.0);
    }

    Note: screenPxRange() should not be lower than 1. If it is lower than 2, anti-aliasing may fail; consider re-generating the field with a wider range.

  3. Use the shape description syntax for text shapes

    master

    When defining text shapes, you can use a specific syntax to describe contours, points, and edge properties.

    Syntax Rules:

    • Contours: Each closed contour is enclosed in braces: { <contour> }.
    • Points: Represented as two real numbers separated by a comma (e.g., x, y).
    • Point Separation: Points within a contour are separated by semicolons ;.
    • Closing Contours: The last point must match the first point, or you can use the # symbol to represent the first point.
    • Edge Segments: You can specify edge properties between points using semicolons. This includes:
      • Color: c (cyan), m (magenta), y (yellow), or w (white).
      • Bézier Curves: One or two control points inside parentheses (x1, y1; x2, y2).
    • Coordinate System: You can specify the Y-axis direction at the beginning of the description using @y-up or @y-down.
  4. Use the msdfgen CLI to generate distance fields

    master

    The msdfgen command-line tool generates various types of distance fields (SDF, PSDF, MSDF, MTSDF) from vector shapes, fonts, or SVG files.

    Usage Pattern: msdfgen <mode> <input specification> <options>

    Modes:

    • sdf: Conventional monochrome (true) signed distance field.
    • psdf: Monochrome signed perpendicular distance field.
    • msdf: Multi-channel signed distance field (default).
    • mtsdf: Combined multi-channel and true signed distance field in the alpha channel.
    • metrics: Report shape metrics only.
  5. Use msdfgen CLI to generate MSDFs from fonts

    master

    The msdfgen command line tool allows you to generate Signed Distance Fields (SDF), Perpendicular SDFs (PSDF), Multi-channel SDFs (MSDF), or Multi-channel True SDFs (MTSDF) from various input sources including fonts, SVGs, and shape descriptions.

    Font Input

    To use a font, use the -font flag followed by the font file path and a character specification. Character specifications can be:

    • A Unicode index (e.g., 65 or 0x41)
    • A character in apostrophes (e.g., 'A')
    • A glyph index prefixed with g (e.g., g36 or g0x24)

    If using variable fonts, use the -varfont flag. You can also use -varfont <file> printvars to list available axes.

    Input Formats

    • Fonts: -font <file.ttf/otf> <char>
    • Variable Fonts: -varfont <file.ttf/otf> <char>
    • SVG: -svg <file.svg> (requires extensions)
    • Shape Description: -defineshape <description> or -shapedesc <file>
    • Standard Input: -stdin
  6. Integrate msdfgen as a C++ library

    master

    To use msdfgen in your own C++ code, follow these steps within the msdfgen namespace:

    1. Acquire a Shape object: Use loadGlyph (requires FreeType), loadSvgShape, or construct it manually using LinearEdge, QuadraticEdge, or CubicEdge.
    2. Normalize and Color: Call shape.normalize(). For MSDF, assign colors to edges using edgeColoringSimple(shape, max_angle) or manually. At least two color channels must be active per edge.
    3. Generate Field: Call generateMSDF, generatePSDF, generateSDF, or generateMTSDF into a Bitmap<float, 3> (for MSDF) or similar object.
    4. Save/Render: Use savePng, saveTiff, etc., to save the result, or renderSDF to create a test render.
    #include <msdfgen.h>
    #include <msdfgen-ext.h>
    
    using namespace msdfgen;
    
    int main() {
        if (FreetypeHandle *ft = initializeFreetype()) {
            if (FontHandle *font = loadFont(ft, "C:\\Windows\\Fonts\\arialbd.ttf")) {
                Shape shape;
                if (loadGlyph(shape, font, 'A', FONT_SCALING_EM_NORMALIZED)) {
                    shape.normalize();
                    //                      max. angle
                    edgeColoringSimple(shape, 3.0);
                    //          output width, height
                    Bitmap<float, 3> msdf(32, 32);
                    //                            scale, translation (in em's)
                    SDFTransformation t(Projection(32.0, Vector2(0.125, 0.125)), Range(0.125));
                    generateMSDF(msdf, shape, t);
                    savePng(msdf, "output.png");
                }
                destroyFont(font);
            }
            deinitializeFreetype(ft);
        }
        return 0;
    }
  7. Use the msdfgen console program

    master

    The standalone msdfgen program can be used to generate distance fields from fonts, SVGs, or shape descriptions via the command line.

    Command Syntax: msdfgen <mode> <input> <options>

    Modes:

    • sdf: Conventional monochrome signed distance field.
    • psdf: Monochrome signed perpendicular distance field.
    • msdf: Multi-channel signed distance field (default).
    • mtsdf: Combined multi-channel and true signed distance field in the alpha channel.

    Input Types:

    • -font <filename.ttf> <character code>: Load a glyph. Character code can be decimal (63), hex (0x3F), or an ASCII character in single quotes ('?').
    • -svg <filename.svg>: Load an SVG file (uses the last vector path).
    • -shapedesc <filename.txt>, -defineshape <definition>, or -stdin: Load a text description of a shape.

    Common Options:

    • -o <filename>: Output file name (format deduced from extension: png, bmp, tiff, rgba, fl32, txt, bin).
    • -dimensions <width> <height>: Output dimensions in pixels.
    • -range <range>: Width of the range in shape units.
    • -pxrange <range>: Width of the range in distance field pixels.
    • -scale <scale>: Scale to convert shape units to pixels.
    • -translate <x> <y> / -pxtranslate <x> <y>: Translation in shape units or pixels.
    • -autoframe: Automatically frames the shape (use for previews only, not for character maps).
    • -angle <angle>: Maximum angle for a corner (radians or degrees with 'D', e.g., 171.9D).
    • -testrender <filename.png> <width> <height>: Renders a test image of the shape.
    • -exportshape <filename.txt>: Saves the shape description with edge coloring.
    msdfgen msdf -font C:\Windows\Fonts\arialbd.ttf 'M' -o msdf.png -dimensions 32 32 -pxrange 4 -autoframe -testrender render.png 1024 1024
  8. Configure msdfgen error correction modes

    master

    Use -errorcorrection <mode> to adjust how MSDF/MTSDF errors are handled:

    • auto-mixed (default): Detects inversions by distance evaluation and distance errors that do not affect edges by range testing.
    • auto-fast: Detects inversion artifacts and distance errors that do not affect edges by range testing.
    • auto-full: Detects inversion artifacts and distance errors that do not affect edges by exact distance evaluation.
    • distance-fast: Detects distance errors by range testing (ignores edges/corners).
    • distance-full: Detects distance errors by exact distance evaluation (slow).
    • edge-fast: Detects inversion artifacts only by range testing.
    • edge-full: Detects inversion artifacts only by exact distance evaluation.
    • disabled: Disables error correction.
  9. Specify input for msdfgen

    master

    You can provide input shapes to msdfgen using several methods:

    • -defineshape <definition>: Use an ad-hoc text definition of the shape.
    • -font <filename.ttf> <character code>: Load a single glyph from a font file. Character codes can be:
      • ? (Unicode value)
      • 0x3F (Hexadecimal Unicode)
      • 63 (Decimal Unicode)
      • g34 (Glyph index)
    • -shapedesc <filename.txt>: Load a text shape description from a file.
    • -stdin: Read shape description from standard input.
    • -svg <filename.svg>: Load the last vector path found in the specified SVG file.
    • -varfont <filename and variables> <character code>: Load a glyph from a variable font. Variables are specified as file.ttf?axis1=val&axis2=val. To list available axes, use -varfont <filename> printvars.
  10. Preview generated distance fields

    master

    Use test render commands to quickly preview the result of your generation:

    • -testrender <filename.ext> <width> <height>: Renders an image preview using the generated distance field and saves it (as PNG if available, otherwise BMP).
    • -testrendermulti <filename.ext> <width> <height>: Renders an image preview without resolving the color channels.
  11. Configure msdfgen output options

    master

    Control how the generated distance field is saved and formatted using these options:

    • -o <filename>: Sets the output file name. Defaults to output.[extension].
    • -dimensions <width> <height>: Sets the output image dimensions.
    • -format <format>: Specifies the output format. If not specified, it is deduced from the file extension.
      • Supported formats: png, bmp, tiff, rgba, fl32, text, textfloat, bin, binfloat, binfloatbe.
    • -stdout: Prints the output to standard output (only supported for text formats).
    • -yflip: Inverts the Y-axis in the output (default is upward orientation).
  12. Configure msdfgen CLI coloring and edge colors

    master

    For multi-channel MSDF generation, you can control how colors are assigned to edges:

    Coloring Strategy

    Use -coloringstrategy <strategy> or -edgecoloring <strategy>:

    • simple: Simple coloring.
    • inktrap: Inktrap coloring.
    • distance: Coloring by distance.

    Edge Color Assignment

    Use -edgecolors <sequence> to specify color assignments for contours. The sequence can contain ?, c, m, w, y, C, M, W, Y. Use commas to separate contours and ? to keep the default assignment for a contour.