Changeset 282211 in webkit
- Timestamp:
- Sep 9, 2021, 6:59:41 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
-
ChangeLog (modified) (1 diff)
-
layout/integration/LayoutIntegrationInlineContent.cpp (modified) (1 diff)
-
layout/integration/LayoutIntegrationInlineContent.h (modified) (4 diffs)
-
layout/integration/LayoutIntegrationLineLayout.cpp (modified) (6 diffs)
-
layout/integration/LayoutIntegrationLineLayout.h (modified) (1 diff)
-
layout/integration/LayoutIntegrationRunIterator.cpp (modified) (2 diffs)
-
layout/integration/LayoutIntegrationRunIterator.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r282209 r282211 1 2021-09-09 Antti Koivisto <antti@apple.com> 2 3 Add cache to InlineContent for O(1) inline box access 4 https://bugs.webkit.org/show_bug.cgi?id=230092 5 6 Reviewed by Alan Bujtas. 7 8 Add lazy caches for getting the index of the first run and all non-root inline boxes for a layout box. 9 10 * layout/integration/LayoutIntegrationInlineContent.cpp: 11 (WebCore::LayoutIntegration::InlineContent::indexForRun const): 12 (WebCore::LayoutIntegration::InlineContent::firstRunForLayoutBox const): 13 (WebCore::LayoutIntegration::InlineContent::firstRunIndexForLayoutBox const): 14 15 For small run vectors (<16) just search directly. 16 17 (WebCore::LayoutIntegration::InlineContent::nonRootInlineBoxIndexesForLayoutBox const): 18 (WebCore::LayoutIntegration::InlineContent::releaseCaches): 19 20 Memory cleanup support. 21 22 (WebCore::LayoutIntegration::InlineContent::shrinkToFit): 23 (WebCore::LayoutIntegration::InlineContent::iteratorForRun const): Deleted. 24 (WebCore::LayoutIntegration::InlineContent::iteratorForTextRun const): Deleted. 25 26 Cleanup the interface by removing iterator dependency (iterator depends on InlineContent, not other way round). 27 28 * layout/integration/LayoutIntegrationInlineContent.h: 29 (WebCore::LayoutIntegration::InlineContent::traverseNonRootInlineBoxes): 30 31 Traversal helper. 32 33 (WebCore::LayoutIntegration::InlineContent::shrinkToFit): Deleted. 34 * layout/integration/LayoutIntegrationLineLayout.cpp: 35 (WebCore::LayoutIntegration::LineLayout::textRunsFor const): 36 (WebCore::LayoutIntegration::LineLayout::runFor const): 37 (WebCore::LayoutIntegration::LineLayout::firstInlineBoxRect const): 38 (WebCore::LayoutIntegration::LineLayout::visualOverflowBoundingBoxRectFor const): 39 (WebCore::LayoutIntegration::LineLayout::collectInlineBoxRects const): 40 41 Use the new cache-backed interfaces. 42 43 (WebCore::LayoutIntegration::LineLayout::releaseCaches): 44 (WebCore::LayoutIntegration::LineLayout::paintTextRunUsingPhysicalCoordinates): 45 (WebCore::LayoutIntegration::LineLayout::releaseInlineItemCache): Deleted. 46 * layout/integration/LayoutIntegrationLineLayout.h: 47 * layout/integration/LayoutIntegrationRunIterator.cpp: 48 (WebCore::LayoutIntegration::textRunFor): 49 (WebCore::LayoutIntegration::runFor): 50 * layout/integration/LayoutIntegrationRunIterator.h: 51 1 52 2021-09-09 Frederic Wang <fwang@igalia.com> 2 53 -
trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContent.cpp
r282050 r282211 79 79 } 80 80 81 RunIterator InlineContent::iteratorForRun(const Run& run) const81 size_t InlineContent::indexForRun(const Run& run) const 82 82 { 83 return { RunIteratorModernPath { *this, static_cast<size_t>(&run - runs.begin()) } }; 83 auto index = static_cast<size_t>(&run - runs.begin()); 84 RELEASE_ASSERT(index < runs.size()); 85 return index; 84 86 } 85 87 86 TextRunIterator InlineContent::iteratorForTextRun(const Run& run) const88 const Run* InlineContent::firstRunForLayoutBox(const Layout::Box& layoutBox) const 87 89 { 88 ASSERT(run.text()); 89 return { RunIteratorModernPath { *this, static_cast<size_t>(&run - runs.begin()) } }; 90 auto index = firstRunIndexForLayoutBox(layoutBox); 91 return index ? &runs[*index] : nullptr; 92 } 93 94 std::optional<size_t> InlineContent::firstRunIndexForLayoutBox(const Layout::Box& layoutBox) const 95 { 96 constexpr auto cacheThreshold = 16; 97 98 if (runs.size() < cacheThreshold) { 99 for (size_t i = 0; i < runs.size(); ++i) { 100 auto& run = runs[i]; 101 if (&run.layoutBox() == &layoutBox) 102 return i; 103 } 104 return { }; 105 } 106 107 if (!m_firstRunIndexCache) { 108 m_firstRunIndexCache = makeUnique<FirstRunIndexCache>(); 109 for (size_t i = 0; i < runs.size(); ++i) { 110 auto& run = runs[i]; 111 if (run.isRootInlineBox()) 112 continue; 113 m_firstRunIndexCache->add(run.layoutBox(), i); 114 } 115 } 116 117 auto it = m_firstRunIndexCache->find(layoutBox); 118 if (it == m_firstRunIndexCache->end()) 119 return { }; 120 121 return it->value; 122 } 123 124 const Vector<size_t>& InlineContent::nonRootInlineBoxIndexesForLayoutBox(const Layout::Box& layoutBox) const 125 { 126 ASSERT(layoutBox.isContainerBox()); 127 128 if (!m_inlineBoxIndexCache) { 129 m_inlineBoxIndexCache = makeUnique<InlineBoxIndexCache>(); 130 for (size_t i = 0; i < runs.size(); ++i) { 131 auto& run = runs[i]; 132 if (!run.isNonRootInlineBox()) 133 continue; 134 m_inlineBoxIndexCache->ensure(run.layoutBox(), [&] { 135 return Vector<size_t> { }; 136 }).iterator->value.append(i); 137 } 138 for (auto entry : *m_inlineBoxIndexCache) 139 entry.value.shrinkToFit(); 140 } 141 142 auto it = m_inlineBoxIndexCache->find(layoutBox); 143 if (it == m_inlineBoxIndexCache->end()) { 144 static NeverDestroyed<Vector<size_t>> emptyVector; 145 return emptyVector.get(); 146 } 147 148 return it->value; 149 } 150 151 void InlineContent::releaseCaches() 152 { 153 m_firstRunIndexCache = { }; 154 m_inlineBoxIndexCache = { }; 155 } 156 157 void InlineContent::shrinkToFit() 158 { 159 runs.shrinkToFit(); 160 lines.shrinkToFit(); 90 161 } 91 162 -
trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContent.h
r282072 r282211 32 32 #include <wtf/IteratorRange.h> 33 33 #include <wtf/Vector.h> 34 #include <wtf/WeakHashMap.h> 34 35 #include <wtf/WeakPtr.h> 35 36 … … 46 47 47 48 class LineLayout; 48 class RunIterator;49 class TextRunIterator;50 49 51 50 using Run = Layout::Run; … … 73 72 const RenderBlockFlow& containingBlock() const; 74 73 75 RunIterator iteratorForRun(const Run&) const; 76 TextRunIterator iteratorForTextRun(const Run&) const; 74 size_t indexForRun(const Run&) const; 75 76 const Run* firstRunForLayoutBox(const Layout::Box&) const; 77 template<typename Function> void traverseNonRootInlineBoxes(const Layout::Box&, Function&&); 78 79 std::optional<size_t> firstRunIndexForLayoutBox(const Layout::Box&) const; 80 const Vector<size_t>& nonRootInlineBoxIndexesForLayoutBox(const Layout::Box&) const; 81 82 void releaseCaches(); 77 83 78 84 private: … … 80 86 81 87 WeakPtr<const LineLayout> m_lineLayout; 88 89 using FirstRunIndexCache = WeakHashMap<Layout::Box, size_t>; 90 mutable std::unique_ptr<FirstRunIndexCache> m_firstRunIndexCache; 91 92 using InlineBoxIndexCache = WeakHashMap<Layout::Box, Vector<size_t>>; 93 mutable std::unique_ptr<InlineBoxIndexCache> m_inlineBoxIndexCache; 82 94 }; 83 95 84 inline void InlineContent::shrinkToFit()96 template<typename Function> void InlineContent::traverseNonRootInlineBoxes(const Layout::Box& layoutBox, Function&& function) 85 97 { 86 runs.shrinkToFit();87 lines.shrinkToFit();98 for (auto index : nonRootInlineBoxIndexesForLayoutBox(layoutBox)) 99 function(runs[index]); 88 100 } 89 101 -
trunk/Source/WebCore/layout/integration/LayoutIntegrationLineLayout.cpp
r282202 r282211 365 365 if (!m_inlineContent) 366 366 return { }; 367 367 368 auto& layoutBox = m_boxTree.layoutBoxForRenderer(renderText); 368 369 auto firstIndex = [&]() -> std::optional<size_t> { 370 for (size_t i = 0; i < m_inlineContent->runs.size(); ++i) { 371 if (&m_inlineContent->runs[i].layoutBox() == &layoutBox) 372 return i; 373 } 374 return { }; 375 }(); 376 369 auto firstIndex = m_inlineContent->firstRunIndexForLayoutBox(layoutBox); 377 370 if (!firstIndex) 378 371 return { }; 379 372 380 return { RunIteratorModernPath(*m_inlineContent, *firstIndex) };373 return LayoutIntegration::textRunFor(*m_inlineContent, *firstIndex); 381 374 } 382 375 … … 385 378 if (!m_inlineContent) 386 379 return { }; 380 387 381 auto& layoutBox = m_boxTree.layoutBoxForRenderer(renderElement); 388 389 for (size_t i = 0; i < m_inlineContent->runs.size(); ++i) { 390 auto& run = m_inlineContent->runs[i]; 391 if (&run.layoutBox() == &layoutBox) 392 return { RunIteratorModernPath(*m_inlineContent, i) }; 393 } 394 395 return { }; 382 auto firstIndex = m_inlineContent->firstRunIndexForLayoutBox(layoutBox); 383 if (!firstIndex) 384 return { }; 385 386 return LayoutIntegration::runFor(*m_inlineContent, *firstIndex); 396 387 } 397 388 … … 415 406 { 416 407 auto& layoutBox = m_boxTree.layoutBoxForRenderer(renderInline); 417 for (auto& run : m_inlineContent->runs) { 418 if (&run.layoutBox() == &layoutBox)419 return Layout::toLayoutRect(run.logicalRect());420 } 408 409 if (auto* run = m_inlineContent->firstRunForLayoutBox(layoutBox)) 410 return Layout::toLayoutRect(run->logicalRect()); 411 421 412 return { }; 422 413 } … … 436 427 LayoutRect LineLayout::visualOverflowBoundingBoxRectFor(const RenderInline& renderInline) const 437 428 { 429 auto& layoutBox = m_boxTree.layoutBoxForRenderer(renderInline); 430 438 431 LayoutRect result; 432 m_inlineContent->traverseNonRootInlineBoxes(layoutBox, [&](auto& inlineBox) { 433 result.unite(Layout::toLayoutRect(inlineBox.inkOverflow())); 434 }); 435 436 return result; 437 } 438 439 Vector<FloatRect> LineLayout::collectInlineBoxRects(const RenderInline& renderInline) const 440 { 441 if (!m_inlineContent) 442 return { }; 439 443 440 444 auto& layoutBox = m_boxTree.layoutBoxForRenderer(renderInline); 441 for (auto& run : m_inlineContent->runs) {442 if (&run.layoutBox() != &layoutBox)443 continue;444 result.unite(Layout::toLayoutRect(run.inkOverflow()));445 }446 447 return result;448 }449 450 Vector<FloatRect> LineLayout::collectInlineBoxRects(const RenderInline& renderInline) const451 {452 if (!m_inlineContent)453 return { };454 445 455 446 Vector<FloatRect> result; 456 457 auto& layoutBox = m_boxTree.layoutBoxForRenderer(renderInline); 458 for (auto& run : m_inlineContent->runs) { 459 if (&run.layoutBox() != &layoutBox) 460 continue; 461 result.append(run.logicalRect()); 462 } 447 m_inlineContent->traverseNonRootInlineBoxes(layoutBox, [&](auto& inlineBox) { 448 result.append(inlineBox.logicalRect()); 449 }); 463 450 464 451 return result; … … 552 539 for (auto& renderer : descendantsOfType<RenderBlockFlow>(view)) { 553 540 if (auto* lineLayout = renderer.modernLineLayout()) 554 lineLayout->release InlineItemCache();555 } 556 } 557 558 void LineLayout::release InlineItemCache()541 lineLayout->releaseCaches(); 542 } 543 } 544 545 void LineLayout::releaseCaches() 559 546 { 560 547 m_inlineFormattingState.inlineItems().clear(); 548 if (m_inlineContent) 549 m_inlineContent->releaseCaches(); 561 550 } 562 551 … … 631 620 auto& textRenderer = downcast<RenderText>(m_boxTree.rendererForLayoutBox(run.layoutBox())); 632 621 auto decorationPainter = TextDecorationPainter { paintContext, style.textDecorationsInEffect(), textRenderer, false, fontCascade }; 633 decorationPainter.setTextRunIterator( m_inlineContent->iteratorForTextRun(run));622 decorationPainter.setTextRunIterator(textRunFor(*m_inlineContent, run)); 634 623 decorationPainter.setWidth(runRect.width()); 635 624 decorationPainter.paintTextDecoration(textRun, textOrigin, runRect.location() + physicalPaintOffset); -
trunk/Source/WebCore/layout/integration/LayoutIntegrationLineLayout.h
r282202 r282211 123 123 const Layout::ContainerBox& rootLayoutBox() const; 124 124 Layout::ContainerBox& rootLayoutBox(); 125 void release InlineItemCache();125 void releaseCaches(); 126 126 127 127 BoxTree m_boxTree; -
trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIterator.cpp
r281241 r282211 196 196 } 197 197 198 TextRunIterator textRunFor(const InlineContent& content, const Run& run) 199 { 200 return textRunFor(content, content.indexForRun(run)); 201 } 202 203 TextRunIterator textRunFor(const InlineContent& content, size_t runIndex) 204 { 205 ASSERT(content.runs[runIndex].text()); 206 return { RunIteratorModernPath { content, runIndex } }; 207 } 208 198 209 TextRunRange textRunsFor(const RenderText& text) 199 210 { … … 219 230 } 220 231 232 RunIterator runFor(const InlineContent& content, size_t runIndex) 233 { 234 return { RunIteratorModernPath { content, runIndex } }; 235 } 236 221 237 #if ENABLE(LAYOUT_FORMATTING_CONTEXT) 222 238 const RunIteratorModernPath& PathRun::modernPath() const -
trunk/Source/WebCore/layout/integration/LayoutIntegrationRunIterator.h
r281241 r282211 202 202 TextRunIterator firstTextRunInTextOrderFor(const RenderText&); 203 203 TextRunIterator textRunFor(const LegacyInlineTextBox*); 204 TextRunIterator textRunFor(const InlineContent&, const Run&); 205 TextRunIterator textRunFor(const InlineContent&, size_t runIndex); 204 206 TextRunRange textRunsFor(const RenderText&); 205 207 RunIterator runFor(const RenderLineBreak&); 206 208 RunIterator runFor(const RenderBox&); 209 RunIterator runFor(const InlineContent&, size_t runIndex); 207 210 208 211 // -----------------------------------------------
Note:
See TracChangeset
for help on using the changeset viewer.