Merge pull request #260 from jpirnay/feat-expose-override
feat: Expose override menu
This commit is contained in:
@@ -596,6 +596,7 @@ STR_WEATHER_MOON_INFO: "Moon"
|
||||
STR_WEATHER_SUN_INFO: "Sun"
|
||||
STR_READER_BOOKMARKS: "Bookmarks & Footnotes"
|
||||
STR_READER_OVERRIDES: "Book-specific overrides"
|
||||
STR_QUICK_OVERRIDES: "Quick Overrides"
|
||||
STR_READER_UTILS: "Helper"
|
||||
STR_READER_TOOLS: "Tools"
|
||||
STR_READER_NAVIGATION: "Navigation"
|
||||
@@ -688,6 +689,7 @@ STR_BIONIC_READING: "Bionic Reading"
|
||||
STR_BTN_ACT_TOGGLE_BIONIC_READING: "Toggle Bionic Reading"
|
||||
STR_BTN_ACT_CYCLE_FONT_SIZE: "Change Font Size"
|
||||
STR_BTN_ACT_CYCLE_ORIENTATION: "Change Orientation"
|
||||
STR_BTN_ACT_QUICK_OVERRIDES: "Quick Overrides"
|
||||
STR_RESTART_DEVICE: "Restart Device"
|
||||
STR_SD_FIRMWARE_UPDATE: "SD Card Firmware Update"
|
||||
STR_SELECT_FIRMWARE_FILE: "Select firmware file (.bin)"
|
||||
|
||||
@@ -342,6 +342,7 @@ class CrossPointSettings {
|
||||
BTN_KOREADER_SYNC,
|
||||
BTN_CYCLE_FONT_SIZE,
|
||||
BTN_CYCLE_ORIENTATION,
|
||||
BTN_QUICK_OVERRIDES,
|
||||
BUTTON_ACTION_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -492,6 +492,8 @@ bool JsonSettingsIO::saveRecentBooks(const RecentBooksStore& store, const char*
|
||||
obj["fontSizeOverride"] = book.fontSizeOverride;
|
||||
obj["bionicReadingOverride"] = book.bionicReadingOverride;
|
||||
obj["paragraphAlignmentOverride"] = book.paragraphAlignmentOverride;
|
||||
obj["textAntiAliasingOverride"] = book.textAntiAliasingOverride;
|
||||
obj["hyphenationOverride"] = book.hyphenationOverride;
|
||||
}
|
||||
|
||||
String json;
|
||||
@@ -537,6 +539,8 @@ bool JsonSettingsIO::loadRecentBooks(RecentBooksStore& store, const char* json)
|
||||
book.bionicReadingOverride = clampInt8(obj["bionicReadingOverride"] | -1, -1, 1, -1);
|
||||
book.paragraphAlignmentOverride =
|
||||
clampInt8(obj["paragraphAlignmentOverride"] | -1, -1, CrossPointSettings::PARAGRAPH_ALIGNMENT_COUNT - 1, -1);
|
||||
book.textAntiAliasingOverride = clampInt8(obj["textAntiAliasingOverride"] | -1, -1, 1, -1);
|
||||
book.hyphenationOverride = clampInt8(obj["hyphenationOverride"] | -1, -1, 1, -1);
|
||||
store.recentBooks.push_back(book);
|
||||
}
|
||||
|
||||
|
||||
+29
-19
@@ -18,34 +18,27 @@ RecentBooksStore RecentBooksStore::instance;
|
||||
|
||||
void RecentBooksStore::addBook(const std::string& path, const std::string& title, const std::string& author,
|
||||
const std::string& series, const std::string& coverBmpPath) {
|
||||
int8_t embeddedStyleOverride = -1;
|
||||
int8_t imageRenderingOverride = -1;
|
||||
int8_t fontFamilyOverride = -1;
|
||||
std::string sdFontFamilyOverride;
|
||||
int8_t fontSizeOverride = -1;
|
||||
int8_t bionicReadingOverride = -1;
|
||||
int8_t paragraphAlignmentOverride = -1;
|
||||
RecentBook newBook{path, title, author, series, coverBmpPath};
|
||||
|
||||
pruneMissing();
|
||||
|
||||
// Remove existing entry if present
|
||||
// Remove existing entry if present, preserving its per-book overrides.
|
||||
auto it =
|
||||
std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; });
|
||||
if (it != recentBooks.end()) {
|
||||
embeddedStyleOverride = it->embeddedStyleOverride;
|
||||
imageRenderingOverride = it->imageRenderingOverride;
|
||||
fontFamilyOverride = it->fontFamilyOverride;
|
||||
sdFontFamilyOverride = it->sdFontFamilyOverride;
|
||||
fontSizeOverride = it->fontSizeOverride;
|
||||
bionicReadingOverride = it->bionicReadingOverride;
|
||||
paragraphAlignmentOverride = it->paragraphAlignmentOverride;
|
||||
newBook.embeddedStyleOverride = it->embeddedStyleOverride;
|
||||
newBook.imageRenderingOverride = it->imageRenderingOverride;
|
||||
newBook.fontFamilyOverride = it->fontFamilyOverride;
|
||||
newBook.sdFontFamilyOverride = it->sdFontFamilyOverride;
|
||||
newBook.fontSizeOverride = it->fontSizeOverride;
|
||||
newBook.bionicReadingOverride = it->bionicReadingOverride;
|
||||
newBook.paragraphAlignmentOverride = it->paragraphAlignmentOverride;
|
||||
newBook.textAntiAliasingOverride = it->textAntiAliasingOverride;
|
||||
newBook.hyphenationOverride = it->hyphenationOverride;
|
||||
recentBooks.erase(it);
|
||||
}
|
||||
|
||||
// Add to front
|
||||
recentBooks.insert(recentBooks.begin(), {path, title, author, series, coverBmpPath, embeddedStyleOverride,
|
||||
imageRenderingOverride, fontFamilyOverride, sdFontFamilyOverride,
|
||||
fontSizeOverride, bionicReadingOverride, paragraphAlignmentOverride});
|
||||
recentBooks.insert(recentBooks.begin(), std::move(newBook));
|
||||
|
||||
// Trim to max size
|
||||
if (recentBooks.size() > MAX_RECENT_BOOKS) {
|
||||
@@ -181,6 +174,21 @@ bool RecentBooksStore::setReaderOverrides(const std::string& path, const int8_t
|
||||
if (it == recentBooks.end()) {
|
||||
return false;
|
||||
}
|
||||
return setReaderOverrides(path, embeddedStyleOverride, imageRenderingOverride, fontFamilyOverride,
|
||||
sdFontFamilyOverride, fontSizeOverride, static_cast<int8_t>(bionicReadingOverride ? 1 : 0),
|
||||
paragraphAlignmentOverride, it->textAntiAliasingOverride, it->hyphenationOverride);
|
||||
}
|
||||
|
||||
bool RecentBooksStore::setReaderOverrides(const std::string& path, const int8_t embeddedStyleOverride,
|
||||
const int8_t imageRenderingOverride, const int8_t fontFamilyOverride,
|
||||
const std::string& sdFontFamilyOverride, const int8_t fontSizeOverride,
|
||||
const int8_t bionicReadingOverride, const int8_t paragraphAlignmentOverride,
|
||||
const int8_t textAntiAliasingOverride, const int8_t hyphenationOverride) {
|
||||
auto it =
|
||||
std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; });
|
||||
if (it == recentBooks.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
it->embeddedStyleOverride = embeddedStyleOverride;
|
||||
it->imageRenderingOverride = imageRenderingOverride;
|
||||
@@ -189,6 +197,8 @@ bool RecentBooksStore::setReaderOverrides(const std::string& path, const int8_t
|
||||
it->fontSizeOverride = fontSizeOverride;
|
||||
it->bionicReadingOverride = bionicReadingOverride;
|
||||
it->paragraphAlignmentOverride = paragraphAlignmentOverride;
|
||||
it->textAntiAliasingOverride = textAntiAliasingOverride;
|
||||
it->hyphenationOverride = hyphenationOverride;
|
||||
return saveToFile();
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@ struct RecentBook {
|
||||
int8_t bionicReadingOverride = -1;
|
||||
// -1 = use global setting, otherwise CrossPointSettings::PARAGRAPH_ALIGNMENT value.
|
||||
int8_t paragraphAlignmentOverride = -1;
|
||||
// -1 = use global default, otherwise explicit per-book override (0 = off, 1 = on).
|
||||
int8_t textAntiAliasingOverride = -1;
|
||||
// -1 = use global default, otherwise explicit per-book override (0 = off, 1 = on).
|
||||
int8_t hyphenationOverride = -1;
|
||||
|
||||
bool operator==(const RecentBook& other) const { return path == other.path; }
|
||||
};
|
||||
@@ -89,6 +93,12 @@ class RecentBooksStore {
|
||||
bool setReaderOverrides(const std::string& path, int8_t embeddedStyleOverride, int8_t imageRenderingOverride,
|
||||
int8_t fontFamilyOverride, const std::string& sdFontFamilyOverride, int8_t fontSizeOverride,
|
||||
bool bionicReadingOverride, int8_t paragraphAlignmentOverride);
|
||||
// Master overload — covers every per-book override. The narrower overloads above
|
||||
// all funnel through here, preserving any fields they don't take as arguments.
|
||||
bool setReaderOverrides(const std::string& path, int8_t embeddedStyleOverride, int8_t imageRenderingOverride,
|
||||
int8_t fontFamilyOverride, const std::string& sdFontFamilyOverride, int8_t fontSizeOverride,
|
||||
int8_t bionicReadingOverride, int8_t paragraphAlignmentOverride,
|
||||
int8_t textAntiAliasingOverride, int8_t hyphenationOverride);
|
||||
};
|
||||
|
||||
// Helper macro to access recent books store
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ inline const std::vector<SettingInfo> list = {
|
||||
StrId::STR_BTN_ACT_OPEN_BOOKMARKS, StrId::STR_BTN_ACT_STAR_PAGE, StrId::STR_BTN_ACT_FOOTNOTES, \
|
||||
StrId::STR_BTN_ACT_NEXT_SECTION, StrId::STR_BTN_ACT_PREV_SECTION, StrId::STR_BTN_ACT_EXIT_READER, \
|
||||
StrId::STR_BTN_ACT_READER_MENU, StrId::STR_BTN_ACT_TOGGLE_BIONIC_READING, StrId::STR_BTN_ACT_KOREADER_SYNC, \
|
||||
StrId::STR_BTN_ACT_CYCLE_FONT_SIZE, StrId::STR_BTN_ACT_CYCLE_ORIENTATION
|
||||
StrId::STR_BTN_ACT_CYCLE_FONT_SIZE, StrId::STR_BTN_ACT_CYCLE_ORIENTATION, StrId::STR_BTN_ACT_QUICK_OVERRIDES
|
||||
|
||||
// Back button: short=exit reader, double=ignore, long=go home
|
||||
SettingInfo::Enum(StrId::STR_BTN_SHORT_PRESS, &CrossPointSettings::btnShortBack, {StrId::STR_BTN_DEF_EXIT_READER},
|
||||
|
||||
@@ -31,6 +31,8 @@ struct MenuResult {
|
||||
uint8_t textDarkness = 1;
|
||||
uint8_t bionicReadingOverride = 0;
|
||||
int8_t paragraphAlignmentOverride = -1;
|
||||
int8_t textAntiAliasingOverride = -1;
|
||||
int8_t hyphenationOverride = -1;
|
||||
};
|
||||
|
||||
struct ChapterResult {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "KOReaderDocumentId.h"
|
||||
#include "MappedInputManager.h"
|
||||
#include "QrDisplayActivity.h"
|
||||
#include "QuickOverridesActivity.h"
|
||||
#include "ReaderActivity.h"
|
||||
#include "ReaderUtils.h"
|
||||
#include "ReadingSessionTracker.h"
|
||||
@@ -383,10 +384,10 @@ void EpubReaderActivity::onEnter() {
|
||||
bookFontFamilyOverride = currentBook.fontFamilyOverride;
|
||||
bookSdFontFamilyOverride = currentBook.sdFontFamilyOverride;
|
||||
bookFontSizeOverride = currentBook.fontSizeOverride;
|
||||
bookBionicReadingOverride = (currentBook.bionicReadingOverride >= 0)
|
||||
? static_cast<bool>(currentBook.bionicReadingOverride)
|
||||
: static_cast<bool>(SETTINGS.bionicReading);
|
||||
bookBionicReadingOverride = currentBook.bionicReadingOverride;
|
||||
bookParagraphAlignmentOverride = currentBook.paragraphAlignmentOverride;
|
||||
bookTextAntiAliasingOverride = currentBook.textAntiAliasingOverride;
|
||||
bookHyphenationOverride = currentBook.hyphenationOverride;
|
||||
logReaderMemSnapshot("onEnter_after_recent_books");
|
||||
|
||||
// Start a reading-stats session. We use the cheap filename-based hash here:
|
||||
@@ -1471,6 +1472,15 @@ void EpubReaderActivity::applyBookReaderOverrides(const int8_t embeddedStyleOver
|
||||
const std::string& sdFontFamilyOverride,
|
||||
const int8_t fontSizeOverride, const bool bionicReadingOverride,
|
||||
const int8_t paragraphAlignmentOverride) {
|
||||
applyBookReaderOverrides(embeddedStyleOverride, imageRenderingOverride, fontFamilyOverride, sdFontFamilyOverride,
|
||||
fontSizeOverride, static_cast<int8_t>(bionicReadingOverride ? 1 : 0),
|
||||
paragraphAlignmentOverride, bookTextAntiAliasingOverride, bookHyphenationOverride);
|
||||
}
|
||||
|
||||
void EpubReaderActivity::applyBookReaderOverrides(
|
||||
const int8_t embeddedStyleOverride, const int8_t imageRenderingOverride, const int8_t fontFamilyOverride,
|
||||
const std::string& sdFontFamilyOverride, const int8_t fontSizeOverride, const int8_t bionicReadingOverride,
|
||||
const int8_t paragraphAlignmentOverride, const int8_t textAntiAliasingOverride, const int8_t hyphenationOverride) {
|
||||
if (!epub) {
|
||||
return;
|
||||
}
|
||||
@@ -1488,7 +1498,8 @@ void EpubReaderActivity::applyBookReaderOverrides(const int8_t embeddedStyleOver
|
||||
bookFontFamilyOverride == normalizedFontFamilyOverride &&
|
||||
bookSdFontFamilyOverride == normalizedSdFontFamilyOverride && bookFontSizeOverride == fontSizeOverride &&
|
||||
bookBionicReadingOverride == bionicReadingOverride &&
|
||||
bookParagraphAlignmentOverride == paragraphAlignmentOverride) {
|
||||
bookParagraphAlignmentOverride == paragraphAlignmentOverride &&
|
||||
bookTextAntiAliasingOverride == textAntiAliasingOverride && bookHyphenationOverride == hyphenationOverride) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1499,9 +1510,12 @@ void EpubReaderActivity::applyBookReaderOverrides(const int8_t embeddedStyleOver
|
||||
bookFontSizeOverride = fontSizeOverride;
|
||||
bookBionicReadingOverride = bionicReadingOverride;
|
||||
bookParagraphAlignmentOverride = paragraphAlignmentOverride;
|
||||
bookTextAntiAliasingOverride = textAntiAliasingOverride;
|
||||
bookHyphenationOverride = hyphenationOverride;
|
||||
RECENT_BOOKS.setReaderOverrides(epub->getPath(), bookEmbeddedStyleOverride, bookImageRenderingOverride,
|
||||
bookFontFamilyOverride, bookSdFontFamilyOverride, bookFontSizeOverride,
|
||||
bookBionicReadingOverride, bookParagraphAlignmentOverride);
|
||||
bookBionicReadingOverride, bookParagraphAlignmentOverride,
|
||||
bookTextAntiAliasingOverride, bookHyphenationOverride);
|
||||
|
||||
RenderLock lock(*this);
|
||||
if (section) {
|
||||
@@ -1519,6 +1533,13 @@ bool EpubReaderActivity::getEffectiveEmbeddedStyle() const {
|
||||
return SETTINGS.embeddedStyle != 0;
|
||||
}
|
||||
|
||||
bool EpubReaderActivity::getEffectiveBionicReading() const {
|
||||
if (bookBionicReadingOverride >= 0) {
|
||||
return bookBionicReadingOverride > 0;
|
||||
}
|
||||
return SETTINGS.bionicReading;
|
||||
}
|
||||
|
||||
uint8_t EpubReaderActivity::getEffectiveImageRendering() const {
|
||||
if (bookImageRenderingOverride >= 0) {
|
||||
return static_cast<uint8_t>(bookImageRenderingOverride);
|
||||
@@ -1526,6 +1547,20 @@ uint8_t EpubReaderActivity::getEffectiveImageRendering() const {
|
||||
return SETTINGS.imageRendering;
|
||||
}
|
||||
|
||||
bool EpubReaderActivity::getEffectiveTextAntiAliasing() const {
|
||||
if (bookTextAntiAliasingOverride >= 0) {
|
||||
return bookTextAntiAliasingOverride != 0;
|
||||
}
|
||||
return SETTINGS.textAntiAliasing != 0;
|
||||
}
|
||||
|
||||
bool EpubReaderActivity::getEffectiveHyphenation() const {
|
||||
if (bookHyphenationOverride >= 0) {
|
||||
return bookHyphenationOverride != 0;
|
||||
}
|
||||
return SETTINGS.hyphenationEnabled != 0;
|
||||
}
|
||||
|
||||
uint8_t EpubReaderActivity::getEffectiveParagraphAlignment() const {
|
||||
if (bookParagraphAlignmentOverride >= 0) {
|
||||
return static_cast<uint8_t>(bookParagraphAlignmentOverride);
|
||||
@@ -1849,7 +1884,7 @@ void EpubReaderActivity::render(RenderLock&& lock) {
|
||||
lastRenderStats.embeddedStyle = getEffectiveEmbeddedStyle();
|
||||
lastRenderStats.imageRendering = getEffectiveImageRendering();
|
||||
lastRenderStats.effectiveFontId = getEffectiveReaderFontId();
|
||||
lastRenderStats.textAntiAliasing = SETTINGS.textAntiAliasing;
|
||||
lastRenderStats.textAntiAliasing = getEffectiveTextAntiAliasing();
|
||||
lastRenderStats.freeHeapBefore = esp_get_free_heap_size();
|
||||
lastRenderStats.largestFreeBlockBefore = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_DEFAULT);
|
||||
showTruncatedSectionHintThisRender = false;
|
||||
@@ -1936,7 +1971,7 @@ void EpubReaderActivity::render(RenderLock&& lock) {
|
||||
|
||||
if (!section->loadSectionFile(getEffectiveReaderFontId(), getEffectiveReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, getEffectiveParagraphAlignment(), viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, embeddedStyle, bookBionicReadingOverride,
|
||||
viewportHeight, getEffectiveHyphenation(), embeddedStyle, getEffectiveBionicReading(),
|
||||
imageRendering)) {
|
||||
LOG_DBG("ERS", "Cache not found, building...");
|
||||
lastRenderStats.cacheRebuilt = true;
|
||||
@@ -1958,8 +1993,8 @@ void EpubReaderActivity::render(RenderLock&& lock) {
|
||||
renderer.clearSdCardFontAccumulation();
|
||||
if (!section->createSectionFile(getEffectiveReaderFontId(), getEffectiveReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, getEffectiveParagraphAlignment(), viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, embeddedStyle,
|
||||
bookBionicReadingOverride, imageRendering, progressFn)) {
|
||||
viewportHeight, getEffectiveHyphenation(), embeddedStyle,
|
||||
getEffectiveBionicReading(), imageRendering, progressFn)) {
|
||||
LOG_ERR("ERS", "Failed to persist page data to SD");
|
||||
section.reset();
|
||||
return;
|
||||
@@ -1980,12 +2015,12 @@ void EpubReaderActivity::render(RenderLock&& lock) {
|
||||
renderer.clearSdCardFontAccumulation();
|
||||
if (!section->createSectionFile(getEffectiveReaderFontId(), getEffectiveReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, getEffectiveParagraphAlignment(), viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, embeddedStyle,
|
||||
bookBionicReadingOverride, imageRendering, progressFn)) {
|
||||
viewportHeight, getEffectiveHyphenation(), embeddedStyle,
|
||||
getEffectiveBionicReading(), imageRendering, progressFn)) {
|
||||
LOG_ERR("ERS", "Failed to rebuild CSS section cache; keeping fallback");
|
||||
section->loadSectionFile(getEffectiveReaderFontId(), getEffectiveReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, getEffectiveParagraphAlignment(), viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, embeddedStyle, bookBionicReadingOverride,
|
||||
viewportHeight, getEffectiveHyphenation(), embeddedStyle, getEffectiveBionicReading(),
|
||||
imageRendering);
|
||||
}
|
||||
} else {
|
||||
@@ -2110,7 +2145,7 @@ void EpubReaderActivity::silentIndexNextChapterIfNeeded(const uint16_t viewportW
|
||||
Section nextSection(epub, nextSpineIndex, renderer);
|
||||
if (nextSection.loadSectionFile(getEffectiveReaderFontId(), getEffectiveReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, embeddedStyle, bookBionicReadingOverride,
|
||||
viewportHeight, getEffectiveHyphenation(), embeddedStyle, getEffectiveBionicReading(),
|
||||
imageRendering)) {
|
||||
return;
|
||||
}
|
||||
@@ -2120,8 +2155,8 @@ void EpubReaderActivity::silentIndexNextChapterIfNeeded(const uint16_t viewportW
|
||||
renderer.clearSdCardFontAccumulation();
|
||||
if (!nextSection.createSectionFile(getEffectiveReaderFontId(), getEffectiveReaderLineCompression(),
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.paragraphAlignment, viewportWidth,
|
||||
viewportHeight, SETTINGS.hyphenationEnabled, embeddedStyle,
|
||||
bookBionicReadingOverride, imageRendering)) {
|
||||
viewportHeight, getEffectiveHyphenation(), embeddedStyle,
|
||||
getEffectiveBionicReading(), imageRendering)) {
|
||||
LOG_ERR("ERS", "Failed silent indexing for chapter: %d", nextSpineIndex);
|
||||
}
|
||||
}
|
||||
@@ -2178,7 +2213,7 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
|
||||
logReaderMemSnapshot("prewarm_end");
|
||||
logIntegrityProbe("renderContents_after_fontPrewarm");
|
||||
|
||||
const bool aaConfigured = SETTINGS.textAntiAliasing;
|
||||
const bool aaConfigured = getEffectiveTextAntiAliasing();
|
||||
bool aaEnabledForThisRender = aaConfigured;
|
||||
if (aaConfigured && antiAliasingSuspendedLowMemory) {
|
||||
const uint32_t freeHeapNow = esp_get_free_heap_size();
|
||||
@@ -2459,7 +2494,7 @@ void EpubReaderActivity::displayPreRenderedPage(const Page& page, const int orie
|
||||
// Grayscale AA pass. Prefer the tiled strip path (no BW snapshot needed);
|
||||
// fall back to the legacy storeBwBufferRect path on controllers that don't
|
||||
// support strip grayscale or when the strip scratch can't be allocated.
|
||||
const bool aaConfigured = SETTINGS.textAntiAliasing && !antiAliasingSuspendedLowMemory;
|
||||
const bool aaConfigured = getEffectiveTextAntiAliasing() && !antiAliasingSuspendedLowMemory;
|
||||
if (aaConfigured) {
|
||||
if (runTiledGrayscalePass(renderer, page, getEffectiveReaderFontId(), orientedMarginLeft, contentTop,
|
||||
SETTINGS.fastAntiAliasing)) {
|
||||
@@ -2752,6 +2787,22 @@ bool EpubReaderActivity::drawCurrentPageToBuffer(const std::string& filePath, Gf
|
||||
return true;
|
||||
}
|
||||
|
||||
void EpubReaderActivity::openQuickOverrides() {
|
||||
ReaderUtils::enforceExitFullRefresh(renderer);
|
||||
startActivityForResult(
|
||||
std::make_unique<QuickOverridesActivity>(
|
||||
renderer, mappedInput, bookEmbeddedStyleOverride, bookImageRenderingOverride, bookFontFamilyOverride,
|
||||
bookSdFontFamilyOverride, bookFontSizeOverride, bookBionicReadingOverride, bookParagraphAlignmentOverride,
|
||||
bookTextAntiAliasingOverride, bookHyphenationOverride),
|
||||
[this](const ActivityResult& result) {
|
||||
const auto& menu = std::get<MenuResult>(result.data);
|
||||
applyBookReaderOverrides(menu.embeddedStyleOverride, menu.imageRenderingOverride, menu.fontFamilyOverride,
|
||||
menu.sdFontFamilyOverride, menu.fontSizeOverride,
|
||||
static_cast<int8_t>(menu.bionicReadingOverride), menu.paragraphAlignmentOverride,
|
||||
menu.textAntiAliasingOverride, menu.hyphenationOverride);
|
||||
});
|
||||
}
|
||||
|
||||
void EpubReaderActivity::openReaderMenu() {
|
||||
const int currentPage = section ? section->currentPage + 1 : 0;
|
||||
const int totalPages = section ? section->pageCount : 0;
|
||||
@@ -2782,7 +2833,7 @@ void EpubReaderActivity::openReaderMenu() {
|
||||
std::make_unique<EpubReaderMenuActivity>(
|
||||
renderer, mappedInput, epub->getTitle(), currentPage, totalPages, bookProgressPercent, SETTINGS.orientation,
|
||||
!currentPageFootnotes.empty(), bookEmbeddedStyleOverride, bookImageRenderingOverride, bookFontFamilyOverride,
|
||||
bookSdFontFamilyOverride, bookFontSizeOverride, SETTINGS.textDarkness, bookBionicReadingOverride,
|
||||
bookSdFontFamilyOverride, bookFontSizeOverride, SETTINGS.textDarkness, getEffectiveBionicReading(),
|
||||
bookParagraphAlignmentOverride, !bookmarkStore.isEmpty(), isCurrentPageStarred, hasPrintedPages),
|
||||
[this](const ActivityResult& result) {
|
||||
const auto& menu = std::get<MenuResult>(result.data);
|
||||
@@ -2926,7 +2977,7 @@ void EpubReaderActivity::onButtonAction(const CrossPointSettings::BUTTON_ACTION
|
||||
case BA::BTN_TOGGLE_BIONIC_READING:
|
||||
if (epub) {
|
||||
applyBookReaderOverrides(bookEmbeddedStyleOverride, bookImageRenderingOverride, bookFontFamilyOverride,
|
||||
bookSdFontFamilyOverride, bookFontSizeOverride, !bookBionicReadingOverride,
|
||||
bookSdFontFamilyOverride, bookFontSizeOverride, !getEffectiveBionicReading(),
|
||||
bookParagraphAlignmentOverride);
|
||||
requestUpdate();
|
||||
}
|
||||
@@ -2953,6 +3004,11 @@ void EpubReaderActivity::onButtonAction(const CrossPointSettings::BUTTON_ACTION
|
||||
case BA::BTN_KOREADER_SYNC:
|
||||
launchKOReaderSync(SyncLaunchMode::COMPARE);
|
||||
break;
|
||||
case BA::BTN_QUICK_OVERRIDES:
|
||||
if (epub) {
|
||||
openQuickOverrides();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -242,8 +242,10 @@ class EpubReaderActivity final : public Activity {
|
||||
int8_t bookFontFamilyOverride = -1;
|
||||
std::string bookSdFontFamilyOverride;
|
||||
int8_t bookFontSizeOverride = -1;
|
||||
bool bookBionicReadingOverride = false;
|
||||
int8_t bookBionicReadingOverride = -1;
|
||||
int8_t bookParagraphAlignmentOverride = -1;
|
||||
int8_t bookTextAntiAliasingOverride = -1;
|
||||
int8_t bookHyphenationOverride = -1;
|
||||
|
||||
// Bookmarks (starred pages)
|
||||
BookmarkStore bookmarkStore;
|
||||
@@ -308,10 +310,20 @@ class EpubReaderActivity final : public Activity {
|
||||
void applyBookReaderOverrides(int8_t embeddedStyleOverride, int8_t imageRenderingOverride, int8_t fontFamilyOverride,
|
||||
const std::string& sdFontFamilyOverride, int8_t fontSizeOverride,
|
||||
bool bionicReadingOverride, int8_t paragraphAlignmentOverride);
|
||||
// Wider variant that also covers AA and hyphenation. Used by QuickOverridesActivity;
|
||||
// the narrower overload above funnels through here, preserving the AA/hyphenation
|
||||
// values currently held on this activity.
|
||||
void applyBookReaderOverrides(int8_t embeddedStyleOverride, int8_t imageRenderingOverride, int8_t fontFamilyOverride,
|
||||
const std::string& sdFontFamilyOverride, int8_t fontSizeOverride,
|
||||
int8_t bionicReadingOverride, int8_t paragraphAlignmentOverride,
|
||||
int8_t textAntiAliasingOverride, int8_t hyphenationOverride);
|
||||
void openReaderMenu();
|
||||
void openQuickOverrides();
|
||||
bool getEffectiveEmbeddedStyle() const;
|
||||
uint8_t getEffectiveImageRendering() const;
|
||||
uint8_t getEffectiveParagraphAlignment() const;
|
||||
bool getEffectiveTextAntiAliasing() const;
|
||||
bool getEffectiveHyphenation() const;
|
||||
int getEffectiveReaderFontId() const;
|
||||
float getEffectiveReaderLineCompression() const;
|
||||
bool stepPageState(bool isForwardTurn);
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
#include "QuickOverridesActivity.h"
|
||||
|
||||
#include <GfxRenderer.h>
|
||||
#include <HalDisplay.h>
|
||||
#include <I18n.h>
|
||||
|
||||
#include "MappedInputManager.h"
|
||||
#include "activities/ActivityResult.h"
|
||||
#include "components/UITheme.h"
|
||||
#include "fontIds.h"
|
||||
|
||||
QuickOverridesActivity::QuickOverridesActivity(
|
||||
GfxRenderer& renderer, MappedInputManager& mappedInput, const int8_t initialEmbeddedStyleOverride,
|
||||
const int8_t initialImageRenderingOverride, const int8_t initialFontFamilyOverride,
|
||||
const std::string& initialSdFontFamilyOverride, const int8_t initialFontSizeOverride,
|
||||
const int8_t initialBionicReadingOverride, const int8_t initialParagraphAlignmentOverride,
|
||||
const int8_t initialTextAntiAliasingOverride, const int8_t initialHyphenationOverride)
|
||||
: MenuListActivity("QuickOverrides", renderer, mappedInput),
|
||||
pendingEmbeddedStyleOverride(initialEmbeddedStyleOverride),
|
||||
pendingImageRenderingOverride(initialImageRenderingOverride),
|
||||
pendingFontFamilyOverride(initialFontFamilyOverride),
|
||||
pendingSdFontFamilyOverride(initialSdFontFamilyOverride),
|
||||
pendingFontSizeOverride(initialFontSizeOverride),
|
||||
pendingBionicReadingOverride(initialBionicReadingOverride),
|
||||
pendingParagraphAlignmentOverride(initialParagraphAlignmentOverride),
|
||||
pendingTextAntiAliasingOverride(initialTextAntiAliasingOverride),
|
||||
pendingHyphenationOverride(initialHyphenationOverride) {
|
||||
buildMenuItems();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Three-state cycle helper for overrides represented as int8_t with -1 = default.
|
||||
// slot 0 -> -1 (default)
|
||||
// slot 1 -> 1 (on)
|
||||
// slot 2 -> 0 (off)
|
||||
uint8_t threeStateSlotFromOverride(int8_t value) {
|
||||
if (value < 0) return 0;
|
||||
if (value > 0) return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
int8_t threeStateOverrideFromSlot(uint8_t slot) {
|
||||
if (slot == 0) return -1;
|
||||
if (slot == 1) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void QuickOverridesActivity::buildMenuItems() {
|
||||
menuItems.reserve(8);
|
||||
|
||||
auto* self = this;
|
||||
|
||||
// Embedded style: default / on / off
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_EMBEDDED_STYLE, {StrId::STR_DEFAULT_VALUE, StrId::STR_STATE_ON, StrId::STR_STATE_OFF}, self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
return threeStateSlotFromOverride(
|
||||
static_cast<const QuickOverridesActivity*>(ctx)->pendingEmbeddedStyleOverride);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
static_cast<QuickOverridesActivity*>(ctx)->pendingEmbeddedStyleOverride = threeStateOverrideFromSlot(v);
|
||||
}));
|
||||
|
||||
// Image rendering: default(-1) / display(0) / placeholder(1) / suppress(2)
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_IMAGES,
|
||||
{StrId::STR_DEFAULT_VALUE, StrId::STR_IMAGES_DISPLAY, StrId::STR_IMAGES_PLACEHOLDER, StrId::STR_IMAGES_SUPPRESS},
|
||||
self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
const auto* s = static_cast<const QuickOverridesActivity*>(ctx);
|
||||
return (s->pendingImageRenderingOverride < 0) ? 0 : (s->pendingImageRenderingOverride + 1);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
auto* s = static_cast<QuickOverridesActivity*>(ctx);
|
||||
s->pendingImageRenderingOverride = (v == 0) ? -1 : static_cast<int8_t>(v - 1);
|
||||
}));
|
||||
|
||||
// Font family: built-in only — preserves any SD-family override unless the user
|
||||
// explicitly picks a built-in (which clears it, matching the storage semantics).
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_FONT_FAMILY, {StrId::STR_DEFAULT_VALUE, StrId::STR_BOOKERLY, StrId::STR_NOTO_SANS}, self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
const auto* s = static_cast<const QuickOverridesActivity*>(ctx);
|
||||
return (s->pendingFontFamilyOverride < 0) ? 0 : static_cast<uint8_t>(s->pendingFontFamilyOverride + 1);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
auto* s = static_cast<QuickOverridesActivity*>(ctx);
|
||||
if (v == 0) {
|
||||
s->pendingFontFamilyOverride = -1;
|
||||
} else {
|
||||
s->pendingFontFamilyOverride = static_cast<int8_t>(v - 1);
|
||||
s->pendingSdFontFamilyOverride.clear();
|
||||
}
|
||||
}));
|
||||
|
||||
// Font size: default(-1) -> Small(0) -> Medium(1) -> Large(2) -> X Large(3) -> Tiny(4)
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_FONT_SIZE,
|
||||
{StrId::STR_DEFAULT_VALUE, StrId::STR_SMALL, StrId::STR_MEDIUM, StrId::STR_LARGE, StrId::STR_X_LARGE,
|
||||
StrId::STR_TINY},
|
||||
self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
const auto* s = static_cast<const QuickOverridesActivity*>(ctx);
|
||||
return (s->pendingFontSizeOverride < 0) ? 0 : static_cast<uint8_t>(s->pendingFontSizeOverride + 1);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
auto* s = static_cast<QuickOverridesActivity*>(ctx);
|
||||
s->pendingFontSizeOverride = (v == 0) ? -1 : static_cast<int8_t>(v - 1);
|
||||
}));
|
||||
|
||||
// Bionic: default / on / off
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_BIONIC_READING, {StrId::STR_DEFAULT_VALUE, StrId::STR_STATE_ON, StrId::STR_STATE_OFF}, self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
return threeStateSlotFromOverride(
|
||||
static_cast<const QuickOverridesActivity*>(ctx)->pendingBionicReadingOverride);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
static_cast<QuickOverridesActivity*>(ctx)->pendingBionicReadingOverride = threeStateOverrideFromSlot(v);
|
||||
}));
|
||||
|
||||
// Paragraph alignment: default(-1) + the 5 global options
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_PARA_ALIGNMENT,
|
||||
{StrId::STR_DEFAULT_VALUE, StrId::STR_JUSTIFY, StrId::STR_ALIGN_LEFT, StrId::STR_CENTER, StrId::STR_ALIGN_RIGHT,
|
||||
StrId::STR_BOOK_S_STYLE},
|
||||
self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
const auto* s = static_cast<const QuickOverridesActivity*>(ctx);
|
||||
return (s->pendingParagraphAlignmentOverride < 0)
|
||||
? 0
|
||||
: static_cast<uint8_t>(s->pendingParagraphAlignmentOverride + 1);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
auto* s = static_cast<QuickOverridesActivity*>(ctx);
|
||||
s->pendingParagraphAlignmentOverride = (v == 0) ? -1 : static_cast<int8_t>(v - 1);
|
||||
}));
|
||||
|
||||
// Text anti-aliasing: default / on / off
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_TEXT_AA, {StrId::STR_DEFAULT_VALUE, StrId::STR_STATE_ON, StrId::STR_STATE_OFF}, self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
return threeStateSlotFromOverride(
|
||||
static_cast<const QuickOverridesActivity*>(ctx)->pendingTextAntiAliasingOverride);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
static_cast<QuickOverridesActivity*>(ctx)->pendingTextAntiAliasingOverride = threeStateOverrideFromSlot(v);
|
||||
}));
|
||||
|
||||
// Hyphenation: default / on / off
|
||||
menuItems.push_back(SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_HYPHENATION, {StrId::STR_DEFAULT_VALUE, StrId::STR_STATE_ON, StrId::STR_STATE_OFF}, self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
return threeStateSlotFromOverride(static_cast<const QuickOverridesActivity*>(ctx)->pendingHyphenationOverride);
|
||||
},
|
||||
[](void* ctx, uint8_t v) {
|
||||
static_cast<QuickOverridesActivity*>(ctx)->pendingHyphenationOverride = threeStateOverrideFromSlot(v);
|
||||
}));
|
||||
}
|
||||
|
||||
void QuickOverridesActivity::onEnter() {
|
||||
MenuListActivity::onEnter();
|
||||
// Fast refresh keeps the menu feeling responsive when cycling options. The
|
||||
// parent reader is responsible for its own full refresh on resume if any
|
||||
// override actually changed (applyBookReaderOverrides short-circuits if not).
|
||||
renderer.setNextDisplayRefreshMode(HalDisplay::FAST_REFRESH);
|
||||
}
|
||||
|
||||
void QuickOverridesActivity::onSettingToggled(int /*index*/) {
|
||||
// No persistence on each toggle — overrides are committed on exit through
|
||||
// the result handler in the parent reader activity.
|
||||
renderer.setNextDisplayRefreshMode(HalDisplay::FAST_REFRESH);
|
||||
}
|
||||
|
||||
void QuickOverridesActivity::onBackPressed() { finishWithResult(/*cancelled=*/false); }
|
||||
|
||||
void QuickOverridesActivity::finishWithResult(bool cancelled) {
|
||||
ActivityResult result;
|
||||
result.isCancelled = cancelled;
|
||||
MenuResult payload;
|
||||
payload.action = -1;
|
||||
payload.nameId = -1;
|
||||
payload.embeddedStyleOverride = pendingEmbeddedStyleOverride;
|
||||
payload.imageRenderingOverride = pendingImageRenderingOverride;
|
||||
payload.fontFamilyOverride = pendingFontFamilyOverride;
|
||||
payload.sdFontFamilyOverride = pendingSdFontFamilyOverride;
|
||||
payload.fontSizeOverride = pendingFontSizeOverride;
|
||||
payload.bionicReadingOverride = (pendingBionicReadingOverride > 0) ? 1 : 0;
|
||||
payload.paragraphAlignmentOverride = pendingParagraphAlignmentOverride;
|
||||
payload.textAntiAliasingOverride = pendingTextAntiAliasingOverride;
|
||||
payload.hyphenationOverride = pendingHyphenationOverride;
|
||||
result.data = std::move(payload);
|
||||
setResult(std::move(result));
|
||||
finish();
|
||||
}
|
||||
|
||||
void QuickOverridesActivity::render(RenderLock&&) {
|
||||
renderer.clearScreen();
|
||||
const Rect contentRect = UITheme::getContentRect(renderer, true, false);
|
||||
|
||||
const std::string title = tr(STR_QUICK_OVERRIDES);
|
||||
const int titleX = contentRect.x +
|
||||
(contentRect.width - renderer.getTextWidth(UI_12_FONT_ID, title.c_str(), EpdFontFamily::BOLD)) / 2;
|
||||
renderer.drawText(UI_12_FONT_ID, titleX, 15 + contentRect.y, title.c_str(), true, EpdFontFamily::BOLD);
|
||||
|
||||
const int startY = 50 + contentRect.y;
|
||||
const int listHeight = contentRect.height - (startY - contentRect.y);
|
||||
drawMenuList(Rect{contentRect.x, startY, contentRect.width, listHeight});
|
||||
|
||||
const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN));
|
||||
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||
|
||||
renderer.displayBuffer(HalDisplay::FAST_REFRESH);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <I18n.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../MenuListActivity.h"
|
||||
|
||||
// Bottom-of-the-toolbox quick-overrides menu: shows only the per-book overrides
|
||||
// (font family, size, embedded style, image rendering, bionic, paragraph
|
||||
// alignment, anti-aliasing, hyphenation). Optimised for snappy in-book toggling:
|
||||
// renders in FAST_REFRESH mode and reports back through MenuResult; the parent
|
||||
// reader applies the result through its existing applyBookReaderOverrides()
|
||||
// path, which itself short-circuits when nothing changed.
|
||||
class QuickOverridesActivity final : public MenuListActivity {
|
||||
public:
|
||||
QuickOverridesActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, int8_t initialEmbeddedStyleOverride,
|
||||
int8_t initialImageRenderingOverride, int8_t initialFontFamilyOverride,
|
||||
const std::string& initialSdFontFamilyOverride, int8_t initialFontSizeOverride,
|
||||
int8_t initialBionicReadingOverride, int8_t initialParagraphAlignmentOverride,
|
||||
int8_t initialTextAntiAliasingOverride, int8_t initialHyphenationOverride);
|
||||
|
||||
void onEnter() override;
|
||||
void render(RenderLock&&) override;
|
||||
|
||||
private:
|
||||
void buildMenuItems();
|
||||
void finishWithResult(bool cancelled);
|
||||
|
||||
void onBackPressed() override;
|
||||
void onSettingToggled(int index) override;
|
||||
|
||||
int8_t pendingEmbeddedStyleOverride = -1;
|
||||
int8_t pendingImageRenderingOverride = -1;
|
||||
int8_t pendingFontFamilyOverride = -1;
|
||||
std::string pendingSdFontFamilyOverride;
|
||||
int8_t pendingFontSizeOverride = -1;
|
||||
int8_t pendingBionicReadingOverride = -1;
|
||||
int8_t pendingParagraphAlignmentOverride = -1;
|
||||
int8_t pendingTextAntiAliasingOverride = -1;
|
||||
int8_t pendingHyphenationOverride = -1;
|
||||
};
|
||||
@@ -823,6 +823,9 @@ void loop() {
|
||||
case BA::BTN_CYCLE_ORIENTATION:
|
||||
activityManager.dispatchButtonAction(BA::BTN_CYCLE_ORIENTATION);
|
||||
break;
|
||||
case BA::BTN_QUICK_OVERRIDES:
|
||||
activityManager.dispatchButtonAction(BA::BTN_QUICK_OVERRIDES);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user