Fonts & Text (pocketmage_font)
Font API
FontEngine is the single text path for both displays. Apps pick a logical FontStyle (a role, not a font file) and a DisplayTarget (OLED or E-Ink); the engine resolves the concrete u8g2 font, measures widths, caches metrics, and sets draw colors per target.
Access
#include <pocketmage.h>
FontEngine is a static-only class; there is no instance. The default table is kDefaultFontTable. FontEngine::init() runs inside PocketMage_INIT() and must precede any draw or measure call.
Roles and targets
enum class FontStyle : uint8_t {
Tiny, Body, BodyBold, BodyItalic, BodyBoldItalic, Medium, Small,
BodyNarrow, Mono, MonoBold, MonoItalic, MonoBoldItalic,
Sans, SansBold, SansItalic, SansBoldItalic,
Caption, Heading3, Heading2, Heading1, Large, OledWord,
Terminal, TerminalBig, ClockDigit,
_StyleCount // sentinel, must be last
};
enum class DisplayTarget : uint8_t {
OLED, // u8g2 SSD1326
EINK, // u8g2f bridge on the GxEPD2 buffer
};
Each role maps to a differ fonte per target. The comment on each member in the header names the concrete font (for example Body is ncenR10_tf, Heading1 is ncenB24_tf). Tiny is u8g2_font_5x7_tf, the size used for the OLED status line.
Structs
FontEntry
struct FontEntry {
const uint8_t* oled; // u8g2 font for the OLED
const uint8_t* eink; // u8g2 font for the E-Ink
uint8_t height; // full cell height in pixels
};
FontTable
A complete per-language/region table: one FontEntry per role plus the TXT markdown-editor matrix txt[3][4][4] indexed by family x size x variant. Applied with FontEngine::init(&table); nullptr re-applies the built-in default.
The TXT matrix indices are named constants:
enum : uint8_t {
TxtFamilySerif = 0, TxtFamilySans = 1, TxtFamilyMono = 2,
TxtSizeBody = 0, TxtSizeH3 = 1, TxtSizeH2 = 2, TxtSizeH1 = 3,
TxtVariantN = 0, TxtVariantB = 1, TxtVariantI = 2, TxtVariantBI = 3,
};
Heading regular variants alias to their bold font; headings are always bold. kDefaultFontTable is the English/global table.
FontEngine reference
class FontEngine {
public:
static void init(const FontTable* table = nullptr);
static void drawText(DisplayTarget target, int x, int y,
const char* text, FontStyle style);
static void drawText(DisplayTarget target, int x, int y,
const String& text, FontStyle style);
static void drawGlyph(DisplayTarget target, int x, int y,
uint16_t unicode, FontStyle style);
static int textWidth(DisplayTarget target, const char* text, FontStyle style);
static int textWidth(DisplayTarget target, const String& text, FontStyle style);
static FontStyle fitStyle(DisplayTarget target, const char* text, int maxWidth,
const FontStyle* cascade, int count);
static int charWidth(DisplayTarget target, uint16_t unicode, FontStyle style);
static int fontHeight(DisplayTarget target, FontStyle style);
static int fontAscent(DisplayTarget target, FontStyle style);
static int fontDescent(DisplayTarget target, FontStyle style);
static void setTextColor(DisplayTarget target, uint16_t color);
static void drawTextTxt(DisplayTarget target, int x, int y, const char* text,
uint8_t family, uint8_t sizeIdx, uint8_t variant);
static void drawGlyphTxt(DisplayTarget target, int x, int y, uint16_t unicode,
uint8_t family, uint8_t sizeIdx, uint8_t variant);
static int textWidthTxt(DisplayTarget target, const char* text,
uint8_t family, uint8_t sizeIdx, uint8_t variant);
static int charWidthTxt(DisplayTarget target, uint16_t unicode,
uint8_t family, uint8_t sizeIdx, uint8_t variant);
static int fontHeightTxt(uint8_t family, uint8_t sizeIdx, uint8_t variant);
};
Drawing
drawText/drawGlyphrender UTF-8 text or a single codepoint at(x, y);yis the baseline, not the top (U8g2 convention).- Out-of-range
family/sizeIdx/variantin theTxtvariants clamp to the body entry rather than fault.
Measuring
textWidthmeasures without changing the currently applied font, so layout code can interleave measure/draw freely.charWidthuses a per-style cache for codepoints 32 through 255 on the OLED target; other codepoints and the E-Ink target are measured live.fontHeight/fontAscent/fontDescentare measured lazily on first per (target, style) call and cached; layout code never switches fonts merely to measure.
fitStyle
The width-aware selection used by the HOME/APPLOADER grid to keep localized app names inside the 60px cell pitch: picks the largest cascade entry (ordered largest first) whose textWidth fits maxWidth, or the smallest when none fit. Typical cascade: kLabelCascade (Body, BodyNarrow, Small).
setTextColor
Value semantics match u8g2 draw color: 0 = black, 1 = white. Only the requested target’s color is touched, so an E-Ink status-bar draw never changes the OLED draw color and vice versa. Set the E-Ink color before the first draw of a screen; the bridge defaults are black-on-white from setupEink().
Example
#include <pocketmage.h>
void drawTitle() {
FontEngine::setTextColor(DisplayTarget::EINK, GxEPD_BLACK);
FontEngine::drawText(DisplayTarget::EINK, 8, 60, "PocketMage",
FontStyle::Heading1);
int w = FontEngine::textWidth(DisplayTarget::OLED, "Files", FontStyle::Body);
// center on the OLED
FontEngine::drawText(DisplayTarget::OLED,
(kOledWidth - w) / 2, kOledWordBaseline,
"Files", FontStyle::Body);
}
Remember y is the baseline. kOledWordBaseline (16) and the