Skip to content

Repository files navigation

hlfreetype

This library was inspired by Motion Twin's original HashLink FreeType binding

Native FreeType support for HashLink, with optional Heaps font integration.

What it does

  • adds freetype.Library for plain HashLink projects
  • loads TTF/OTF fonts from memory
  • renders glyphs through FreeType into HashLink bytes
  • adds freetype.heaps.FreeTypeFont for creating h2d.Font from one or more TTF files

Supported formats

  • ttf
  • ttc
  • otf

Plain HashLink usage

final library = new freetype.Library();
final face = library.loadFace(sys.io.File.getBytes("font.ttf"));

face.setPixelSize(0, 32);

final glyph = face.renderCodepoint("A".code);
trace(face.familyName);
trace(glyph.bitmap.width + "x" + glyph.bitmap.height);

face.dispose();
library.dispose();

Useful API:

  • Library.loadFace(bytes, ?index)
  • Library.describeLastError()
  • Face.setPixelSize(width, height)
  • Face.setSize(points, ?dpi)
  • Face.glyphIndex(codepoint)
  • Face.hasGlyph(codepoint)
  • Face.kerning(leftGlyph, rightGlyph)
  • Face.renderCodepoint(codepoint, ?loadFlags, ?renderMode, ?out)

Public data and enum types live in freetype.types, for example:

  • freetype.types.Bitmap
  • freetype.types.Glyph
  • freetype.types.FaceMetrics
  • freetype.types.LoadFlags
  • freetype.types.RenderMode
  • freetype.types.PixelMode

Heaps usage

Create an h2d.Font directly from a TTF file:

final font = freetype.heaps.FreeTypeFont.fromFile("font.ttf", 24, {
	chars: "Hello Привет こんにちは",
	kerning: true,
});

final text = new h2d.Text(font, s2d);
text.text = "Hello Привет こんにちは";

Use multiple font files when your text spans scripts that one font does not cover:

final font = freetype.heaps.FreeTypeFont.fromFiles([
	// windows
	"C:/Windows/Fonts/segoeui.ttf",
	"C:/Windows/Fonts/seguisym.ttf",
	"C:/Windows/Fonts/arial.ttf",
	"C:/Windows/Fonts/Nirmala.ttf",

	// linux
	"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
	"/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf",
	"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"
], 24, {
	chars: "Hello Привет हिन्दी 中文 日本語 한국어",
	kerning: true,
});

fromFiles() bakes one atlas and chooses the first font that contains each requested character. It does not magically cover all Unicode; the provided font files must contain the glyphs you want to render. TTC collections load all contained faces by default. With dynamicFromSources(), set faceIndex on a source to load only one face from a collection.

Use dynamicFromFiles() when text can contain characters that were not known up front. Characters listed in chars are preloaded, and later missing glyphs are rendered into the atlas on demand.

Create from bytes:

final bytes = sys.io.File.getBytes("font.ttf");
final font = freetype.heaps.FreeTypeFont.fromBytes(bytes, 24);

Register TTF/OTF/TTC files as Heaps resources:

--macro freetype.heaps.Macro.main()

Then load them through hxd.Res:

final font = hxd.Res.fonts.my_font.toFont(24);
final dynamicFont = hxd.Res.fonts.my_font.toDynamicFont(24);

If you need access to the generated atlas pixels:

final atlas = freetype.heaps.FreeTypeFont.buildAtlas(bytes, 24, {
	chars: hxd.Charset.DEFAULT_CHARS,
	uploadTexture: true,
});

final font = atlas.font;
final pixels = atlas.pixels;

For multi-font atlases:

final atlas = freetype.heaps.FreeTypeFont.buildAtlasFromFiles(paths, 24, {
	chars: textToRender,
});

Options:

  • chars: characters to bake into the atlas
  • antiAliasing: render grayscale glyphs when enabled
  • kerning: add FreeType kerning pairs
  • padding: glyph padding in the atlas
  • atlasWidth: fixed atlas width, or auto when omitted
  • uploadTexture: create a real Heaps texture when enabled

Build

FreeType is fetched and built automatically by CMake.

The same FreeType version is used on Windows and Linux.

FreeType is linked statically into freetype.hdll, so users do not need a separate FreeType DLL or shared library.

Requirements

Common requirements:

  • CMake 3.10+
  • Ninja
  • Git
  • HASHLINK environment variable pointing to a HashLink installation or source tree

Windows additionally requires:

  • Visual Studio / MSVC build tools

Linux additionally requires:

  • GCC or Clang
  • standard build tools

Build on Windows

Set HASHLINK to your HashLink directory:

$env:HASHLINK = "C:\Path\To\HashLink"

Configure:

cmake --preset windows-release --fresh

Build:

cmake --build --preset windows-release

Output:

out/build/windows-release/extension/freetype.hdll
out/build/windows-release/extension/freetype.lib

The native module is:

freetype.hdll

Place it next to your .hl output, or otherwise make sure HashLink can load it.

Build on Linux

Install the basic build dependencies.

Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y build-essential git cmake ninja-build

Set HASHLINK to your HashLink installation or source tree:

export HASHLINK=/path/to/hashlink

Configure:

cmake --preset linux-release --fresh

Build:

cmake --build --preset linux-release

Output:

out/build/linux-release/extension/freetype.hdll

Place freetype.hdll next to your .hl output, or otherwise make sure HashLink can load it.

If libhl.so is not installed system-wide, make sure it can also be found at runtime, for example:

export LD_LIBRARY_PATH="$HASHLINK:${LD_LIBRARY_PATH:-}"

Tests

The test suite covers:

  • FreeType initialization
  • font loading
  • face metrics
  • kerning
  • glyph lookup
  • glyph rendering
  • TTF/OTF support
  • TTC collections when a TTC test font is available
  • invalid input handling
  • deterministic Heaps atlas creation

Plain HashLink tests

Compile:

cd tests/testMain
haxe test-hl.hxml

Run:

hl test.hl

Heaps tests

Compile:

cd tests/testMain
haxe test-heaps.hxml

Run:

hl test-heaps.hl

Windows test launchers

Convenience launchers are also available on Windows:

  • tests/test-hl.bat
  • tests/test-heaps.bat
  • tests/test-heaps-window.bat

test-hl checks plain FreeType loading, metrics, kerning, glyph rendering and invalid input.

test-heaps checks deterministic h2d.Font atlas creation without opening a window.

test-heaps-window opens a Heaps window and renders multilingual Unicode sample text using multiple fallback fonts. Press Escape to close.

Test fonts

Tests first look for explicitly configured test fonts and then fall back to common system fonts.

To specify a TTF or OTF test font:

Windows

$env:HLFREETYPE_TEST_FONT = "C:\Path\To\font.ttf"

or in cmd.exe:

set HLFREETYPE_TEST_FONT=C:\Path\To\font.ttf

Linux

export HLFREETYPE_TEST_FONT=/path/to/font.ttf

For example:

export HLFREETYPE_TEST_FONT=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf

To explicitly specify a TTC collection:

Windows

$env:HLFREETYPE_TEST_TTC = "C:\Windows\Fonts\msyh.ttc"

Linux

export HLFREETYPE_TEST_TTC=/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc

On Ubuntu/Debian, useful test fonts can be installed with:

sudo apt-get install -y fonts-dejavu-core fonts-noto-cjk

GitHub Actions

GitHub Actions builds and tests the native extension on both Windows and Linux.

The workflow runs against:

  • Windows x86_64
  • Linux x86_64
  • Haxe 4.3.7
  • latest Haxe

Nightly builds are published when changes are pushed to main.

Release artifacts:

hlfreetype-windows.zip
hlfreetype-linux.tar.gz

The Windows archive contains:

freetype.hdll
freetype.lib

The Linux archive contains:

freetype.hdll

FreeType itself is statically linked into the native module.

HashLink must still be installed or otherwise available on the target system.

TODO

  • macOS support

About

HashLink and Heaps wrapper for FreeType

Topics

Resources

Stars

9 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages