Add 2-bit compressed rendering for large UI fonts

Refactor UI font generation to support different rendering modes based on size. Small UI fonts (12pt) use 1-bit rendering for crisp display and reduced flash usage. Large UI fonts (14pt) now use 2-bit compressed rendering to stay smooth when scaled up on touch/high-density boards. Extract font generation logic into reusable generate_ui_font() function.
This commit is contained in:
Justin Mitchell
2026-06-17 01:18:17 -04:00
parent 4a17d21d80
commit 4f55444f67
7 changed files with 7073 additions and 22 deletions
+2
View File
@@ -37,3 +37,5 @@
#include <builtinFonts/ubuntu_10_regular.h>
#include <builtinFonts/ubuntu_12_bold.h>
#include <builtinFonts/ubuntu_12_regular.h>
#include <builtinFonts/ubuntu_14_bold.h>
#include <builtinFonts/ubuntu_14_regular.h>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7
View File
@@ -94,6 +94,13 @@ ruby -rdigest -e 'puts [
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define UI_14_FONT_ID ($(
ruby -rdigest -e 'puts [
"./ubuntu_14_regular.h",
"./ubuntu_14_bold.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))"
echo "#define SMALL_FONT_ID ($(
ruby -rdigest -e 'puts [
"./notosans_8_regular.h",
+31 -12
View File
@@ -28,23 +28,42 @@ for size in ${NOTOSANS_FONT_SIZES[@]}; do
done
done
# Small UI chrome (button devices, uiScale 1.0). Rendered 1-bit: crisp at these
# sizes and half the flash of 2-bit.
UI_FONT_SIZES=(10 12)
# Larger UI chrome substituted in on touch/high-density boards via the uiScale
# remap (see src/main.cpp setupFonts). Rendered 2-bit so it stays smooth when
# enlarged. Touch boards use uiScale 1.2, so UI_12 -> 14.4 -> 14 is the size the
# remap actually lands on; add larger sizes here if a board adopts a higher scale.
UI_FONT_SIZES_LARGE=(14)
UI_FONT_STYLES=("Regular" "Bold")
# Ubuntu lacks the Latin Extended Additional block (U+1EA0-U+1EF9) used for
# Vietnamese tone marks. Append a Vietnamese-only Ubuntu cut so those glyphs are
# filled from it while every glyph Ubuntu already has stays unchanged (fontstack
# is ordered by descending priority). NotoSansHebrew fills U+05D0-U+05EA so the
# Hebrew UI translation renders in menus and settings.
generate_ui_font() {
local size="$1" style="$2" extra_flags="$3"
local font_name="ubuntu_${size}_$(echo $style | tr '[:upper:]' '[:lower:]')"
local font_path="../builtinFonts/source/Ubuntu/Ubuntu-${style}.ttf"
local hebrew_path="../builtinFonts/source/NotoSansHebrew/NotoSansHebrew-${style}.ttf"
local viet_path="../builtinFonts/source/Ubuntu/Ubuntu-Vietnamese-${style}.ttf"
local output_path="../builtinFonts/${font_name}.h"
python fontconvert.py $font_name $size $font_path $hebrew_path $viet_path \
--additional-intervals 0x05D0,0x05EA $extra_flags > $output_path
echo "Generated $output_path"
}
for size in ${UI_FONT_SIZES[@]}; do
for style in ${UI_FONT_STYLES[@]}; do
font_name="ubuntu_${size}_$(echo $style | tr '[:upper:]' '[:lower:]')"
font_path="../builtinFonts/source/Ubuntu/Ubuntu-${style}.ttf"
hebrew_path="../builtinFonts/source/NotoSansHebrew/NotoSansHebrew-${style}.ttf"
# Ubuntu lacks the Latin Extended Additional block (U+1EA0-U+1EF9) used for
# Vietnamese tone marks. Append a Vietnamese-only Ubuntu cut so those glyphs
# are filled from it while every glyph Ubuntu already has stays unchanged
# (fontstack is ordered by descending priority).
viet_path="../builtinFonts/source/Ubuntu/Ubuntu-Vietnamese-${style}.ttf"
output_path="../builtinFonts/${font_name}.h"
python fontconvert.py $font_name $size $font_path $hebrew_path $viet_path \
--additional-intervals 0x05D0,0x05EA > $output_path
echo "Generated $output_path"
generate_ui_font $size $style ""
done
done
for size in ${UI_FONT_SIZES_LARGE[@]}; do
for style in ${UI_FONT_STYLES[@]}; do
generate_ui_font $size $style "--2bit --compress"
done
done
+2
View File
@@ -11,6 +11,7 @@
#define NOTOSANS_18_FONT_ID (37077304)
#define UI_10_FONT_ID (22918846)
#define UI_12_FONT_ID (1635686837)
#define UI_14_FONT_ID (1899049399)
#define SMALL_FONT_ID (674098198)
// Font ID 0 is reserved as the "not found" sentinel.
@@ -25,4 +26,5 @@ static_assert(NOTOSANS_16_FONT_ID != 0, "Font ID collision with sentinel");
static_assert(NOTOSANS_18_FONT_ID != 0, "Font ID collision with sentinel");
static_assert(UI_10_FONT_ID != 0, "Font ID collision with sentinel");
static_assert(UI_12_FONT_ID != 0, "Font ID collision with sentinel");
static_assert(UI_14_FONT_ID != 0, "Font ID collision with sentinel");
static_assert(SMALL_FONT_ID != 0, "Font ID collision with sentinel");
+17 -10
View File
@@ -110,6 +110,12 @@ EpdFont ui12RegularFont(&ubuntu_12_regular);
EpdFont ui12BoldFont(&ubuntu_12_bold);
EpdFontFamily ui12FontFamily(&ui12RegularFont, &ui12BoldFont);
// 14pt UI cut (2-bit) for the enlarged chrome the uiScale remap lands on for
// touch boards. Same Hebrew + Vietnamese coverage as the 10/12pt cuts.
EpdFont ui14RegularFont(&ubuntu_14_regular);
EpdFont ui14BoldFont(&ubuntu_14_bold);
EpdFontFamily ui14FontFamily(&ui14RegularFont, &ui14BoldFont);
// measurement of power button press duration calibration value
unsigned long t1 = 0;
unsigned long t2 = 0;
@@ -297,21 +303,22 @@ void setupDisplayAndFonts(bool seamless = false) {
#endif // OMIT_FONTS
renderer.insertFont(UI_10_FONT_ID, ui10FontFamily);
renderer.insertFont(UI_12_FONT_ID, ui12FontFamily);
renderer.insertFont(UI_14_FONT_ID, ui14FontFamily);
renderer.insertFont(SMALL_FONT_ID, smallFontFamily);
// UI chrome font scaling on touch/high-density boards: Ubuntu UI is only built at
// 10/12pt, so remap the UI fonts up the Noto Sans ladder with uiScale. SMALL is
// deliberately not remapped — it's compact secondary text (status bar, subtitles,
// battery %) that stays small. Reader body fonts aren't remapped either.
// UI chrome font scaling on touch/high-density boards: substitute a larger Ubuntu
// UI cut for each scaled UI font id at lookup time so menus/settings grow to finger
// size. We stay on the Ubuntu ladder (not Noto Sans) because the UI font carries
// Hebrew + Vietnamese glyphs that the Noto Sans reader fonts don't remapping onto
// Noto Sans would drop those scripts from the UI. SMALL is deliberately not remapped
// — it's compact secondary text (status bar, subtitles, battery %) that stays small.
// Reader body fonts aren't remapped either.
if (const float s = UITheme::uiScale(); s > 1.05f) {
auto nearestNotoSans = [](float pt) -> int {
auto nearestUbuntu = [](float pt) -> int {
const struct {
float pt;
int id;
} sizes[] = {{12, NOTOSANS_12_FONT_ID},
{14, NOTOSANS_14_FONT_ID},
{16, NOTOSANS_16_FONT_ID},
{18, NOTOSANS_18_FONT_ID}};
} sizes[] = {{10, UI_10_FONT_ID}, {12, UI_12_FONT_ID}, {14, UI_14_FONT_ID}};
int best = sizes[0].id;
float bestDiff = 1e9f;
for (const auto& z : sizes) {
@@ -324,7 +331,7 @@ void setupDisplayAndFonts(bool seamless = false) {
return best;
};
const int from[2] = {UI_10_FONT_ID, UI_12_FONT_ID};
const int to[2] = {nearestNotoSans(10 * s), nearestNotoSans(12 * s)};
const int to[2] = {nearestUbuntu(10 * s), nearestUbuntu(12 * s)};
renderer.setUiFontRemap(from, to, 2);
}