Skip to content

Commit

Permalink
[IFC] LayoutIntegration::InlineContentBuilder::build cleanup
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=263300

Reviewed by Antti Koivisto.

Decouple full and partial layout update. This is in preparation for handling the invalid case where we are unable to figure out the damaged lines/boxes.

* Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentBuilder.cpp:
(WebCore::LayoutIntegration::InlineContentBuilder::build const):

Canonical link: https://commits.webkit.org/269464@main
  • Loading branch information
alanbaradlay committed Oct 18, 2023
1 parent 825a7cc commit 1b7f44c
Showing 1 changed file with 102 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,115 +59,121 @@ InlineContentBuilder::InlineContentBuilder(const RenderBlockFlow& blockFlow, Box

FloatRect InlineContentBuilder::build(Layout::InlineLayoutResult&& layoutResult, InlineContent& inlineContent, const Layout::InlineDamage* lineDamage) const
{
auto firstDamagedLineIndex = [&]() -> std::optional<size_t> {
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
if (!lineDamage || !lineDamage->start() || !displayContentFromPreviousLayout.lines.size())
return { };
auto canidateLineIndex = lineDamage->start()->lineIndex;
if (canidateLineIndex >= displayContentFromPreviousLayout.lines.size()) {
ASSERT_NOT_REACHED();
return { };
}
return { canidateLineIndex };
}();
inlineContent.releaseCaches();
computeIsFirstIsLastBoxAndBidiReorderingForInlineContent(layoutResult.displayContent.boxes);

auto firstDamagedBoxIndex = [&]() -> std::optional<size_t> {
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
return firstDamagedLineIndex ? std::make_optional(displayContentFromPreviousLayout.lines[*firstDamagedLineIndex].firstBoxIndex()) : std::nullopt;
}();
if (layoutResult.range == Layout::InlineLayoutResult::Range::Full) {
auto damagedRect = FloatRect { };

auto numberOfDamagedLines = [&]() -> std::optional<size_t> {
if (!firstDamagedLineIndex)
return { };
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
ASSERT(layoutResult.range != Layout::InlineLayoutResult::Range::Full);
auto canidateLineCount = layoutResult.range == Layout::InlineLayoutResult::Range::FullFromDamage
? displayContentFromPreviousLayout.lines.size() - *firstDamagedLineIndex
: layoutResult.displayContent.lines.size();
for (auto& line : inlineContent.displayContent().lines)
damagedRect.unite(line.inkOverflow());

if (*firstDamagedLineIndex + canidateLineCount > displayContentFromPreviousLayout.lines.size()) {
ASSERT_NOT_REACHED();
return { };
}
return { canidateLineCount };
}();

auto numberOfDamagedBoxes = [&]() -> std::optional<size_t> {
if (!firstDamagedLineIndex || !numberOfDamagedLines || !firstDamagedBoxIndex)
return { };
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
ASSERT(*firstDamagedLineIndex + *numberOfDamagedLines <= displayContentFromPreviousLayout.lines.size());
size_t boxCount = 0;
for (size_t i = 0; i < *numberOfDamagedLines; ++i)
boxCount += displayContentFromPreviousLayout.lines[*firstDamagedLineIndex + i].boxCount();
ASSERT(boxCount);
return { boxCount };
}();
auto numberOfNewLines = layoutResult.displayContent.lines.size();
auto numberOfNewBoxes = layoutResult.displayContent.boxes.size();

auto damagedRect = FloatRect { };
auto adjustDamagedRectWithLineRange = [&](size_t firstLineIndex, size_t lineCount, auto& lines) {
ASSERT(firstLineIndex + lineCount <= lines.size());
for (size_t i = 0; i < lineCount; ++i)
damagedRect.unite(lines[firstLineIndex + i].inkOverflow());
};
inlineContent.displayContent().set(WTFMove(layoutResult.displayContent));
adjustDisplayLines(inlineContent, 0);

// Repaint the damaged content boundary.
adjustDamagedRectWithLineRange(firstDamagedLineIndex.value_or(0), numberOfDamagedLines.value_or(inlineContent.displayContent().lines.size()), inlineContent.displayContent().lines);
for (auto& line : inlineContent.displayContent().lines)
damagedRect.unite(line.inkOverflow());
return damagedRect;
}

inlineContent.releaseCaches();
auto handlePartialDisplayContentUpdate = [&]() -> FloatRect {

computeIsFirstIsLastBoxAndBidiReorderingForInlineContent(layoutResult.displayContent.boxes);
auto firstDamagedLineIndex = [&]() -> std::optional<size_t> {
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
if (!lineDamage || !lineDamage->start() || !displayContentFromPreviousLayout.lines.size())
return { };
auto canidateLineIndex = lineDamage->start()->lineIndex;
if (canidateLineIndex >= displayContentFromPreviousLayout.lines.size()) {
ASSERT_NOT_REACHED();
return { };
}
return { canidateLineIndex };
}();

auto firstDamagedBoxIndex = [&]() -> std::optional<size_t> {
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
return firstDamagedLineIndex ? std::make_optional(displayContentFromPreviousLayout.lines[*firstDamagedLineIndex].firstBoxIndex()) : std::nullopt;
}();

auto numberOfDamagedLines = [&]() -> std::optional<size_t> {
if (!firstDamagedLineIndex)
return { };
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
ASSERT(layoutResult.range != Layout::InlineLayoutResult::Range::Full);
auto canidateLineCount = layoutResult.range == Layout::InlineLayoutResult::Range::FullFromDamage
? displayContentFromPreviousLayout.lines.size() - *firstDamagedLineIndex
: layoutResult.displayContent.lines.size();

if (*firstDamagedLineIndex + canidateLineCount > displayContentFromPreviousLayout.lines.size()) {
ASSERT_NOT_REACHED();
return { };
}
return { canidateLineCount };
}();

auto numberOfDamagedBoxes = [&]() -> std::optional<size_t> {
if (!firstDamagedLineIndex || !numberOfDamagedLines || !firstDamagedBoxIndex)
return { };
auto& displayContentFromPreviousLayout = inlineContent.displayContent();
ASSERT(*firstDamagedLineIndex + *numberOfDamagedLines <= displayContentFromPreviousLayout.lines.size());
size_t boxCount = 0;
for (size_t i = 0; i < *numberOfDamagedLines; ++i)
boxCount += displayContentFromPreviousLayout.lines[*firstDamagedLineIndex + i].boxCount();
ASSERT(boxCount);
return { boxCount };
}();

switch (layoutResult.range) {
case Layout::InlineLayoutResult::Range::Full:
inlineContent.displayContent().set(WTFMove(layoutResult.displayContent));
break;
case Layout::InlineLayoutResult::Range::FullFromDamage: {
if (!firstDamagedLineIndex || !numberOfDamagedLines || !firstDamagedBoxIndex || !numberOfDamagedBoxes) {
// FIXME: Not sure if inlineContent::set or silent failing is what we should do here.
break;
}
auto& displayContent = inlineContent.displayContent();
displayContent.remove(*firstDamagedLineIndex, *numberOfDamagedLines, *firstDamagedBoxIndex, *numberOfDamagedBoxes);
displayContent.append(WTFMove(layoutResult.displayContent));
break;
}
case Layout::InlineLayoutResult::Range::PartialFromDamage: {
if (!firstDamagedLineIndex || !numberOfDamagedLines || !firstDamagedBoxIndex || !numberOfDamagedBoxes) {
// FIXME: Not sure if inlineContent::set or silent failing is what we should do here.
break;
ASSERT_NOT_REACHED();
return { };
}
auto& displayContent = inlineContent.displayContent();
displayContent.remove(*firstDamagedLineIndex, *numberOfDamagedLines, *firstDamagedBoxIndex, *numberOfDamagedBoxes);
displayContent.insert(WTFMove(layoutResult.displayContent), *firstDamagedLineIndex, *firstDamagedBoxIndex);

auto adjustCachedBoxIndexesIfNeeded = [&] {
if (numberOfNewBoxes == *numberOfDamagedBoxes)
return;
auto firstCleanLineIndex = *firstDamagedLineIndex + *numberOfDamagedLines;
auto offset = numberOfNewBoxes - *numberOfDamagedBoxes;
auto& lines = displayContent.lines;
for (size_t cleanLineIndex = firstCleanLineIndex; cleanLineIndex < lines.size(); ++cleanLineIndex) {
ASSERT(lines[cleanLineIndex].firstBoxIndex() + offset > 0);
auto adjustedFirstBoxIndex = std::max<size_t>(0, lines[cleanLineIndex].firstBoxIndex() + offset);
lines[cleanLineIndex].setFirstBoxIndex(adjustedFirstBoxIndex);
}
auto numberOfNewLines = layoutResult.displayContent.lines.size();
auto numberOfNewBoxes = layoutResult.displayContent.boxes.size();

auto damagedRect = FloatRect { };
auto adjustDamagedRectWithLineRange = [&](size_t firstLineIndex, size_t lineCount) {
auto& lines = inlineContent.displayContent().lines;
ASSERT(firstLineIndex + lineCount <= lines.size());
for (size_t i = 0; i < lineCount; ++i)
damagedRect.unite(lines[firstLineIndex + i].inkOverflow());
};
adjustCachedBoxIndexesIfNeeded();
break;
}
default:
ASSERT_NOT_REACHED();
break;
}

adjustDisplayLines(inlineContent, firstDamagedLineIndex.value_or(0));
// Repaint the new content boundary.
adjustDamagedRectWithLineRange(firstDamagedLineIndex.value_or(0), numberOfNewLines, inlineContent.displayContent().lines);
// Repaint the damaged content boundary.
adjustDamagedRectWithLineRange(*firstDamagedLineIndex, *numberOfDamagedLines);

if (layoutResult.range == Layout::InlineLayoutResult::Range::FullFromDamage) {
auto& displayContent = inlineContent.displayContent();
displayContent.remove(*firstDamagedLineIndex, *numberOfDamagedLines, *firstDamagedBoxIndex, *numberOfDamagedBoxes);
displayContent.append(WTFMove(layoutResult.displayContent));
} else if (layoutResult.range == Layout::InlineLayoutResult::Range::PartialFromDamage) {
auto& displayContent = inlineContent.displayContent();
displayContent.remove(*firstDamagedLineIndex, *numberOfDamagedLines, *firstDamagedBoxIndex, *numberOfDamagedBoxes);
displayContent.insert(WTFMove(layoutResult.displayContent), *firstDamagedLineIndex, *firstDamagedBoxIndex);

auto adjustCachedBoxIndexesIfNeeded = [&] {
if (numberOfNewBoxes == *numberOfDamagedBoxes)
return;
auto firstCleanLineIndex = *firstDamagedLineIndex + *numberOfDamagedLines;
auto offset = numberOfNewBoxes - *numberOfDamagedBoxes;
auto& lines = displayContent.lines;
for (size_t cleanLineIndex = firstCleanLineIndex; cleanLineIndex < lines.size(); ++cleanLineIndex) {
ASSERT(lines[cleanLineIndex].firstBoxIndex() + offset > 0);
auto adjustedFirstBoxIndex = std::max<size_t>(0, lines[cleanLineIndex].firstBoxIndex() + offset);
lines[cleanLineIndex].setFirstBoxIndex(adjustedFirstBoxIndex);
}
};
adjustCachedBoxIndexesIfNeeded();
} else
ASSERT_NOT_REACHED();

return damagedRect;
adjustDisplayLines(inlineContent, *firstDamagedLineIndex);
// Repaint the new content boundary.
adjustDamagedRectWithLineRange(*firstDamagedLineIndex, numberOfNewLines);

return damagedRect;
};
return handlePartialDisplayContentUpdate();
}

void InlineContentBuilder::updateLineOverflow(InlineContent& inlineContent) const
Expand Down

0 comments on commit 1b7f44c

Please sign in to comment.