mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-05 07:07:38 +03:00
Fix font loading: V1 support, V0 header fix, flexible discovery, doc cleanup
This commit is contained in:
parent
6f05731189
commit
0a3a2cef5d
@ -1,37 +0,0 @@
|
|||||||
# Font Conversion Guide
|
|
||||||
|
|
||||||
To use custom fonts with the CrossPoint Reader, you must convert standard `.ttf` or `.otf` font files into the specific `.epdfont` binary format used by the compiled firmware.
|
|
||||||
|
|
||||||
We use a Python script located at `lib/EpdFont/scripts/fontconvert.py`.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
- Python 3
|
|
||||||
- `freetype-py` library (`pip install freetype-py`)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Run the script from the project root:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 lib/EpdFont/scripts/fontconvert.py --binary [Family-Style-Size] [Size] [PathToFont]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Arguments
|
|
||||||
1. `name`: The output filename (without extension). **Convention:** `Family-Style-Size` (e.g. `Bookerly-Regular-12`).
|
|
||||||
2. `size`: The integer point size (e.g. `12`).
|
|
||||||
3. `fontstack`: Path to the source font file (e.g. `fonts/Bookerly-Regular.ttf`).
|
|
||||||
4. `--binary`: **REQUIRED**. Flags the script to output the `.epdfont` binary instead of a C header.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
To convert `Bookerly-Regular.ttf` to a size 12 font:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python3 lib/EpdFont/scripts/fontconvert.py --binary Bookerly-Regular-12 12 fonts/Bookerly-Regular.ttf
|
|
||||||
```
|
|
||||||
|
|
||||||
This will generate `Bookerly-Regular-12.epdfont` in your current directory.
|
|
||||||
|
|
||||||
## Installing on Device
|
|
||||||
1. Rename the file if necessary to match the pattern: `Family-Style-Size.epdfont`.
|
|
||||||
2. Copy the `.epdfont` file to the `/fonts` directory on your SD card.
|
|
||||||
@ -73,3 +73,10 @@ The EPUB reader core was modified to improve stability, performance, and memory
|
|||||||
* Rendering: `lib/GfxRenderer/GfxRenderer.{cpp,h}`, `lib/EpdFont/EpdFont.{cpp,h}`
|
* Rendering: `lib/GfxRenderer/GfxRenderer.{cpp,h}`, `lib/EpdFont/EpdFont.{cpp,h}`
|
||||||
* EPUB Engine: `lib/Epub/*` (various files optimized and cleaned)
|
* EPUB Engine: `lib/Epub/*` (various files optimized and cleaned)
|
||||||
* Tools: `lib/EpdFont/scripts/fontconvert.py`
|
* Tools: `lib/EpdFont/scripts/fontconvert.py`
|
||||||
|
|
||||||
|
### Update: Enhanced Font Discovery & Format Support (2025-01-20)
|
||||||
|
|
||||||
|
* **V1 Format Support**: Added full support for the newer V1 `.epdfont` format (32-byte header, uint32 offsets) used by the web-based converter (`epdfont.clev.app`).
|
||||||
|
* **V0 Format Fix**: Fixed a regression in V0 font loading where the header read was truncated to 32 bytes (instead of 48), restoring support for `LibreBaskerville` and other legacy fonts.
|
||||||
|
* **Flexible Discovery**: Updated `FontManager` to support `Family_Style_Size` (underscore-separated) naming conventions, enabling compatibility with a wider range of auto-generated filenames.
|
||||||
|
* **Documentation**: Rewrote `FONT_CONVERSION.md` to cover both the Python script and the new web converter.
|
||||||
@ -19,7 +19,9 @@ To optimize for the limited RAM of the ESP32 and the specific requirements of E-
|
|||||||
* **Input**: TTF/OTF files.
|
* **Input**: TTF/OTF files.
|
||||||
* **Output**: `.epdfont` binary file.
|
* **Output**: `.epdfont` binary file.
|
||||||
* **Format Details**:
|
* **Format Details**:
|
||||||
* **Header**: Contains metadata (magic "EPDF", version, metrics, offsets).
|
* **Header**:
|
||||||
|
* **Version 1 (New)**: 32-byte header, uint32 offsets. Compact and efficient.
|
||||||
|
* **Version 0 (Legacy)**: 48-byte header, uint16 offsets. Retained for backward compatibility.
|
||||||
* **Intervals**: Unicode ranges supported by the font.
|
* **Intervals**: Unicode ranges supported by the font.
|
||||||
* **Glyphs**: Metrics for each character (width, height, advance, offsets).
|
* **Glyphs**: Metrics for each character (width, height, advance, offsets).
|
||||||
* **Bitmaps**: 1-bit or 2-bit (antialiased) pixel data for glyphs.
|
* **Bitmaps**: 1-bit or 2-bit (antialiased) pixel data for glyphs.
|
||||||
@ -29,9 +31,10 @@ To optimize for the limited RAM of the ESP32 and the specific requirements of E-
|
|||||||
Fonts are stored on the SD card in the `/fonts` directory.
|
Fonts are stored on the SD card in the `/fonts` directory.
|
||||||
|
|
||||||
* **Location**: `/fonts`
|
* **Location**: `/fonts`
|
||||||
* **Naming Convention**: `Family-Style-Size.epdfont`
|
* **Naming Convention**:
|
||||||
* Example: `Literata-Regular-14.epdfont`
|
* **Standard**: `Family-Style-Size.epdfont` (e.g., `LibreBaskerville-Regular-14.epdfont`)
|
||||||
* Example: `Literata-BoldItalic-14.epdfont`
|
* **Web Converter**: `Family_Style_Size.epdfont` (e.g., `Aileron_Regular_18.epdfont`)
|
||||||
|
* **Single File**: `Family.epdfont` (e.g., `Aileron.epdfont`) - automatically detected as Regular style.
|
||||||
* **Manager**: `src/managers/FontManager.cpp`
|
* **Manager**: `src/managers/FontManager.cpp`
|
||||||
* **Scans** the `/fonts` directory on startup/demand.
|
* **Scans** the `/fonts` directory on startup/demand.
|
||||||
* **Groups** files into `Family -> Size -> Styles (Regular, Bold, Italic, BoldItalic)`.
|
* **Groups** files into `Family -> Size -> Styles (Regular, Bold, Italic, BoldItalic)`.
|
||||||
73
docs/FONT_CONVERSION.md
Normal file
73
docs/FONT_CONVERSION.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Font Conversion Guide
|
||||||
|
|
||||||
|
To use custom fonts with the CrossPoint Reader, you must convert standard `.ttf` or `.otf` font files into the specific `.epdfont` binary format used by the compiled firmware.
|
||||||
|
|
||||||
|
## Supported Formats
|
||||||
|
|
||||||
|
The CrossPoint Reader supports two versions of the `.epdfont` format:
|
||||||
|
1. **Version 1 (Recommended):** The newer, optimized format generated by the web converter.
|
||||||
|
2. **Version 0 (Legacy):** The original format generated by the Python script.
|
||||||
|
|
||||||
|
## Method 1: Web Converter (Recommended)
|
||||||
|
|
||||||
|
The easiest way to generate compatible fonts is using the online converter.
|
||||||
|
|
||||||
|
1. Go to [https://epdfont.clev.app/](https://epdfont.clev.app/).
|
||||||
|
2. Select your `.ttf` or `.otf` file.
|
||||||
|
3. Choose the font size (e.g., 18).
|
||||||
|
4. Download the generated `.epdfont` file.
|
||||||
|
|
||||||
|
### Filename Requirements
|
||||||
|
|
||||||
|
The firmware scans for fonts in the `/fonts` directory on the SD card. It attempts to parse the filename to determine the Font Family, Style, and Size.
|
||||||
|
|
||||||
|
For best results, rename your downloaded file to match one of these patterns:
|
||||||
|
|
||||||
|
* `Family_Style_Size.epdfont` (e.g., `Aileron_Regular_18.epdfont`)
|
||||||
|
* `Family-Style-Size.epdfont` (e.g., `LibreBaskerville-Bold-14.epdfont`)
|
||||||
|
|
||||||
|
**Supported Styles:**
|
||||||
|
* `Regular`
|
||||||
|
* `Bold`
|
||||||
|
* `Italic`
|
||||||
|
* `BoldItalic`
|
||||||
|
|
||||||
|
**Note:** If you download a file named just `Aileron.epdfont`, the reader will try to load it, but using the explicit naming convention above ensures the correct style and size are recognized.
|
||||||
|
|
||||||
|
## Method 2: Python Script (Legacy)
|
||||||
|
|
||||||
|
You can also use the included Python script located at `lib/EpdFont/scripts/fontconvert.py`.
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
- Python 3
|
||||||
|
- `freetype-py` library (`pip install freetype-py`)
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Run the script from the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 lib/EpdFont/scripts/fontconvert.py --binary [Family-Style-Size] [Size] [PathToFont]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
1. `name`: The output filename (without extension). **Convention:** `Family-Style-Size` (e.g. `Bookerly-Regular-12`).
|
||||||
|
2. `size`: The integer point size (e.g. `12`).
|
||||||
|
3. `fontstack`: Path to the source font file (e.g. `fonts/Bookerly-Regular.ttf`).
|
||||||
|
4. `--binary`: **REQUIRED**. Flags the script to output the `.epdfont` binary instead of a C header.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
To convert `Bookerly-Regular.ttf` to a size 12 font:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 lib/EpdFont/scripts/fontconvert.py --binary Bookerly-Regular-12 12 fonts/Bookerly-Regular.ttf
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate `Bookerly-Regular-12.epdfont` in your current directory.
|
||||||
|
|
||||||
|
## Installing on Device
|
||||||
|
|
||||||
|
1. Copy your generated `.epdfont` files to the `/fonts` directory on your SD card.
|
||||||
|
2. Restart the CrossPoint Reader.
|
||||||
|
3. Go to **Settings** -> **Set Custom Font Family** to select your loaded fonts.
|
||||||
@ -6,12 +6,13 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
CustomEpdFont::CustomEpdFont(const String& filePath, const EpdFontData* data, uint32_t offsetIntervals,
|
CustomEpdFont::CustomEpdFont(const String& filePath, const EpdFontData* data, uint32_t offsetIntervals,
|
||||||
uint32_t offsetGlyphs, uint32_t offsetBitmaps)
|
uint32_t offsetGlyphs, uint32_t offsetBitmaps, int version)
|
||||||
: EpdFont(data),
|
: EpdFont(data),
|
||||||
filePath(filePath),
|
filePath(filePath),
|
||||||
offsetIntervals(offsetIntervals),
|
offsetIntervals(offsetIntervals),
|
||||||
offsetGlyphs(offsetGlyphs),
|
offsetGlyphs(offsetGlyphs),
|
||||||
offsetBitmaps(offsetBitmaps) {
|
offsetBitmaps(offsetBitmaps),
|
||||||
|
version(version) {
|
||||||
// Initialize bitmap cache
|
// Initialize bitmap cache
|
||||||
for (size_t i = 0; i < BITMAP_CACHE_CAPACITY; i++) {
|
for (size_t i = 0; i < BITMAP_CACHE_CAPACITY; i++) {
|
||||||
bitmapCache[i].data = nullptr;
|
bitmapCache[i].data = nullptr;
|
||||||
@ -112,26 +113,8 @@ const EpdGlyph* CustomEpdFont::getGlyph(uint32_t cp, const EpdFontStyles::Style
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foundInterval) {
|
if (foundInterval) {
|
||||||
// Calculate total glyphs to ensure bounds safety
|
uint32_t stride = (version == 1) ? 16 : 13;
|
||||||
uint32_t totalGlyphCount = (offsetBitmaps - offsetGlyphs) / 13;
|
uint32_t glyphFileOffset = offsetGlyphs + (glyphIndex * stride);
|
||||||
if (glyphIndex >= totalGlyphCount) {
|
|
||||||
Serial.printf("CustomEpdFont: Glyph index %u out of bounds (total %u)\n", glyphIndex, totalGlyphCount);
|
|
||||||
// If out of bounds, and we haven't tried fallback, try it.
|
|
||||||
if (!triedFallback) {
|
|
||||||
if (currentCp == 0x2018 || currentCp == 0x2019) {
|
|
||||||
currentCp = 0x0027;
|
|
||||||
triedFallback = true;
|
|
||||||
continue;
|
|
||||||
} else if (currentCp == 0x201C || currentCp == 0x201D) {
|
|
||||||
currentCp = 0x0022;
|
|
||||||
triedFallback = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t glyphFileOffset = offsetGlyphs + (glyphIndex * 13);
|
|
||||||
|
|
||||||
if (!fontFile.isOpen()) {
|
if (!fontFile.isOpen()) {
|
||||||
if (!SdMan.openFileForRead("CustomFont", filePath.c_str(), fontFile)) {
|
if (!SdMan.openFileForRead("CustomFont", filePath.c_str(), fontFile)) {
|
||||||
@ -146,22 +129,62 @@ const EpdGlyph* CustomEpdFont::getGlyph(uint32_t cp, const EpdFontStyles::Style
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t glyphBuf[13];
|
uint8_t w, h, adv, res = 0;
|
||||||
if (fontFile.read(glyphBuf, 13) != 13) {
|
int16_t l, t = 0;
|
||||||
Serial.println("CustomEpdFont: Read failed (glyph entry)");
|
uint32_t dLen, dOffset = 0;
|
||||||
fontFile.close();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t w = glyphBuf[0];
|
if (version == 1) {
|
||||||
uint8_t h = glyphBuf[1];
|
// New format (16 bytes)
|
||||||
uint8_t adv = glyphBuf[2];
|
uint8_t glyphBuf[16];
|
||||||
int8_t l = (int8_t)glyphBuf[3];
|
if (fontFile.read(glyphBuf, 16) != 16) {
|
||||||
// glyphBuf[4] unused
|
Serial.println("CustomEpdFont: Read failed (glyph entry v1)");
|
||||||
int8_t t = (int8_t)glyphBuf[5];
|
fontFile.close();
|
||||||
// glyphBuf[6] unused
|
return nullptr;
|
||||||
uint16_t dLen = glyphBuf[7] | (glyphBuf[8] << 8);
|
}
|
||||||
uint32_t dOffset = glyphBuf[9] | (glyphBuf[10] << 8) | (glyphBuf[11] << 16) | (glyphBuf[12] << 24);
|
|
||||||
|
/*
|
||||||
|
view.setUint8(offset++, glyph.width);
|
||||||
|
view.setUint8(offset++, glyph.height);
|
||||||
|
view.setUint8(offset++, glyph.advanceX);
|
||||||
|
view.setUint8(offset++, 0);
|
||||||
|
view.setInt16(offset, glyph.left, true);
|
||||||
|
offset += 2;
|
||||||
|
view.setInt16(offset, glyph.top, true);
|
||||||
|
offset += 2;
|
||||||
|
view.setUint32(offset, glyph.dataLength, true);
|
||||||
|
offset += 4;
|
||||||
|
view.setUint32(offset, glyph.dataOffset, true);
|
||||||
|
offset += 4;
|
||||||
|
*/
|
||||||
|
|
||||||
|
w = glyphBuf[0];
|
||||||
|
h = glyphBuf[1];
|
||||||
|
adv = glyphBuf[2];
|
||||||
|
res = glyphBuf[3];
|
||||||
|
l = (int16_t)(glyphBuf[4] | (glyphBuf[5] << 8)); // Little endian int16
|
||||||
|
t = (int16_t)(glyphBuf[6] | (glyphBuf[7] << 8)); // Little endian int16
|
||||||
|
dLen = glyphBuf[8] | (glyphBuf[9] << 8) | (glyphBuf[10] << 16) | (glyphBuf[11] << 24);
|
||||||
|
dOffset = glyphBuf[12] | (glyphBuf[13] << 8) | (glyphBuf[14] << 16) | (glyphBuf[15] << 24);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Old format (13 bytes)
|
||||||
|
uint8_t glyphBuf[13];
|
||||||
|
if (fontFile.read(glyphBuf, 13) != 13) {
|
||||||
|
Serial.println("CustomEpdFont: Read failed (glyph entry)");
|
||||||
|
fontFile.close();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = glyphBuf[0];
|
||||||
|
h = glyphBuf[1];
|
||||||
|
adv = glyphBuf[2];
|
||||||
|
l = (int8_t)glyphBuf[3];
|
||||||
|
// glyphBuf[4] unused
|
||||||
|
t = (int8_t)glyphBuf[5];
|
||||||
|
// glyphBuf[6] unused
|
||||||
|
dLen = glyphBuf[7] | (glyphBuf[8] << 8);
|
||||||
|
dOffset = glyphBuf[9] | (glyphBuf[10] << 8) | (glyphBuf[11] << 16) | (glyphBuf[12] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Serial.printf("[CEF] Parsed Glyph %u: Off=%u, Len=%u, W=%u, H=%u, L=%d, T=%d\n",
|
Serial.printf("[CEF] Parsed Glyph %u: Off=%u, Len=%u, W=%u, H=%u, L=%d, T=%d\n",
|
||||||
|
|||||||
@ -22,7 +22,7 @@ struct GlyphStructCacheEntry {
|
|||||||
class CustomEpdFont : public EpdFont {
|
class CustomEpdFont : public EpdFont {
|
||||||
public:
|
public:
|
||||||
CustomEpdFont(const String& filePath, const EpdFontData* data, uint32_t offsetIntervals, uint32_t offsetGlyphs,
|
CustomEpdFont(const String& filePath, const EpdFontData* data, uint32_t offsetIntervals, uint32_t offsetGlyphs,
|
||||||
uint32_t offsetBitmaps);
|
uint32_t offsetBitmaps, int version = 0);
|
||||||
~CustomEpdFont() override;
|
~CustomEpdFont() override;
|
||||||
|
|
||||||
const EpdGlyph* getGlyph(uint32_t cp, const EpdFontStyles::Style style = EpdFontStyles::REGULAR) const override;
|
const EpdGlyph* getGlyph(uint32_t cp, const EpdFontStyles::Style style = EpdFontStyles::REGULAR) const override;
|
||||||
@ -45,6 +45,7 @@ class CustomEpdFont : public EpdFont {
|
|||||||
mutable GlyphStructCacheEntry glyphCache[GLYPH_CACHE_CAPACITY];
|
mutable GlyphStructCacheEntry glyphCache[GLYPH_CACHE_CAPACITY];
|
||||||
|
|
||||||
mutable uint32_t currentAccessCount = 0;
|
mutable uint32_t currentAccessCount = 0;
|
||||||
|
int version = 0;
|
||||||
|
|
||||||
void clearCache() const;
|
void clearCache() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,7 +11,7 @@ typedef struct {
|
|||||||
uint8_t advanceX; ///< Distance to advance cursor (x axis)
|
uint8_t advanceX; ///< Distance to advance cursor (x axis)
|
||||||
int16_t left; ///< X dist from cursor pos to UL corner
|
int16_t left; ///< X dist from cursor pos to UL corner
|
||||||
int16_t top; ///< Y dist from cursor pos to UL corner
|
int16_t top; ///< Y dist from cursor pos to UL corner
|
||||||
uint16_t dataLength; ///< Size of the font data.
|
uint32_t dataLength; ///< Size of the font data.
|
||||||
uint32_t dataOffset; ///< Pointer into EpdFont->bitmap
|
uint32_t dataOffset; ///< Pointer into EpdFont->bitmap
|
||||||
} EpdGlyph;
|
} EpdGlyph;
|
||||||
|
|
||||||
|
|||||||
@ -56,10 +56,21 @@ void FontManager::scanFonts() {
|
|||||||
|
|
||||||
String name = String(filename);
|
String name = String(filename);
|
||||||
if (name.endsWith(".epdfont")) {
|
if (name.endsWith(".epdfont")) {
|
||||||
// Expected format: Family-Style-Size.epdfont
|
// Expected format: Family-Style-Size.epdfont or Family_Size.epdfont
|
||||||
int firstDash = name.indexOf('-');
|
// Or just Family.epdfont (V1 single file)
|
||||||
if (firstDash > 0) {
|
|
||||||
String family = name.substring(0, firstDash);
|
String family;
|
||||||
|
int separator = name.indexOf('-');
|
||||||
|
if (separator < 0) separator = name.indexOf('_');
|
||||||
|
|
||||||
|
if (separator > 0) {
|
||||||
|
family = name.substring(0, separator);
|
||||||
|
} else {
|
||||||
|
// No separator, take the whole name (minus .epdfont)
|
||||||
|
family = name.substring(0, name.length() - 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (family.length() > 0) {
|
||||||
if (std::find(availableFamilies.begin(), availableFamilies.end(), family.c_str()) ==
|
if (std::find(availableFamilies.begin(), availableFamilies.end(), family.c_str()) ==
|
||||||
availableFamilies.end()) {
|
availableFamilies.end()) {
|
||||||
availableFamilies.push_back(family.c_str());
|
availableFamilies.push_back(family.c_str());
|
||||||
@ -124,23 +135,83 @@ CustomEpdFont* loadFontFile(const String& path) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t intervalCount = buf[1];
|
Serial.printf("[FontMgr] Header Dump %s: ", path.c_str());
|
||||||
uint32_t fileSize = buf[2];
|
for (int i = 0; i < 12; i++) Serial.printf("%08X ", buf[i]);
|
||||||
uint32_t height = buf[3];
|
Serial.println();
|
||||||
uint32_t glyphCount = buf[4];
|
|
||||||
int32_t ascender = (int32_t)buf[5];
|
|
||||||
int32_t descender = (int32_t)buf[7];
|
|
||||||
|
|
||||||
uint32_t offsetIntervals = buf[9];
|
/*
|
||||||
uint32_t offsetGlyphs = buf[10];
|
* Version Detection Improved
|
||||||
uint32_t offsetBitmaps = buf[11];
|
*
|
||||||
|
* V1:
|
||||||
|
* Offset 20 (buf[5]) is OffsetIntervals. It matches header size = 32.
|
||||||
|
* Offset 4 (buf[1]) low 16 bits is Version = 1.
|
||||||
|
*
|
||||||
|
* V0:
|
||||||
|
* Offset 36 (buf[9]) is OffsetIntervals. It matches header size = 48.
|
||||||
|
*/
|
||||||
|
|
||||||
Serial.printf("[FontMgr] parsed header: intv=%u, glyphs=%u, fileSz=%u, h=%u, asc=%d, desc=%d\n", intervalCount,
|
int version = -1;
|
||||||
glyphCount, fileSize, height, ascender, descender);
|
|
||||||
Serial.printf("[FontMgr] offsets: intv=%u, gly=%u, bmp=%u\n", offsetIntervals, offsetGlyphs, offsetBitmaps);
|
// Check for V1
|
||||||
|
if (buf[5] == 32 && (buf[1] & 0xFFFF) == 1) {
|
||||||
|
version = 1;
|
||||||
|
}
|
||||||
|
// Check for V0
|
||||||
|
else if (buf[9] == 48) {
|
||||||
|
version = 0;
|
||||||
|
}
|
||||||
|
// Fallback: Use the old file size check if offsets are weird (detected from legacy files?)
|
||||||
|
else if (buf[2] > 10000) {
|
||||||
|
// V0 has fileSize at offset 8 (buf[2])
|
||||||
|
version = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t intervalCount, fileSize, glyphCount, offsetIntervals, offsetGlyphs, offsetBitmaps;
|
||||||
|
uint8_t height, advanceY;
|
||||||
|
int32_t ascender, descender;
|
||||||
|
bool is2Bit;
|
||||||
|
|
||||||
|
if (version == 1) {
|
||||||
|
// V1 Parsing
|
||||||
|
uint8_t* b8 = (uint8_t*)buf;
|
||||||
|
|
||||||
|
is2Bit = (b8[6] != 0);
|
||||||
|
advanceY = b8[8];
|
||||||
|
ascender = (int8_t)b8[9];
|
||||||
|
descender = (int8_t)b8[10];
|
||||||
|
|
||||||
|
intervalCount = b8[12] | (b8[13] << 8) | (b8[14] << 16) | (b8[15] << 24);
|
||||||
|
glyphCount = b8[16] | (b8[17] << 8) | (b8[18] << 16) | (b8[19] << 24);
|
||||||
|
offsetIntervals = b8[20] | (b8[21] << 8) | (b8[22] << 16) | (b8[23] << 24);
|
||||||
|
offsetGlyphs = b8[24] | (b8[25] << 8) | (b8[26] << 16) | (b8[27] << 24);
|
||||||
|
offsetBitmaps = b8[28] | (b8[29] << 8) | (b8[30] << 16) | (b8[31] << 24);
|
||||||
|
|
||||||
|
height = advanceY;
|
||||||
|
fileSize = 0; // Unknown
|
||||||
|
|
||||||
|
} else if (version == 0) {
|
||||||
|
// V0 Parsing
|
||||||
|
// We already read 48 bytes into buf
|
||||||
|
intervalCount = buf[1];
|
||||||
|
fileSize = buf[2];
|
||||||
|
height = buf[3];
|
||||||
|
glyphCount = buf[4];
|
||||||
|
ascender = (int32_t)buf[5];
|
||||||
|
descender = (int32_t)buf[7];
|
||||||
|
is2Bit = (buf[8] != 0);
|
||||||
|
|
||||||
|
offsetIntervals = buf[9];
|
||||||
|
offsetGlyphs = buf[10];
|
||||||
|
offsetBitmaps = buf[11];
|
||||||
|
} else {
|
||||||
|
Serial.printf("[FontMgr] Unknown version for %s\n", path.c_str());
|
||||||
|
f.close();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
if (offsetIntervals >= fileSize || offsetGlyphs >= fileSize || offsetBitmaps >= fileSize) {
|
// For V1, we trust offsets generated by the tool
|
||||||
|
if (offsetIntervals == 0 || offsetGlyphs == 0 || offsetBitmaps == 0) {
|
||||||
Serial.println("[FontMgr] Invalid offsets in header");
|
Serial.println("[FontMgr] Invalid offsets in header");
|
||||||
f.close();
|
f.close();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -178,11 +249,10 @@ CustomEpdFont* loadFontFile(const String& path) {
|
|||||||
fontData->advanceY = (uint8_t)height;
|
fontData->advanceY = (uint8_t)height;
|
||||||
fontData->ascender = ascender;
|
fontData->ascender = ascender;
|
||||||
fontData->descender = descender;
|
fontData->descender = descender;
|
||||||
fontData->descender = descender;
|
fontData->is2Bit = is2Bit;
|
||||||
fontData->is2Bit = (buf[8] != 0);
|
|
||||||
fontData->bitmap = nullptr;
|
fontData->bitmap = nullptr;
|
||||||
|
|
||||||
return new CustomEpdFont(path, fontData, offsetIntervals, offsetGlyphs, offsetBitmaps);
|
return new CustomEpdFont(path, fontData, offsetIntervals, offsetGlyphs, offsetBitmaps, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
EpdFontFamily* FontManager::getCustomFontFamily(const std::string& familyName, int fontSize) {
|
EpdFontFamily* FontManager::getCustomFontFamily(const std::string& familyName, int fontSize) {
|
||||||
@ -194,9 +264,29 @@ EpdFontFamily* FontManager::getCustomFontFamily(const std::string& familyName, i
|
|||||||
String sizeStr = String(fontSize);
|
String sizeStr = String(fontSize);
|
||||||
|
|
||||||
CustomEpdFont* regular = loadFontFile(basePath + "Regular-" + sizeStr + ".epdfont");
|
CustomEpdFont* regular = loadFontFile(basePath + "Regular-" + sizeStr + ".epdfont");
|
||||||
|
|
||||||
|
if (!regular) regular = loadFontFile("/fonts/" + String(familyName.c_str()) + "_Regular_" + sizeStr + ".epdfont");
|
||||||
|
if (!regular) regular = loadFontFile("/fonts/" + String(familyName.c_str()) + "_" + sizeStr + ".epdfont");
|
||||||
|
if (!regular) regular = loadFontFile("/fonts/" + String(familyName.c_str()) + ".epdfont");
|
||||||
|
if (!regular) regular = loadFontFile("/fonts/" + String(familyName.c_str()) + "-Regular.epdfont");
|
||||||
|
if (!regular) regular = loadFontFile("/fonts/" + String(familyName.c_str()) + "_Regular.epdfont");
|
||||||
|
if (!regular) regular = loadFontFile("/fonts/" + String(familyName.c_str()) + "-" + sizeStr + ".epdfont");
|
||||||
|
|
||||||
CustomEpdFont* bold = loadFontFile(basePath + "Bold-" + sizeStr + ".epdfont");
|
CustomEpdFont* bold = loadFontFile(basePath + "Bold-" + sizeStr + ".epdfont");
|
||||||
|
if (!bold) bold = loadFontFile("/fonts/" + String(familyName.c_str()) + "_Bold_" + sizeStr + ".epdfont");
|
||||||
|
if (!bold) bold = loadFontFile("/fonts/" + String(familyName.c_str()) + "-Bold.epdfont");
|
||||||
|
if (!bold) bold = loadFontFile("/fonts/" + String(familyName.c_str()) + "_Bold.epdfont");
|
||||||
|
|
||||||
CustomEpdFont* italic = loadFontFile(basePath + "Italic-" + sizeStr + ".epdfont");
|
CustomEpdFont* italic = loadFontFile(basePath + "Italic-" + sizeStr + ".epdfont");
|
||||||
|
if (!italic) italic = loadFontFile("/fonts/" + String(familyName.c_str()) + "_Italic_" + sizeStr + ".epdfont");
|
||||||
|
if (!italic) italic = loadFontFile("/fonts/" + String(familyName.c_str()) + "-Italic.epdfont");
|
||||||
|
if (!italic) italic = loadFontFile("/fonts/" + String(familyName.c_str()) + "_Italic.epdfont");
|
||||||
|
|
||||||
CustomEpdFont* boldItalic = loadFontFile(basePath + "BoldItalic-" + sizeStr + ".epdfont");
|
CustomEpdFont* boldItalic = loadFontFile(basePath + "BoldItalic-" + sizeStr + ".epdfont");
|
||||||
|
if (!boldItalic)
|
||||||
|
boldItalic = loadFontFile("/fonts/" + String(familyName.c_str()) + "_BoldItalic_" + sizeStr + ".epdfont");
|
||||||
|
if (!boldItalic) boldItalic = loadFontFile("/fonts/" + String(familyName.c_str()) + "-BoldItalic.epdfont");
|
||||||
|
if (!boldItalic) boldItalic = loadFontFile("/fonts/" + String(familyName.c_str()) + "_BoldItalic.epdfont");
|
||||||
|
|
||||||
if (!regular) {
|
if (!regular) {
|
||||||
if (bold) regular = bold;
|
if (bold) regular = bold;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user