Note: VGlyph is in active development (v0.1.0). The API is stabilizing but may change.
A high-performance text rendering engine for the V programming language, built on Pango, HarfBuzz, FreeType, and Sokol.
VGlyph provides production-grade text layout—including bidirectional text, complex scripts, and rich text markup—while remaining easy to use.
- API Reference: Detailed API documentation for
TextSystem,TextConfig, etc. - Guides: Rich Text Markup, Font Loading, and Performance tips.
- Accessibility: Comprehensive guide to using
vglyphwith screen readers. - Architecture: High-level design and data flow.
- Complex Layout: Proper support for Arabic, Hebrew, and advanced typography via Pango.
- Advanced Typography: Support for OpenType features (small caps, old-style nums) and custom tab stops.
- Rich Text: Use
<span>tags for colors, fonts, and styles within a single string. - High Performance: Automatic layout caching (10,000+ entry LRU cache), batched GPU rendering, and dynamic glyph atlas resizing.
- Local Fonts: Load
.ttf/.otffiles directly from your assets folder. - Hit Testing: Efficiently retrieve character indices or bounding boxes from mouse coordinates.
- Font Fallback: Automatic multilingual support with robust font fallback for emojis and complex scripts.
- Text Decorations: Built-in underline and strikethrough support via
TextConfig. - High-DPI Support: Automatic DPI scaling for crisp rendering on all displays.
- LCD Subpixel Antialiasing: Exploits LCD subpixel structure for sharper text rendering, combined with Subpixel Positioning for smooth animations.
- Variable Fonts: Support for variable axes like weight (
wght) and width (wdth) for fluid typography animations. - Text Measurement: Query text dimensions (
text_width,text_height,font_height) for precise layout calculations. - Lists: Built-in support for hanging indents to easily create unordered and ordered lists with custom markers.
- Accessibility: Automatic integration with macOS VoiceOver (and future screen readers) via a simple API switch.
You must have Pango and FreeType installed.
brew install pango freetype pkg-configsudo apt-get install libpango1.0-dev libfreetype6-dev pkg-config
# For comprehensive emoji and multilingual support
sudo apt-get install fonts-noto fonts-noto-color-emoji# vcpkg
vcpkg install pango freetype
# Or MSYS2
pacman -S mingw-w64-x86_64-pango mingw-w64-x86_64-freetypeUse the TextSystem for the easiest integration. It handles initialization,
caching, and rendering.
import vglyph
import gg
struct App {
mut:
gg &gg.Context = unsafe { nil }
ts &vglyph.TextSystem = unsafe { nil }
}
fn main() {
mut app := &App{}
app.gg = gg.new_context(
bg_color: gg.white
width: 800
height: 600
window_title: 'VGlyph Demo'
init_fn: init
frame_fn: frame
user_data: app
)
app.gg.run()
}
fn init(mut app App) {
// 1. Initialize TextSystem
app.ts = vglyph.new_text_system(mut app.gg) or { panic(err) }
}
fn frame(mut app App) {
app.gg.begin()
// 2. Draw Text
// Coordinates are (x, y)
app.ts.draw_text(100, 100, 'Hello VGlyph!', vglyph.TextConfig{
style: vglyph.TextStyle{
font_name: 'Sans Bold 30'
color: gg.black
}
}) or { println(err) }
app.gg.end()
// 3. Commit Texture Uploads (Important!)
app.ts.commit()
}The examples/ directory contains several demonstrations:
demo.v- Multilingual text, wrapping, and rich text markupemoji_demo.v- Emoji and color bitmap renderingeditor_demo.v- Interactive text editing with cursor placementtypography_demo.v- OpenType features and custom tab stopsvariable_font_demo.v- Variable font animation (weight/width axes)list_demo.v- Unordered and ordered lists with hanging indentsstress_demo.v- Performance testing with thousands of glyphs
Run any example with:
v run examples/demo.vwidth := app.ts.text_width('Hello', cfg)!
height := app.ts.text_height('Hello', cfg)!
font_h := app.ts.font_height(cfg)
// Check which font Pango actually resolved
actual_font := app.ts.resolve_font_name('Sans Bold 30')
println('Using font: ${actual_font}')
// Get layout for hit testing or custom rendering
layout := app.ts.layout_text('Click me', cfg)!
char_idx := layout.hit_test(mouse_x, mouse_y)
rects := layout.get_selection_rects(0, 5)
// Import vglyph
rt := vglyph.RichText{
runs: [
vglyph.StyleRun{ text: 'Hello ' },
vglyph.StyleRun{
text: 'World',
style: vglyph.TextStyle{
color: gg.red,
underline: true
}
}
]
}
layout := app.ts.layout_rich_text(rt, cfg)!
app.ts.draw_layout(layout, x, y)
Ensure you're calling commit() at the end of each frame. Without it, new
glyphs won't upload to the GPU.
Install comprehensive fallback fonts:
- macOS: System fonts should cover most cases
- Linux:
sudo apt-get install fonts-noto fonts-noto-color-emoji - Windows: Install Noto fonts from Google Fonts
Use the font's family name, not the filename. Check with:
println(app.ts.resolve_font_name('YourFont'))
TextSystem automatically caches layouts. If text changes every frame (e.g.,
FPS counter), consider using a monospace font and fixed-width formatting to
minimize layout variations.
MIT
