godotengine/godot
Text server
Purpose
Godot's text rendering — labels, rich text, code editors, file dialogs, the inspector, the script editor — runs through TextServer. The server abstracts shaping (turning Unicode strings into glyph runs), bidirectional ordering, line breaking, font fallback, and font-feature handling. Two implementations ship: an "advanced" server using HarfBuzz + ICU + FreeType, and a "fallback" server using only FreeType for builds where minimizing binary size matters.
Directory layout
servers/text/
├── text_server.cpp / .h Abstract TextServer interface (~107 KB cpp, ~38 KB h)
├── text_server_extension.cpp / .h Subclassing hook for module-supplied servers
├── text_server_dummy.h Inert text server (no shaping)
modules/text_server_adv/ Advanced server: HarfBuzz + ICU + FreeType + msdfgen
modules/text_server_fb/ Fallback server: FreeType onlyPublic API surface
TextServer operations group into:
- Font management —
font_create,font_set_data,font_set_face_index,font_set_style(bold, italic),font_set_variation_coordinates(variable fonts),font_set_msdf_*(multi-channel signed distance field rendering for crisp scaling). - Glyph rasterization —
font_render_glyphreturns texture-atlas data for a glyph at a given size, plus advance/offset metrics. - Shaped text buffers —
create_shaped_text(direction, orientation),shaped_text_add_string,shaped_text_add_object,shaped_text_substr,shaped_text_get_glyphs. A "shaped text" is the cached result of running a string through the shaper. - Line breaking —
shaped_text_get_line_breaks_adv,shaped_text_fit_to_width,shaped_text_tab_align. - BiDi — bidirectional ordering with
Direction::DIR_AUTO/DIR_LTR/DIR_RTL. - Glyph inspection — per-glyph metrics, justification opportunities, hyphenation hints, OpenType features.
- Locale-aware utilities —
string_to_upper/lower,string_get_word_breaks,string_get_character_breaks,is_confusable(used by the URL/identifier validation in editor + GDExtension loader). - Spoofing detection —
parse_structured_textfor editor URL safety;is_confusableflags Unicode confusables.
Backends
text_server_adv (default)
- HarfBuzz for shaping (
thirdparty/harfbuzz). - ICU for BiDi, line breaking, locale data, normalization, case mapping (
thirdparty/icu4c). - FreeType for glyph rasterization (
thirdparty/freetype). - msdfgen + msdf-atlas-gen for MSDF font generation (
thirdparty/msdfgen). - Graphite support optional (legacy).
This server handles complex scripts (Arabic, Devanagari, Khmer, …), variable fonts, OpenType features (small caps, stylistic sets), kerning, and font subsetting.
text_server_fb (fallback)
- FreeType-only.
- No HarfBuzz, no ICU, no MSDF.
- Suitable for size-constrained builds (e.g., specific export configurations) where only Latin/Cyrillic/Greek content matters.
TextServerManager (servers/text_server.h) keeps a list of servers and a current "primary" pointer. Multiple servers can be loaded simultaneously — handy when bridging legacy resources to the advanced server while keeping an old fallback active.
Shaped text lifecycle
sequenceDiagram
participant Caller as Label / RichTextLabel / TextEdit
participant TS as TextServer
participant HB as HarfBuzz
participant ICU as ICU
Caller->>TS: create_shaped_text(direction, orientation)
Caller->>TS: shaped_text_add_string(rid, "Hello", fonts, size, opentype_features, lang)
TS->>ICU: bidi analysis, script run detection
TS->>HB: shape per script run (font + features)
HB-->>TS: glyph buffer (gid, x_advance, y_advance, x_offset, y_offset)
TS-->>Caller: cached shaped buffer
Caller->>TS: shaped_text_get_glyphs(rid)
TS-->>Caller: Glyph[] for drawing
Caller->>RS: RenderingServer::canvas_item_add_texture_rect_region(...)
Note over Caller: Glyphs are drawn from the font's MSDF or bitmap atlasShaped buffers are cached. RichTextLabel builds its own paragraphs as shaped buffers per line, with embedded "objects" (inline images, custom effects) interleaved into the buffer.
Embedding objects in shaped text
shaped_text_add_object(rid, key, size, inline_align, length, baseline) lets a caller insert a non-glyph "object" into a shaped buffer (e.g., an inline image in a RichTextLabel). The shaper treats it as a bounding box; shaped_text_get_object_* recovers its position after layout. This is how BBCode [img]/[hint] tags participate in line breaking.
Key abstractions
| Abstraction | File | Role |
|---|---|---|
TextServer |
servers/text/text_server.h |
Abstract API |
TextServerManager |
servers/text/text_server.h |
Active server list |
TextServerExtension |
servers/text/text_server_extension.h |
Subclass hook for non-built-in servers |
TextServerAdvanced |
modules/text_server_adv/text_server_adv.cpp |
Default backend |
TextServerFallback |
modules/text_server_fb/text_server_fb.cpp |
Minimal backend |
FontFile, FontVariation, SystemFont |
scene/resources/font.cpp |
Resource wrappers around server font RIDs |
Integration points
Label,RichTextLabel,Button,LineEdit,TextEdit,CodeEdit,Tree,MenuBar, … all create shaped buffers viaTextServerManager::get_primary_interface().- The editor's script editor sets up
CodeEditwith code-aware shaping (BiDi, but also code-folding gutter glyphs). - Translation strings (
tr("…")) flow throughTextServer::format_numberand number/date formatting (locale-aware) where relevant. Themeresources reference fonts; the activeTextServerrasterizes the glyphs the theme uses.
Entry points for modification
- Custom shaper or layout algorithm → subclass
TextServerExtensionand ship the implementation in a module. - Adding font features → expose new methods on
Font/FontVariationand forward tofont_set_*on the server. - Adding a new font format → write a
ResourceFormatLoaderthat produces aFontFile, then wire it throughfont_set_data(the server is format-agnostic once the data is loaded).
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.