Address review comment: fix bionic reading on continuation

This commit is contained in:
spfenwick
2026-05-02 16:59:03 +12:00
parent c04ec25dc7
commit 0a5fee2839
2 changed files with 44 additions and 26 deletions
+42 -25
View File
@@ -215,13 +215,16 @@ void ParsedText::layoutAndExtractLines(
}
// Apply fixed transforms before any per-line layout work.
// Skip on continuation flushes: the words are mid-paragraph and have
// already been transformed by the initial layoutAndExtractLines call.
// Paragraph indent only applies to the first layout pass; skip on continuations.
if (!isContinuation_) {
applyParagraphIndent();
if (bionicReadingEnabled) {
applyBionicReadingTransform();
}
}
// Bionic transform is incremental: applyBionicReadingTransform() is a no-op
// for already-transformed words (bionicTransformedUpTo_ == words.size()) and
// only processes raw words appended since the last flush, so it is always safe
// to call regardless of isContinuation_.
if (bionicReadingEnabled) {
applyBionicReadingTransform();
}
// Ensure SD card font glyph metrics are loaded before measuring word widths.
@@ -382,6 +385,9 @@ void ParsedText::layoutAndExtractLines(
wordStyles.shrink_to_fit();
wordContinues.shrink_to_fit();
isContinuation_ = !includeLastLine;
// All remaining words were already transformed before the flush; reset the
// watermark so that words appended by addWord() are processed next time.
bionicTransformedUpTo_ = words.size();
}
}
@@ -585,18 +591,23 @@ void ParsedText::applyParagraphIndent() {
}
void ParsedText::applyBionicReadingTransform() {
if (words.empty()) {
// Only transform words that haven't been processed yet. On a fresh block
// bionicTransformedUpTo_ == 0 so all words are processed. After an
// intermediate flush, only the new raw words appended since the last flush
// (indices bionicTransformedUpTo_..words.size()-1) need transformation.
if (words.empty() || bionicTransformedUpTo_ >= words.size()) {
return;
}
std::vector<std::string> transformedWords;
std::vector<EpdFontFamily::Style> transformedStyles;
std::vector<bool> transformedContinues;
transformedWords.reserve(words.size() * 2);
transformedStyles.reserve(wordStyles.size() * 2);
transformedContinues.reserve(wordContinues.size() * 2);
const size_t suffixStart = bionicTransformedUpTo_;
std::vector<std::string> transformedSuffix;
std::vector<EpdFontFamily::Style> transformedSuffixStyles;
std::vector<bool> transformedSuffixContinues;
transformedSuffix.reserve((words.size() - suffixStart) * 2);
transformedSuffixStyles.reserve(transformedSuffix.capacity());
transformedSuffixContinues.reserve(transformedSuffix.capacity());
for (size_t i = 0; i < words.size(); ++i) {
for (size_t i = suffixStart; i < words.size(); ++i) {
std::string source = std::move(words[i]);
const auto originalStyle = wordStyles[i];
const bool originalAttachToPrevious = wordContinues[i];
@@ -638,29 +649,35 @@ void ParsedText::applyBionicReadingTransform() {
std::string suffix(reinterpret_cast<const char*>(prefixEnd), token.size() - prefixByteCount);
token.resize(prefixByteCount);
const auto boldStyle = static_cast<EpdFontFamily::Style>(originalStyle | EpdFontFamily::BOLD);
transformedWords.push_back(std::move(token));
transformedStyles.push_back(boldStyle);
transformedContinues.push_back(attachToPrevious);
transformedSuffix.push_back(std::move(token));
transformedSuffixStyles.push_back(boldStyle);
transformedSuffixContinues.push_back(attachToPrevious);
transformedWords.push_back(std::move(suffix));
transformedStyles.push_back(originalStyle);
transformedContinues.push_back(true);
transformedSuffix.push_back(std::move(suffix));
transformedSuffixStyles.push_back(originalStyle);
transformedSuffixContinues.push_back(true);
attachToPrevious = true;
continue;
}
}
}
transformedWords.push_back(std::move(token));
transformedStyles.push_back(originalStyle);
transformedContinues.push_back(attachToPrevious);
transformedSuffix.push_back(std::move(token));
transformedSuffixStyles.push_back(originalStyle);
transformedSuffixContinues.push_back(attachToPrevious);
attachToPrevious = true;
}
}
words = std::move(transformedWords);
wordStyles = std::move(transformedStyles);
wordContinues = std::move(transformedContinues);
// Replace the (now move-emptied) suffix with the transformed version.
words.resize(suffixStart);
wordStyles.resize(suffixStart);
wordContinues.resize(suffixStart);
words.insert(words.end(), std::make_move_iterator(transformedSuffix.begin()),
std::make_move_iterator(transformedSuffix.end()));
wordStyles.insert(wordStyles.end(), transformedSuffixStyles.begin(), transformedSuffixStyles.end());
wordContinues.insert(wordContinues.end(), transformedSuffixContinues.begin(), transformedSuffixContinues.end());
bionicTransformedUpTo_ = words.size();
}
// Builds break indices while opportunistically splitting the word that would overflow the current line.
+2 -1
View File
@@ -27,7 +27,8 @@ class ParsedText {
bool extraParagraphSpacing;
bool hyphenationEnabled;
bool bionicReadingEnabled;
bool isContinuation_ = false; ///< true after an intermediate flush; suppresses re-applying indent/transforms
bool isContinuation_ = false; ///< true after an intermediate flush; suppresses re-applying paragraph indent
size_t bionicTransformedUpTo_ = 0; ///< words[0..bionicTransformedUpTo_) have already been bionic-transformed
void applyParagraphIndent();
void applyBionicReadingTransform();