This commit is contained in:
Arthur Tazhitdinov 2026-01-07 02:34:58 +05:00
parent 54669a8fd4
commit 81ad6fa6c4
2 changed files with 1 additions and 99 deletions

View File

@ -30,7 +30,6 @@ void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fo
// Apply fixed transforms before any per-line layout work. // Apply fixed transforms before any per-line layout work.
applyParagraphIndent(); applyParagraphIndent();
ensureHyphenationFitsViewport(renderer, fontId, viewportWidth);
const int pageWidth = viewportWidth; const int pageWidth = viewportWidth;
const int spaceWidth = renderer.getSpaceWidth(fontId); const int spaceWidth = renderer.getSpaceWidth(fontId);
@ -155,100 +154,6 @@ void ParsedText::applyParagraphIndent() {
words.front().insert(0, "\xe2\x80\x83"); words.front().insert(0, "\xe2\x80\x83");
} }
void ParsedText::ensureHyphenationFitsViewport(const GfxRenderer& renderer, const int fontId, const int viewportWidth) {
if (!hyphenationEnabled || viewportWidth <= 0) {
return;
}
auto wordIt = words.begin();
auto styleIt = wordStyles.begin();
while (wordIt != words.end() && styleIt != wordStyles.end()) {
const int wordWidth = renderer.getTextWidth(fontId, wordIt->c_str(), *styleIt);
if (wordWidth <= viewportWidth) {
++wordIt;
++styleIt;
continue;
}
auto chunks = hyphenateWordToFit(*wordIt, renderer, fontId, *styleIt, viewportWidth);
if (chunks.empty()) {
++wordIt;
++styleIt;
continue;
}
*wordIt = chunks.front();
auto wordInsertPos = std::next(wordIt);
auto styleInsertPos = std::next(styleIt);
for (size_t idx = 1; idx < chunks.size(); ++idx) {
wordInsertPos = words.insert(wordInsertPos, chunks[idx]);
styleInsertPos = wordStyles.insert(styleInsertPos, *styleIt);
++wordInsertPos;
++styleInsertPos;
}
++wordIt;
++styleIt;
}
}
std::vector<std::string> ParsedText::hyphenateWordToFit(const std::string& word, const GfxRenderer& renderer,
const int fontId, const EpdFontFamily::Style style,
const int viewportWidth) const {
std::vector<std::string> chunks;
if (word.empty() || viewportWidth <= 0) {
return chunks;
}
const int hyphenWidth = renderer.getTextWidth(fontId, "-", style);
std::string remaining = word;
while (!remaining.empty()) {
const int remainingWidth = renderer.getTextWidth(fontId, remaining.c_str(), style);
if (remainingWidth <= viewportWidth) {
chunks.push_back(remaining);
break;
}
const auto breakOffsets = Hyphenator::breakOffsets(remaining, true);
if (breakOffsets.empty()) {
return {};
}
size_t chosenOffset = 0;
int chosenWidth = -1;
for (const size_t offset : breakOffsets) {
if (offset == 0 || offset >= remaining.size()) {
continue;
}
const std::string candidate = remaining.substr(0, offset);
const int candidateWidth = renderer.getTextWidth(fontId, candidate.c_str(), style) + hyphenWidth;
if (candidateWidth > viewportWidth) {
continue;
}
if (candidateWidth > chosenWidth) {
chosenWidth = candidateWidth;
chosenOffset = offset;
}
}
if (chosenWidth < 0) {
return {};
}
std::string chunk = remaining.substr(0, chosenOffset);
chunk.push_back('-');
chunks.push_back(std::move(chunk));
remaining.erase(0, chosenOffset);
}
return chunks;
}
// 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.
std::vector<size_t> ParsedText::computeHyphenatedLineBreaks(const GfxRenderer& renderer, const int fontId, std::vector<size_t> ParsedText::computeHyphenatedLineBreaks(const GfxRenderer& renderer, const int fontId,
const int pageWidth, const int spaceWidth, const int pageWidth, const int spaceWidth,

View File

@ -20,14 +20,11 @@ class ParsedText {
bool hyphenationEnabled; bool hyphenationEnabled;
void applyParagraphIndent(); void applyParagraphIndent();
void ensureHyphenationFitsViewport(const GfxRenderer& renderer, int fontId, int viewportWidth); std::vector<size_t> computeLineBreaks(int pageWidth, int spaceWidth, const std::vector<uint16_t>& wordWidths) const;
std::vector<std::string> hyphenateWordToFit(const std::string& word, const GfxRenderer& renderer, int fontId,
EpdFontFamily::Style style, int viewportWidth) const;
std::vector<size_t> computeHyphenatedLineBreaks(const GfxRenderer& renderer, int fontId, int pageWidth, std::vector<size_t> computeHyphenatedLineBreaks(const GfxRenderer& renderer, int fontId, int pageWidth,
int spaceWidth, std::vector<uint16_t>& wordWidths); int spaceWidth, std::vector<uint16_t>& wordWidths);
bool hyphenateWordAtIndex(size_t wordIndex, int availableWidth, const GfxRenderer& renderer, int fontId, bool hyphenateWordAtIndex(size_t wordIndex, int availableWidth, const GfxRenderer& renderer, int fontId,
std::vector<uint16_t>& wordWidths); std::vector<uint16_t>& wordWidths);
std::vector<size_t> computeLineBreaks(int pageWidth, int spaceWidth, const std::vector<uint16_t>& wordWidths) const;
void extractLine(size_t breakIndex, int pageWidth, int spaceWidth, const std::vector<uint16_t>& wordWidths, void extractLine(size_t breakIndex, int pageWidth, int spaceWidth, const std::vector<uint16_t>& wordWidths,
const std::vector<size_t>& lineBreakIndices, const std::vector<size_t>& lineBreakIndices,
const std::function<void(std::shared_ptr<TextBlock>)>& processLine); const std::function<void(std::shared_ptr<TextBlock>)>& processLine);