A Rust 🦀️ font loading, positioning and rendering toolkit

Overview

Toolkit used to load, match, measure and render texts.

NOTE: This project is a work in progress. Text measuring and positioning is a complex topic. A more mature library is a sensible choice.

Compile the module:

npm run build
npm run build:wasi
node examples/node.mjs

Font querying

This module uses a special font matching logic. A font's identity contains the font family (name), weight, italic, and stretch (font width). When querying, any subset of the memtioned information is allowed except that the font family is required.

The query is then splitted into 4 filters, in the order of family -> weight -> italic -> stretch. Each filter could strim the result set, and:

  • If after any filter the result contains only one font, it is immediately returned.
  • If after all filters, 0 or more than 1 font are left, the query fails

General API (WASM API)

new FontKit()

Create a new font registry

fontkit.add_font_from_buffer(buffer: Uint8Array) -> FontKey

Add a font from a buffer, return the standard key of this font

fontkit.query(key: FontKey) -> Font | undefined

Query a font

font.has_glyph(c: char) -> boolean

Check if the font contains glyph for a given char

font.ascender() -> number

The ascender metric of the font

font.descender() -> number

The descender metric of the font

font.units_per_em() -> number

The units of metrics of this font

font.glyph_path(c: char) -> GlyphPath | undefined

Get the glyph path of a char, if any

glyphPath.scale(scaleFactor: number)

The glyph of font is very large (by the unit of units_per_em), the method could scale the path for convenience

glyphPath.translate(x: number, y: number)

Translate the path

glyphPath.to_string() -> string

Export the glyph path as an SVG path string

Node.js Support

Currently this module supports Node.js via WASI API. This requires the --experimental-wasi-unstable-preview1 flag and only limited APIs are provided.

Example

import { dirname } from 'path';
import { fileURLToPath } from 'url';

// Import the Node.js specific entry module
import { FontKitIndex } from '../node.mjs';

// Get current path, or you could use any path containing font files
const __dirname = dirname(fileURLToPath(import.meta.url));

// Create an instance of `FontKitIndex`, which is generally a font registry.
// By doing this, an object is created in Rust. So be sure to call `.free()`
// later
const fontkit = new FontKitIndex();

// Await here is needed as it initiate the WASM module
await fontkit.initiate();

// Add a search path, fonts are recursively indexed. This method could
// be called multiple times
fontkit.addSearchPath(__dirname);

// Query a font, additional params including weight, stretch, italic are supported
const font = fontkit.font('Open Sans');

// Get the actual path of the font
console.log(font.path());

// Free the memory of the registry
fontkit.free();

Being a minimal API, after getting the actual path of the font, you could load the file into a Uint8Array buffer, and use the normal WASM APIs to load / use the font. So basically the Node.js API here is only for indexing and querying fonts.

API

new FontKitIndex()

Create a new font registry only for indexing. Holding the info (not the actual buffers) of the fonts it found.

fontkitIndex.addSearchPath(path: string)

Search recursively in a path for new fonts. Supports ttf/otf/woff/woff2 fonts. The fonts are loaded to grab their info, and then immediately released.

fontkitIndex.query(family: string, weight?=400, italic?=false, strech?=5) -> Font | undefined

Query a font. Check querying for details

fontkitIndex.free()

Free the registry. Further calls will panic the program

font.path() -> string

Get the path of the font

Comments
  • fix(ras): fix text angle render

    fix(ras): fix text angle render

    当glyph path中存在角度较小的尖角,并且设置较大的stroke-width的时候会出现尖角突出过长,违背了本身的拓扑关系,这种情况和stroke-linejoinstroke-miterlimit相关。pathfinder默认miterlimit为10,缩小这个值可以改善尖角渲染的问题,现保持与SVG spec一致。

    opened by KylinLee 2
  • feat(lib): js new class syntax support

    feat(lib): js new class syntax support

    js new class syntax support for FontKey and Width classes

    BREAKING CHNAGE: new method of FontKey and Width class not be used.

    difference:

    • Before:
    FontKey.new(...params)
    Width.new(str)
    
    • After:
    new FontKey(...params)
    new Width(str)
    

    use new keyword is more intuitive.

    opened by KylinLee 1
  • feat(ras): expose stroke style param

    feat(ras): expose stroke style param

    expose two stroke style param (line-cap, line-join) may be sometimes need custom the stroke style like SVG stroke-linecap and stroke-linejoin. I added two parameters for Font::bitmap, set None to use fontkit default.

    opened by KylinLee 0
  • feat(ras): add stroke offset correction

    feat(ras): add stroke offset correction

    when render glyph path with stroke, we'll get two bitmaps, these layers has different width and height, so we need to align this two layers, but simply calculate the width and height can not work well, we need a offset correction to set the new position of stroke bitmap pixel. the x, y correction mostly be a positive number, because stroke always larger than the fill bitmap.

    opened by KylinLee 0
  • fix(ras): fix stroke broken

    fix(ras): fix stroke broken

    fix stroke broken

    fix stroke

    to fix this, remove obtuse angle in quadratic bezier curve. if path's last end point is equal to the first move segment(M) point, stroke width will loss at the last end point.

    Snipaste_2022-12-28_16-34-57

    this pr only remove line-to segment(L) which end point is equal to move segment(M)

    I'm not sure if it will affect the correct path, so is't a experimental function.

    opened by KylinLee 0
  • Support TextMetrics  API

    Support TextMetrics API

    https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics

    • [ ] actualBoundingBoxAscent
    • [ ] actualBoundingBoxDescent
    • [ ] actualBoundingBoxLeft
    • [ ] actualBoundingBoxRight
    • [ ] alphabeticBaseline
    • [ ] emHeightAscent
    • [ ] emHeightDescent
    • [ ] fontBoundingBoxAscent
    • [ ] fontBoundingBoxDescent
    • [ ] hangingBaseline
    • [ ] ideographicBaseline
    • [ ] width
    opened by yisibl 0
Owner
Alibaba
Alibaba Open Source
Alibaba
A library for loading and executing PE (Portable Executable) from memory without ever touching the disk

memexec A library for loading and executing PE (Portable Executable) from memory without ever touching the disk This is my own version for specific pr

FssAy 5 Aug 27, 2022
Safer Nostr is a service that helps protect users by loading sensitive information (IP leak) and using AI to prevent inappropriate images from being uploaded.

Safer Nostr is a service that helps protect users by loading sensitive information (IP leak) and using AI to prevent inappropriate images from being uploaded. It also offers image optimization and storage options. It has configurable privacy and storage settings, as well as custom cache expiration.

Thomas 4 Dec 29, 2022
ufo2nft is a CLI Rust tool to automate creating on-chain SVG NFTs from UFO font sources

ufo2nft is a CLI Rust program created by Eli Heuer at the 2022 Seattle Solana Hacker House event. It uses Norad to create on-chain SVG images from UFO font sources, and prepares them for minting as Solana NFTs. For Ethereum NFTs the program can just export the SVGs and Ethereum NFTs can be built manually.

Eli Heuer 1 Feb 10, 2022
A simple command line tool for creating font palettes for engines like libtcod

palscii A simple command line tool for creating font palettes for engines like libtcod. Usage This can also be viewed by running palscii --help. palsc

Steve Troetti 2 May 2, 2022
Figma Agent for Linux (a.k.a. Font Helper)

Figma Agent for Linux (a.k.a. Font Helper)

Neetly 32 Dec 25, 2022
🔣 nerdfix helps you to find/fix obsolete Nerd Font icons in your project.

?? nerdfix nerdfix helps you to find/fix obsolete Nerd Font icons in your project. ?? Why Nerd Fonts is used in many projects for a beautiful UI. It p

Loi Chyan 80 Apr 8, 2023
A tool to compare how Typst documents would look using different fonts or font variants.

typst-font-compare A tool to compare how Typst documents would look using different fonts or font variants. Installation cargo install --path . Usage

null 3 Feb 15, 2024
A minimal browser with a super simple rendering engine for HTML and CSS, using Rust.

minimal-browser A minimal browser with a super simple rendering engine for HTML and CSS, using Rust. Credit: https://github.com/mbrubeck and https://l

Federico Baldini 3 Jan 15, 2023
A rust crate for rendering large text to the terminal using font8x8 and ratatui.

tui-big-text tui-big-text is a rust crate that renders large pixel text as a ratatui widget using the glyphs from the font8x8 crate. Installation carg

Josh McKinney 7 Sep 7, 2023
A binary that bootstraps a Leptos application with client side rendering, tailwind, and vercel

create-leptos-csr-tw This CLI provides a quick setup to start building web applications using the Leptos web framework integrated with TailwindCSS. It

Matthew 3 Nov 3, 2023
Metaballs (blobs) coded in Rust. 100% software rendering.

Metaballs (blobs) coded in Rust. 100% software rendering. It is basically a Rust version of my old demo effect from the 90s (back then we'd use a fake Phong shading, though).

Maciej Sinilo 7 Dec 4, 2022
General purpose cross-platform GIS-rendering library written in Rust

Galileo is a general purpose cross-platform geo-rendering library. Web examples Raster tile layer (OSM) Vector tile layer (Maplibre) Use buttons at th

Maxim 16 Dec 15, 2023
A CLI tool used for rendering Blender files to a cropped spritesheet

BuilderGenerator A CLI tool used for rendering Blender files to a cropped spritesheet Clients Rust

Eric Olson 1 Feb 18, 2022
Make data-driven table rendering easy with Dioxus

Dioxus Table Make data-driven table rendering easy with Dioxus Installation Until the next release of Dioxus this requires Dioxus nightly from git. Th

null 9 Oct 9, 2022
💫 List-rendering component utilizing FLIP position transitions for Leptos

<AnimatedFor /> component for Leptos FLIP animations for element and component groups inspired by Vue's <TransitionGroup>. This crate exports a compon

Kajetan Welc 6 Nov 13, 2023
A PostgreSQL extension for rendering the Tera HTML templating language.

PGTera PGTera is a PostgreSQL extension that provides functions for using Tera to render HTML templates. When used with a tool like Postgrest, you can

Frankie 4 Feb 16, 2024
Fermyon Spin + Dioxus - Client Side Rendering (CSR) template with TailwindCSS

spin-dioxus-csr Fermyon Spin + Dioxus - Client Side Rendering (CSR) template with Tailwind Setup Accomodate "chicken & egg" issue for https://github.c

null 4 Apr 9, 2024
Oxygen is a voice journal and audio analysis toolkit for people who want to change the way their voice comes across.

Oxygen Voice Journal Oxygen is a voice journal and audio analysis toolkit for people who want to change the way their voice comes across. Or rather, i

Jocelyn Stericker 32 Oct 20, 2022
Xsv - A fast CSV command line toolkit written in Rust.

xsv is a command line program for indexing, slicing, analyzing, splitting and joining CSV files. Commands should be simple, fast and composable: Simpl

Andrew Gallant 9.1k Dec 31, 2022