Add css cache
This commit is contained in:
@@ -165,6 +165,20 @@ std::vector<size_t> ParsedText::computeLineBreaks(const GfxRenderer& renderer, c
|
||||
|
||||
const size_t totalWordCount = words.size();
|
||||
|
||||
// Pre-compute inter-word gaps once so the O(n²) DP inner loop avoids repeated
|
||||
// codepoint scanning and renderer calls for every (i,j) pair.
|
||||
// interWordGaps[j] = the spacing between words[j-1] and words[j] (0 for j==0).
|
||||
std::vector<int> interWordGaps(totalWordCount, 0);
|
||||
for (size_t j = 1; j < totalWordCount; ++j) {
|
||||
if (!continuesVec[j]) {
|
||||
interWordGaps[j] =
|
||||
renderer.getSpaceAdvance(fontId, lastCodepoint(words[j - 1]), firstCodepoint(words[j]), wordStyles[j - 1]);
|
||||
} else {
|
||||
interWordGaps[j] =
|
||||
renderer.getKerning(fontId, lastCodepoint(words[j - 1]), firstCodepoint(words[j]), wordStyles[j - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// DP table to store the minimum badness (cost) of lines starting at index i
|
||||
std::vector<int> dp(totalWordCount);
|
||||
// 'ans[i]' stores the index 'j' of the *last word* in the optimal line starting at 'i'
|
||||
@@ -182,15 +196,7 @@ std::vector<size_t> ParsedText::computeLineBreaks(const GfxRenderer& renderer, c
|
||||
const int effectivePageWidth = i == 0 ? pageWidth - firstLineIndent : pageWidth;
|
||||
|
||||
for (size_t j = i; j < totalWordCount; ++j) {
|
||||
// Add space before word j, unless it's the first word on the line or a continuation
|
||||
int gap = 0;
|
||||
if (j > static_cast<size_t>(i) && !continuesVec[j]) {
|
||||
gap =
|
||||
renderer.getSpaceAdvance(fontId, lastCodepoint(words[j - 1]), firstCodepoint(words[j]), wordStyles[j - 1]);
|
||||
} else if (j > static_cast<size_t>(i) && continuesVec[j]) {
|
||||
// Cross-boundary kerning for continuation words (e.g. nonbreaking spaces, attached punctuation)
|
||||
gap = renderer.getKerning(fontId, lastCodepoint(words[j - 1]), firstCodepoint(words[j]), wordStyles[j - 1]);
|
||||
}
|
||||
const int gap = (j > static_cast<size_t>(i)) ? interWordGaps[j] : 0;
|
||||
currlen += wordWidths[j] + gap;
|
||||
|
||||
if (currlen > effectivePageWidth) {
|
||||
@@ -284,6 +290,21 @@ std::vector<size_t> ParsedText::computeHyphenatedLineBreaks(const GfxRenderer& r
|
||||
? blockStyle.textIndent
|
||||
: 0;
|
||||
|
||||
// Pre-compute inter-word gaps to avoid repeated codepoint scanning and renderer
|
||||
// calls in the inner loop. When hyphenateWordAtIndex inserts a new word, we insert
|
||||
// a placeholder gap (0) at that position to keep the vector in sync; the remainder
|
||||
// is always the first word on the next line so its spacing is never used.
|
||||
std::vector<int> interWordGaps(wordWidths.size(), 0);
|
||||
for (size_t j = 1; j < wordWidths.size(); ++j) {
|
||||
if (!continuesVec[j]) {
|
||||
interWordGaps[j] =
|
||||
renderer.getSpaceAdvance(fontId, lastCodepoint(words[j - 1]), firstCodepoint(words[j]), wordStyles[j - 1]);
|
||||
} else {
|
||||
interWordGaps[j] =
|
||||
renderer.getKerning(fontId, lastCodepoint(words[j - 1]), firstCodepoint(words[j]), wordStyles[j - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<size_t> lineBreakIndices;
|
||||
size_t currentIndex = 0;
|
||||
bool isFirstLine = true;
|
||||
@@ -298,15 +319,7 @@ std::vector<size_t> ParsedText::computeHyphenatedLineBreaks(const GfxRenderer& r
|
||||
// Consume as many words as possible for current line, splitting when prefixes fit
|
||||
while (currentIndex < wordWidths.size()) {
|
||||
const bool isFirstWord = currentIndex == lineStart;
|
||||
int spacing = 0;
|
||||
if (!isFirstWord && !continuesVec[currentIndex]) {
|
||||
spacing = renderer.getSpaceAdvance(fontId, lastCodepoint(words[currentIndex - 1]),
|
||||
firstCodepoint(words[currentIndex]), wordStyles[currentIndex - 1]);
|
||||
} else if (!isFirstWord && continuesVec[currentIndex]) {
|
||||
// Cross-boundary kerning for continuation words (e.g. nonbreaking spaces, attached punctuation)
|
||||
spacing = renderer.getKerning(fontId, lastCodepoint(words[currentIndex - 1]),
|
||||
firstCodepoint(words[currentIndex]), wordStyles[currentIndex - 1]);
|
||||
}
|
||||
const int spacing = isFirstWord ? 0 : interWordGaps[currentIndex];
|
||||
const int candidateWidth = spacing + wordWidths[currentIndex];
|
||||
|
||||
// Word fits on current line
|
||||
@@ -322,6 +335,9 @@ std::vector<size_t> ParsedText::computeHyphenatedLineBreaks(const GfxRenderer& r
|
||||
|
||||
if (availableWidth > 0 &&
|
||||
hyphenateWordAtIndex(currentIndex, availableWidth, renderer, fontId, wordWidths, allowFallbackBreaks)) {
|
||||
// Keep interWordGaps in sync: insert placeholder for the new remainder word.
|
||||
// The remainder is always the first word on the next line so this slot is never read.
|
||||
interWordGaps.insert(interWordGaps.begin() + currentIndex + 1, 0);
|
||||
// Prefix now fits; append it to this line and move to next line
|
||||
lineWidth += spacing + wordWidths[currentIndex];
|
||||
++currentIndex;
|
||||
|
||||
Reference in New Issue
Block a user