Font Studio - Custom Hand-Drawn Fonts
Status: Implemented in v0.3.1
Complexity: High
Dependencies: opentype.js
Files: js/FontStudio.js, js/FontStudioUI.js
Overview
Font Studio allows users to create custom fonts by drawing each character (glyph) on a dedicated canvas. The system captures Paper.js paths, converts them to OpenType glyph commands, and generates valid OTF font files that can be downloaded or used directly in PinePaper.
Quick Start
- Click the Font button in the left toolbar (or access via
window.fontStudioUI.show()) - Select a character from the grid
- Draw the character using the brush tool
- Click Save to store the glyph
- Repeat for all characters
- Export as OTF or use directly in PinePaper
User Interface
Main Panels
| Panel | Description |
|---|---|
| Left | Character grid with completion status (green = done) |
| Center | Drawing canvas with guide lines |
| Right | Preview, settings, metrics, and export options |
Learning Features
Font Studio includes built-in educational tools to help users understand typography:
- Learn Button: Toggle a typography guide explaining font basics
- Guide Lines: Visual reference lines with hover tooltips
- Cap Height (red): Top of capital letters (H, T, A)
- x-Height (cyan): Top of lowercase letters (a, e, x)
- Baseline (green): Where letters “sit”
- Descender (purple): Below baseline for g, p, y, j
- Character Tips: Context-specific drawing hints for each character
- Hover Tooltips: Explanations throughout the UI
Drawing Tools
| Tool | Shortcut | Description |
|---|---|---|
| Brush | B | Draw strokes (adjust size with slider) |
| Eraser | E | Remove strokes by clicking on them |
| Undo | Ctrl+Z | Remove last stroke |
| Clear | - | Clear all strokes |
| Save | S | Save current drawing as glyph |
Keyboard Shortcuts
| Key | Action |
|---|---|
| ← → | Navigate characters |
| B | Brush tool |
| E | Eraser tool |
| S | Save glyph |
| Ctrl+Z | Undo stroke |
| Esc | Close Font Studio |
Typography Guide Lines
Understanding these lines is essential for consistent fonts:
Cap Height ───────────────── (y = 100) Top of H, T, A
│
x-Height ───────────────── (y = 200) Top of a, e, x
│
│ ← Main drawing area
│
Baseline ───────────────── (y = 400) Letters sit here
│
Descender ───────────────── (y = 480) Below for g, p, y
Tips for Consistent Fonts:
- Keep stroke width consistent across all characters
- Uppercase letters should touch the cap height line
- Lowercase letters (except b, d, f, h, k, l, t) stay within x-height
- Letters g, j, p, q, y extend below the baseline to the descender
Character Sets
Minimum (63 characters)
Essential characters for basic text:
- A-Z (26 uppercase)
- a-z (26 lowercase)
- 0-9 (10 digits)
- Space (1)
Standard (90+ characters)
Adds punctuation for complete sentences:
- All minimum characters
!?.,;:'"()-@#$%&*+=/\[]{}|<>~^_`
API Usage
FontStudio Core (js/FontStudio.js)
// Access via app
const fontStudio = app.fontStudio;
// Or via UI
const fontStudioUI = window.fontStudioUI;
const fontStudio = fontStudioUI.fontStudio;
// Set font name
fontStudio.setFontName('MyHandwriting');
// Get required characters
const chars = fontStudio.getRequiredCharacters('minimum'); // or 'standard'
// Check completion status
const status = fontStudio.getCompletionStatus();
// { total: 63, completed: 10, pending: 53, percentage: 16, ... }
// Create glyph from Paper.js path
fontStudio.createGlyph('A', paperPath);
// Create space glyph (no drawing needed)
fontStudio.createSpaceGlyph();
// Generate and download font
fontStudio.downloadFont('otf'); // Downloads MyHandwriting.otf
// Load font into document for immediate use
const result = await fontStudio.loadIntoDocument();
// { success: true, fontName: 'MyHandwriting', message: '...' }
// Export/Import font data (for saving progress)
const data = fontStudio.exportData();
fontStudio.importData(data);
// Get font info
const info = fontStudio.getFontInfo();
// { name, metrics, glyphCount, completion, isComplete }
FontStudioUI (js/FontStudioUI.js)
// Show/hide Font Studio modal
window.fontStudioUI.show();
window.fontStudioUI.hide();
window.fontStudioUI.toggle();
// Check visibility
if (window.fontStudioUI.isVisible) { ... }
// Access FontStudio instance
const fontStudio = window.fontStudioUI.fontStudio;
Font Metrics
// Set custom metrics (advanced)
fontStudio.setMetrics({
unitsPerEm: 1000, // Coordinate grid size
ascender: 800, // Height above baseline
descender: -200, // Depth below baseline (negative)
xHeight: 500, // Lowercase letter height
capHeight: 700 // Capital letter height
});
Path Cleanup Functions
Font Studio includes professional path cleanup functions inspired by FontForge:
// Remove overlapping areas from paths (like FontForge's RemoveOverlap)
// Merges multiple overlapping paths into a single clean outline
const cleanPath = fontStudio.removeOverlap(paperPath);
// Correct path winding direction (like FontForge's CorrectDirection)
// Ensures proper fill rendering: outer contours clockwise, holes counter-clockwise
const correctedPath = fontStudio.correctDirection(paperPath);
// Apply all cleanup operations in order (removeOverlap -> correctDirection -> smooth)
const processedPath = fontStudio.cleanupPath(paperPath, {
removeOverlap: true, // Merge overlapping strokes
correctDirection: true, // Fix winding direction
smooth: true, // Apply path smoothing
smoothTolerance: 2.5 // Smoothing tolerance
});
// Individual path operations
fontStudio.smoothPath(paperPath, 2.5); // Simplify hand-drawn curves
fontStudio.normalizePath(paperPath); // Scale to fit standard metrics
| Function | Purpose | When to Use |
|---|---|---|
removeOverlap(path) |
Merge crossing strokes | Strokes that intersect or overlap |
correctDirection(path) |
Fix winding for fills | After combining paths, before export |
smoothPath(path, tolerance) |
Simplify curves | Hand-drawn paths with many points |
normalizePath(path) |
Consistent sizing | All glyphs for uniform appearance |
cleanupPath(path, options) |
All-in-one cleanup | Recommended for production fonts |
Technical Details
Path Conversion
Font Studio converts Paper.js paths to OpenType glyph commands:
- Coordinate Transform: Canvas Y-axis (top-down) → Font Y-axis (bottom-up)
- Scaling: Canvas pixels → Font units (typically 1000 units per em)
- Command Extraction: Bezier curves, lines, move commands
- Path Closing: Ensures closed paths for filled glyphs
Glyph Normalization
When saving a glyph:
- Paths are combined into a compound path
- Optional smoothing applied (
path.simplify()) - Scaled to fit standard metrics
- Centered horizontally
- Aligned to baseline
File Formats
| Format | Description | Use Case |
|---|---|---|
| OTF | OpenType Font | Desktop apps, print, web |
Save & Load Progress
Font Studio supports saving work-in-progress:
// Save to JSON file
const data = fontStudio.exportData();
// Downloads: MyHandwriting-data.json
// Load from JSON file
fontStudio.importData(jsonData);
// Restores all glyphs and settings
The JSON format includes:
- Font name and metrics
- All glyph path commands
- Advance widths
Integration
Using Custom Fonts in PinePaper
After creating a font:
// Method 1: Click "Use in PinePaper" button
// Makes font immediately available in font picker
// Method 2: Programmatic
await fontStudio.loadIntoDocument();
app.create('text', {
content: 'Hello',
fontFamily: 'MyHandwriting',
x: 400, y: 300
});
Template Support
Custom fonts can be embedded in templates (future enhancement).
Tips for Great Fonts
Stroke Consistency
- Use the same brush size for all characters
- Size 6-10 for regular weight, 12-18 for bold
Character Proportions
- Lowercase should be ~50-60% of cap height
- Numbers are often slightly shorter than capitals
- Punctuation typically aligns with lowercase
Common Mistakes
- Inconsistent stroke width
- Not using guide lines
- Forgetting the space character
- Descenders not extending below baseline
Character-Specific Tips
Each character has specific guidance displayed when selected:
- “A”: Two diagonal strokes meeting at cap height, horizontal crossbar
- “g”: Bowl at x-height with descending loop below baseline
- “0”: Oval shape, narrower than O
Copyright & Ownership
Users own full copyright to fonts they create with Font Studio:
- Original Work: Hand-drawn glyphs are the user’s original creative work
- Full Rights: Users can use, distribute, sell, or license their fonts
- OTF Format: Standard format compatible with all major platforms
- No Platform Claims: PinePaper makes no claims on user-created fonts
For distribution, users may consider:
- SIL Open Font License (OFL) — Popular open-source option
- Commercial licensing for paid fonts
- Attribution requirements for free distribution
Resources
- OpenType Specification
- opentype.js Documentation
- Font Metrics Explained
- Typography Terms Glossary
- SIL Open Font License — Open-source font licensing
- Font Licensing Guide — Licensing basics