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