SVG Text to Path / Outline - Complete Guide
Convert text to vector outlines for advanced animation, styling control, and font-independent rendering. This guide covers the Text Outliner feature for transforming editable text into SVG paths.
Overview
The Convert to Outlines feature transforms text objects into vector paths. This is essential for:
- Draw-in animations - Hand-drawn text reveal effects
- Font independence - Export without font embedding concerns
- Advanced styling - Apply gradients, patterns, and path effects
- Precision control - Edit individual letter shapes
TEXT OUTLINING WORKFLOW
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ HELLO │ ───▶ │ Outliner │ ───▶ │ ▓▓▓▓▓▓▓▓ │ │
│ │ (Text) │ │ Engine │ │ (Paths) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ Editable text svg-text-to-path Vector outlines │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Convert to Outlines Panel
Location
Select a text object → Inspector Panel → Convert to outlines section
Interface
┌──────────────────────────────────────────────────────────────────────┐
│ Convert to outlines │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ Create editable paths │
│ │
│ [ Preview ] [ Convert ] │
│ │
└──────────────────────────────────────────────────────────────────────┘
Controls
| Button | Description |
|---|---|
| Preview | Shows outline preview before converting |
| Convert | Converts text to vector paths |
Preview Panel
┌──────────────────────────────────────────────────────────────────────┐
│ Outline preview │
├──────────────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ▓▓▓▓ ▓▓▓▓ ▓ ▓ ▓▓▓▓ │ │
│ │ ▓ ▓ ▓ ▓ ▓ ▓ ▓ │ │
│ │ ▓▓▓▓ ▓▓▓ ▓ ▓ ▓ ▓ │ │
│ │ ▓ ▓ ▓ ▓ ▓ ▓ ▓ │ │
│ │ ▓ ▓ ▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓ │ │
│ │ │ │
│ │ "HELLO" as outlined paths │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
Conversion Process
Step-by-Step
CONVERSION PIPELINE
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 1. SELECT TEXT │
│ ┌───────────────┐ │
│ │ Hello! 👋 │ ← Click text object │
│ └───────────────┘ │
│ │ │
│ ▼ │
│ 2. CLICK "PREVIEW" (Optional) │
│ ┌───────────────────────────────────────────────┐ │
│ │ Preview shows what outlines will look like │ │
│ └───────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 3. CLICK "CONVERT" │
│ ┌───────────────────────────────────────────────┐ │
│ │ • Font loaded from project fonts │ │
│ │ • svg-text-to-path engine processes text │ │
│ │ • Glyph outlines extracted as SVG paths │ │
│ └───────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 4. RESULT │
│ ┌───────────────────────────────────────────────┐ │
│ │ ✓ Text replaced with SVG path group │ │
│ │ ✓ Original transform/position preserved │ │
│ │ ✓ Fill/stroke colors maintained │ │
│ │ ✓ "Outlined text" badge shown │ │
│ └───────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
What Happens During Conversion
| Step | Description |
|---|---|
| Font Loading | Required font file loaded from project fonts |
| Text Parsing | Text content, size, weight, style extracted |
| Glyph Tracing | Each character converted to vector path |
| Path Assembly | Paths grouped preserving layout |
| Store Update | Text object replaced with outlined paths |
Supported Fonts
The outliner supports these bundled fonts:
Sans-Serif Fonts
| Font | Weights | Use Case |
|---|---|---|
| Noto Sans | Variable (100-900) | Multi-language support |
| Mukta | ExtraLight, Regular, Medium | Clean modern text |
| Hind | Light, Regular, Bold | UI and body text |
Serif Fonts
| Font | Weights | Use Case |
|---|---|---|
| Noto Serif | Variable (100-900) | Formal documents |
Display/Script Fonts
| Font | Weights | Use Case |
|---|---|---|
| Jumps Winter | Regular | Playful headlines |
| Kalam | Regular, Bold | Handwritten style |
Devanagari Fonts
| Font | Weights | Use Case |
|---|---|---|
| Noto Sans Devanagari | Variable | Hindi/Sanskrit UI |
| Noto Serif Devanagari | Variable | Hindi/Sanskrit formal |
| Tiro Devanagari Hindi | Regular, Italic | Hindi body text |
For best results, use bundled fonts. Custom fonts may not outline correctly if the font file is not available.
What Gets Preserved
Properties Maintained
PRESERVED PROPERTIES
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ ORIGINAL TEXT OUTLINED PATHS │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Position (x,y) │ ═══════▶ │ Position (x,y) │ ✓ Preserved │
│ │ Fill color │ │ Fill color │ ✓ Preserved │
│ │ Stroke color │ │ Stroke color │ ✓ Preserved │
│ │ Stroke width │ │ Stroke width │ ✓ Preserved │
│ │ Opacity │ │ Opacity │ ✓ Preserved │
│ │ Transform │ │ Transform │ ✓ Preserved │
│ │ Layer order │ │ Layer order │ ✓ Preserved │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ LOST AFTER CONVERSION │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ • Editable text content (becomes fixed paths) │ │
│ │ • Font family (embedded in path shapes) │ │
│ │ • Font size changes (must scale paths instead) │ │
│ │ • Text alignment adjustments │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Path Structure
Each character becomes one or more paths:
OUTLINED TEXT STRUCTURE
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ "Aa" │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ paths: [ │ │
│ │ { id: "text-1-outline-0", d: "M10 20 L..." }, ← 'A' │ │
│ │ { id: "text-1-outline-1", d: "M50 20 L..." }, ← 'a' │ │
│ │ ] │ │
│ │ │ │
│ │ Each path includes: │ │
│ │ • d: SVG path data │ │
│ │ • fill: inherited fill color │ │
│ │ • stroke: inherited stroke color │ │
│ │ • strokeWidth: inherited width │ │
│ │ • fillRule: 'nonzero' or 'evenodd' │ │
│ │ • len: total path length (for draw animation) │ │
│ │ • bbox: bounding box {x, y, width, height} │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Use Cases
1. Draw-In Animation
Convert text to paths for hand-drawn reveal effect:
DRAW-IN ANIMATION WORKFLOW
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ 1. Create text → 2. Convert to outlines → 3. Enable Draw-In │
│ │
│ ┌──────────┐ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ Hello │ ─▶ │ ▓▓▓▓▓ (paths) │ ─▶ │ ✋ draws "Hello" │ │
│ │ (text) │ │ │ │ with pen tool │ │
│ └──────────┘ └──────────────────┘ └──────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
2. Gradient Fill
Apply gradient to text (not possible with editable text):
GRADIENT TEXT
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ Before: "HELLO" (solid fill) │
│ After: "HELLO" (gradient fill from blue to purple) │
│ │
│ ░░░▒▒▒▓▓▓███████▓▓▓▒▒▒░░░ │
│ H E L L O │
│ │
└─────────────────────────────────────────────────────────────────────────┘
3. Font-Free Export
Export animations without font embedding issues:
| Without Outlining | With Outlining |
|---|---|
| Font file required | No font required |
| Text may render differently | Always renders correctly |
| Larger file if embedding | Paths self-contained |
Status Messages
Success
┌──────────────────────────────────────────────────────┐
│ ✓ Text converted to outlines. Undo with Ctrl+Z. │
└──────────────────────────────────────────────────────┘
Partial Success
┌─────────────────────────────────────────────────────────────────────────┐
│ ⚠ Some characters are not supported by the current outline font │
│ and were skipped. │
└─────────────────────────────────────────────────────────────────────────┘
Error
┌──────────────────────────────────────────────────────┐
│ ✕ Could not convert text to outlines │
│ (no paths produced). │
└──────────────────────────────────────────────────────┘
Undo/Redo
Conversion is a single atomic operation:
| Action | Keyboard | Effect |
|---|---|---|
| Undo | Ctrl+Z / ⌘+Z | Restores original editable text |
| Redo | Ctrl+Shift+Z / ⌘+Shift+Z | Re-applies outlined paths |
After undo, your original text is restored exactly as before - all editing capabilities return.
Inspector Badge
After conversion, outlined paths show a badge:
OUTLINED TEXT BADGE
┌──────────────────────────────────────────────────────────────────────┐
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ 📐 SVG Path [ OUTLINED TEXT ] │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ Mode [ Standard ▼ ] │
│ Speed [ Duration ▼ ] [ 1 ] │
│ Stroke [ ████ ] Width [ 1 ] │
│ │
└──────────────────────────────────────────────────────────────────────┘
The "OUTLINED TEXT" badge is runtime-only and helps identify converted text. After project reload, outlined paths appear as regular SVG paths.
Limitations
Selection Rules
| Selection | Convert Available? |
|---|---|
| Single text object | ✅ Yes |
| Multiple text objects | ❌ No (select one at a time) |
| Mixed selection (text + shapes) | ❌ No |
| Non-text object | ❌ No |
Font Support
| Scenario | Behavior |
|---|---|
| Bundled font | ✅ Full outline support |
| Web font (Google Fonts) | ⚠️ Requires font URL access |
| System font | ⚠️ May fallback to sans-serif |
| Custom uploaded font | ⚠️ Depends on font file format |
Character Support
| Characters | Support |
|---|---|
| Latin A-Z, a-z | ✅ Full |
| Numbers 0-9 | ✅ Full |
| Common punctuation | ✅ Full |
| Devanagari (Hindi) | ✅ Full (with Devanagari fonts) |
| Emoji | ⚠️ Limited |
| Complex scripts | ⚠️ Varies by font |
Performance
Guidelines
| Text Length | Expected Time | Notes |
|---|---|---|
| < 50 chars | < 50ms | Instant |
| 50-200 chars | 50-200ms | Fast |
| 200-400 chars | 200-500ms | Acceptable |
| > 400 chars | 500ms+ | Consider splitting text |
For very long text (400+ characters), consider splitting into multiple text objects before converting. Large conversions may cause brief UI lag.
Worker Execution
The outliner runs in a Web Worker to avoid blocking the UI:
WORKER ARCHITECTURE
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ ┌─────────────────────┐ ┌────────────┐ │
│ │ Main │ ───▶ │ Web Worker │ ───▶ │ Result │ │
│ │ Thread │ │ (svg-text-to-path) │ │ Paths │ │
│ │ │ │ │ │ │ │
│ │ UI stays │ │ Heavy font parsing │ │ Paths │ │
│ │ responsive │ │ + glyph tracing │ │ returned │ │
│ └─────────────┘ └─────────────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Technical Details
Data Flow
TEXT TO PATH DATA FLOW
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ SceneObject (type: 'text') │
│ ├── id: "text-abc123" │
│ ├── content: "Hello World" │
│ ├── fontFamily: "Mukta" │
│ ├── fontSize: 48 │
│ ├── fontWeight: 500 │
│ ├── fill: "#333333" │
│ └── x: 100, y: 200 │
│ │ │
│ ▼ │
│ TextToPathRequest │
│ ├── textNodes: [{ id, content, fontFamily, fontSize, ... }] │
│ │ │
│ ▼ │
│ svg-text-to-path Engine │
│ ├── Load font via ConfigProvider │
│ ├── Parse text → glyph outlines │
│ ├── Generate SVG <path> elements │
│ │ │
│ ▼ │
│ TextToPathResponse │
│ ├── status: 'success' | 'partialSuccess' │
│ ├── results: [{ originalNodeId, pathData, bbox }] │
│ └── diagnostics: { totalGlyphs, durationMs, workerUsed } │
│ │ │
│ ▼ │
│ SceneObject (type: 'svgPath') │
│ ├── id: "text-abc123" (preserved) │
│ ├── paths: [{ id, d, fill, stroke, ... }] │
│ ├── x: 100, y: 200 (preserved) │
│ └── metadata: { outlinedText: true } (runtime only) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Error Codes
| Code | Description |
|---|---|
UnsupportedFont | Font file not available or incompatible |
MalformedTextNode | Text content or properties invalid |
ConversionTimeout | Conversion took too long |
WorkerError | Web Worker failed to process |
Best Practices
When to Convert
✅ Convert when:
- You need draw-in animation on text
- Exporting to platforms without font support
- Applying gradient/pattern fills
- Final polish before export
❌ Don't convert when:
- Text may need future edits
- Working on draft content
- Font is already embedded in export
Workflow Tips
- Finalize text first - Edit all content before converting
- Use Preview - Check outline quality before committing
- Keep original - Duplicate layer before converting if unsure
- Batch wisely - Convert text objects one at a time
Troubleshooting
Outlines Look Different from Text
- Check if using a bundled font
- Verify font weight matches (Regular vs Bold)
- Preview before converting to compare
Missing Characters
- Check if font supports the characters
- Use a different font with broader character set
- For Hindi text, use Devanagari fonts
Conversion Fails
- Check if text object is selected (not group)
- Ensure text is not empty
- Try a different font
- Check browser console for errors
Undo Not Working
- Undo immediately after conversion
- Check undo history hasn't been cleared
- Reload project if undo stack corrupted
File Locations
| Component | Path |
|---|---|
| Text Outliner Action | frontend/src/features/properties-panel/TextOutlinerAction.tsx |
| Outliner Bridge | frontend/src/plugins/text-outliner/textOutlinerBridge.ts |
| Text-to-Path Service | core/vector/trunk/services/textToPathService.ts |
| Environment Port | core/vector/roots/nodes/textToPathRoot.ts |
| Contracts | core/vector/trunk/contracts/textToPathContracts.ts |
| Implementation Plan | docs/features/text-outliner-implementation-plan.md |