Changeset 286541 in webkit
- Timestamp:
- Dec 6, 2021, 12:13:26 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
-
ChangeLog (modified) (1 diff)
-
layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp (modified) (5 diffs)
-
layout/formattingContexts/inline/display/InlineDisplayBox.h (modified) (5 diffs)
-
layout/integration/InlineIteratorBoxModernPath.h (modified) (5 diffs)
-
layout/integration/InlineIteratorTextBox.h (modified) (2 diffs)
-
layout/integration/LayoutIntegrationPagination.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r286538 r286541 1 2021-12-06 Antti Koivisto <antti@apple.com> 2 3 [LFC][Integration] Use end bits in text box iterator 4 https://bugs.webkit.org/show_bug.cgi?id=233858 5 6 Reviewed by Alan Bujtas. 7 8 Make text box traversal work correctly in bidi context where encountering a different 9 layout box does not necessarily mean there are no further text boxes for the layout box. 10 11 * layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp: 12 (WebCore::Layout::InlineDisplayContentBuilder::processBidiContent): 13 (WebCore::Layout::InlineDisplayContentBuilder::computeIsFirstIsLastBoxForInlineContent): 14 15 Set the bits for all box types. 16 17 * layout/formattingContexts/inline/display/InlineDisplayBox.h: 18 (WebCore::InlineDisplay::Box::Box): 19 (WebCore::InlineDisplay::Box::isTextOrSoftLineBreak const): 20 (WebCore::InlineDisplay::Box::isFirstForLayoutBox const): 21 (WebCore::InlineDisplay::Box::isLastForLayoutBox const): 22 (WebCore::InlineDisplay::Box::setIsFirstForLayoutBox): 23 (WebCore::InlineDisplay::Box::setIsLastForLayoutBox): 24 (WebCore::InlineDisplay::Box::isFirstBox const): Deleted. 25 (WebCore::InlineDisplay::Box::isLastBox const): Deleted. 26 (WebCore::InlineDisplay::Box::setIsLastBox): Deleted. 27 (WebCore::InlineDisplay::Box::setIsFirstBox): Deleted. 28 29 Renamed for clarity and correctness. 30 31 * layout/integration/InlineIteratorBoxModernPath.h: 32 (WebCore::InlineIterator::BoxModernPath::isText const): 33 (WebCore::InlineIterator::BoxModernPath::traverseNextTextBox): 34 35 Use the isLastForLayoutBox bit to end the traversal. 36 37 (WebCore::InlineIterator::BoxModernPath::traverseNextInlineBox): 38 (WebCore::InlineIterator::BoxModernPath::traversePreviousInlineBox): 39 (WebCore::InlineIterator::BoxModernPath::traverseNextWithSameLayoutBox): 40 (WebCore::InlineIterator::BoxModernPath::traversePreviousWithSameLayoutBox): 41 42 Factor into helpers. 43 44 * layout/integration/InlineIteratorTextBox.h: 45 1 46 2021-12-05 Said Abou-Hallawa <said@apple.com> 2 47 -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp
r286534 r286541 479 479 auto isFirstFragment = !lastDisplayBoxForInlineBoxIndex; 480 480 if (!isFirstFragment) 481 boxes[lastDisplayBoxForInlineBoxIndex].setIsLast Box(false);481 boxes[lastDisplayBoxForInlineBoxIndex].setIsLastForLayoutBox(false); 482 482 inlineBoxDisplayBoxMap.set(inlineBox, index); 483 483 … … 535 535 auto& boxGeometry = formattingState().boxGeometry(inlineBoxDisplayBox.layoutBox()); 536 536 auto contentRight = displayBox.logicalRight(); 537 if (inlineBoxDisplayBox.isLast Box()) {537 if (inlineBoxDisplayBox.isLastForLayoutBox()) { 538 538 accumulatedOffset += boxGeometry.borderAndPaddingEnd() + boxGeometry.marginEnd(); 539 539 inlineBoxDisplayBox.setLogicalRight(contentRight + boxGeometry.borderAndPaddingEnd()); … … 541 541 inlineBoxDisplayBox.setLogicalRight(contentRight); 542 542 } 543 if (displayBox.isNonRootInlineBox() && displayBox.isFirst Box()) {543 if (displayBox.isNonRootInlineBox() && displayBox.isFirstForLayoutBox()) { 544 544 auto& layoutBox = displayBox.layoutBox(); 545 545 auto& boxGeometry = formattingState().boxGeometry(layoutBox); … … 557 557 for (auto& inlineBoxRange : inlineBoxRangeList) { 558 558 auto& inlineBoxDisplayBox = boxes[inlineBoxRange.begin()]; 559 setInlineBoxGeometry(inlineBoxDisplayBox.layoutBox(), inlineBoxDisplayBox.logicalRect(), inlineBoxDisplayBox.isFirst Box());559 setInlineBoxGeometry(inlineBoxDisplayBox.layoutBox(), inlineBoxDisplayBox.logicalRect(), inlineBoxDisplayBox.isFirstForLayoutBox()); 560 560 } 561 561 }; … … 654 654 void InlineDisplayContentBuilder::computeIsFirstIsLastBoxForInlineContent(DisplayBoxes& boxes) 655 655 { 656 HashMap<const Box*, size_t> lastDisplayBoxForInlineTextBoxIndexes; 656 HashMap<const Box*, size_t> lastDisplayBoxForLayoutBoxIndexes; 657 657 658 ASSERT(boxes[0].isRootInlineBox()); 659 boxes[0].setIsFirstForLayoutBox(true); 660 size_t lastRootInlineBoxIndex = 0; 661 658 662 for (size_t index = 1; index < boxes.size(); ++index) { 659 663 auto& displayBox = boxes[index]; 660 // FIXME: Transition the inline box isFirst/isLast computation here as well. 661 if (!displayBox.isText()) 662 continue; 664 if (displayBox.isRootInlineBox()) { 665 lastRootInlineBoxIndex = index; 666 continue; 667 } 663 668 auto& layoutBox = displayBox.layoutBox(); 664 if (!lastDisplayBoxForInlineTextBoxIndexes.contains(&layoutBox)) 665 displayBox.setIsFirstBox(true); 666 lastDisplayBoxForInlineTextBoxIndexes.set(&layoutBox, index); 667 } 668 for (auto lastDisplayBoxForInlineTextBoxIndex : lastDisplayBoxForInlineTextBoxIndexes) 669 boxes[lastDisplayBoxForInlineTextBoxIndex.value].setIsLastBox(true); 669 if (lastDisplayBoxForLayoutBoxIndexes.set(&layoutBox, index).isNewEntry) 670 displayBox.setIsFirstForLayoutBox(true); 671 } 672 for (auto index : lastDisplayBoxForLayoutBoxIndexes.values()) 673 boxes[index].setIsLastForLayoutBox(true); 674 675 boxes[lastRootInlineBoxIndex].setIsLastForLayoutBox(true); 670 676 } 671 677 -
trunk/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h
r286534 r286541 75 75 Last = 1 << 1 76 76 }; 77 Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const Layout::InlineRect&, const Layout::InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, OptionSet<PositionWithinInlineLevelBox> = { PositionWithinInlineLevelBox::First, PositionWithinInlineLevelBox::Last});77 Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const Layout::InlineRect&, const Layout::InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, OptionSet<PositionWithinInlineLevelBox> = { }); 78 78 79 79 bool isText() const { return m_type == Type::Text; } 80 80 bool isEllipsis() const { return m_type == Type::Ellipsis; } 81 81 bool isSoftLineBreak() const { return m_type == Type::SoftLineBreak; } 82 bool isTextOrSoftLineBreak() const { return isText() || isSoftLineBreak(); } 82 83 bool isLineBreakBox() const { return m_type == Type::LineBreakBox; } 83 84 bool isLineBreak() const { return isSoftLineBreak() || isLineBreakBox(); } … … 106 107 Layout::InlineLayoutUnit logicalHeight() const { return logicalRect().height(); } 107 108 108 void moveVertically(Layout::InlineLayoutUnit offset) { m_logicalRect.moveVertically(offset); } 109 void moveHorizontally(Layout::InlineLayoutUnit offset) { m_logicalRect.moveHorizontally(offset); } 109 void moveVertically(Layout::InlineLayoutUnit offset) 110 { 111 m_logicalRect.moveVertically(offset); 112 m_inkOverflow.moveVertically(offset); 113 } 114 void moveHorizontally(Layout::InlineLayoutUnit offset) 115 { 116 m_logicalRect.moveHorizontally(offset); 117 m_inkOverflow.moveHorizontally(offset); 118 } 110 119 void adjustInkOverflow(const Layout::InlineRect& childBorderBox) { return m_inkOverflow.expandToContain(childBorderBox); } 111 120 void truncate(Layout::InlineLayoutUnit truncatedwidth = 0.f); … … 127 136 // These functions tell you whether this display box is the first/last for the associated inline level box (Layout::Box) and not whether it's the first/last box on the line. 128 137 // (e.g. always true for atomic boxes, but inline boxes spanning over multiple lines can produce individual first/last boxes). 129 bool isFirst Box() const { return m_isFirstWithinInlineLevelBox; }130 bool isLast Box() const { return m_isLastWithinInlineLevelBox; }138 bool isFirstForLayoutBox() const { return m_isFirstForLayoutBox; } 139 bool isLastForLayoutBox() const { return m_isLastForLayoutBox; } 131 140 132 void setIs LastBox(bool isLastBox) { m_isLastWithinInlineLevelBox = isLastBox; }133 void setIs FirstBox(bool isFirstBox) { m_isFirstWithinInlineLevelBox = isFirstBox; }141 void setIsFirstForLayoutBox(bool isFirstBox) { m_isFirstForLayoutBox = isFirstBox; } 142 void setIsLastForLayoutBox(bool isLastBox) { m_isLastForLayoutBox = isLastBox; } 134 143 135 144 private: … … 141 150 Layout::InlineRect m_inkOverflow; 142 151 bool m_hasContent : 1; 143 bool m_isFirst WithinInlineLevelBox : 1;144 bool m_isLast WithinInlineLevelBox : 1;152 bool m_isFirstForLayoutBox : 1; 153 bool m_isLastForLayoutBox : 1; 145 154 Expansion m_expansion; 146 155 std::optional<Text> m_text; … … 155 164 , m_inkOverflow(inkOverflow) 156 165 , m_hasContent(hasContent) 157 , m_isFirst WithinInlineLevelBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::First))158 , m_isLast WithinInlineLevelBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::Last))166 , m_isFirstForLayoutBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::First)) 167 , m_isLastForLayoutBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::Last)) 159 168 , m_expansion(expansion) 160 169 , m_text(text) -
trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h
r286113 r286541 49 49 } 50 50 51 bool isText() const { return !!box().text(); }51 bool isText() const { return box().isTextOrSoftLineBreak(); } 52 52 bool isInlineBox() const { return box().isInlineBox(); } 53 53 bool isRootInlineBox() const { return box().isRootInlineBox(); } … … 107 107 { 108 108 ASSERT(!atEnd()); 109 ASSERT(box().text()); 110 111 auto& layoutBox = box().layoutBox(); 109 ASSERT(box().isTextOrSoftLineBreak()); 110 111 if (box().isLastForLayoutBox()) { 112 setAtEnd(); 113 return; 114 } 115 116 traverseNextWithSameLayoutBox(); 117 118 ASSERT(box().isTextOrSoftLineBreak()); 119 } 120 121 void traverseNextOnLine() 122 { 123 ASSERT(!atEnd()); 124 125 auto oldLineIndex = box().lineIndex(); 112 126 113 127 traverseNextLeaf(); 114 128 115 if (!atEnd() && &layoutBox != &box().layoutBox()) 116 setAtEnd(); 117 118 ASSERT(atEnd() || box().text()); 119 } 120 121 void traverseNextOnLine() 129 if (!atEnd() && oldLineIndex != box().lineIndex()) 130 setAtEnd(); 131 } 132 133 void traversePreviousOnLine() 122 134 { 123 135 ASSERT(!atEnd()); … … 125 137 auto oldLineIndex = box().lineIndex(); 126 138 127 traverse NextLeaf();139 traversePreviousLeaf(); 128 140 129 141 if (!atEnd() && oldLineIndex != box().lineIndex()) … … 131 143 } 132 144 133 void traversePreviousOnLine()134 {135 ASSERT(!atEnd());136 137 auto oldLineIndex = box().lineIndex();138 139 traversePreviousLeaf();140 141 if (!atEnd() && oldLineIndex != box().lineIndex())142 setAtEnd();143 }144 145 145 void traverseNextInlineBox() 146 146 { 147 ASSERT(box().isInlineBox()); 148 149 if (box().isLastBox()) { 147 ASSERT(!atEnd()); 148 ASSERT(box().isInlineBox()); 149 150 if (box().isLastForLayoutBox()) { 150 151 setAtEnd(); 151 152 return; 152 153 } 153 154 154 auto& layoutBox = box().layoutBox(); 155 do { 156 traverseNextBox(); 157 } while (!atEnd() && &box().layoutBox() != &layoutBox); 158 159 ASSERT(atEnd() || box().isInlineBox()); 155 traverseNextWithSameLayoutBox(); 156 157 ASSERT(box().isInlineBox()); 160 158 } 161 159 162 160 void traversePreviousInlineBox() 163 161 { 164 ASSERT(box().isInlineBox()); 165 166 if (box().isFirstBox()) { 162 ASSERT(!atEnd()); 163 ASSERT(box().isInlineBox()); 164 165 if (box().isFirstForLayoutBox()) { 167 166 setAtEnd(); 168 167 return; 169 168 } 170 169 171 auto& layoutBox = box().layoutBox(); 172 do { 173 traversePreviousBox(); 174 } while (!atEnd() && &box().layoutBox() != &layoutBox); 175 176 ASSERT(atEnd() || box().isInlineBox()); 170 traversePreviousWithSameLayoutBox(); 171 172 ASSERT(box().isInlineBox()); 177 173 } 178 174 … … 250 246 } 251 247 248 void traverseNextWithSameLayoutBox() 249 { 250 auto& layoutBox = box().layoutBox(); 251 do { 252 traverseNextBox(); 253 } while (!atEnd() && &box().layoutBox() != &layoutBox); 254 } 255 256 void traversePreviousWithSameLayoutBox() 257 { 258 auto& layoutBox = box().layoutBox(); 259 do { 260 traversePreviousBox(); 261 } while (!atEnd() && &box().layoutBox() != &layoutBox); 262 } 263 252 264 void setAtEnd() { m_boxIndex = boxes().size(); } 253 265 -
trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h
r285938 r286541 60 60 const LegacyInlineTextBox* legacyInlineBox() const { return downcast<LegacyInlineTextBox>(Box::legacyInlineBox()); } 61 61 62 // This returns the next text box generated for the same RenderText/Layout::InlineTextBox. 62 63 TextBoxIterator nextTextBox() const; 63 TextBoxIterator previousTextBox() const;64 64 }; 65 65 … … 75 75 const TextBox* operator->() const { return &get(); } 76 76 77 // This traverses to the next text box generated for the same RenderText/Layout::InlineTextBox. 77 78 TextBoxIterator& traverseNextTextBox(); 78 79 -
trunk/Source/WebCore/layout/integration/LayoutIntegrationPagination.cpp
r285083 r286541 143 143 auto adjustedBox = [&](const InlineDisplay::Box& box, float offset) 144 144 { 145 return InlineDisplay::Box { 146 box.lineIndex(), 147 box.type(), 148 box.layoutBox(), 149 box.bidiLevel(), 150 moveVertically(box.logicalRect(), offset), 151 moveVertically(box.inkOverflow(), offset), 152 box.expansion(), 153 box.text() 154 }; 145 auto adjustedBox = box; 146 adjustedBox.moveVertically(offset); 147 return adjustedBox; 155 148 }; 156 149
Note:
See TracChangeset
for help on using the changeset viewer.