Multi-Language Fonts & CJK Support
The core challenge of multi-language text animation is correctly segmenting CJK (Chinese/Japanese/Korean) characters and handling Unicode code points. Texturge solves this through FCharBreakIterator, the Texturge::Unicode utilities, and code-unit/glyph bidirectional mapping.
NOTE
Texturge has no
UTexturgeFontAsset, font atlas baking, or SDF glyph cache. Character rendering is handled by the standard UMG/Slate font pipeline; the plugin only handles animation curve logic and glyph segmentation.
Glyph Segmentation Pipeline
Why Special Handling Is Needed
- CJK text does not use spaces for tokenization; every character is independently meaningful
- UTF-16 code units (TCHAR) are not Unicode code points: supplementary-plane characters like Emoji consist of surrogate pairs (2 code units)
- Per-glyph animation must operate on code points, not code units
FCharBreakIterator
FCharBreakIterator implements the IBreakIterator interface and precomputes all break points at SetString:
// Implements the IBreakIterator interface
FCharBreakIterator Iterator;
Iterator.SetString(InText); // precomputes the break point array (including 0 and the end)
int32 Pos = Iterator.ResetToBeginning();
while ((Pos = Iterator.MoveToNext()) != INDEX_NONE)
{
// each break point = one glyph boundary
}
Key capabilities:
- Surrogate-pair safe — supplementary-plane characters (Emoji 🎮 etc.) count as one glyph and never split
- CJK attachment — CJK punctuation attaches correctly (
IsCJKPunctuation) - Hangul syllables — Hangul syllable blocks are handled as a whole
- Full cursor interface:
GetCurrentPosition()/MoveToPrevious()/MoveToCandidateBefore/MoveToCandidateAfter
Code Unit ↔ Glyph Bidirectional Mapping
UTextAnimator maintains two mapping arrays (introduced in 0.2.0, unified by code point index across the whole text):
| Mapping | Description |
|---|---|
CodeUnitToGlyphIndex | code unit index → glyph index (both units of a surrogate pair map to the same glyph) |
GlyphIndexToCodeUnit | glyph index → code unit index |
GetGlyphIndexForCodeUnit(int32) exposes a public query. Typewriter reveal and rich text segment extraction (SerializeSubstring) both operate on code point indices.
Compared with Traditional Methods
| Method | Latin | CJK | Emoji (surrogate pairs) |
|---|---|---|---|
| Split by TCHAR (UTF-16 code unit) | Correct | Correct | Wrong (splits into 2 glyphs) |
| Split by byte | Wrong | Wrong | Wrong |
FCharBreakIterator + code point index | Correct | Correct | Correct |
Unicode Utility Class
The Texturge::Unicode namespace provides code-point-level classification functions (UnicodeUtils.h, all FORCEINLINE):
| Function | Classification range |
|---|---|
IsCJKUnifiedIdeographs(uint32) | main block + Ext A~F/I + compatibility ideographs (0x3400-0x2FA1F) |
IsHiragana(uint32) | hiragana 0x3040-0x309F |
IsKatakana(uint32) | katakana 0x30A0-0x30FF, 0x31F0-0x31FF |
IsHangulSyllables(uint32) | Hangul syllables 0xAC00-0xD7AF, Hangul Jamo 0x1100-0x11FF |
IsCJKPunctuation(uint32) | CJK punctuation 0x3000-0x303F, 0xFE30-0xFE4F, 0xFF01-0xFF60, 0xFFE0-0xFFEE |
IsCJK(uint32) | aggregation of the above five |
IsHighSurrogate(TCHAR) / IsLowSurrogate(TCHAR) | UTF-16 surrogate zone classification |
ComposeSurrogatePair(TCHAR, TCHAR) | surrogate pair composition to a 32-bit code point |
These utilities classify each glyph in BuildScheduleInfos (bIsWhitespace / bIsPunctuation / bIsCJK / bIsDecorator), determining its scheduling behavior.
Font Fallback
Texturge does not manage font assets directly and relies on the UMG font pipeline:
- Set the primary font in the
Fontproperty ofUAnimatedTextBlock/UAnimatedRichTextBlock(inherited from the base class) - UE5’s Composite Font system automatically handles missing-character fallback
- For complex multi-language coverage, use composite fonts’ Sub-Font feature to assign a font per writing system
TIP
For multi-language projects, use the composite font’s sub-font feature to assign fonts per writing system instead of stacking multiple widgets.
Testing CJK Animations
Recommended Test Text
Enter the following mixed text in the preview text box of STextAnimationDesignerView (UTexturgePreviewSceneConfig::PreviewText) to verify support:
English 日本語 한국어 中文 العربية हिन्दी
Emoji: 🎮🎯✨
全角:ABCD1234
Verification Checklist
- Glyph count correct — each CJK character / Emoji counts as one glyph (surrogate pairs never split)
- Scheduling delay uniform — per-glyph rhythm does not skip frames due to varying character encoding lengths
- Classification correct — whitespace / punctuation / CJK / decorator classifications are correct in the
BuildScheduleInfosoutput - RTL text — Arabic lays out right-to-left correctly (layout handled by Slate)