VGlyph
This is a work in progress and is not production-ready!
A high-performance, feature-rich text rendering engine for the V programming language, built on top
of
Pango
This library provides production-grade text layout capabilities, including bidirectional text support (Arabic/Hebrew), complex script shaping, text wrapping, rich text markup, local font loading (TTF/OTF), and sub-pixel accurate rendering, while maintaining a pure V-friendly API.
Prerequisites
This library relies on
Pango
macOS (Homebrew)
brew install pango freetype pkg-config
Linux (Debian/Ubuntu)
sudo apt-get install libpango1.0-dev libfreetype6-dev pkg-config
Linux (Fedora)
sudo dnf install pango-devel freetype-devel pkgconf-pkg-config
Architecture
The system is designed to decouple
Text Layout
Data Flow
graph TD
Input[Input String] --> Context
Context -->|Pango/HarfBuzz| LayoutEngine[Layout Engine]
LayoutEngine -->|Shape & Wrap| LayoutStruct[Layout Info]
subgraph "Pure V Land"
LayoutStruct --Contains--> Items[Runs & Glyphs]
LayoutStruct --Contains--> CharRects[Hit Detection Rects]
LayoutStruct --> HitTest[Hit Test API]
end
LayoutStruct --> Renderer
Renderer -->|Cache Miss| FreeType[FreeType Rasterizer]
FreeType -->|Alpha Bitmap| Atlas[Glyph Atlas]
Atlas --Batch Update--> GPU[Sokol Texture]
Renderer -->|Draw Call| GPU
Key Components
-
Context (
vglyph.Context) : - Manages the connection to Pango and FontConfig.
- Responsible for the heavy lifting of text shaping, wrapping, and laying out.
- Produces a
Layoutobject.
-
Layout (
vglyph.Layout) : - A lightweight, pure V struct containing all necessary information to draw text or perform hit tests.
- Stores text as "Runs" (
Item), which contain shaped "Glyphs". - Stores "Baked" Character Rectangles (
CharRect) for O(1) or O(N) hit testing without querying Pango again.
-
Renderer (
vglyph.Renderer) : - Manages the
GlyphAtlas(dynamic texture packing) and Glyph Cache. - Renders
Layoutobjects to the screen using Sokol gg. - Handles color tinting and texture coordinates.
- Manages the
-
Glyph Atlas
: - Dynamically packs grayscale bitmaps of glyphs into a single GPU texture.
- Uses a "dirty" flag system to batch uploads, ensuring only one
sg_update_imagecall per frame (sokol requirement).
Rich Text Markup
The library supports
Pango Markup
use_markup: true
TextConfig
Supported Tags
-
<b>, <strong>: Bold -
<i>, <em>: Italic -
<u>: -
<s>: Strikethrough -
<tt>, <monospace>: Monospace font -
<big>, <small>: Relative font size changes -
<sup>, <sub>: Superscript and Subscript -
<span>: General span for applying attributes
Supported Attributes (in
<span>
)
-
foreground: Text color (name, hex, or rgb style). Example: #FF0000, blue. -
background: Background color (highlight). Example: yellow, #00FF00. -
underline: Style of underline ( none, single, double, low, error). -
strikethrough: trueor false. -
font_desc: Full font description string. Example: Sans Italic 12. -
size: Font size (absolute or relative words like small, x-large). -
weight: Font weight ( bold, light, heavy, etc.).
Example Markup:
markup_text := '<span foreground="blue" size="x-large">Blue</span> ' + '<u>Underline</u> ' +
'<span background="yellow">Highlight</span>'
Technical Nuances & Discrepancies
Logical vs. Ink Rectangles (Hit Testing vs. Rendering)
You may observe that certain characters (especially Emojis or script fonts with large swashes) render outside their hit-test rectangle.
-
Logical Rectangle (Hit Test)
: This is the typographic "cell" determined by Pango. It ensures consistent line spacing and cursor placement. The Layout.hit_test()method uses these bounds. -
Ink Rectangle (Visual)
: This is the actual bounding box of the pixels drawn. FreeType respects the font's vertical bearings ( bitmap_top), allowing glyphs to "bleed" out of their logical line height.
This is intentional behavior.
Coordinate Systems
-
Pango Units
: Internally, Pango uses integers scaled by 1024 ( PANGO_SCALE). The Layoutstruct normalizes these to standard floating-point pixels ( f32) for the user. -
RTL Text
: For Right-to-Left languages, Pango may return negative width extents to indicate directionality. The library automatically normalizes these into standard positive-width rectangles during the "baking" phase of the layout.
Rendering Cycle
To satisfy Sokol's requirement of a single texture update per frame, the Renderer separates
Draw
-
draw_layout(...): Queues quads and loads new glyphs into the CPU-side atlas if needed. -
commit(): Must be called onceat the end of the frame to upload any new glyph data to the GPU. Not calling this will result in invisible text for newly loaded characters.
Usage
Simplified Usage (
TextSystem
)
For most use cases, use the high-level
TextSystem
import vglyph
import gg
struct App {
mut:
ctx &gg.Context
ts &vglyph.TextSystem
}
fn init(mut app App) {
// Initialize TextSystem with your gg.Context
app.ts = vglyph.new_text_system(mut app.ctx) or { panic(err) }
}
fn frame(mut app App) {
// Draw text directly - layout is cached internally
app.ts.draw_text(100, 100, 'Hello High-Level API!', vglyph.TextConfig{
font_name: 'Sans 20'
align: .center
}) or { panic(err) }
// Upload texture data at end of frame
app.ts.commit()
}
Local Fonts & Icon Support
You can load custom font files (TTF/OTF) at runtime using
add_font_file
Note:
TextConfig
// 1. Load the font file (e.g. in init)
// Returns true on success
app.ts.add_font_file('assets/icons.ttf')
// 2. Use the Family Name (e.g. "Feather")
// Use unicode escape sequences for icons
app.ts.draw_text(50, 50, '\uF100', vglyph.TextConfig{
font_name: 'Feather 24'
})
Advanced Usage (Manual Layout Management)
// 1. Initialize
mut tr_ctx := vglyph.new_context()!
mut renderer := vglyph.new_renderer(mut gg_ctx)
// 2. Layout Text (Expensive - do this when text changes)
cfg := vglyph.TextConfig
{
font_name: 'Sans 20'
width: 400
wrap: .word
}
layout := tr_ctx.layout_text('Hello World', cfg)!
// 3. Render (Cheap - do this every frame)
renderer.draw_layout(layout, x, y)
renderer.commit()
// 4. Hit Test
index := layout.hit_test(mouse_x, mouse_y)
About
VGlyph is a high-performance text rendering engine designed specifically for the V programming language by integrating the capabilities of Pango, FreeType, and Sokol. Its primary architecture focuses on decoupling text layout from rendering, which allows developers to calculate complex typography—such as bidirectional scripts and rich text markup—without straining the graphics system. Key features include sub-pixel accurate rendering, dynamic glyph atlas management for efficient GPU usage, and robust hit-testing for interactive user interfaces. By offering both a high-level TextSystem API for ease of use and manual controls for advanced performance, the library provides a flexible solution for displaying sophisticated, production-grade typography in V-based applications.