Changeset 286782 in webkit
- Timestamp:
- Dec 9, 2021, 9:10:03 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp (modified) (8 diffs)
-
layout/formattingContexts/inline/InlineDisplayContentBuilder.h (modified) (2 diffs)
-
layout/formattingContexts/inline/InlineRect.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r286780 r286782 1 2021-12-09 Alan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Make collectInkOverflowForInlineBoxes propagate ink overflow using the display box list 4 https://bugs.webkit.org/show_bug.cgi?id=233950 5 6 Reviewed by Antti Koivisto. 7 8 This is in preparation for supporting ink overflow across bidi boundaries. 9 10 The current HashMap<const Box*, size_t> approach does not work when a layout box could 11 produce multiple inline box type of display boxes on the same line (at bidi boundaries). 12 Instead let's propagate ink overflow by traversing the display box list starting 13 at the end and bubble up the inflated ink overflow rect to the parent inline boxes. 14 15 * layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp: 16 (WebCore::Layout::InlineDisplayContentBuilder::build): 17 (WebCore::Layout::computeBoxShadowInkOverflow): 18 (WebCore::Layout::InlineDisplayContentBuilder::appendAtomicInlineLevelDisplayBox): 19 (WebCore::Layout::InlineDisplayContentBuilder::appendInlineBoxDisplayBox): 20 (WebCore::Layout::InlineDisplayContentBuilder::appendSpanningInlineBoxDisplayBox): 21 (WebCore::Layout::InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes): 22 (WebCore::Layout::addBoxShadowInkOverflow): Deleted. 23 * layout/formattingContexts/inline/InlineDisplayContentBuilder.h: 24 1 25 2021-12-09 Tyler Wilcock <tyler_w@apple.com> 2 26 -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp
r286541 r286782 75 75 processNonBidiContent(lineContent, lineBox, lineBoxLogicalRect.topLeft(), boxes); 76 76 processOverflownRunsForEllipsis(boxes, lineBoxLogicalRect.right()); 77 collectInkOverflowForInlineBoxes( lineBox,boxes);77 collectInkOverflowForInlineBoxes(boxes); 78 78 return boxes; 79 79 } 80 80 81 static inline void addBoxShadowInkOverflow(const RenderStyle& style, InlineRect& inkOverflow)81 static inline bool computeBoxShadowInkOverflow(const RenderStyle& style, InlineRect& inkOverflow) 82 82 { 83 83 auto topBoxShadow = LayoutUnit { }; … … 88 88 auto rightBoxShadow = LayoutUnit { }; 89 89 style.getBoxShadowInlineDirectionExtent(leftBoxShadow, rightBoxShadow); 90 if (!topBoxShadow && !bottomBoxShadow && !leftBoxShadow && !rightBoxShadow) 91 return false; 90 92 inkOverflow.inflate(InlineLayoutUnit { topBoxShadow }, InlineLayoutUnit { rightBoxShadow }, InlineLayoutUnit { bottomBoxShadow }, InlineLayoutUnit { leftBoxShadow }); 93 return true; 91 94 } 92 95 … … 169 172 170 173 auto& layoutBox = lineRun.layoutBox(); 171 // FIXME: Add ink overflow support for atomic inline level boxes (e.g. box shadow). 174 auto inkOverflow = [&] { 175 auto inkOverflow = borderBoxRect; 176 computeBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow); 177 // Atomic inline box contribute to their inline box parents ink overflow at all times (e.g. <span><img></span>). 178 m_contentHasInkOverflow = m_contentHasInkOverflow || &layoutBox.parent() != &root(); 179 return inkOverflow; 180 }; 172 181 boxes.append({ m_lineIndex 173 182 , InlineDisplay::Box::Type::AtomicInlineLevelBox … … 175 184 , lineRun.bidiLevel() 176 185 , borderBoxRect 177 , borderBoxRect186 , inkOverflow() 178 187 , lineRun.expansion() 179 188 , { } }); 180 181 189 // Note that inline boxes are relative to the line and their top position can be negative. 182 190 // Atomic inline boxes are all set. Their margin/border/content box geometries are already computed. We just have to position them here. 183 auto& boxGeometry = formattingState().boxGeometry(layoutBox); 184 boxGeometry.setLogicalTopLeft(toLayoutPoint(borderBoxRect.topLeft())); 185 186 auto adjustParentInlineBoxInkOverflow = [&] { 187 auto& parentInlineBox = layoutBox.parent(); 188 if (&parentInlineBox == &root()) { 189 // We don't collect ink overflow for the root inline box. 190 return; 191 } 192 RELEASE_ASSERT(m_inlineBoxIndexMap.contains(&parentInlineBox)); 193 194 auto boxInkOverflow = borderBoxRect; 195 addBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), boxInkOverflow); 196 boxes[m_inlineBoxIndexMap.get(&parentInlineBox)].adjustInkOverflow(boxInkOverflow); 197 }; 198 adjustParentInlineBoxInkOverflow(); 191 formattingState().boxGeometry(layoutBox).setLogicalTopLeft(toLayoutPoint(borderBoxRect.topLeft())); 199 192 } 200 193 … … 221 214 222 215 auto& layoutBox = lineRun.layoutBox(); 223 if (linehasContent) { 224 auto inkOverflow = [&] { 225 auto inkOverflow = inlineBoxBorderBox; 226 addBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow); 227 return inkOverflow; 228 }; 216 217 if (!linehasContent) { 229 218 // FIXME: It's expected to not have any boxes on empty lines. We should reconsider this. 230 m_inlineBoxIndexMap.add(&layoutBox, boxes.size()); 231 232 ASSERT(inlineBox.isInlineBox()); 233 ASSERT(inlineBox.isFirstBox()); 234 boxes.append({ m_lineIndex 235 , InlineDisplay::Box::Type::NonRootInlineBox 236 , layoutBox 237 , lineRun.bidiLevel() 238 , inlineBoxBorderBox 239 , inkOverflow() 240 , { } 241 , { } 242 , inlineBox.hasContent() 243 , isFirstLastBox(inlineBox) }); 219 setInlineBoxGeometry(layoutBox, inlineBoxBorderBox, true); 220 return; 244 221 } 245 222 223 auto inkOverflow = [&] { 224 auto inkOverflow = inlineBoxBorderBox; 225 m_contentHasInkOverflow = computeBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow) || m_contentHasInkOverflow; 226 return inkOverflow; 227 }; 228 ASSERT(inlineBox.isInlineBox()); 229 ASSERT(inlineBox.isFirstBox()); 230 boxes.append({ m_lineIndex 231 , InlineDisplay::Box::Type::NonRootInlineBox 232 , layoutBox 233 , lineRun.bidiLevel() 234 , inlineBoxBorderBox 235 , inkOverflow() 236 , { } 237 , { } 238 , inlineBox.hasContent() 239 , isFirstLastBox(inlineBox) }); 246 240 // This inline box showed up first on this line. 247 241 setInlineBoxGeometry(layoutBox, inlineBoxBorderBox, true); … … 253 247 254 248 auto& layoutBox = lineRun.layoutBox(); 255 m_inlineBoxIndexMap.add(&layoutBox, boxes.size());256 257 249 auto inkOverflow = [&] { 258 250 auto inkOverflow = inlineBoxBorderBox; 259 addBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow);251 m_contentHasInkOverflow = computeBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow) || m_contentHasInkOverflow; 260 252 return inkOverflow; 261 253 }; … … 271 263 , inlineBox.hasContent() 272 264 , isFirstLastBox(inlineBox) }); 273 274 265 // Middle or end of the inline box. Let's stretch the box as needed. 275 266 setInlineBoxGeometry(layoutBox, inlineBoxBorderBox, false); … … 628 619 } 629 620 630 void InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes(const LineBox& lineBox, DisplayBoxes& boxes) 631 { 632 if (m_inlineBoxIndexMap.isEmpty() || !lineBox.hasContent()) { 633 // This line has no inline box (only root, but we don't collect ink overflow for the root inline box atm) 621 void InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes(DisplayBoxes& boxes) 622 { 623 if (!m_contentHasInkOverflow) 634 624 return; 635 }636 637 auto& nonRootInlineLevelBoxes = lineBox.nonRootInlineLevelBoxes();638 625 // Visit the inline boxes and propagate ink overflow to their parents -except to the root inline box. 639 626 // (e.g. <span style="font-size: 10px;">Small font size<span style="font-size: 300px;">Larger font size. This overflows the top most span.</span></span>). 640 for (size_t index = nonRootInlineLevelBoxes.size(); index--;) { 641 if (!nonRootInlineLevelBoxes[index].isInlineBox()) 642 continue; 643 auto& inlineBox = nonRootInlineLevelBoxes[index].layoutBox(); 644 auto& parentInlineBox = inlineBox.parent(); 645 if (&parentInlineBox == &root()) 646 continue; 647 RELEASE_ASSERT(m_inlineBoxIndexMap.contains(&inlineBox) && m_inlineBoxIndexMap.contains(&parentInlineBox)); 648 auto& inkOverflow = boxes[m_inlineBoxIndexMap.get(&inlineBox)].inkOverflow(); 649 auto& parentDisplayBox = boxes[m_inlineBoxIndexMap.get(&parentInlineBox)]; 650 parentDisplayBox.adjustInkOverflow(inkOverflow); 627 auto accumulatedInkOverflowRect = InlineRect { { }, { } }; 628 for (size_t index = boxes.size(); index--;) { 629 auto& displayBox = boxes[index]; 630 631 auto mayHaveInkOverflow = displayBox.isAtomicInlineLevelBox() || displayBox.isGenericInlineLevelBox() || displayBox.isNonRootInlineBox(); 632 if (!mayHaveInkOverflow) 633 continue; 634 if (displayBox.isNonRootInlineBox() && !accumulatedInkOverflowRect.isEmpty()) 635 displayBox.adjustInkOverflow(accumulatedInkOverflowRect); 636 637 // We stop collecting ink overflow for at root inline box (i.e. don't inflate the root inline box with the inline content here). 638 auto parentBoxIsRoot = &displayBox.layoutBox().parent() == &root(); 639 if (parentBoxIsRoot) 640 accumulatedInkOverflowRect = InlineRect { { }, { } }; 641 else if (accumulatedInkOverflowRect.isEmpty()) 642 accumulatedInkOverflowRect = displayBox.inkOverflow(); 643 else 644 accumulatedInkOverflowRect.expandToContain(displayBox.inkOverflow()); 651 645 } 652 646 } -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.h
r286534 r286782 50 50 void processBidiContent(const LineBuilder::LineContent&, const LineBox&, const InlineLayoutPoint& lineBoxLogicalTopLeft, DisplayBoxes&); 51 51 void processOverflownRunsForEllipsis(DisplayBoxes&, InlineLayoutUnit lineBoxLogicalRight); 52 void collectInkOverflowForInlineBoxes( const LineBox&,DisplayBoxes&);52 void collectInkOverflowForInlineBoxes(DisplayBoxes&); 53 53 54 54 void appendTextDisplayBox(const Line::Run&, const InlineRect&, DisplayBoxes&); … … 68 68 const ContainerBox& m_formattingContextRoot; 69 69 InlineFormattingState& m_formattingState; 70 HashMap<const Box*, size_t> m_inlineBoxIndexMap;71 70 size_t m_lineIndex { 0 }; 71 bool m_contentHasInkOverflow { false }; 72 72 }; 73 73 -
trunk/Source/WebCore/layout/formattingContexts/inline/InlineRect.h
r286178 r286782 72 72 void inflate(InlineLayoutUnit top, InlineLayoutUnit right, InlineLayoutUnit bottom, InlineLayoutUnit left); 73 73 74 bool isEmpty() const; 75 74 76 operator InlineLayoutRect() const; 75 77 … … 309 311 } 310 312 313 inline bool InlineRect::isEmpty() const 314 { 315 ASSERT(hasValidGeometry()); 316 return m_rect.isEmpty(); 317 } 318 311 319 inline InlineRect::operator InlineLayoutRect() const 312 320 {
Note:
See TracChangeset
for help on using the changeset viewer.