Changeset 267404 in webkit
- Timestamp:
- Sep 22, 2020, 6:34:07 AM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
layout/inlineformatting/InlineLineBreaker.cpp (modified) (23 diffs)
-
layout/inlineformatting/InlineLineBreaker.h (modified) (3 diffs)
-
layout/inlineformatting/InlineLineBuilder.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r267402 r267404 1 2020-09-22 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] TextUtil::split needs logical left 4 https://bugs.webkit.org/show_bug.cgi?id=216798 5 6 Reviewed by Antti Koivisto. 7 8 Measuring text content requires logical left offset (e.g. tab size depends on the logical position). 9 Let's pass in the current logical left position to TextUtil::split. 10 11 * layout/inlineformatting/InlineLineBreaker.cpp: 12 (WebCore::Layout::ContinuousContent::runs const): 13 (WebCore::Layout::ContinuousContent::isEmpty const): 14 (WebCore::Layout::ContinuousContent::logicalWidth const): 15 (WebCore::Layout::ContinuousContent::logicalLeft const): 16 (WebCore::Layout::ContinuousContent::nonCollapsibleLogicalWidth const): 17 (WebCore::Layout::LineBreaker::isContentWrappingAllowed const): 18 (WebCore::Layout::LineBreaker::shouldKeepEndOfLineWhitespace const): 19 (WebCore::Layout::LineBreaker::shouldWrapInlineContent): 20 (WebCore::Layout::LineBreaker::tryWrappingInlineContent const): 21 (WebCore::Layout::LineBreaker::wrapTextContent const): 22 (WebCore::Layout::LineBreaker::tryBreakingTextRun const): 23 (WebCore::Layout::ContinuousContent::ContinuousContent): 24 (WebCore::Layout::ContinuousContent::hasTextContentOnly const): 25 (WebCore::Layout::ContinuousContent::isVisuallyEmptyWhitespaceContentOnly const): 26 (WebCore::Layout::ContinuousContent::firstTextRunIndex const): 27 (WebCore::Layout::ContinuousContent::lastContentRunIndex const): 28 (WebCore::Layout::ContinuousContent::hasNonContentRunsOnly const): 29 (WebCore::Layout::ContinuousContent::size const): Deleted. 30 (WebCore::Layout::ContinuousContent::width const): Deleted. 31 (WebCore::Layout::ContinuousContent::nonCollapsibleWidth const): Deleted. 32 * layout/inlineformatting/InlineLineBreaker.h: 33 * layout/inlineformatting/InlineLineBuilder.cpp: 34 (WebCore::Layout::LineBuilder::handleFloatsAndInlineContent): 35 1 36 2020-09-22 Sam Weinig <weinig@apple.com> 2 37 -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp
r262796 r267404 64 64 65 65 struct ContinuousContent { 66 ContinuousContent(const LineBreaker:: RunList&, InlineLayoutUnit contentLogicalWidth);67 68 const LineBreaker::RunList& runs() const { return m_ runs; }69 bool isEmpty() const { return m_runs.isEmpty(); }66 ContinuousContent(const LineBreaker::CandidateContent&); 67 68 const LineBreaker::RunList& runs() const { return m_candidateContent.runs; } 69 bool isEmpty() const { return runs().isEmpty(); } 70 70 bool hasTextContentOnly() const; 71 71 bool isVisuallyEmptyWhitespaceContentOnly() const; 72 72 bool hasNonContentRunsOnly() const; 73 size_t size() const { return m_runs.size(); }74 InlineLayoutUnit width() const { return m_width; }75 InlineLayoutUnit nonCollapsible Width() const { return m_width- m_trailingCollapsibleContent.width; }73 InlineLayoutUnit logicalWidth() const { return m_candidateContent.logicalWidth; } 74 InlineLayoutUnit logicalLeft() const { return m_candidateContent.logicalLeft; } 75 InlineLayoutUnit nonCollapsibleLogicalWidth() const { return logicalWidth() - m_trailingCollapsibleContent.width; } 76 76 77 77 bool hasTrailingCollapsibleContent() const { return !!m_trailingCollapsibleContent.width; } … … 82 82 83 83 private: 84 const LineBreaker:: RunList& m_runs;84 const LineBreaker::CandidateContent& m_candidateContent; 85 85 struct TrailingCollapsibleContent { 86 86 void reset(); … … 90 90 }; 91 91 TrailingCollapsibleContent m_trailingCollapsibleContent; 92 InlineLayoutUnit m_width { 0 };93 92 }; 94 93 95 94 struct WrappedTextContent { 96 unsignedtrailingRunIndex { 0 };95 size_t trailingRunIndex { 0 }; 97 96 bool contentOverflows { false }; 98 97 Optional<LineBreaker::PartialRun> partialTrailingRun; 99 98 }; 100 99 101 bool LineBreaker::isContentWrappingAllowed(const ContinuousContent& c andidateRuns) const100 bool LineBreaker::isContentWrappingAllowed(const ContinuousContent& continuousContent) const 102 101 { 103 102 // Use the last inline item with content (where we would be wrapping) to decide if content wrapping is allowed. 104 auto runIndex = candidateRuns.lastContentRunIndex().valueOr(candidateRuns.size() - 1); 105 return isWrappingAllowed(candidateRuns.runs()[runIndex].inlineItem.style()); 106 } 107 108 bool LineBreaker::shouldKeepEndOfLineWhitespace(const ContinuousContent& candidateRuns) const 103 auto& continuousRuns = continuousContent.runs(); 104 auto runIndex = continuousContent.lastContentRunIndex().valueOr(continuousRuns.size() - 1); 105 return isWrappingAllowed(continuousRuns[runIndex].inlineItem.style()); 106 } 107 108 bool LineBreaker::shouldKeepEndOfLineWhitespace(const ContinuousContent& continuousContent) const 109 109 { 110 110 // Grab the style and check for white-space property to decided whether we should let this whitespace content overflow the current line. … … 112 112 // It might very well get collapsed when we close the line (normal/nowrap/pre-line). 113 113 // See https://www.w3.org/TR/css-text-3/#white-space-property 114 auto whitespace = c andidateRuns.runs()[*candidateRuns.firstTextRunIndex()].inlineItem.style().whiteSpace();114 auto whitespace = continuousContent.runs()[*continuousContent.firstTextRunIndex()].inlineItem.style().whiteSpace(); 115 115 return whitespace == WhiteSpace::Normal || whitespace == WhiteSpace::NoWrap || whitespace == WhiteSpace::PreWrap || whitespace == WhiteSpace::PreLine; 116 116 } 117 117 118 LineBreaker::Result LineBreaker::shouldWrapInlineContent(const RunList& candidateRuns, InlineLayoutUnit candidateContentLogicalWidth, const LineStatus& lineStatus)118 LineBreaker::Result LineBreaker::shouldWrapInlineContent(const CandidateContent& candidateContent, const LineStatus& lineStatus) 119 119 { 120 120 auto inlineContentWrapping = [&] { 121 if (candidateContent LogicalWidth <= lineStatus.availableWidth)121 if (candidateContent.logicalWidth <= lineStatus.availableWidth) 122 122 return Result { Result::Action::Keep }; 123 123 #if USE_FLOAT_AS_INLINE_LAYOUT_UNIT 124 124 // Preferred width computation sums up floats while line breaker substracts them. This can lead to epsilon-scale differences. 125 if (WTF::areEssentiallyEqual(candidateContent LogicalWidth, lineStatus.availableWidth))125 if (WTF::areEssentiallyEqual(candidateContent.logicalWidth, lineStatus.availableWidth)) 126 126 return Result { Result::Action::Keep }; 127 127 #endif 128 return tryWrappingInlineContent(candidate Runs, candidateContentLogicalWidth, lineStatus);128 return tryWrappingInlineContent(candidateContent, lineStatus); 129 129 }; 130 130 … … 133 133 // If this is not the end of the line, hold on to the last eligible line wrap opportunity so that we could revert back 134 134 // to this position if no other line breaking opportunity exists in this content. 135 if (auto lastLineWrapOpportunityIndex = lastWrapOpportunityIndex(candidate Runs)) {135 if (auto lastLineWrapOpportunityIndex = lastWrapOpportunityIndex(candidateContent.runs)) { 136 136 auto isEligibleLineWrapOpportunity = [&] (auto& candidateItem) { 137 137 // Just check for leading collapsible whitespace for now. … … 140 140 return shouldKeepBeginningOfLineWhitespace(candidateItem.style()); 141 141 }; 142 auto& lastWrapOpportunityCandidateItem = candidate Runs[*lastLineWrapOpportunityIndex].inlineItem;142 auto& lastWrapOpportunityCandidateItem = candidateContent.runs[*lastLineWrapOpportunityIndex].inlineItem; 143 143 if (isEligibleLineWrapOpportunity(lastWrapOpportunityCandidateItem)) { 144 144 result.lastWrapOpportunityItem = &lastWrapOpportunityCandidateItem; … … 150 150 } 151 151 152 LineBreaker::Result LineBreaker::tryWrappingInlineContent(const RunList& candidateRuns, InlineLayoutUnit candidateContentLogicalWidth, const LineStatus& lineStatus) const153 { 154 auto c andidateContent = ContinuousContent { candidateRuns, candidateContentLogicalWidth};155 ASSERT(!c andidateContent.isEmpty());156 157 ASSERT(c andidateContent.width() > lineStatus.availableWidth);158 if (c andidateContent.hasTrailingCollapsibleContent()) {159 ASSERT(c andidateContent.hasTextContentOnly());160 auto IsEndOfLine = isContentWrappingAllowed(c andidateContent) ? IsEndOfLine::Yes : IsEndOfLine::No;152 LineBreaker::Result LineBreaker::tryWrappingInlineContent(const CandidateContent& candidateContent, const LineStatus& lineStatus) const 153 { 154 auto continuousContent = ContinuousContent { candidateContent }; 155 ASSERT(!continuousContent.isEmpty()); 156 157 ASSERT(continuousContent.logicalWidth() > lineStatus.availableWidth); 158 if (continuousContent.hasTrailingCollapsibleContent()) { 159 ASSERT(continuousContent.hasTextContentOnly()); 160 auto IsEndOfLine = isContentWrappingAllowed(continuousContent) ? IsEndOfLine::Yes : IsEndOfLine::No; 161 161 // First check if the content fits without the trailing collapsible part. 162 if (c andidateContent.nonCollapsibleWidth() <= lineStatus.availableWidth)162 if (continuousContent.nonCollapsibleLogicalWidth() <= lineStatus.availableWidth) 163 163 return { Result::Action::Keep, IsEndOfLine }; 164 164 // Now check if we can trim the line too. 165 if (lineStatus.lineHasFullyCollapsibleTrailingRun && c andidateContent.isTrailingContentFullyCollapsible()) {165 if (lineStatus.lineHasFullyCollapsibleTrailingRun && continuousContent.isTrailingContentFullyCollapsible()) { 166 166 // If this new content is fully collapsible, it should surely fit. 167 167 return { Result::Action::Keep, IsEndOfLine }; 168 168 } 169 } else if (lineStatus.collapsibleWidth && c andidateContent.hasNonContentRunsOnly()) {169 } else if (lineStatus.collapsibleWidth && continuousContent.hasNonContentRunsOnly()) { 170 170 // Let's see if the non-content runs fit when the line has trailing collapsible content. 171 171 // "text content <span style="padding: 1px"></span>" <- the <span></span> runs could fit after collapsing the trailing whitespace. 172 if (c andidateContent.width() <= lineStatus.availableWidth + lineStatus.collapsibleWidth)172 if (continuousContent.logicalWidth() <= lineStatus.availableWidth + lineStatus.collapsibleWidth) 173 173 return { Result::Action::Keep }; 174 174 } 175 if (c andidateContent.isVisuallyEmptyWhitespaceContentOnly() && shouldKeepEndOfLineWhitespace(candidateContent)) {175 if (continuousContent.isVisuallyEmptyWhitespaceContentOnly() && shouldKeepEndOfLineWhitespace(continuousContent)) { 176 176 // This overflowing content apparently falls into the remove/hang end-of-line-spaces category. 177 177 // see https://www.w3.org/TR/css-text-3/#white-space-property matrix … … 179 179 } 180 180 181 if (candidateContent.hasTextContentOnly()) { 182 auto& runs = candidateContent.runs(); 183 if (auto wrappedTextContent = wrapTextContent(runs, lineStatus)) { 181 if (continuousContent.hasTextContentOnly()) { 182 if (auto wrappedTextContent = wrapTextContent(continuousContent, lineStatus)) { 184 183 if (!wrappedTextContent->trailingRunIndex && wrappedTextContent->contentOverflows) { 185 184 // We tried to split the content but the available space can't even accommodate the first character. … … 188 187 if (!lineStatus.lineIsEmpty) 189 188 return { Result::Action::Push, IsEndOfLine::Yes, { } }; 190 auto firstTextRunIndex = *c andidateContent.firstTextRunIndex();191 auto& inlineTextItem = downcast<InlineTextItem>( runs[firstTextRunIndex].inlineItem);189 auto firstTextRunIndex = *continuousContent.firstTextRunIndex(); 190 auto& inlineTextItem = downcast<InlineTextItem>(continuousContent.runs()[firstTextRunIndex].inlineItem); 192 191 ASSERT(inlineTextItem.length()); 193 192 if (inlineTextItem.length() == 1) … … 207 206 } 208 207 // Now either wrap here or at an earlier position, or not wrap at all. 209 if (isContentWrappingAllowed(c andidateContent))208 if (isContentWrappingAllowed(continuousContent)) 210 209 return { Result::Action::Push, IsEndOfLine::Yes }; 211 210 if (m_hasWrapOpportunityAtPreviousPosition) … … 214 213 } 215 214 216 Optional<WrappedTextContent> LineBreaker::wrapTextContent(const RunList& runs, const LineStatus& lineStatus) const217 { 218 auto is ContentSplitAllowed= [] (auto& run) {215 Optional<WrappedTextContent> LineBreaker::wrapTextContent(const ContinuousContent& continuousContent, const LineStatus& lineStatus) const 216 { 217 auto isBreakableRun = [] (auto& run) { 219 218 ASSERT(run.inlineItem.isText() || run.inlineItem.isContainerStart() || run.inlineItem.isContainerEnd()); 220 219 if (!run.inlineItem.isText()) { 221 // Can't splithorizontal spacing -> e.g. <span style="padding-right: 100px;">textcontent</span>, if the [container end] is the overflown inline item220 // Can't break horizontal spacing -> e.g. <span style="padding-right: 100px;">textcontent</span>, if the [container end] is the overflown inline item 222 221 // we need to check if there's another inline item beyond the [container end] to split. 223 222 return false; 224 223 } 224 // Check if this text run needs to stay on the current line. 225 225 return isWrappingAllowed(run.inlineItem.style()); 226 226 }; … … 228 228 // Check where the overflow occurs and use the corresponding style to figure out the breaking behaviour. 229 229 // <span style="word-break: normal">first</span><span style="word-break: break-all">second</span><span style="word-break: normal">third</span> 230 InlineLayoutUnit accumulatedRunWidth = 0; 231 unsigned index = 0; 230 auto& runs = continuousContent.runs(); 231 auto accumulatedRunWidth = InlineLayoutUnit { }; 232 size_t index = 0; 232 233 while (index < runs.size()) { 233 234 auto& run = runs[index]; 234 235 ASSERT(run.inlineItem.isText() || run.inlineItem.isContainerStart() || run.inlineItem.isContainerEnd()); 235 if (accumulatedRunWidth + run.logicalWidth > lineStatus.availableWidth && is ContentSplitAllowed(run)) {236 if (accumulatedRunWidth + run.logicalWidth > lineStatus.availableWidth && isBreakableRun(run)) { 236 237 // At this point the available width can very well be negative e.g. when some part of the continuous text content can not be broken into parts -> 237 238 // <span style="word-break: keep-all">textcontentwithnobreak</span><span>textcontentwithyesbreak</span> 238 239 // When the first span computes longer than the available space, by the time we get to the second span, the adjusted available space becomes negative. 239 240 auto adjustedAvailableWidth = std::max<InlineLayoutUnit>(0, lineStatus.availableWidth - accumulatedRunWidth); 240 if (auto partialRun = tryBreakingTextRun(run, adjustedAvailableWidth)) {241 if (auto partialRun = tryBreakingTextRun(run, continuousContent.logicalLeft() + accumulatedRunWidth, adjustedAvailableWidth)) { 241 242 if (partialRun->length) 242 243 return WrappedTextContent { index, false, partialRun }; … … 247 248 return WrappedTextContent { 0, true, { } }; 248 249 } 249 // If this run is not breakable, we need to check if any previous run is breakable 250 // If this run is not breakable, we need to check if any previous run is breakable. 250 251 break; 251 252 } … … 254 255 } 255 256 // We did not manage to break the run that actually overflows the line. 256 // Let's try to find the first breakablerun and wrap it at the content boundary (as it surely fits).257 // Let's try to find the last breakable position starting from the overflowing run and wrap it at the content boundary (as it surely fits). 257 258 while (index--) { 258 259 auto& run = runs[index]; 259 if (isContentSplitAllowed(run)) { 260 accumulatedRunWidth -= run.logicalWidth; 261 if (isBreakableRun(run)) { 260 262 ASSERT(run.inlineItem.isText()); 261 if (auto partialRun = tryBreakingTextRun(run, maxInlineLayoutUnit())) {263 if (auto partialRun = tryBreakingTextRun(run, continuousContent.logicalLeft() + accumulatedRunWidth, maxInlineLayoutUnit())) { 262 264 // We know this run fits, so if wrapping is allowed on the run, it should return a non-empty left-side. 263 265 ASSERT(partialRun->length); … … 296 298 } 297 299 298 Optional<LineBreaker::PartialRun> LineBreaker::tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit availableWidth) const300 Optional<LineBreaker::PartialRun> LineBreaker::tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit logicalLeft, InlineLayoutUnit availableWidth) const 299 301 { 300 302 ASSERT(overflowRun.inlineItem.isText()); … … 310 312 return PartialRun { inlineTextItem.length(), overflowRun.logicalWidth, false }; 311 313 } 312 // FIXME: Pass in the content logical left to be able to measure tabs. 313 auto splitData = TextUtil::split(inlineTextItem.inlineTextBox(), inlineTextItem.start(), inlineTextItem.length(), overflowRun.logicalWidth, availableWidth, { }); 314 auto splitData = TextUtil::split(inlineTextItem.inlineTextBox(), inlineTextItem.start(), inlineTextItem.length(), overflowRun.logicalWidth, availableWidth, logicalLeft); 314 315 return PartialRun { splitData.length, splitData.logicalWidth, false }; 315 316 } … … 334 335 if (availableWidthExcludingHyphen <= 0 || !enoughWidthForHyphenation(availableWidthExcludingHyphen, fontCascade.pixelSize())) 335 336 return { }; 336 leftSideLength = TextUtil::split(inlineTextItem.inlineTextBox(), inlineTextItem.start(), runLength, overflowRun.logicalWidth, availableWidthExcludingHyphen, { }).length;337 leftSideLength = TextUtil::split(inlineTextItem.inlineTextBox(), inlineTextItem.start(), runLength, overflowRun.logicalWidth, availableWidthExcludingHyphen, logicalLeft).length; 337 338 } 338 339 if (leftSideLength < limitBefore) … … 352 353 } 353 354 354 ContinuousContent::ContinuousContent(const LineBreaker::RunList& runs, InlineLayoutUnit contentLogicalWidth) 355 : m_runs(runs) 356 , m_width(contentLogicalWidth) 355 ContinuousContent::ContinuousContent(const LineBreaker::CandidateContent& candidateContent) 356 : m_candidateContent(candidateContent) 357 357 { 358 358 // Figure out the trailing collapsible state. 359 for (auto& run : WTF::makeReversedRange( m_runs)) {359 for (auto& run : WTF::makeReversedRange(runs())) { 360 360 auto& inlineItem = run.inlineItem; 361 361 if (inlineItem.isBox()) { … … 391 391 // <span>text</span> is considered a text run even with the [container start][container end] inline items. 392 392 // Due to commit boundary rules, we just need to check the first non-typeless inline item (can't have both [img] and [text]) 393 for (auto& run : m_runs) {393 for (auto& run : runs()) { 394 394 auto& inlineItem = run.inlineItem; 395 395 if (inlineItem.isContainerStart() || inlineItem.isContainerEnd()) … … 405 405 // [<span style="border: 1px solid red"></span> ] while this is whitespace content only, it is not considered visually empty. 406 406 // Due to commit boundary rules, we just need to check the first non-typeless inline item (can't have both [img] and [text]) 407 for (auto& run : m_runs) {407 for (auto& run : runs()) { 408 408 auto& inlineItem = run.inlineItem; 409 409 // FIXME: check for padding border etc. … … 417 417 Optional<size_t> ContinuousContent::firstTextRunIndex() const 418 418 { 419 for (size_t index = 0; index < m_runs.size(); ++index) { 420 if (m_runs[index].inlineItem.isText()) 419 auto& runs = this->runs(); 420 for (size_t index = 0; index < runs.size(); ++index) { 421 if (runs[index].inlineItem.isText()) 421 422 return index; 422 423 } … … 426 427 Optional<size_t> ContinuousContent::lastContentRunIndex() const 427 428 { 428 for (size_t index = m_runs.size(); index--;) { 429 if (m_runs[index].inlineItem.isText() || m_runs[index].inlineItem.isBox()) 429 auto& runs = this->runs(); 430 for (auto index = runs.size(); index--;) { 431 if (runs[index].inlineItem.isText() || runs[index].inlineItem.isBox()) 430 432 return index; 431 433 } … … 436 438 { 437 439 // <span></span> <- non content runs. 438 for (auto& run : m_runs) {440 for (auto& run : runs()) { 439 441 auto& inlineItem = run.inlineItem; 440 442 if (inlineItem.isContainerStart() || inlineItem.isContainerEnd()) -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h
r257208 r267404 77 77 using RunList = Vector<Run, 3>; 78 78 79 struct CandidateContent { 80 const RunList& runs; 81 InlineLayoutUnit logicalLeft { 0 }; 82 InlineLayoutUnit logicalWidth { 0 }; 83 }; 79 84 struct LineStatus { 80 85 InlineLayoutUnit availableWidth { 0 }; … … 83 88 bool lineIsEmpty { true }; 84 89 }; 85 Result shouldWrapInlineContent(const RunList& candidateRuns, InlineLayoutUnit candidateContentLogicalWidth, const LineStatus&);90 Result shouldWrapInlineContent(const CandidateContent&, const LineStatus&); 86 91 87 92 void setHyphenationDisabled() { n_hyphenationIsDisabled = true; } … … 97 102 // [container start][span1][container end][between][container start][span2][container end] 98 103 // see https://drafts.csswg.org/css-text-3/#line-break-details 99 Optional<WrappedTextContent> wrapTextContent(const RunList&, const LineStatus&) const;100 Result tryWrappingInlineContent(const RunList&, InlineLayoutUnit candidateContentLogicalWidth, const LineStatus&) const;101 Optional<PartialRun> tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit availableWidth) const;104 Optional<WrappedTextContent> wrapTextContent(const ContinuousContent&, const LineStatus&) const; 105 Result tryWrappingInlineContent(const CandidateContent&, const LineStatus&) const; 106 Optional<PartialRun> tryBreakingTextRun(const Run& overflowRun, InlineLayoutUnit logicalLeft, InlineLayoutUnit availableWidth) const; 102 107 103 108 enum class WordBreakRule { -
trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp
r267308 r267404 532 532 LineBuilder::Result LineBuilder::handleFloatsAndInlineContent(LineBreaker& lineBreaker, const InlineItemRange& layoutRange, const LineCandidate& lineCandidate) 533 533 { 534 auto& inlineContent = lineCandidate.inlineContent;535 auto& candidateRuns = inlineContent.runs();534 auto& candidateInlineContent = lineCandidate.inlineContent; 535 auto& candidateRuns = candidateInlineContent.runs(); 536 536 if (candidateRuns.isEmpty()) { 537 537 commitFloats(lineCandidate); … … 552 552 auto isLineConsideredEmpty = m_line.isVisuallyEmpty() && !m_contentIsConstrainedByFloat; 553 553 auto lineStatus = LineBreaker::LineStatus { availableWidth, m_line.trimmableTrailingWidth(), m_line.isTrailingRunFullyTrimmable(), isLineConsideredEmpty }; 554 auto result = lineBreaker.shouldWrapInlineContent(candidateRuns, inlineContent.logicalWidth(), lineStatus); 554 auto candidateInlineContentLogicalLeft = m_line.contentLogicalWidth(); 555 auto result = lineBreaker.shouldWrapInlineContent({ candidateRuns, candidateInlineContentLogicalLeft, candidateInlineContent.logicalWidth() }, lineStatus); 555 556 if (result.lastWrapOpportunityItem) 556 557 m_lastWrapOpportunityItem = result.lastWrapOpportunityItem;
Note:
See TracChangeset
for help on using the changeset viewer.