# Font Creator

A programmatic font creation tool for defining fonts in code and exporting them to standard font formats (TTF, WOFF, WOFF2).

## ⚠️ Project Status: Educational Archive

This project was an experimental exploration into **procedural font generation and distortion** (v2.1.0). After real-world testing with the [Living OS narrative project](examples/LIVING_OS_EXPERIMENT_CONCLUSION.md), we discovered that **procedural distortion doesn't produce the visual impact needed for dynamic narrative fonts**.

**Key Finding:** While font-creator itself works well for basic programmatic font generation, applying procedural noise/distortion to make fonts "evolve" is fundamentally limited. The distortion effects are subtle and barely perceptible, and manually designing readable geometric characters defeats the purpose of procedural generation.

→ See [LIVING_OS_EXPERIMENT_CONCLUSION.md](examples/LIVING_OS_EXPERIMENT_CONCLUSION.md) for detailed learnings and why we're not pursuing this approach further.

### What This Means

✅ **Still useful for:**
- Static programmatic font generation
- Pixel/geometric font creation
- Learning font structure and format
- Exporting fonts to TTF/WOFF/WOFF2

❌ **Not recommended for:**
- Procedurally distorted "living" fonts
- Fonts that need to "evolve" via noise/distortion
- Expecting subtle procedural changes to drive narrative

If you want **dynamic font appearance changes**, consider instead:
- Pre-designed font variants for different states
- CSS/rendering effects (skew, blur, glitch effects)
- Custom SVG text rendering with transforms
- Existing variable font tools

---

## Overview

Font Creator allows you to:
- Define fonts programmatically using JavaScript classes
- Generate fonts using various algorithms (pixel, geometric, path-based, algorithmic)
- Export fonts to TTF/WOFF2 formats using both JavaScript and Python
- Explore and understand existing font structures
- Preview fonts interactively in the browser

This is a **standalone tool** for **experimental and educational font generation**, not production typography.

## Quick Start

### Browser Usage

1. Open `font-preview.html` in a web browser
2. Click "Generate Example" to create a sample font
3. Preview and export your font

### Node.js Usage

```javascript
const { FontDefinition, GlyphDefinition, Contour } = require('./core/font-definition.js');
const { generateSimplePixelFont } = require('./generators/pixel-font-generator.js');
const FontExporterJS = require('./export/js-exporter.js');

// Create a font
const font = generateSimplePixelFont('MyFont');

// Export to TTF
const exporter = new FontExporterJS();
const buffer = exporter.exportToArrayBuffer(font, 'ttf');
```

### Python Usage

```python
from export.python_exporter import FontExporterPython
import json

exporter = FontExporterPython()

# Export from JSON
exporter.export('font.json', 'output.ttf', format='ttf')
```

## Project Structure

```
font-creator/
├── docs/
│   ├── TOOL_EVALUATION.md              # Tool comparison and evaluation
│   └── SMART_DISTORTION_GUIDE.md       # Smart distortion (v2.1) - now archived
├── font-explorer/                       # Tools for exploring existing fonts
│   ├── font-parser.js                  # Parse TTF/WOFF files
│   └── font-visualizer.html            # Visual font explorer
├── core/                                # Core font definition classes
│   ├── font-definition.js              # FontDefinition, GlyphDefinition, Contour
│   ├── font-serializer.js              # JSON serialization
│   ├── smart-distortion.js             # Procedural distortion (v2.1, experimental)
│   ├── auto-kerning.js
│   ├── variable-font.js
│   ├── glyph-components.js
│   └── glyph-metrics.js
├── generators/                          # Font generators
│   ├── pixel-font-generator.js
│   ├── geometric-font-generator.js
│   ├── path-font-generator.js
│   ├── algorithmic-font-generator.js
│   ├── character-library.js
│   └── complete-alphabet.js
├── export/                              # Font exporters
│   ├── js-exporter.js                  # JavaScript exporter (opentype.js)
│   ├── woff2-exporter.js               # WOFF2 exporter with Brotli
│   └── python-exporter.py              # Python exporter (fonttools)
├── examples/                            # Example usage and experiments
│   ├── LIVING_OS_FONT_FINDINGS.md      # Initial v2.0 feature request
│   ├── LIVING_OS_FONT_V2_FEATURE_REQUEST.md  # v2.1 feature request
│   └── LIVING_OS_EXPERIMENT_CONCLUSION.md    # ← Read this for learnings
├── tools/                               # Development tools
│   └── glyph-debugger.html             # Interactive glyph visualization
├── font-preview.html                    # Interactive preview tool
├── package.json                         # JavaScript dependencies
└── requirements.txt                     # Python dependencies
```

## Core Concepts

### FontDefinition

Main class representing a complete font:

```javascript
const font = new FontDefinition('MyFont', {
  unitsPerEm: 1000,
  ascender: 800,
  descender: -200
});
```

### GlyphDefinition

Represents a single character:

```javascript
const glyph = new GlyphDefinition('A', 600);
glyph.createContour(contour => {
  contour.addPoint(100, 0, true);
  contour.addPoint(500, 0, true);
  contour.addPoint(300, 700, true);
  contour.close();
});
font.addGlyph(glyph);
```

### Contour

Represents a path within a glyph:

```javascript
const contour = new Contour();
contour.addPoint(100, 0, true);  // on-curve point
contour.addPoint(500, 0, true);
contour.addPoint(300, 700, true);
contour.close();
```

## Font Generators

### Pixel Font Generator

Creates pixel-art style fonts from 2D grids:

```javascript
const { generateSimplePixelFont } = require('./generators/pixel-font-generator.js');
const font = generateSimplePixelFont('PixelFont');
```

### Geometric Font Generator

Creates fonts using simple geometric shapes:

```javascript
const { generateGeometricFont } = require('./generators/geometric-font-generator.js');
const font = generateGeometricFont('GeometricFont', {
  thickness: 50
});
```

### Path Font Generator

Creates fonts from SVG paths:

```javascript
const { generatePathFont } = require('./generators/path-font-generator.js');
const font = generatePathFont('PathFont', {
  'A': 'M 100 0 L 500 0 L 300 700 Z'
});
```

### Algorithmic Font Generator

Creates fonts using algorithms (noise, fractals):

```javascript
const { generateAlgorithmicFont } = require('./generators/algorithmic-font-generator.js');
const font = generateAlgorithmicFont('OrganicFont', {
  algorithm: 'noise'
});
```

## Exporting Fonts

### JavaScript Export (Browser/Node.js)

```javascript
const FontExporterJS = require('./export/js-exporter.js');
const exporter = new FontExporterJS();

// Export to file (browser)
exporter.exportToFile(font, 'myfont', 'ttf');

// Export to ArrayBuffer
const buffer = exporter.exportToArrayBuffer(font, 'ttf');
```

### Python Export

```bash
# Install dependencies
pip install -r requirements.txt

# Export from JSON
python export/python-exporter.py font.json output.ttf
```

```python
from export.python_exporter import FontExporterPython

exporter = FontExporterPython()
exporter.export('font.json', 'output.ttf', format='ttf')
exporter.export('font.json', 'output.woff2', format='woff2')
```

## JSON Format

Fonts are serialized to a JSON format that both exporters understand:

```json
{
  "name": "MyFont",
  "metrics": {
    "unitsPerEm": 1000,
    "ascender": 800,
    "descender": -200
  },
  "glyphs": {
    "A": {
      "char": "A",
      "unicode": 65,
      "width": 600,
      "contours": [
        {
          "points": [
            {"x": 100, "y": 0, "onCurve": true},
            {"x": 500, "y": 0, "onCurve": true},
            {"x": 300, "y": 700, "onCurve": true}
          ]
        }
      ]
    }
  }
}
```

## Installation

### JavaScript Dependencies

```bash
npm install
```

Or use via CDN in HTML:
```html
<script src="https://cdn.jsdelivr.net/npm/opentype.js@1.3.4/dist/opentype.min.js"></script>
```

### Python Dependencies

```bash
pip install -r requirements.txt
```

## Tools

### Font Explorer

Open `font-explorer/font-visualizer.html` to:
- Parse and visualize existing font files
- View glyph paths and metrics
- Understand font structure

### Font Preview

Open `font-preview.html` to:
- Load or generate fonts
- Preview text rendering
- View glyph grids
- Export fonts

## Examples

See the `examples/` directory for complete examples:
- `simple-pixel-font.js` - Basic pixel font
- `geometric-font.js` - Geometric shapes font
- `algorithmic-font.js` - Algorithmic/organic font

## Documentation

- [Tool Evaluation](docs/TOOL_EVALUATION.md) - Comparison of existing tools vs custom approach
- [Core API](core/README.md) - Core font definition classes
- [Generators](generators/README.md) - Font generator examples
- [Exporters](export/README.md) - Font export functionality

## Learnings & Recommendations

### What We Learned from the Living OS Experiment

We attempted to use procedural distortion to create a font that visually evolves with narrative growth. After building and testing, we learned:

1. **Procedural distortion is subtle** - Even at maximum distortion levels (15+), the visual changes are barely perceptible. Text looks "slightly wavy" rather than "obviously transformed."

2. **Character design is hard** - While simple shapes (L, I, O) work, flowing characters (S, R, G, B) are unreadable. You end up needing manual character design, defeating the procedural purpose.

3. **Visual impact matters more than cleverness** - For narrative games/experiences, obvious visual changes (glitch effects, rendering transforms, completely different fonts) work better than subtle procedural variations.

4. **This isn't the tool for "living fonts"** - If you want fonts that evolve during gameplay, use pre-designed variants or rendering effects instead.

### Better Approaches for Dynamic Fonts

If you want fonts to change during your narrative/game:

- **Multiple font variants**: Design 3-4 fonts (clean → organic → alien → transformed) and switch between them
- **Rendering effects**: Use CSS skew, blur, opacity, scan lines, color shifts for more obvious distortion
- **Glitch effects**: Duplicate layers, offset/color-shift text for "system breaking down" appearance
- **SVG rendering**: Custom SVG text with full control over transforms and effects
- **Variable fonts**: Use CSS `font-variation-settings` if you really need smooth transitions

### What Font-Creator IS Good For

- Learning how fonts work
- Creating simple procedural fonts (pixel, geometric)
- Exporting programmatically-defined glyphs to TTF/WOFF2
- Rapid experimentation with font structure
- Educational projects about typography

### What Font-Creator Isn't Good For

- Production fonts (use FontForge, Glyphs, or hire a designer)
- Dynamically evolving fonts (use multiple variants or effects instead)
- Complex character design (requires manual work in proper tools)
- Professional typographic features (use established tools)

---

## Notes for Users

- This tool is best used for **learning and experimentation**, not production
- The Python exporter produces higher quality fonts than the JavaScript exporter
- WOFF2 compression requires the Python exporter
- Before investing time in procedural distortion, read the [Living OS conclusion](examples/LIVING_OS_EXPERIMENT_CONCLUSION.md) - you might save yourself effort
- For production fonts, use professional tools like FontForge, Glyphs, or hire a font designer

---

## For Future Explorers

If you're thinking about doing something similar (procedural fonts, generative typography, etc.):

1. **Test early and visually** - Don't spend weeks on code before seeing what it actually looks like
2. **Subtle effects don't work for UX** - If you want something to be visible to users, make it *obviously* visible
3. **Character design matters** - Procedural generation works for simple glyphs (I, O, L) but not for complex ones (S, R, G)
4. **Question the approach** - If you're fighting the tool, maybe the tool isn't right for the task

This project's value is partly in showing what *doesn't* work. Hopefully it saves someone else from going down the same road! 🎨

---

## License

MIT

## Contributing

This project is primarily an educational/archival project. The code is intentionally left as-is to document a complete experiment cycle. If you're building on it for your own project, feel free to fork and modify!

## Acknowledgments

Special thanks to the Living OS project for the real-world testing that led to these learnings. The experimental work and honest assessment of results is valuable for the broader creative coding community.
