Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
# OpenSpec Change: enterprise-font-convert
- **Change ID**: enterprise-font-convert
- **Package**: `@suaveplan/font-convert`
- **Category**: universal
- **Target path**: `universal/compression/font-convert`
- **Status**: PROPOSED
- **Date**: 2026-04-25
- **Reference source**: `/mnt/s/web/suaveplan/packages/universal/font-compress/src/converter/`
---
## Summary
Deliver `@suaveplan/font-convert` on the genesis branch from scratch at enterprise quality. The package converts TTF/OTF font files to the typeface.js JSON format used by Three.js. It parses binary fonts via `opentype.js`, extracts glyph outline commands, corrects path winding order for TrueType fonts, and emits a `TypefaceFont` JSON structure. Also defines the shared `TypefaceFont` and `PathCommand` types consumed by `@suaveplan/font-compress` and `@suaveplan/font-decompress`.
---
## Current-state audit (genesis)
The package does not exist on genesis yet. The original logic lived inside `@suaveplan/font-compress` on main; it is extracted here as a standalone package.
---
## Available workspace deps on genesis
| Package | Role |
|---|---|
| `@suaveplan/error` (`workspace:^`) | Base class for `FontConvertError`; `FONT_CONVERT.*` codes |
| `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock` |
| `opentype.js` (`catalog:fonts`) | Font binary parsing (TTF/OTF/WOFF/WOFF2) |
| `@types/opentype.js` (`catalog:fonts`) | Type definitions for opentype.js |
| `zod` (`catalog:forms`) | Zod schemas for public option types |
| `@opentelemetry/api` (`catalog:observability`) | Spans + counters |
Dev deps: `vitest`, `@vitest/coverage-istanbul`, `fast-check`, `mitata` (all `catalog:testing`).
---
## Shared types (canonical source for downstream packages)
```ts
/** A single path command in typeface.js outline format */
export type PathCommandType = "m" | "l" | "q" | "b" | "z";
export interface PathCommand {
type: PathCommandType;
x?: number;
y?: number;
x1?: number;
y1?: number;
x2?: number;
y2?: number;
}
/** Typeface.js glyph outline */
export interface TypefaceGlyph {
ha: number; // horizontal advance
x_min: number;
x_max: number;
o: string; // outline string: space-separated "type x y ..." tokens
}
/** Typeface.js font format — output of FontConverter, input to BinaryFontPacker */
export interface TypefaceFont {
glyphs: Record<string, TypefaceGlyph>;
familyName: string;
ascender: number;
descender: number;
underlinePosition: number;
underlineThickness: number;
boundingBox: { yMin: number; xMin: number; yMax: number; xMax: number };
resolution: number;
original_font_information: unknown;
cssFontWeight: string;
cssFontStyle: string;
reversed?: boolean;
}
```
## Public API
```ts
class FontConvertError extends SuaveplanError<FontConvertErrorCode>
type FontConvertErrorCode =
| 'FONT_CONVERT_PARSE_FAILED'
| 'FONT_CONVERT_ENCODE_FAILED'
| 'FONT_CONVERT_INVALID_OPTIONS'
| 'FONT_CONVERT_UNSUPPORTED_FORMAT'
interface ConversionOptions {
reverseTypeface?: boolean // default: false — reverse winding for CFF fonts
restrictCharacters?: boolean // default: false
restrictCharacterSet?: string // characters to include when restrictCharacters=true
}
class FontConverter {
constructor(options?: FontConverterOptions)
convert(data: Uint8Array | ArrayBuffer, options?: ConversionOptions): TypefaceFont
convertFromParsed(font: opentype.Font, options?: ConversionOptions): TypefaceFont
}
class BatchConverter {
constructor(options?: FontConverterOptions)
convertAll(items: Array<{ name: string; data: Uint8Array }>): Array<{ name: string; font: TypefaceFont }>
}
function createFontConverter(options?: FontConverterOptions): FontConverter
```
---
## File layout
```text
universal/compression/font-convert/
package.json
tsconfig.lib.json
vitest.config.ts
vite.config.ts
src/
index.ts
error-codes.ts
constants/
index.ts
types/
typeface.ts # TypefaceFont, TypefaceGlyph, PathCommand types
typeface.md
core/
font-converter/
font-converter.ts
font-converter.md
font-converter.types.ts
font-converter.test.ts
index.ts
batch-converter/
batch-converter.ts
batch-converter.md
batch-converter.test.ts
index.ts
utils/
reverse-winding.ts
reverse-winding.md
reverse-winding.test.ts
outline-to-string.ts
outline-to-string.md
outline-to-string.test.ts
__benchmarks__/
font-convert.bench.ts
tests/
integration.test.ts
```
---
## Impact
**Downstream**: `@suaveplan/font-compress` (BTF packing), `@suaveplan/font-decompress` (BTF unpacking) both import `TypefaceFont` and `PathCommand` from this package.
**Breaking changes**: none — fresh build.
**Prerequisites**: none (leaf-level except `opentype.js`).