Add css cache

This commit is contained in:
jpirnay
2026-03-28 20:49:03 +01:00
parent 5b43639f98
commit 6daf3fd1bb
3 changed files with 92 additions and 26 deletions
+34 -18
View File
@@ -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;