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

  1. Click the Font button in the left toolbar (or access via window.fontStudioUI.show())
  2. Select a character from the grid
  3. Draw the character using the brush tool
  4. Click Save to store the glyph
  5. Repeat for all characters
  6. 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:

  1. Coordinate Transform: Canvas Y-axis (top-down) → Font Y-axis (bottom-up)
  2. Scaling: Canvas pixels → Font units (typically 1000 units per em)
  3. Command Extraction: Bezier curves, lines, move commands
  4. Path Closing: Ensures closed paths for filled glyphs

Glyph Normalization

When saving a glyph:

  1. Paths are combined into a compound path
  2. Optional smoothing applied (path.simplify())
  3. Scaled to fit standard metrics
  4. Centered horizontally
  5. 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

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