Xteink-X4-crosspoint-reader/lib/EpdFont/SdFontFormat.h
Eunchurn Park 68ce6db291
feat: Add custom font selection from SD card
Allow users to select custom fonts (.epdfont files) from the
/.crosspoint/fonts/ directory on the SD card for EPUB/TXT reading.

Features:
- New FontSelectionActivity for browsing and selecting fonts
- SdFont and SdFontFamily classes for loading fonts from SD card
- Dynamic font reloading without device reboot
- Reader cache invalidation when font changes
- Hash-based font ID generation for proper cache management

The custom fonts use the .epdfont binary format which supports:
- 2-bit antialiasing for smooth text rendering
- Efficient on-demand glyph loading with LRU cache
- Memory-optimized design for ESP32-C3 constraints
2026-01-18 18:46:23 +09:00

80 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* .epdfont Binary Font Format Specification
*
* This format is designed for on-demand loading from SD card
* with minimal RAM usage on embedded devices.
*
* File Layout:
* ┌─────────────────────────────────────────────────────┐
* │ Header (32 bytes) │
* ├─────────────────────────────────────────────────────┤
* │ Intervals[] (intervalCount × 12 bytes) │
* ├─────────────────────────────────────────────────────┤
* │ Glyphs[] (glyphCount × 16 bytes) │
* ├─────────────────────────────────────────────────────┤
* │ Bitmap data (variable size) │
* └─────────────────────────────────────────────────────┘
*/
#pragma once
#include <cstdint>
// Magic number: "EPDF" in little-endian
#define EPDFONT_MAGIC 0x46445045
// Current format version
#define EPDFONT_VERSION 1
#pragma pack(push, 1)
/**
* File header - 32 bytes
*/
struct EpdFontHeader {
uint32_t magic; // 0x46445045 ("EPDF")
uint16_t version; // Format version (1)
uint8_t is2Bit; // 1 = 2-bit grayscale, 0 = 1-bit
uint8_t reserved1; // Reserved for alignment
uint8_t advanceY; // Line height
int8_t ascender; // Max height above baseline
int8_t descender; // Max depth below baseline (negative)
uint8_t reserved2; // Reserved for alignment
uint32_t intervalCount; // Number of unicode intervals
uint32_t glyphCount; // Total number of glyphs
uint32_t intervalsOffset; // File offset to intervals array
uint32_t glyphsOffset; // File offset to glyphs array
uint32_t bitmapOffset; // File offset to bitmap data
};
/**
* Unicode interval - 12 bytes
* Same as EpdUnicodeInterval but with explicit packing
*/
struct EpdFontInterval {
uint32_t first; // First unicode code point
uint32_t last; // Last unicode code point
uint32_t offset; // Index into glyph array
};
/**
* Glyph data - 16 bytes
* Same as EpdGlyph but with explicit packing
*/
struct EpdFontGlyph {
uint8_t width; // Bitmap width in pixels
uint8_t height; // Bitmap height in pixels
uint8_t advanceX; // Horizontal advance
uint8_t reserved; // Reserved for alignment
int16_t left; // X offset from cursor
int16_t top; // Y offset from cursor
uint32_t dataLength; // Bitmap data size in bytes
uint32_t dataOffset; // Offset into bitmap section
};
#pragma pack(pop)
// Sanity checks for struct sizes
static_assert(sizeof(EpdFontHeader) == 32, "EpdFontHeader must be 32 bytes");
static_assert(sizeof(EpdFontInterval) == 12, "EpdFontInterval must be 12 bytes");
static_assert(sizeof(EpdFontGlyph) == 16, "EpdFontGlyph must be 16 bytes");