Changeset 246114 in webkit
- Timestamp:
- Jun 5, 2019, 10:34:20 AM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
layout/inlineformatting/InlineFormattingContext.h (modified) (1 diff)
-
layout/inlineformatting/InlineFormattingContextLineLayout.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r246108 r246114 1 2019-06-05 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] LineLayout::placeInlineItems should not apply float contraint. 4 https://bugs.webkit.org/show_bug.cgi?id=198565 5 <rdar://problem/51440718> 6 7 Reviewed by Antti Koivisto. 8 9 This patch moves float constraint handling from placeInlineItems() to LineLayout::layout(). 10 When placeInlineItems() is called by the preferred width computation, intruding floats should be ignored 11 since they don't constrain the "min/max lines". 12 13 * layout/inlineformatting/InlineFormattingContext.h: 14 * layout/inlineformatting/InlineFormattingContextLineLayout.cpp: 15 (WebCore::Layout::InlineFormattingContext::LineLayout::LineInput::HorizontalConstraint::HorizontalConstraint): 16 (WebCore::Layout::InlineFormattingContext::LineLayout::LineInput::LineInput): 17 (WebCore::Layout::InlineFormattingContext::LineLayout::placeInlineItems const): 18 (WebCore::Layout::InlineFormattingContext::LineLayout::layout const): 19 (WebCore::Layout::constructLine): Deleted. 20 1 21 2019-06-05 Truitt Savell <tsavell@apple.com> 2 22 -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h
r246067 r246114 67 67 68 68 struct LineInput { 69 LineInput(LayoutUnit logicalTop, LayoutUnit availableLogicalWidth, unsigned firstInlineItemIndex, const InlineItems&); 69 LineInput(LayoutPoint logicalTopLeft, LayoutUnit availableLogicalWidth, unsigned firstInlineItemIndex, const InlineItems&); 70 struct HorizontalConstraint { 71 HorizontalConstraint(LayoutPoint logicalTopLeft, LayoutUnit availableLogicalWidth); 70 72 71 LayoutUnit logicalTop; 72 LayoutUnit availableLogicalWidth; 73 LayoutPoint logicalTopLeft; 74 LayoutUnit availableLogicalWidth; 75 }; 76 HorizontalConstraint horizontalConstraint; 73 77 unsigned firstInlineItemIndex { 0 }; 74 78 const InlineItems& inlineItems; -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp
r246105 r246114 73 73 } 74 74 75 InlineFormattingContext::LineLayout::LineInput:: LineInput(LayoutUnit logicalTop, LayoutUnit availableLogicalWidth, unsigned firstInlineItemIndex, const InlineItems& inlineItems)76 : logicalTop (logicalTop)75 InlineFormattingContext::LineLayout::LineInput::HorizontalConstraint::HorizontalConstraint(LayoutPoint logicalTopLeft, LayoutUnit availableLogicalWidth) 76 : logicalTopLeft(logicalTopLeft) 77 77 , availableLogicalWidth(availableLogicalWidth) 78 { 79 } 80 81 InlineFormattingContext::LineLayout::LineInput::LineInput(LayoutPoint logicalTopLeft, LayoutUnit availableLogicalWidth, unsigned firstInlineItemIndex, const InlineItems& inlineItems) 82 : horizontalConstraint(logicalTopLeft, availableLogicalWidth) 78 83 , firstInlineItemIndex(firstInlineItemIndex) 79 84 , inlineItems(inlineItems) … … 143 148 } 144 149 145 static std::unique_ptr<Line> constructLine(const LayoutState& layoutState, const FloatingState& floatingState, const Box& formattingRoot, 146 LayoutUnit lineLogicalTop, LayoutUnit availableWidth) 147 { 148 auto& formattingRootDisplayBox = layoutState.displayBoxForLayoutBox(formattingRoot); 150 InlineFormattingContext::LineLayout::LineContent InlineFormattingContext::LineLayout::placeInlineItems(const LineInput& lineInput) const 151 { 152 auto mimimumLineHeight = m_formattingRoot.style().computedLineHeight(); 153 auto baselineOffset = Line::halfLeadingMetrics(m_formattingRoot.style().fontMetrics(), mimimumLineHeight).height; 154 auto line = Line { layoutState(), lineInput.horizontalConstraint.logicalTopLeft, lineInput.horizontalConstraint.availableLogicalWidth, mimimumLineHeight, baselineOffset }; 155 156 Vector<WeakPtr<InlineItem>> floats; 157 unsigned committedInlineItemCount = 0; 158 159 UncommittedContent uncommittedContent; 160 auto commitPendingContent = [&] { 161 if (uncommittedContent.isEmpty()) 162 return; 163 committedInlineItemCount += uncommittedContent.size(); 164 for (auto& uncommittedRun : uncommittedContent.runs()) { 165 auto& inlineItem = uncommittedRun.inlineItem; 166 if (inlineItem.isHardLineBreak()) 167 line.appendHardLineBreak(inlineItem); 168 else if (is<InlineTextItem>(inlineItem)) 169 line.appendTextContent(downcast<InlineTextItem>(inlineItem), uncommittedRun.size); 170 else if (inlineItem.isContainerStart()) 171 line.appendInlineContainerStart(inlineItem, uncommittedRun.size); 172 else if (inlineItem.isContainerEnd()) 173 line.appendInlineContainerEnd(inlineItem, uncommittedRun.size); 174 else if (inlineItem.layoutBox().isReplaced()) 175 line.appendReplacedInlineBox(inlineItem, uncommittedRun.size); 176 else 177 line.appendNonReplacedInlineBox(inlineItem, uncommittedRun.size); 178 } 179 uncommittedContent.reset(); 180 }; 181 182 auto closeLine = [&] { 183 // This might change at some point. 184 ASSERT(committedInlineItemCount); 185 return LineContent { lineInput.firstInlineItemIndex + (committedInlineItemCount - 1), WTFMove(floats), line.close() }; 186 }; 187 LineBreaker lineBreaker; 188 // Iterate through the inline content and place the inline boxes on the current line. 189 for (auto inlineItemIndex = lineInput.firstInlineItemIndex; inlineItemIndex < lineInput.inlineItems.size(); ++inlineItemIndex) { 190 auto availableWidth = line.availableWidth() - uncommittedContent.width(); 191 auto currentLogicalRight = line.contentLogicalRight() + uncommittedContent.width(); 192 auto& inlineItem = lineInput.inlineItems[inlineItemIndex]; 193 auto itemLogicalWidth = inlineItemWidth(layoutState(), *inlineItem, currentLogicalRight); 194 195 // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed. 196 auto breakingContext = lineBreaker.breakingContext(*inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, line.trailingTrimmableWidth(), !line.hasContent() }); 197 if (breakingContext.isAtBreakingOpportunity) 198 commitPendingContent(); 199 200 // Content does not fit the current line. 201 if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap) 202 return closeLine(); 203 204 // Partial content stays on the current line. 205 if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Split) { 206 ASSERT(inlineItem->isText()); 207 208 ASSERT_NOT_IMPLEMENTED_YET(); 209 return closeLine(); 210 } 211 212 ASSERT(breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Keep); 213 if (inlineItem->isFloat()) { 214 auto& floatBox = inlineItem->layoutBox(); 215 ASSERT(layoutState().hasDisplayBox(floatBox)); 216 // Shrink availble space for current line and move existing inline runs. 217 auto floatBoxWidth = layoutState().displayBoxForLayoutBox(floatBox).marginBoxWidth(); 218 floatBox.isLeftFloatingPositioned() ? line.moveLogicalLeft(floatBoxWidth) : line.moveLogicalRight(floatBoxWidth); 219 floats.append(makeWeakPtr(*inlineItem)); 220 ++committedInlineItemCount; 221 continue; 222 } 223 if (inlineItem->isHardLineBreak()) { 224 uncommittedContent.add(*inlineItem, { itemLogicalWidth, inlineItemHeight(layoutState(), *inlineItem) }); 225 commitPendingContent(); 226 return closeLine(); 227 } 228 229 uncommittedContent.add(*inlineItem, { itemLogicalWidth, inlineItemHeight(layoutState(), *inlineItem) }); 230 if (breakingContext.isAtBreakingOpportunity) 231 commitPendingContent(); 232 } 233 commitPendingContent(); 234 return closeLine(); 235 } 236 237 void InlineFormattingContext::LineLayout::layout(LayoutUnit widthConstraint) const 238 { 239 ASSERT(!m_formattingState.inlineItems().isEmpty()); 240 241 auto& formattingRootDisplayBox = layoutState().displayBoxForLayoutBox(m_formattingRoot); 242 auto lineLogicalTop = formattingRootDisplayBox.contentBoxTop(); 149 243 auto lineLogicalLeft = formattingRootDisplayBox.contentBoxLeft(); 150 244 151 // Check for intruding floats and adjust logical left/available width for this line accordingly. 152 if (!floatingState.isEmpty()) { 153 auto floatConstraints = floatingState.constraints({ lineLogicalTop }, formattingRoot); 245 auto applyFloatConstraint = [&](auto& lineHorizontalConstraint) { 246 // Check for intruding floats and adjust logical left/available width for this line accordingly. 247 if (m_floatingState.isEmpty()) 248 return; 249 auto availableWidth = lineHorizontalConstraint.availableLogicalWidth; 250 auto lineLogicalLeft = lineHorizontalConstraint.logicalTopLeft.x(); 251 auto floatConstraints = m_floatingState.constraints({ lineLogicalTop }, m_formattingRoot); 154 252 // Check if these constraints actually put limitation on the line. 155 253 if (floatConstraints.left && *floatConstraints.left <= formattingRootDisplayBox.contentBoxLeft()) … … 171 269 availableWidth = *floatConstraints.right - lineLogicalLeft; 172 270 } 173 } 174 175 auto& formattingRootStyle = formattingRoot.style(); 176 auto mimimumLineHeight = formattingRootStyle.computedLineHeight(); 177 auto baselineOffset = Line::halfLeadingMetrics(formattingRootStyle.fontMetrics(), mimimumLineHeight).height; 178 return std::make_unique<Line>(layoutState, LayoutPoint { lineLogicalLeft, lineLogicalTop }, availableWidth, mimimumLineHeight, baselineOffset); 179 } 180 181 InlineFormattingContext::LineLayout::LineContent InlineFormattingContext::LineLayout::placeInlineItems(const LineInput& lineInput) const 182 { 183 auto line = constructLine(layoutState(), m_floatingState, m_formattingRoot, lineInput.logicalTop, lineInput.availableLogicalWidth); 184 Vector<WeakPtr<InlineItem>> floats; 185 unsigned committedInlineItemCount = 0; 186 187 UncommittedContent uncommittedContent; 188 auto commitPendingContent = [&] { 189 if (uncommittedContent.isEmpty()) 190 return; 191 committedInlineItemCount += uncommittedContent.size(); 192 for (auto& uncommittedRun : uncommittedContent.runs()) { 193 auto& inlineItem = uncommittedRun.inlineItem; 194 if (inlineItem.isHardLineBreak()) 195 line->appendHardLineBreak(inlineItem); 196 else if (is<InlineTextItem>(inlineItem)) 197 line->appendTextContent(downcast<InlineTextItem>(inlineItem), uncommittedRun.size); 198 else if (inlineItem.isContainerStart()) 199 line->appendInlineContainerStart(inlineItem, uncommittedRun.size); 200 else if (inlineItem.isContainerEnd()) 201 line->appendInlineContainerEnd(inlineItem, uncommittedRun.size); 202 else if (inlineItem.layoutBox().isReplaced()) 203 line->appendReplacedInlineBox(inlineItem, uncommittedRun.size); 204 else 205 line->appendNonReplacedInlineBox(inlineItem, uncommittedRun.size); 206 } 207 uncommittedContent.reset(); 271 lineHorizontalConstraint.availableLogicalWidth = availableWidth; 272 lineHorizontalConstraint.logicalTopLeft.setX(lineLogicalLeft); 208 273 }; 209 274 210 auto closeLine = [&] {211 // This might change at some point.212 ASSERT(committedInlineItemCount);213 return LineContent { lineInput.firstInlineItemIndex + (committedInlineItemCount - 1), WTFMove(floats), line->close() };214 };215 LineBreaker lineBreaker;216 // Iterate through the inline content and place the inline boxes on the current line.217 for (auto inlineItemIndex = lineInput.firstInlineItemIndex; inlineItemIndex < lineInput.inlineItems.size(); ++inlineItemIndex) {218 auto availableWidth = line->availableWidth() - uncommittedContent.width();219 auto currentLogicalRight = line->contentLogicalRight() + uncommittedContent.width();220 auto& inlineItem = lineInput.inlineItems[inlineItemIndex];221 auto itemLogicalWidth = inlineItemWidth(layoutState(), *inlineItem, currentLogicalRight);222 223 // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed.224 auto breakingContext = lineBreaker.breakingContext(*inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, line->trailingTrimmableWidth(), !line->hasContent() });225 if (breakingContext.isAtBreakingOpportunity)226 commitPendingContent();227 228 // Content does not fit the current line.229 if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)230 return closeLine();231 232 // Partial content stays on the current line.233 if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Split) {234 ASSERT(inlineItem->isText());235 236 ASSERT_NOT_IMPLEMENTED_YET();237 return closeLine();238 }239 240 ASSERT(breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Keep);241 if (inlineItem->isFloat()) {242 auto& floatBox = inlineItem->layoutBox();243 ASSERT(layoutState().hasDisplayBox(floatBox));244 // Shrink availble space for current line and move existing inline runs.245 auto floatBoxWidth = layoutState().displayBoxForLayoutBox(floatBox).marginBoxWidth();246 floatBox.isLeftFloatingPositioned() ? line->moveLogicalLeft(floatBoxWidth) : line->moveLogicalRight(floatBoxWidth);247 floats.append(makeWeakPtr(*inlineItem));248 ++committedInlineItemCount;249 continue;250 }251 if (inlineItem->isHardLineBreak()) {252 uncommittedContent.add(*inlineItem, { itemLogicalWidth, inlineItemHeight(layoutState(), *inlineItem) });253 commitPendingContent();254 return closeLine();255 }256 257 uncommittedContent.add(*inlineItem, { itemLogicalWidth, inlineItemHeight(layoutState(), *inlineItem) });258 if (breakingContext.isAtBreakingOpportunity)259 commitPendingContent();260 }261 commitPendingContent();262 return closeLine();263 }264 265 void InlineFormattingContext::LineLayout::layout(LayoutUnit widthConstraint) const266 {267 ASSERT(!m_formattingState.inlineItems().isEmpty());268 269 auto lineLogicalTop = layoutState().displayBoxForLayoutBox(m_formattingRoot).contentBoxTop();270 275 auto& inlineItems = m_formattingState.inlineItems(); 271 276 unsigned currentInlineItemIndex = 0; 272 277 while (currentInlineItemIndex < inlineItems.size()) { 273 auto lineContent = placeInlineItems({ lineLogicalTop, widthConstraint, currentInlineItemIndex, inlineItems }); 278 auto lineInput = LineInput { { lineLogicalLeft, lineLogicalTop }, widthConstraint, currentInlineItemIndex, inlineItems }; 279 applyFloatConstraint(lineInput.horizontalConstraint); 280 auto lineContent = placeInlineItems(lineInput); 274 281 createDisplayRuns(*lineContent.runs, lineContent.floats, widthConstraint); 275 282 // We should always put at least one run on the line atm. This might change later on though.
Note:
See TracChangeset
for help on using the changeset viewer.