Address review comment: fix bionic reading on continuation
This commit is contained in:
@@ -215,13 +215,16 @@ void ParsedText::layoutAndExtractLines(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply fixed transforms before any per-line layout work.
|
// Apply fixed transforms before any per-line layout work.
|
||||||
// Skip on continuation flushes: the words are mid-paragraph and have
|
// Paragraph indent only applies to the first layout pass; skip on continuations.
|
||||||
// already been transformed by the initial layoutAndExtractLines call.
|
|
||||||
if (!isContinuation_) {
|
if (!isContinuation_) {
|
||||||
applyParagraphIndent();
|
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.
|
// Ensure SD card font glyph metrics are loaded before measuring word widths.
|
||||||
@@ -382,6 +385,9 @@ void ParsedText::layoutAndExtractLines(
|
|||||||
wordStyles.shrink_to_fit();
|
wordStyles.shrink_to_fit();
|
||||||
wordContinues.shrink_to_fit();
|
wordContinues.shrink_to_fit();
|
||||||
isContinuation_ = !includeLastLine;
|
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() {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> transformedWords;
|
const size_t suffixStart = bionicTransformedUpTo_;
|
||||||
std::vector<EpdFontFamily::Style> transformedStyles;
|
std::vector<std::string> transformedSuffix;
|
||||||
std::vector<bool> transformedContinues;
|
std::vector<EpdFontFamily::Style> transformedSuffixStyles;
|
||||||
transformedWords.reserve(words.size() * 2);
|
std::vector<bool> transformedSuffixContinues;
|
||||||
transformedStyles.reserve(wordStyles.size() * 2);
|
transformedSuffix.reserve((words.size() - suffixStart) * 2);
|
||||||
transformedContinues.reserve(wordContinues.size() * 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]);
|
std::string source = std::move(words[i]);
|
||||||
const auto originalStyle = wordStyles[i];
|
const auto originalStyle = wordStyles[i];
|
||||||
const bool originalAttachToPrevious = wordContinues[i];
|
const bool originalAttachToPrevious = wordContinues[i];
|
||||||
@@ -638,29 +649,35 @@ void ParsedText::applyBionicReadingTransform() {
|
|||||||
std::string suffix(reinterpret_cast<const char*>(prefixEnd), token.size() - prefixByteCount);
|
std::string suffix(reinterpret_cast<const char*>(prefixEnd), token.size() - prefixByteCount);
|
||||||
token.resize(prefixByteCount);
|
token.resize(prefixByteCount);
|
||||||
const auto boldStyle = static_cast<EpdFontFamily::Style>(originalStyle | EpdFontFamily::BOLD);
|
const auto boldStyle = static_cast<EpdFontFamily::Style>(originalStyle | EpdFontFamily::BOLD);
|
||||||
transformedWords.push_back(std::move(token));
|
transformedSuffix.push_back(std::move(token));
|
||||||
transformedStyles.push_back(boldStyle);
|
transformedSuffixStyles.push_back(boldStyle);
|
||||||
transformedContinues.push_back(attachToPrevious);
|
transformedSuffixContinues.push_back(attachToPrevious);
|
||||||
|
|
||||||
transformedWords.push_back(std::move(suffix));
|
transformedSuffix.push_back(std::move(suffix));
|
||||||
transformedStyles.push_back(originalStyle);
|
transformedSuffixStyles.push_back(originalStyle);
|
||||||
transformedContinues.push_back(true);
|
transformedSuffixContinues.push_back(true);
|
||||||
attachToPrevious = true;
|
attachToPrevious = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transformedWords.push_back(std::move(token));
|
transformedSuffix.push_back(std::move(token));
|
||||||
transformedStyles.push_back(originalStyle);
|
transformedSuffixStyles.push_back(originalStyle);
|
||||||
transformedContinues.push_back(attachToPrevious);
|
transformedSuffixContinues.push_back(attachToPrevious);
|
||||||
attachToPrevious = true;
|
attachToPrevious = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
words = std::move(transformedWords);
|
// Replace the (now move-emptied) suffix with the transformed version.
|
||||||
wordStyles = std::move(transformedStyles);
|
words.resize(suffixStart);
|
||||||
wordContinues = std::move(transformedContinues);
|
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.
|
// Builds break indices while opportunistically splitting the word that would overflow the current line.
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ class ParsedText {
|
|||||||
bool extraParagraphSpacing;
|
bool extraParagraphSpacing;
|
||||||
bool hyphenationEnabled;
|
bool hyphenationEnabled;
|
||||||
bool bionicReadingEnabled;
|
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 applyParagraphIndent();
|
||||||
void applyBionicReadingTransform();
|
void applyBionicReadingTransform();
|
||||||
|
|||||||
Reference in New Issue
Block a user