Yet another bionic reading implementation
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -26,8 +26,10 @@ class ParsedText {
|
||||
BlockStyle blockStyle;
|
||||
bool extraParagraphSpacing;
|
||||
bool hyphenationEnabled;
|
||||
bool bionicReadingEnabled;
|
||||
|
||||
void applyParagraphIndent();
|
||||
void applyBionicReadingTransform();
|
||||
std::vector<size_t> computeLineBreaks(const GfxRenderer& renderer, int fontId, int pageWidth,
|
||||
std::vector<uint16_t>& wordWidths, std::vector<bool>& continuesVec);
|
||||
std::vector<size_t> computeHyphenatedLineBreaks(const GfxRenderer& renderer, int fontId, int pageWidth,
|
||||
@@ -60,8 +62,11 @@ class ParsedText {
|
||||
|
||||
public:
|
||||
explicit ParsedText(const bool extraParagraphSpacing, const bool hyphenationEnabled = false,
|
||||
const BlockStyle& blockStyle = BlockStyle())
|
||||
: blockStyle(blockStyle), extraParagraphSpacing(extraParagraphSpacing), hyphenationEnabled(hyphenationEnabled) {}
|
||||
const BlockStyle& blockStyle = BlockStyle(), const bool bionicReadingEnabled = false)
|
||||
: blockStyle(blockStyle),
|
||||
extraParagraphSpacing(extraParagraphSpacing),
|
||||
hyphenationEnabled(hyphenationEnabled),
|
||||
bionicReadingEnabled(bionicReadingEnabled) {}
|
||||
~ParsedText() = default;
|
||||
|
||||
void addWord(std::string word, EpdFontFamily::Style fontStyle, bool underline = false, bool attachToPrevious = false);
|
||||
|
||||
@@ -598,3 +598,5 @@ STR_KB_HINT_SECONDARY_CHAR: "Hold SELECT for secondary char"
|
||||
STR_KB_HINT_UPPER_SECONDARY: "Hold SELECT for UPPERCASE or secondary char"
|
||||
STR_KB_HINT_LOWER_SECONDARY: "Hold SELECT for lowercase or secondary char"
|
||||
STR_KB_HINT_URL_SNIPPETS: "Press URL for snippets"
|
||||
STR_BIONIC_READING: "Bionic Reading"
|
||||
STR_BTN_ACT_TOGGLE_BIONIC_READING: "Toggle Bionic Reading"
|
||||
@@ -284,6 +284,7 @@ class CrossPointSettings {
|
||||
BTN_PREV_SECTION,
|
||||
BTN_EXIT_READER,
|
||||
BTN_READER_MENU,
|
||||
BTN_TOGGLE_BIONIC_READING,
|
||||
BTN_KOREADER_SYNC,
|
||||
BUTTON_ACTION_COUNT
|
||||
};
|
||||
|
||||
@@ -418,6 +418,7 @@ bool JsonSettingsIO::saveRecentBooks(const RecentBooksStore& store, const char*
|
||||
obj["imageRenderingOverride"] = book.imageRenderingOverride;
|
||||
obj["fontFamilyOverride"] = book.fontFamilyOverride;
|
||||
obj["fontSizeOverride"] = book.fontSizeOverride;
|
||||
obj["bionicReadingOverride"] = book.bionicReadingOverride;
|
||||
}
|
||||
|
||||
String json;
|
||||
@@ -455,6 +456,7 @@ bool JsonSettingsIO::loadRecentBooks(RecentBooksStore& store, const char* json)
|
||||
book.fontFamilyOverride =
|
||||
clampInt8(obj["fontFamilyOverride"] | -1, -1, CrossPointSettings::FONT_FAMILY_COUNT - 1, -1);
|
||||
book.fontSizeOverride = clampInt8(obj["fontSizeOverride"] | -1, -1, CrossPointSettings::FONT_SIZE_COUNT - 1, -1);
|
||||
book.bionicReadingOverride = obj["bionicReadingOverride"] | false;
|
||||
store.recentBooks.push_back(book);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ void RecentBooksStore::addBook(const std::string& path, const std::string& title
|
||||
int8_t imageRenderingOverride = -1;
|
||||
int8_t fontFamilyOverride = -1;
|
||||
int8_t fontSizeOverride = -1;
|
||||
bool bionicReadingOverride = false;
|
||||
|
||||
// Remove existing entry if present
|
||||
auto it =
|
||||
@@ -35,12 +36,14 @@ void RecentBooksStore::addBook(const std::string& path, const std::string& title
|
||||
imageRenderingOverride = it->imageRenderingOverride;
|
||||
fontFamilyOverride = it->fontFamilyOverride;
|
||||
fontSizeOverride = it->fontSizeOverride;
|
||||
bionicReadingOverride = it->bionicReadingOverride;
|
||||
recentBooks.erase(it);
|
||||
}
|
||||
|
||||
// Add to front
|
||||
recentBooks.insert(recentBooks.begin(), {path, title, author, series, coverBmpPath, embeddedStyleOverride,
|
||||
imageRenderingOverride, fontFamilyOverride, fontSizeOverride});
|
||||
recentBooks.insert(recentBooks.begin(),
|
||||
{path, title, author, series, coverBmpPath, embeddedStyleOverride, imageRenderingOverride,
|
||||
fontFamilyOverride, fontSizeOverride, bionicReadingOverride});
|
||||
|
||||
// Trim to max size
|
||||
if (recentBooks.size() > MAX_RECENT_BOOKS) {
|
||||
@@ -83,19 +86,19 @@ RecentBook RecentBooksStore::getBookByPath(const std::string& path) const {
|
||||
}
|
||||
|
||||
bool RecentBooksStore::setReaderOverrides(const std::string& path, const int8_t embeddedStyleOverride,
|
||||
const int8_t imageRenderingOverride) {
|
||||
const int8_t imageRenderingOverride, const bool bionicReadingOverride) {
|
||||
auto it =
|
||||
std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; });
|
||||
if (it == recentBooks.end()) {
|
||||
return false;
|
||||
}
|
||||
return setReaderOverrides(path, embeddedStyleOverride, imageRenderingOverride, it->fontFamilyOverride,
|
||||
it->fontSizeOverride);
|
||||
it->fontSizeOverride, bionicReadingOverride);
|
||||
}
|
||||
|
||||
bool RecentBooksStore::setReaderOverrides(const std::string& path, const int8_t embeddedStyleOverride,
|
||||
const int8_t imageRenderingOverride, const int8_t fontFamilyOverride,
|
||||
const int8_t fontSizeOverride) {
|
||||
const int8_t fontSizeOverride, const bool bionicReadingOverride) {
|
||||
auto it =
|
||||
std::find_if(recentBooks.begin(), recentBooks.end(), [&](const RecentBook& book) { return book.path == path; });
|
||||
if (it == recentBooks.end()) {
|
||||
@@ -106,6 +109,7 @@ bool RecentBooksStore::setReaderOverrides(const std::string& path, const int8_t
|
||||
it->imageRenderingOverride = imageRenderingOverride;
|
||||
it->fontFamilyOverride = fontFamilyOverride;
|
||||
it->fontSizeOverride = fontSizeOverride;
|
||||
it->bionicReadingOverride = bionicReadingOverride;
|
||||
return saveToFile();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ struct RecentBook {
|
||||
int8_t fontFamilyOverride = -1;
|
||||
// -1 = use global setting, otherwise CrossPointSettings::FONT_SIZE value.
|
||||
int8_t fontSizeOverride = -1;
|
||||
bool bionicReadingOverride = false;
|
||||
|
||||
bool operator==(const RecentBook& other) const { return path == other.path; }
|
||||
};
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ inline const std::vector<SettingInfo> list = {
|
||||
StrId::STR_BTN_ACT_FORCE_REFRESH, StrId::STR_BTN_ACT_OPEN_TOC, 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_KOREADER_SYNC
|
||||
StrId::STR_BTN_ACT_TOGGLE_BIONIC_READING, StrId::STR_BTN_ACT_KOREADER_SYNC
|
||||
|
||||
// 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},
|
||||
|
||||
@@ -28,6 +28,7 @@ struct MenuResult {
|
||||
int8_t fontFamilyOverride = -1;
|
||||
int8_t fontSizeOverride = -1;
|
||||
uint8_t textDarkness = 1;
|
||||
uint8_t bionicReadingOverride = 0;
|
||||
};
|
||||
|
||||
struct ChapterResult {
|
||||
|
||||
@@ -135,6 +135,7 @@ class EpubReaderActivity final : public Activity {
|
||||
int8_t bookImageRenderingOverride = -1;
|
||||
int8_t bookFontFamilyOverride = -1;
|
||||
int8_t bookFontSizeOverride = -1;
|
||||
bool bookBionicReadingOverride = false;
|
||||
|
||||
// Bookmarks (starred pages)
|
||||
BookmarkStore bookmarkStore;
|
||||
|
||||
@@ -30,14 +30,12 @@ std::string defaultFontFamilyLabel(const SettingInfo& item) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
|
||||
const std::string& title, const int currentPage, const int totalPages,
|
||||
const int bookProgressPercent, const uint8_t currentOrientation,
|
||||
const bool hasFootnotes, const int8_t initialEmbeddedStyleOverride,
|
||||
const int8_t initialImageRenderingOverride,
|
||||
const int8_t initialFontFamilyOverride,
|
||||
const int8_t initialFontSizeOverride, const uint8_t initialTextDarkness,
|
||||
const bool hasStarredPages, const bool isCurrentPageStarred)
|
||||
EpubReaderMenuActivity::EpubReaderMenuActivity(
|
||||
GfxRenderer& renderer, MappedInputManager& mappedInput, const std::string& title, const int currentPage,
|
||||
const int totalPages, const int bookProgressPercent, const uint8_t currentOrientation, const bool hasFootnotes,
|
||||
const int8_t initialEmbeddedStyleOverride, const int8_t initialImageRenderingOverride,
|
||||
const int8_t initialFontFamilyOverride, const int8_t initialFontSizeOverride, const uint8_t initialTextDarkness,
|
||||
const bool initialBionicReadingOverride, const bool hasStarredPages, const bool isCurrentPageStarred)
|
||||
: MenuListActivity("EpubReaderMenu", renderer, mappedInput),
|
||||
currentPageStarred(isCurrentPageStarred),
|
||||
pendingOrientation(currentOrientation),
|
||||
@@ -46,6 +44,7 @@ EpubReaderMenuActivity::EpubReaderMenuActivity(GfxRenderer& renderer, MappedInpu
|
||||
pendingFontFamilyOverride(initialFontFamilyOverride),
|
||||
pendingFontSizeOverride(initialFontSizeOverride),
|
||||
pendingTextDarkness(initialTextDarkness),
|
||||
pendingBionicReading(initialBionicReadingOverride),
|
||||
title(title),
|
||||
currentPage(currentPage),
|
||||
totalPages(totalPages),
|
||||
@@ -161,6 +160,15 @@ void EpubReaderMenuActivity::buildMenuItems(bool hasFootnotes, bool hasStarredPa
|
||||
[](void* ctx, uint8_t v) { static_cast<EpubReaderMenuActivity*>(ctx)->pendingTextDarkness = v; })
|
||||
.withSubmenu(StrId::STR_READER_OVERRIDES));
|
||||
|
||||
menuItems.push_back(
|
||||
SettingInfo::DynamicEnumCtx(
|
||||
StrId::STR_BIONIC_READING, {StrId::STR_STATE_OFF, StrId::STR_STATE_ON}, self,
|
||||
[](const void* ctx) -> uint8_t {
|
||||
return static_cast<const EpubReaderMenuActivity*>(ctx)->pendingBionicReading ? 1 : 0;
|
||||
},
|
||||
[](void* ctx, uint8_t v) { static_cast<EpubReaderMenuActivity*>(ctx)->pendingBionicReading = (v != 0); })
|
||||
.withSubmenu(StrId::STR_READER_OVERRIDES));
|
||||
|
||||
// Helper functions, reading ruler, auto page turn, orientation
|
||||
menuItems.push_back(SettingInfo::Separator(StrId::STR_READER_UTILS));
|
||||
// Auto page turn: ACTION type with custom cycling in onActionSelected
|
||||
@@ -240,7 +248,7 @@ EpubReaderMenuActivity::MenuAction EpubReaderMenuActivity::actionForSettingActio
|
||||
void EpubReaderMenuActivity::finishWithAction(MenuAction action) {
|
||||
setResult(MenuResult{static_cast<int>(action), -1, pendingOrientation, selectedPageTurnOption,
|
||||
pendingEmbeddedStyleOverride, pendingImageRenderingOverride, pendingFontFamilyOverride,
|
||||
pendingFontSizeOverride, pendingTextDarkness});
|
||||
pendingFontSizeOverride, pendingTextDarkness, static_cast<uint8_t>(pendingBionicReading)});
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -273,7 +281,8 @@ void EpubReaderMenuActivity::onBackPressed() {
|
||||
pendingImageRenderingOverride,
|
||||
pendingFontFamilyOverride,
|
||||
pendingFontSizeOverride,
|
||||
pendingTextDarkness};
|
||||
pendingTextDarkness,
|
||||
static_cast<uint8_t>(pendingBionicReading)};
|
||||
setResult(std::move(result));
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ class EpubReaderMenuActivity final : public MenuListActivity {
|
||||
const uint8_t currentOrientation, const bool hasFootnotes,
|
||||
const int8_t initialEmbeddedStyleOverride, const int8_t initialImageRenderingOverride,
|
||||
const int8_t initialFontFamilyOverride, const int8_t initialFontSizeOverride,
|
||||
const uint8_t initialTextDarkness, const bool hasStarredPages,
|
||||
const bool isCurrentPageStarred);
|
||||
const uint8_t initialTextDarkness, const bool initialBionicReadingOverride,
|
||||
const bool hasStarredPages, const bool isCurrentPageStarred);
|
||||
|
||||
void onEnter() override;
|
||||
void render(RenderLock&&) override;
|
||||
@@ -69,6 +69,7 @@ class EpubReaderMenuActivity final : public MenuListActivity {
|
||||
int8_t pendingFontFamilyOverride = -1;
|
||||
int8_t pendingFontSizeOverride = -1;
|
||||
uint8_t pendingTextDarkness = 1;
|
||||
bool pendingBionicReading = false;
|
||||
|
||||
static constexpr const char* pageTurnLabels[] = {"", "1", "3", "6", "12"};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user