Reverts UI font change and adds setting for AA sd fonts

This commit is contained in:
Justin Mitchell
2026-07-06 18:59:25 -04:00
parent 72b99a2a9c
commit e69241ef54
15 changed files with 11299 additions and 9667 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-9
View File
@@ -99,12 +99,3 @@ ruby -rdigest -e 'puts [
"./notosans_8_regular.h", "./notosans_8_regular.h",
].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)' ].map{|f| Digest::SHA256.hexdigest(File.read(f)).to_i(16) }.sum % (2 ** 32) - (2 ** 31)'
))" ))"
echo ""
echo "// Font ID 0 is reserved as the \"not found\" sentinel."
echo "// Guard against any hash accidentally producing 0."
for id in NOTOSERIF_12 NOTOSERIF_14 NOTOSERIF_16 NOTOSERIF_18 \
NOTOSANS_12 NOTOSANS_14 NOTOSANS_16 NOTOSANS_18 \
UI_10 UI_12 SMALL; do
echo "static_assert(${id}_FONT_ID != 0, \"Font ID collision with sentinel\");"
done
+2 -5
View File
@@ -42,11 +42,8 @@ for size in ${UI_FONT_SIZES[@]}; do
# (fontstack is ordered by descending priority). # (fontstack is ordered by descending priority).
viet_path="../builtinFonts/source/Ubuntu/Ubuntu-Vietnamese-${style}.ttf" viet_path="../builtinFonts/source/Ubuntu/Ubuntu-Vietnamese-${style}.ttf"
output_path="../builtinFonts/${font_name}.h" output_path="../builtinFonts/${font_name}.h"
# 2-bit like the reader fonts: full coverage renders solid in BW mode and
# partial edge coverage dithers (GfxRenderer renderCharImpl), so UI text is
# anti-aliased on 1-bit panels and blends properly in grayscale passes.
python fontconvert.py $font_name $size $font_path $hebrew_path $viet_path \ python fontconvert.py $font_name $size $font_path $hebrew_path $viet_path \
--2bit --compress --additional-intervals 0x05D0,0x05EA > $output_path --additional-intervals 0x05D0,0x05EA > $output_path
echo "Generated $output_path" echo "Generated $output_path"
done done
done done
@@ -54,7 +51,7 @@ done
python fontconvert.py notosans_8_regular 8 \ python fontconvert.py notosans_8_regular 8 \
../builtinFonts/source/NotoSans/NotoSans-Regular.ttf \ ../builtinFonts/source/NotoSans/NotoSans-Regular.ttf \
../builtinFonts/source/NotoSansHebrew/NotoSansHebrew-Regular.ttf \ ../builtinFonts/source/NotoSansHebrew/NotoSansHebrew-Regular.ttf \
--2bit --compress --additional-intervals 0x05D0,0x05EA > ../builtinFonts/notosans_8_regular.h --additional-intervals 0x05D0,0x05EA > ../builtinFonts/notosans_8_regular.h
echo "" echo ""
echo "Running compression verification..." echo "Running compression verification..."
+9 -6
View File
@@ -282,12 +282,15 @@ static void renderCharImpl(const GfxRenderer& renderer, GfxRenderer::RenderMode
const uint8_t bmpVal = 3 - ((byte >> bit_index) & 0x3); const uint8_t bmpVal = 3 - ((byte >> bit_index) & 0x3);
if (renderMode == GfxRenderer::BW && bmpVal < 3) { if (renderMode == GfxRenderer::BW && bmpVal < 3) {
// Full coverage is solid ink; partial (anti-aliased edge) coverage // Default: gray pixels paint solid black. Required when grayscale
// dithers with the same period-2 patterns as fillRectDither // passes follow (their LUT lightens pixels it assumes were just
// (dark grey = 50% checkerboard, light grey = 25%), so 2-bit fonts // driven solid black), and it is the plain non-AA look otherwise.
// render anti-aliased on BW passes instead of bolding every edge // Fast AA: partial (anti-aliased edge) coverage dithers with the
// pixel to black. Skipped pixels leave the background untouched. // same period-2 patterns as fillRectDither (dark grey = 50%
if (bmpVal == 0 || (bmpVal == 1 && ((screenX + screenY) & 1) == 0) || // checkerboard, light grey = 25%), approximating AA in a single
// BW pass. Skipped pixels leave the background untouched.
if (!renderer.isFastAntiAliasing() || bmpVal == 0 ||
(bmpVal == 1 && ((screenX + screenY) & 1) == 0) ||
(bmpVal == 2 && (screenX & 1) == 0 && (screenY & 1) == 0)) { (bmpVal == 2 && (screenX & 1) == 0 && (screenY & 1) == 0)) {
renderer.drawPixel(screenX, screenY, pixelState); renderer.drawPixel(screenX, screenY, pixelState);
} }
+9
View File
@@ -44,6 +44,13 @@ class GfxRenderer {
RenderMode renderMode; RenderMode renderMode;
Orientation orientation; Orientation orientation;
bool fadingFix; bool fadingFix;
// Fast text anti-aliasing: when set, BW-mode rendering of 2-bit glyphs
// dithers partial-coverage (gray) pixels instead of painting them solid
// black, approximating AA in a single BW pass with no grayscale refresh.
// Must stay false when grayscale LSB/MSB passes follow the BW render: the
// gray LUT lightens pixels it assumes were just driven solid black, and
// dither-skipped white pixels would take its white-drive frames unopposed.
bool fastAntiAliasing = false;
uint8_t* frameBuffer = nullptr; uint8_t* frameBuffer = nullptr;
uint16_t panelWidth = HalDisplay::DISPLAY_WIDTH; uint16_t panelWidth = HalDisplay::DISPLAY_WIDTH;
uint16_t panelHeight = HalDisplay::DISPLAY_HEIGHT; uint16_t panelHeight = HalDisplay::DISPLAY_HEIGHT;
@@ -224,6 +231,8 @@ class GfxRenderer {
// Grayscale functions // Grayscale functions
void setRenderMode(const RenderMode mode) { this->renderMode = mode; } void setRenderMode(const RenderMode mode) { this->renderMode = mode; }
RenderMode getRenderMode() const { return renderMode; } RenderMode getRenderMode() const { return renderMode; }
void setFastAntiAliasing(const bool enabled) { this->fastAntiAliasing = enabled; }
bool isFastAntiAliasing() const { return fastAntiAliasing; }
// Grayscale preconditioning settle pass (no-op on X4). The rect overload // Grayscale preconditioning settle pass (no-op on X4). The rect overload
// takes the gray region in LOGICAL screen coordinates and rotates it to the // takes the gray region in LOGICAL screen coordinates and rotates it to the
// panel; the no-arg overload settles the full frame. Call after the BW base // panel; the no-arg overload settles the full frame. Call after the BW base
+2
View File
@@ -66,6 +66,8 @@ STR_SLEEP_COVER_MODE: "Sleep Screen Cover Mode"
STR_HIDE_BATTERY: "Hide Battery %" STR_HIDE_BATTERY: "Hide Battery %"
STR_EXTRA_SPACING: "Extra Paragraph Spacing" STR_EXTRA_SPACING: "Extra Paragraph Spacing"
STR_TEXT_AA: "Text Anti-Aliasing" STR_TEXT_AA: "Text Anti-Aliasing"
STR_TEXT_AA_FULL: "Full"
STR_TEXT_AA_FAST: "Fast"
STR_IMAGES: "Images" STR_IMAGES: "Images"
STR_IMAGES_DISPLAY: "Display" STR_IMAGES_DISPLAY: "Display"
STR_IMAGES_PLACEHOLDER: "Placeholder" STR_IMAGES_PLACEHOLDER: "Placeholder"
+8 -1
View File
@@ -173,6 +173,13 @@ class CrossPointSettings {
// Image rendering in EPUB reader // Image rendering in EPUB reader
enum IMAGE_RENDERING { IMAGES_DISPLAY = 0, IMAGES_PLACEHOLDER = 1, IMAGES_SUPPRESS = 2, IMAGE_RENDERING_COUNT }; enum IMAGE_RENDERING { IMAGES_DISPLAY = 0, IMAGES_PLACEHOLDER = 1, IMAGES_SUPPRESS = 2, IMAGE_RENDERING_COUNT };
// Text anti-aliasing mode for 2-bit fonts. FULL runs the grayscale LUT
// passes after the BW page render (extra refresh per page turn). FAST
// approximates AA inside the single BW pass by dithering partial-coverage
// glyph pixels (GfxRenderer fast anti-aliasing flag). Value 1 must stay
// FULL: it was the "on" value of the old on/off toggle in saved settings.
enum TEXT_ANTIALIASING { TEXT_AA_OFF = 0, TEXT_AA_FULL = 1, TEXT_AA_FAST = 2, TEXT_ANTIALIASING_COUNT };
enum TILT_PAGE_TURN { TILT_OFF = 0, TILT_NORMAL = 1, TILT_NVERTED = 2, TILT_PAGE_TURN_COUNT }; enum TILT_PAGE_TURN { TILT_OFF = 0, TILT_NORMAL = 1, TILT_NVERTED = 2, TILT_PAGE_TURN_COUNT };
enum QUICK_RESUME_SLEEP_SCREEN { enum QUICK_RESUME_SLEEP_SCREEN {
@@ -209,7 +216,7 @@ class CrossPointSettings {
uint8_t clockHasBeenSynced = 0; uint8_t clockHasBeenSynced = 0;
// Text rendering settings // Text rendering settings
uint8_t extraParagraphSpacing = 1; uint8_t extraParagraphSpacing = 1;
uint8_t textAntiAliasing = 1; uint8_t textAntiAliasing = TEXT_AA_FULL;
// Short power button click behaviour // Short power button click behaviour
uint8_t shortPwrBtn = IGNORE; uint8_t shortPwrBtn = IGNORE;
// EPUB reading orientation settings // EPUB reading orientation settings
+4 -1
View File
@@ -157,7 +157,10 @@ inline std::vector<SettingInfo> getSettingsList(const SdCardFontRegistry* regist
"orientation", StrId::STR_CAT_READER), "orientation", StrId::STR_CAT_READER),
SettingInfo::Toggle(StrId::STR_EXTRA_SPACING, &CrossPointSettings::extraParagraphSpacing, SettingInfo::Toggle(StrId::STR_EXTRA_SPACING, &CrossPointSettings::extraParagraphSpacing,
"extraParagraphSpacing", StrId::STR_CAT_READER), "extraParagraphSpacing", StrId::STR_CAT_READER),
SettingInfo::Toggle(StrId::STR_TEXT_AA, &CrossPointSettings::textAntiAliasing, "textAntiAliasing", // Option order must match TEXT_ANTIALIASING values (popup index is
// stored directly): OFF=0, FULL=1 (legacy toggle "on"), FAST=2.
SettingInfo::Enum(StrId::STR_TEXT_AA, &CrossPointSettings::textAntiAliasing,
{StrId::STR_STATE_OFF, StrId::STR_TEXT_AA_FULL, StrId::STR_TEXT_AA_FAST}, "textAntiAliasing",
StrId::STR_CAT_READER), StrId::STR_CAT_READER),
SettingInfo::Enum(StrId::STR_IMAGES, &CrossPointSettings::imageRendering, SettingInfo::Enum(StrId::STR_IMAGES, &CrossPointSettings::imageRendering,
{StrId::STR_IMAGES_DISPLAY, StrId::STR_IMAGES_PLACEHOLDER, StrId::STR_IMAGES_SUPPRESS}, {StrId::STR_IMAGES_DISPLAY, StrId::STR_IMAGES_PLACEHOLDER, StrId::STR_IMAGES_SUPPRESS},
+8 -1
View File
@@ -1241,7 +1241,8 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
const auto tPrewarm = millis(); const auto tPrewarm = millis();
const bool pageHasImages = page->hasImages(); const bool pageHasImages = page->hasImages();
const bool needsTextGrayscale = SETTINGS.textAntiAliasing; const bool needsTextGrayscale = SETTINGS.textAntiAliasing == CrossPointSettings::TEXT_AA_FULL;
const bool fastTextAA = SETTINGS.textAntiAliasing == CrossPointSettings::TEXT_AA_FAST;
const bool needsAnyGrayscale = needsTextGrayscale || pageHasImages; const bool needsAnyGrayscale = needsTextGrayscale || pageHasImages;
auto renderGrayscalePass = [&]() { auto renderGrayscalePass = [&]() {
if (needsTextGrayscale) { if (needsTextGrayscale) {
@@ -1251,7 +1252,11 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
} }
}; };
// Fast AA dithers 2-bit glyph edges in the BW pass itself, no grayscale
// refresh. Scoped to the page render so nothing else inherits the flag.
renderer.setFastAntiAliasing(fastTextAA);
page->render(renderer, fontId, orientedMarginLeft, orientedMarginTop); page->render(renderer, fontId, orientedMarginLeft, orientedMarginTop);
renderer.setFastAntiAliasing(false);
renderStatusBar(); renderStatusBar();
const auto tBwRender = millis(); const auto tBwRender = millis();
@@ -1268,7 +1273,9 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
// Re-render page content to restore images into the blanked area // Re-render page content to restore images into the blanked area
// Status bar is not re-rendered here to avoid reading stale dynamic values (e.g. battery %) // Status bar is not re-rendered here to avoid reading stale dynamic values (e.g. battery %)
renderer.setFastAntiAliasing(fastTextAA);
page->render(renderer, fontId, orientedMarginLeft, orientedMarginTop); page->render(renderer, fontId, orientedMarginLeft, orientedMarginTop);
renderer.setFastAntiAliasing(false);
renderer.displayBuffer(HalDisplay::FAST_REFRESH); renderer.displayBuffer(HalDisplay::FAST_REFRESH);
} else { } else {
renderer.displayBuffer(HalDisplay::HALF_REFRESH); renderer.displayBuffer(HalDisplay::HALF_REFRESH);
+5 -2
View File
@@ -400,13 +400,16 @@ void TxtReaderActivity::renderPage() {
renderLines(); // scan pass — text accumulated, no drawing renderLines(); // scan pass — text accumulated, no drawing
scope.endScanAndPrewarm(); scope.endScanAndPrewarm();
// BW rendering // BW rendering. Fast AA dithers 2-bit glyph edges in this single pass;
// scoped to the page text so nothing else inherits the flag.
renderer.setFastAntiAliasing(SETTINGS.textAntiAliasing == CrossPointSettings::TEXT_AA_FAST);
renderLines(); renderLines();
renderer.setFastAntiAliasing(false);
renderStatusBar(); renderStatusBar();
ReaderUtils::displayWithRefreshCycle(renderer, pagesUntilFullRefresh); ReaderUtils::displayWithRefreshCycle(renderer, pagesUntilFullRefresh);
if (SETTINGS.textAntiAliasing) { if (SETTINGS.textAntiAliasing == CrossPointSettings::TEXT_AA_FULL) {
ReaderUtils::renderAntiAliased(renderer, [&renderLines]() { renderLines(); }); ReaderUtils::renderAntiAliased(renderer, [&renderLines]() { renderLines(); });
} }
// scope destructor clears font cache via FontCacheManager // scope destructor clears font cache via FontCacheManager
+3 -3
View File
@@ -9,9 +9,9 @@
#define NOTOSANS_14_FONT_ID (-1589315735) #define NOTOSANS_14_FONT_ID (-1589315735)
#define NOTOSANS_16_FONT_ID (1669013660) #define NOTOSANS_16_FONT_ID (1669013660)
#define NOTOSANS_18_FONT_ID (37077304) #define NOTOSANS_18_FONT_ID (37077304)
#define UI_10_FONT_ID (418318152) #define UI_10_FONT_ID (22918846)
#define UI_12_FONT_ID (-1702441159) #define UI_12_FONT_ID (1635686837)
#define SMALL_FONT_ID (-1846631915) #define SMALL_FONT_ID (674098198)
// Font ID 0 is reserved as the "not found" sentinel. // Font ID 0 is reserved as the "not found" sentinel.
// Guard against any hash accidentally producing 0. // Guard against any hash accidentally producing 0.