ttf-rs 0.1.0

A Rust library for reading, writing, and operating on TTF (TrueType Font) files
Documentation
# ttf-rs Technical Specification

## Overview

`ttf-rs` is a comprehensive Rust library for reading, writing, and manipulating TrueType Font (TTF) files. The library provides both high-level convenience APIs and low-level access to font structures.

## Technical Requirements

### Language & Edition
- **Rust Edition**: 2024
- **Minimum Rust Version**: 1.80.0+
- **Dependencies**: Minimal external dependencies (thiserror for error handling)

### Performance Goals
- Zero-copy parsing where possible
- Lazy loading of font tables
- Efficient binary I/O operations
- Memory-efficient glyph data access

### Safety & Correctness
- Memory-safe operations (no unsafe code unless absolutely necessary)
- Proper error handling for all fallible operations
- Big-endian byte order handling
- Checksum validation for font integrity

## Font File Format

### SFNT Structure
TTF files follow the SFNT (Scalable Font) format:

```
Offset Table (12 bytes)
├── scaler_type: u32      (0x00010000 for TrueType)
├── num_tables: u16       (number of tables)
├── search_range: u16     (largest power of 2 <= num_tables * 16)
├── entry_selector: u16   (log2(search_range/16))
└── range_shift: u16      (num_tables * 16 - search_range)

Table Records (16 bytes each)
├── tag: [u8; 4]          (table identifier)
├── checksum: u32         (table checksum)
├── offset: u32           (offset from beginning of file)
└── length: u32           (length of table in bytes)

Table Data
└── [variable length data for each table]
```

## Supported TTF Tables

### Required Tables

#### 1. head - Font Header
- **Size**: 54 bytes
- **Purpose**: Basic font-wide information
- **Key Fields**:
  - `version`: Fixed (1.0)
  - `font_revision`: Fixed
  - `checksum_adjustment`: u32
  - `magic_number`: u32 (0x5F0F3CF5)
  - `flags`: u16
  - `units_per_em`: u16 (16-2048, power of 2 recommended)
  - `created`: i64 (seconds since 1904-01-01)
  - `modified`: i64
  - `x_min`, `y_min`, `x_max`, `y_max`: i16
  - `mac_style`: u16
  - `lowest_rec_ppem`: u16
  - `font_direction_hint`: i16
  - `index_to_loc_format`: i16 (0=short, 1=long)
  - `glyph_data_format`: i16

#### 2. maxp - Maximum Profile
- **Size**: 32 bytes (version 1.0)
- **Purpose**: Memory allocation requirements
- **Key Fields**:
  - `version`: Fixed
  - `num_glyphs`: u16
  - `max_points`: u16
  - `max_contours`: u16
  - `max_composite_points`: u16
  - `max_composite_contours`: u16
  - `max_zones`: u16
  - `max_twilight_points`: u16
  - `max_storage`: u16
  - `max_function_defs`: u16
  - `max_instruction_defs`: u16
  - `max_stack_elements`: u16
  - `max_size_of_instructions`: u16
  - `max_component_elements`: u16
  - `max_component_depth`: u16

#### 3. cmap - Character to Glyph Mapping
- **Purpose**: Map Unicode code points to glyph indices
- **Supported Formats**:
  - **Format 0**: Byte encoding (256 glyphs max)
  - **Format 4**: Segment mapping (BMP only, most common)
  - **Format 6**: Trimmed table (planned)
  - **Format 12**: Segmented coverage (planned)

#### 4. name - Naming Table
- **Purpose**: Human-readable font names and metadata
- **Name IDs**:
  - 0: Copyright
  - 1: Font Family
  - 2: Font Subfamily
  - 3: Unique Identifier
  - 4: Full Font Name
  - 5: Version String
  - 6: PostScript Name
  - 7: Trademark
  - 8: Manufacturer
  - 9: Designer
  - 10: Description
  - 11: Vendor URL
  - 12: Designer URL

#### 5. hhea - Horizontal Header
- **Size**: 36 bytes
- **Purpose**: Horizontal layout metrics
- **Key Fields**:
  - `version`: Fixed
  - `ascent`: i16
  - `descent`: i16
  - `line_gap`: i16
  - `advance_width_max`: u16
  - `min_left_side_bearing`: i16
  - `min_right_side_bearing`: i16
  - `x_max_extent`: i16
  - `caret_slope_rise`: i16
  - `caret_slope_run`: i16
  - `caret_offset`: i16
  - `metric_data_format`: i16
  - `num_h_metrics`: u16

#### 6. hmtx - Horizontal Metrics
- **Purpose**: Per-glyph horizontal metrics
- **Structure**:
  - Long horizontal metrics: (advance_width: u16, lsb: i16) × num_h_metrics
  - Left side bearings: i16 × (num_glyphs - num_h_metrics)

#### 7. loca - Index to Location
- **Purpose**: Glyph data offsets in glyf table
- **Formats**:
  - Short (offset/2): u16 array
  - Long: u32 array

#### 8. glyf - Glyph Data
- **Purpose**: Glyph outline definitions
- **Glyph Types**:
  - **Simple Glyphs**: Contour-based outlines
    - On-curve points (bit 0 = 1)
    - Off-curve control points (bit 0 = 0)
  - **Composite Glyphs**: References to other glyphs with transformations
  - **Empty Glyphs**: No outline data

#### 9. post - PostScript Information
- **Purpose**: PostScript compatibility data
- **Key Fields**:
  - `version`: Fixed
  - `italic_angle`: Fixed
  - `underline_position`: i16
  - `underline_thickness`: i16
  - `is_fixed_pitch`: u32
  - Memory usage minimums

#### 10. OS/2 - OS/2 and Windows Metrics
- **Purpose**: OS/2 and Windows-specific metrics
- **Key Fields**:
  - `version`: u16
  - `x_avg_char_width`: i16
  - `us_weight_class`: u16
  - `us_width_class`: u16
  - `fs_type`: u16 (embedding permissions)
  - `y_subscript/superscript` metrics
  - `y_strikeout` metrics
  - `s_family_class`: i16
  - `panose`: [u8; 10]
  - Unicode ranges
  - `ach_vend_id`: [u8; 4]
  - `fs_selection`: u16
  - `us_first_char_index`: u16
  - `us_last_char_index`: u16
  - Typographic metrics

## API Specification

### High-Level API

#### Font Loading
```rust
pub struct Font {
    data: Vec<u8>,
    table_records: Vec<TableRecord>,
}

impl Font {
    pub fn load<P: AsRef<Path>>(path: P) -> Result<Self>;
    pub fn from_data(data: Vec<u8>) -> Result<Self>;
}
```

#### Table Access
```rust
impl Font {
    pub fn head_table(&self) -> Result<HeadTable>;
    pub fn maxp_table(&self) -> Result<MaxpTable>;
    pub fn cmap_table(&self) -> Result<CmapTable>;
    pub fn name_table(&self) -> Result<NameTable>;
    pub fn hhea_table(&self) -> Result<HheaTable>;
    pub fn hmtx_table(&self) -> Result<HmtxTable>;
    pub fn glyf_table(&self) -> Result<GlyfTable>;
    pub fn loca_table(&self) -> Result<LocaTable>;
    pub fn post_table(&self) -> Result<PostTable>;
    pub fn os2_table(&self) -> Result<Os2Table>;
}
```

#### Convenience Methods
```rust
impl Font {
    pub fn char_to_glyph(&self, c: char) -> Result<u16>;
    pub fn num_glyphs(&self) -> Result<u16>;
    pub fn units_per_em(&self) -> Result<u16>;
    pub fn list_tables(&self) -> Vec<String>;
}
```

#### Font Writing
```rust
impl Font {
    pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()>;
    pub fn to_bytes(&self) -> Result<Vec<u8>>;
}
```

### Low-Level API

#### Binary Reading
```rust
pub struct FontReader<'a> {
    data: &'a [u8],
    position: usize,
}

impl<'a> FontReader<'a> {
    pub fn new(data: &'a [u8]) -> Self;
    pub fn read_u8(&mut self) -> Result<u8>;
    pub fn read_i8(&mut self) -> Result<i8>;
    pub fn read_u16(&mut self) -> Result<u16>;
    pub fn read_i16(&mut self) -> Result<i16>;
    pub fn read_u32(&mut self) -> Result<u32>;
    pub fn read_i32(&mut self) -> Result<i32>;
    pub fn read_fixed(&mut self) -> Result<f64>;
    pub fn read_bytes(&mut self, count: usize) -> Result<&'a [u8]>;
    pub fn seek(&mut self, position: usize);
    pub fn position(&self) -> usize;
    pub fn remaining(&self) -> usize;
}
```

#### Binary Writing
```rust
pub struct FontWriter {
    data: Vec<u8>,
}

impl FontWriter {
    pub fn new() -> Self;
    pub fn write_u8(&mut self, value: u8);
    pub fn write_i8(&mut self, value: i8);
    pub fn write_u16(&mut self, value: u16);
    pub fn write_i16(&mut self, value: i16);
    pub fn write_u32(&mut self, value: u32);
    pub fn write_i32(&mut self, value: i32);
    pub fn write_fixed(&mut self, value: f64);
    pub fn write_bytes(&mut self, bytes: &[u8]);
    pub fn into_vec(self) -> Vec<u8>;
}
```

#### Checksum Calculation
```rust
pub fn calculate_checksum(data: &[u8]) -> u32;
```

## Error Handling

```rust
#[derive(Debug, thiserror::Error)]
pub enum FontError {
    #[error("Invalid font format")]
    InvalidFormat,
    
    #[error("Table not found: {0}")]
    TableNotFound(String),
    
    #[error("Invalid table data: {0}")]
    InvalidTableData(String),
    
    #[error("Unexpected end of data")]
    UnexpectedEof,
    
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),
    
    #[error("Invalid checksum")]
    InvalidChecksum,
    
    #[error("Unsupported format: {0}")]
    UnsupportedFormat(String),
}

pub type Result<T> = std::result::Result<T, FontError>;
```

## Testing Requirements

### Unit Tests
- Binary I/O operations
- Checksum calculation
- Table parsing
- Error handling

### Integration Tests
- Load real TTF files
- Round-trip save/load
- Character to glyph mapping
- Glyph data extraction

### Test Coverage Goals
- Core functionality: >90%
- Table parsers: >85%
- Binary I/O: >95%

## Future Enhancements

### Phase 1: Font Modification
- Modify font metadata (name table)
- Update font metrics
- Add/remove glyphs
- Modify glyph outlines

### Phase 2: Advanced Features
- Font subsetting
- Glyph outline rendering
- Additional cmap formats (6, 12)
- Variable fonts support (gvar, fvar, avar)

### Phase 3: Extended Support
- TrueType instructions (fpgm, prep, cvt)
- Color fonts (COLR, CPAL, SVG)
- Font validation
- Format conversion

## Performance Benchmarks

Target performance metrics:
- Load 1MB font: <10ms
- Parse all tables: <5ms
- Character lookup: <1μs
- Glyph data access: <10μs
- Save font: <20ms

## Compatibility

### Font Format Support
- TrueType (.ttf)
- OpenType with TrueType outlines (.otf)

### Platform Support
- Linux
- macOS
- Windows
- WebAssembly (future)

## References

- [Microsoft OpenType Specification]https://docs.microsoft.com/en-us/typography/opentype/spec/
- [Apple TrueType Reference Manual]https://developer.apple.com/fonts/TrueType-Reference-Manual/
- [ISO/IEC 14496-22:2019 (Open Font Format)]https://www.iso.org/standard/74461.html