// From // https://github.com/vroland/epdiy/blob/c61e9e923ce2418150d54f88cea5d196cdc40c54/src/epd_internals.h #pragma once #include /// Font metrics use "fixed-point 4" (4 fractional bits, i.e. 1/16-pixel /// resolution). Both the 12.4 glyph advances (uint16_t) and the 4.4 kern /// values (int8_t) share the same 4 fractional bits, so they can be freely /// added into a single int32_t accumulator during text layout. The /// accumulator is snapped to the nearest whole pixel only at render time, /// which avoids the per-character rounding errors that plagued integer-only /// layout. /// /// The helpers below eliminate the raw bit-shifts that would otherwise be /// scattered across every layout / measurement call site. namespace fp4 { constexpr int FRAC_BITS = 4; constexpr int32_t HALF = 1 << (FRAC_BITS - 1); // 8, added before shift for round-to-nearest /// Convert an integer pixel value to 12.4 fixed-point. constexpr int32_t fromPixel(int px) { return static_cast(px) << FRAC_BITS; } /// Snap a fixed-point value to the nearest integer pixel. constexpr int toPixel(int32_t fp) { return static_cast((fp + HALF) >> FRAC_BITS); } /// Convert a fixed-point value to float (mainly useful for debug logging). constexpr float toFloat(int32_t fp) { return fp / static_cast(1 << FRAC_BITS); } } // namespace fp4 /// Fixed-point conventions used by EpdGlyph and EpdFontData: /// advanceX: 12.4 unsigned fixed-point in uint16_t (use fp4::toPixel) /// kernMatrix: 4.4 signed fixed-point in int8_t (use fp4::toPixel) /// Both share 4 fractional bits so they combine directly in an accumulator. /// Font data stored PER GLYPH typedef struct { uint8_t width; ///< Bitmap dimensions in pixels uint8_t height; ///< Bitmap dimensions in pixels uint16_t advanceX; ///< Distance to advance cursor (x axis), 12.4 fixed-point in pixels int16_t left; ///< X 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 dataOffset; ///< Pointer into EpdFont->bitmap (or within-group offset for compressed fonts) } EpdGlyph; /// Compressed font group: a DEFLATE-compressed block of glyph bitmaps typedef struct { uint32_t compressedOffset; ///< Byte offset into compressed data array uint32_t compressedSize; ///< Compressed DEFLATE stream size uint32_t uncompressedSize; ///< Decompressed size uint16_t glyphCount; ///< Number of glyphs in this group uint16_t firstGlyphIndex; ///< First glyph index in the global glyph array } EpdFontGroup; /// Glyph interval structure typedef struct { uint32_t first; ///< The first unicode code point of the interval uint32_t last; ///< The last unicode code point of the interval uint32_t offset; ///< Index of the first code point into the glyph array } EpdUnicodeInterval; /// Maps a codepoint to a kerning class ID, sorted by codepoint for binary search. /// Class IDs are 1-based; codepoints not in the table have implicit class 0 (no kerning). typedef struct { uint16_t codepoint; ///< Unicode codepoint uint8_t classId; ///< 1-based kerning class ID } __attribute__((packed)) EpdKernClassEntry; /// Ligature substitution for a specific glyph pair, sorted by `pair` for binary search. /// `pair` encodes (leftCodepoint << 16 | rightCodepoint) for single-key lookup. typedef struct { uint32_t pair; ///< Packed codepoint pair (left << 16 | right) uint32_t ligatureCp; ///< Codepoint of the replacement ligature glyph } __attribute__((packed)) EpdLigaturePair; /// Data stored for FONT AS A WHOLE typedef struct { const uint8_t* bitmap; ///< Glyph bitmaps, concatenated const EpdGlyph* glyph; ///< Glyph array const EpdUnicodeInterval* intervals; ///< Valid unicode intervals for this font uint32_t intervalCount; ///< Number of unicode intervals. uint8_t advanceY; ///< Newline distance (y axis) int ascender; ///< Maximal height of a glyph above the base line int descender; ///< Maximal height of a glyph below the base line bool is2Bit; const EpdFontGroup* groups; ///< NULL for uncompressed fonts uint16_t groupCount; ///< 0 for uncompressed fonts const EpdKernClassEntry* kernLeftClasses; ///< Sorted left-side class map (nullptr if none) const EpdKernClassEntry* kernRightClasses; ///< Sorted right-side class map (nullptr if none) const int8_t* kernMatrix; ///< Flat leftClassCount x rightClassCount matrix, 4.4 fixed-point in pixels uint16_t kernLeftEntryCount; ///< Entries in kernLeftClasses uint16_t kernRightEntryCount; ///< Entries in kernRightClasses uint8_t kernLeftClassCount; ///< Number of distinct left classes (matrix rows) uint8_t kernRightClassCount; ///< Number of distinct right classes (matrix cols) const EpdLigaturePair* ligaturePairs; ///< Sorted ligature pair table (nullptr if none) uint32_t ligaturePairCount; ///< Number of entries in ligaturePairs } EpdFontData;