Add hyphenation support and update settings management
- Introduced hyphenationEnabled flag in ParsedText and Section classes. - Updated constructors and methods to handle hyphenation settings. - Modified settings file versioning to include hyphenationEnabled. - Enhanced settings UI to allow toggling of hyphenation feature.
This commit is contained in:
parent
26bea34921
commit
ca88c2eef7
@ -36,6 +36,7 @@ void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fo
|
||||
const int spaceWidth = renderer.getSpaceWidth(fontId);
|
||||
// Maintain classic prose indenting when extra paragraph spacing is disabled.
|
||||
const bool allowIndent = !extraParagraphSpacing && (style == TextBlock::JUSTIFIED || style == TextBlock::LEFT_ALIGN);
|
||||
const bool allowHyphenation = hyphenationEnabled;
|
||||
const int indentWidth = allowIndent ? renderer.getTextWidth(fontId, "m", REGULAR) : 0;
|
||||
const int firstLinePageWidth = allowIndent ? std::max(pageWidth - indentWidth, 0) : pageWidth;
|
||||
auto pageWidthForLine = [&](const bool isFirstLine) -> int { return isFirstLine ? firstLinePageWidth : pageWidth; };
|
||||
@ -153,7 +154,7 @@ void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fo
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lineWordCount > 0 && availableWidth > 0) {
|
||||
if (allowHyphenation && lineWordCount > 0 && availableWidth > 0) {
|
||||
// Try hyphenating the next word so the current line stays compact.
|
||||
HyphenationResult split;
|
||||
if (Hyphenator::splitWord(renderer, fontId, *wordIt, *styleIt, availableWidth, &split, false)) {
|
||||
|
||||
@ -17,10 +17,12 @@ class ParsedText {
|
||||
std::list<EpdFontStyle> wordStyles;
|
||||
TextBlock::BLOCK_STYLE style;
|
||||
bool extraParagraphSpacing;
|
||||
bool hyphenationEnabled;
|
||||
|
||||
public:
|
||||
explicit ParsedText(const TextBlock::BLOCK_STYLE style, const bool extraParagraphSpacing)
|
||||
: style(style), extraParagraphSpacing(extraParagraphSpacing) {}
|
||||
explicit ParsedText(const TextBlock::BLOCK_STYLE style, const bool extraParagraphSpacing,
|
||||
const bool hyphenationEnabled)
|
||||
: style(style), extraParagraphSpacing(extraParagraphSpacing), hyphenationEnabled(hyphenationEnabled) {}
|
||||
~ParsedText() = default;
|
||||
|
||||
void addWord(std::string word, EpdFontStyle fontStyle);
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "parsers/ChapterHtmlSlimParser.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 5;
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 6;
|
||||
}
|
||||
|
||||
void Section::onPageComplete(std::unique_ptr<Page> page) {
|
||||
@ -27,7 +27,7 @@ void Section::onPageComplete(std::unique_ptr<Page> page) {
|
||||
|
||||
void Section::writeCacheMetadata(const int fontId, const float lineCompression, const int marginTop,
|
||||
const int marginRight, const int marginBottom, const int marginLeft,
|
||||
const bool extraParagraphSpacing) const {
|
||||
const bool extraParagraphSpacing, const bool hyphenationEnabled) const {
|
||||
std::ofstream outputFile(("/sd" + cachePath + "/section.bin").c_str());
|
||||
serialization::writePod(outputFile, SECTION_FILE_VERSION);
|
||||
serialization::writePod(outputFile, fontId);
|
||||
@ -37,13 +37,14 @@ void Section::writeCacheMetadata(const int fontId, const float lineCompression,
|
||||
serialization::writePod(outputFile, marginBottom);
|
||||
serialization::writePod(outputFile, marginLeft);
|
||||
serialization::writePod(outputFile, extraParagraphSpacing);
|
||||
serialization::writePod(outputFile, hyphenationEnabled);
|
||||
serialization::writePod(outputFile, pageCount);
|
||||
outputFile.close();
|
||||
}
|
||||
|
||||
bool Section::loadCacheMetadata(const int fontId, const float lineCompression, const int marginTop,
|
||||
const int marginRight, const int marginBottom, const int marginLeft,
|
||||
const bool extraParagraphSpacing) {
|
||||
const bool extraParagraphSpacing, const bool hyphenationEnabled) {
|
||||
if (!SD.exists(cachePath.c_str())) {
|
||||
return false;
|
||||
}
|
||||
@ -69,6 +70,7 @@ bool Section::loadCacheMetadata(const int fontId, const float lineCompression, c
|
||||
int fileFontId, fileMarginTop, fileMarginRight, fileMarginBottom, fileMarginLeft;
|
||||
float fileLineCompression;
|
||||
bool fileExtraParagraphSpacing;
|
||||
bool fileHyphenationEnabled;
|
||||
serialization::readPod(inputFile, fileFontId);
|
||||
serialization::readPod(inputFile, fileLineCompression);
|
||||
serialization::readPod(inputFile, fileMarginTop);
|
||||
@ -76,10 +78,11 @@ bool Section::loadCacheMetadata(const int fontId, const float lineCompression, c
|
||||
serialization::readPod(inputFile, fileMarginBottom);
|
||||
serialization::readPod(inputFile, fileMarginLeft);
|
||||
serialization::readPod(inputFile, fileExtraParagraphSpacing);
|
||||
serialization::readPod(inputFile, fileHyphenationEnabled);
|
||||
|
||||
if (fontId != fileFontId || lineCompression != fileLineCompression || marginTop != fileMarginTop ||
|
||||
marginRight != fileMarginRight || marginBottom != fileMarginBottom || marginLeft != fileMarginLeft ||
|
||||
extraParagraphSpacing != fileExtraParagraphSpacing) {
|
||||
extraParagraphSpacing != fileExtraParagraphSpacing || hyphenationEnabled != fileHyphenationEnabled) {
|
||||
inputFile.close();
|
||||
Serial.printf("[%lu] [SCT] Deserialization failed: Parameters do not match\n", millis());
|
||||
clearCache();
|
||||
@ -116,7 +119,7 @@ bool Section::clearCache() const {
|
||||
|
||||
bool Section::persistPageDataToSD(const int fontId, const float lineCompression, const int marginTop,
|
||||
const int marginRight, const int marginBottom, const int marginLeft,
|
||||
const bool extraParagraphSpacing) {
|
||||
const bool extraParagraphSpacing, const bool hyphenationEnabled) {
|
||||
const auto localPath = epub->getSpineItem(spineIndex);
|
||||
|
||||
// TODO: Should we get rid of this file all together?
|
||||
@ -137,7 +140,7 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
const auto sdTmpHtmlPath = "/sd" + tmpHtmlPath;
|
||||
|
||||
ChapterHtmlSlimParser visitor(sdTmpHtmlPath.c_str(), renderer, fontId, lineCompression, marginTop, marginRight,
|
||||
marginBottom, marginLeft, extraParagraphSpacing,
|
||||
marginBottom, marginLeft, extraParagraphSpacing, hyphenationEnabled,
|
||||
[this](std::unique_ptr<Page> page) { this->onPageComplete(std::move(page)); });
|
||||
success = visitor.parseAndBuildPages();
|
||||
|
||||
@ -147,7 +150,8 @@ bool Section::persistPageDataToSD(const int fontId, const float lineCompression,
|
||||
return false;
|
||||
}
|
||||
|
||||
writeCacheMetadata(fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft, extraParagraphSpacing);
|
||||
writeCacheMetadata(fontId, lineCompression, marginTop, marginRight, marginBottom, marginLeft, extraParagraphSpacing,
|
||||
hyphenationEnabled);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ class Section {
|
||||
std::string cachePath;
|
||||
|
||||
void writeCacheMetadata(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom,
|
||||
int marginLeft, bool extraParagraphSpacing) const;
|
||||
int marginLeft, bool extraParagraphSpacing, bool hyphenationEnabled) const;
|
||||
void onPageComplete(std::unique_ptr<Page> page);
|
||||
|
||||
public:
|
||||
@ -26,10 +26,10 @@ class Section {
|
||||
}
|
||||
~Section() = default;
|
||||
bool loadCacheMetadata(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom,
|
||||
int marginLeft, bool extraParagraphSpacing);
|
||||
int marginLeft, bool extraParagraphSpacing, bool hyphenationEnabled);
|
||||
void setupCacheDir() const;
|
||||
bool clearCache() const;
|
||||
bool persistPageDataToSD(int fontId, float lineCompression, int marginTop, int marginRight, int marginBottom,
|
||||
int marginLeft, bool extraParagraphSpacing);
|
||||
int marginLeft, bool extraParagraphSpacing, bool hyphenationEnabled);
|
||||
std::unique_ptr<Page> loadPageFromSD() const;
|
||||
};
|
||||
|
||||
@ -48,7 +48,7 @@ void ChapterHtmlSlimParser::startNewTextBlock(const TextBlock::BLOCK_STYLE style
|
||||
|
||||
makePages();
|
||||
}
|
||||
currentTextBlock.reset(new ParsedText(style, extraParagraphSpacing));
|
||||
currentTextBlock.reset(new ParsedText(style, extraParagraphSpacing, hyphenationEnabled));
|
||||
}
|
||||
|
||||
void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char* name, const XML_Char** atts) {
|
||||
|
||||
@ -36,6 +36,7 @@ class ChapterHtmlSlimParser {
|
||||
int marginBottom;
|
||||
int marginLeft;
|
||||
bool extraParagraphSpacing;
|
||||
bool hyphenationEnabled;
|
||||
|
||||
void startNewTextBlock(TextBlock::BLOCK_STYLE style);
|
||||
void makePages();
|
||||
@ -48,6 +49,7 @@ class ChapterHtmlSlimParser {
|
||||
explicit ChapterHtmlSlimParser(const char* filepath, GfxRenderer& renderer, const int fontId,
|
||||
const float lineCompression, const int marginTop, const int marginRight,
|
||||
const int marginBottom, const int marginLeft, const bool extraParagraphSpacing,
|
||||
const bool hyphenationEnabled,
|
||||
const std::function<void(std::unique_ptr<Page>)>& completePageFn)
|
||||
: filepath(filepath),
|
||||
renderer(renderer),
|
||||
@ -58,6 +60,7 @@ class ChapterHtmlSlimParser {
|
||||
marginBottom(marginBottom),
|
||||
marginLeft(marginLeft),
|
||||
extraParagraphSpacing(extraParagraphSpacing),
|
||||
hyphenationEnabled(hyphenationEnabled),
|
||||
completePageFn(completePageFn) {}
|
||||
~ChapterHtmlSlimParser() = default;
|
||||
bool parseAndBuildPages();
|
||||
|
||||
@ -12,7 +12,7 @@ CrossPointSettings CrossPointSettings::instance;
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
||||
constexpr uint8_t SETTINGS_COUNT = 2;
|
||||
constexpr uint8_t SETTINGS_COUNT = 3;
|
||||
constexpr char SETTINGS_FILE[] = "/sd/.crosspoint/settings.bin";
|
||||
} // namespace
|
||||
|
||||
@ -25,6 +25,7 @@ bool CrossPointSettings::saveToFile() const {
|
||||
serialization::writePod(outputFile, SETTINGS_COUNT);
|
||||
serialization::writePod(outputFile, whiteSleepScreen);
|
||||
serialization::writePod(outputFile, extraParagraphSpacing);
|
||||
serialization::writePod(outputFile, hyphenationEnabled);
|
||||
outputFile.close();
|
||||
|
||||
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
|
||||
@ -50,15 +51,15 @@ bool CrossPointSettings::loadFromFile() {
|
||||
uint8_t fileSettingsCount = 0;
|
||||
serialization::readPod(inputFile, fileSettingsCount);
|
||||
|
||||
// load settings that exist
|
||||
switch (fileSettingsCount) {
|
||||
case 1:
|
||||
serialization::readPod(inputFile, whiteSleepScreen);
|
||||
break;
|
||||
case 2:
|
||||
// load settings that exist in the file (supports backward compatibility)
|
||||
if (fileSettingsCount >= 1) {
|
||||
serialization::readPod(inputFile, whiteSleepScreen);
|
||||
}
|
||||
if (fileSettingsCount >= 2) {
|
||||
serialization::readPod(inputFile, extraParagraphSpacing);
|
||||
break;
|
||||
}
|
||||
if (fileSettingsCount >= 3) {
|
||||
serialization::readPod(inputFile, hyphenationEnabled);
|
||||
}
|
||||
|
||||
inputFile.close();
|
||||
|
||||
@ -20,6 +20,7 @@ class CrossPointSettings {
|
||||
|
||||
// Text rendering settings
|
||||
uint8_t extraParagraphSpacing = 1;
|
||||
uint8_t hyphenationEnabled = 1;
|
||||
|
||||
~CrossPointSettings() = default;
|
||||
|
||||
|
||||
@ -207,7 +207,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
Serial.printf("[%lu] [ERS] Loading file: %s, index: %d\n", millis(), filepath.c_str(), currentSpineIndex);
|
||||
section = std::unique_ptr<Section>(new Section(epub, currentSpineIndex, renderer));
|
||||
if (!section->loadCacheMetadata(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom, marginLeft,
|
||||
SETTINGS.extraParagraphSpacing)) {
|
||||
SETTINGS.extraParagraphSpacing, SETTINGS.hyphenationEnabled)) {
|
||||
Serial.printf("[%lu] [ERS] Cache not found, building...\n", millis());
|
||||
|
||||
{
|
||||
@ -227,7 +227,7 @@ void EpubReaderActivity::renderScreen() {
|
||||
|
||||
section->setupCacheDir();
|
||||
if (!section->persistPageDataToSD(READER_FONT_ID, lineCompression, marginTop, marginRight, marginBottom,
|
||||
marginLeft, SETTINGS.extraParagraphSpacing)) {
|
||||
marginLeft, SETTINGS.extraParagraphSpacing, SETTINGS.hyphenationEnabled)) {
|
||||
Serial.printf("[%lu] [ERS] Failed to persist page data to SD\n", millis());
|
||||
section.reset();
|
||||
return;
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
|
||||
const SettingInfo SettingsActivity::settingsList[settingsCount] = {
|
||||
{"White Sleep Screen", &CrossPointSettings::whiteSleepScreen},
|
||||
{"Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing}};
|
||||
{"Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing},
|
||||
{"Hyphenation", &CrossPointSettings::hyphenationEnabled}};
|
||||
|
||||
void SettingsActivity::taskTrampoline(void* param) {
|
||||
auto* self = static_cast<SettingsActivity*>(param);
|
||||
|
||||
@ -25,7 +25,7 @@ class SettingsActivity final : public Activity {
|
||||
const std::function<void()> onGoHome;
|
||||
|
||||
// Static settings list
|
||||
static constexpr int settingsCount = 2; // Number of settings
|
||||
static constexpr int settingsCount = 3; // Number of settings
|
||||
static const SettingInfo settingsList[settingsCount];
|
||||
|
||||
static void taskTrampoline(void* param);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user