Diff
Modified: trunk/Source/WebCore/ChangeLog (252862 => 252863)
--- trunk/Source/WebCore/ChangeLog 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/ChangeLog 2019-11-25 17:29:31 UTC (rev 252863)
@@ -1,5 +1,47 @@
2019-11-25 Zalan Bujtas <[email protected]>
+ [LFC][IFC] Rename LineLayout to LineLayoutContext
+ https://bugs.webkit.org/show_bug.cgi?id=204582
+ <rdar://problem/57474018>
+
+ Reviewed by Antti Koivisto.
+
+ LineLayoutContext is the context for the inline content and not just for a single line.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::lineLayout):
+ (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):
+ (WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
+ * layout/inlineformatting/InlineFormattingContext.h:
+ * layout/inlineformatting/InlineLineBreaker.cpp:
+ (WebCore::Layout::LineBreaker::breakingContextForInlineContent):
+ (WebCore::Layout::LineBreaker::wordBreakingBehavior const):
+ (WebCore::Layout::LineBreaker::tryBreakingTextRun const):
+ * layout/inlineformatting/InlineLineBreaker.h:
+ * layout/inlineformatting/LineLayoutContext.cpp: Renamed from Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp.
+ (WebCore::Layout::inlineItemWidth):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::add):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::reset):
+ (WebCore::Layout::LineLayoutContext::LineLayoutContext):
+ (WebCore::Layout::LineLayoutContext::layoutLine):
+ (WebCore::Layout::LineLayoutContext::commitPendingContent):
+ (WebCore::Layout::LineLayoutContext::close):
+ (WebCore::Layout::LineLayoutContext::placeInlineItem):
+ (WebCore::Layout::LineLayoutContext::processUncommittedContent):
+ (WebCore::Layout::LineLayoutContext::shouldProcessUncommittedContent const):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::trim):
+ * layout/inlineformatting/LineLayoutContext.h: Renamed from Source/WebCore/layout/inlineformatting/InlineLineLayout.h.
+ (WebCore::Layout::LineLayoutContext::formattingContext const):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::runs):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::runs const):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::isEmpty const):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::size const):
+ (WebCore::Layout::LineLayoutContext::UncommittedContent::width const):
+
+2019-11-25 Zalan Bujtas <[email protected]>
+
[LFC] Pass UsedHorizontal/VerticalValues in by const reference
https://bugs.webkit.org/show_bug.cgi?id=204563
<rdar://problem/57464129>
Modified: trunk/Source/WebCore/Sources.txt (252862 => 252863)
--- trunk/Source/WebCore/Sources.txt 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/Sources.txt 2019-11-25 17:29:31 UTC (rev 252863)
@@ -1440,8 +1440,8 @@
layout/inlineformatting/InlineItem.cpp
layout/inlineformatting/InlineLine.cpp
layout/inlineformatting/InlineLineBreaker.cpp
-layout/inlineformatting/InlineLineLayout.cpp
layout/inlineformatting/InlineTextItem.cpp
+layout/inlineformatting/LineLayoutContext.cpp
layout/inlineformatting/text/TextUtil.cpp
layout/invalidation/InvalidationContext.cpp
layout/invalidation/InvalidationState.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (252862 => 252863)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-11-25 17:29:31 UTC (rev 252863)
@@ -2023,7 +2023,7 @@
6F0CD695229ED32700C5994E /* InlineLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F0CD694229ED32700C5994E /* InlineLine.h */; };
6F1CC1DE225F8B4900720AD2 /* InlineTextItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F1CC1DD225F8B4200720AD2 /* InlineTextItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
6F26BB6C23343E6F002F2BEA /* LayoutContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F26BB6B23343E5B002F2BEA /* LayoutContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 6F26EB48234004A5006906E2 /* InlineLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F26EB46234004A5006906E2 /* InlineLineLayout.h */; };
+ 6F26EB48234004A5006906E2 /* LineLayoutContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F26EB46234004A5006906E2 /* LineLayoutContext.h */; };
6F3E1F622136142000A65A08 /* FloatBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F3E1F612136141700A65A08 /* FloatBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
6F77868823491AD8004D9636 /* DisplayPainter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F77868723491AD7004D9636 /* DisplayPainter.h */; settings = {ATTRIBUTES = (Private, ); }; };
6F7CA3C6208C2957002F29AB /* LayoutState.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F7CA3C4208C2956002F29AB /* LayoutState.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9252,10 +9252,10 @@
6F1CC1DD225F8B4200720AD2 /* InlineTextItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InlineTextItem.h; sourceTree = "<group>"; };
6F222B741AB52D640094651A /* WebGLVertexArrayObjectBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGLVertexArrayObjectBase.h; sourceTree = "<group>"; };
6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebGLVertexArrayObjectBase.cpp; sourceTree = "<group>"; };
- 6F25B200220A85AB0000011B /* InlineLineLayout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineLineLayout.cpp; sourceTree = "<group>"; };
+ 6F25B200220A85AB0000011B /* LineLayoutContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LineLayoutContext.cpp; sourceTree = "<group>"; };
6F26BB6923343E5A002F2BEA /* LayoutContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutContext.cpp; sourceTree = "<group>"; };
6F26BB6B23343E5B002F2BEA /* LayoutContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutContext.h; sourceTree = "<group>"; };
- 6F26EB46234004A5006906E2 /* InlineLineLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineLineLayout.h; sourceTree = "<group>"; };
+ 6F26EB46234004A5006906E2 /* LineLayoutContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineLayoutContext.h; sourceTree = "<group>"; };
6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextGeometry.cpp; sourceTree = "<group>"; };
6F3E1F5F2136141700A65A08 /* FloatBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatBox.cpp; sourceTree = "<group>"; };
6F3E1F612136141700A65A08 /* FloatBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatBox.h; sourceTree = "<group>"; };
@@ -16691,10 +16691,10 @@
6FB47E612277425A00C7BCB0 /* InlineLineBox.h */,
6FE198132178397B00446F08 /* InlineLineBreaker.cpp */,
6FE198152178397C00446F08 /* InlineLineBreaker.h */,
- 6F25B200220A85AB0000011B /* InlineLineLayout.cpp */,
- 6F26EB46234004A5006906E2 /* InlineLineLayout.h */,
6F1CC1DC225F8B4100720AD2 /* InlineTextItem.cpp */,
6F1CC1DD225F8B4200720AD2 /* InlineTextItem.h */,
+ 6F25B200220A85AB0000011B /* LineLayoutContext.cpp */,
+ 6F26EB46234004A5006906E2 /* LineLayoutContext.h */,
);
path = inlineformatting;
sourceTree = "<group>";
@@ -30176,7 +30176,6 @@
6F0CD695229ED32700C5994E /* InlineLine.h in Headers */,
6FB47E632277425A00C7BCB0 /* InlineLineBox.h in Headers */,
6FE198172178397C00446F08 /* InlineLineBreaker.h in Headers */,
- 6F26EB48234004A5006906E2 /* InlineLineLayout.h in Headers */,
AA4C3A770B2B1679002334A2 /* InlineStyleSheetOwner.h in Headers */,
BCEA485A097D93020094C9E4 /* InlineTextBox.h in Headers */,
1C010701192594DF008A4201 /* InlineTextBoxStyle.h in Headers */,
@@ -31182,6 +31181,7 @@
84730D911248F0B300D3A9C9 /* LightSource.h in Headers */,
B22279650D00BF220071B782 /* LinearGradientAttributes.h in Headers */,
AB31C91E10AE1B8E000C7B92 /* LineClampValue.h in Headers */,
+ 6F26EB48234004A5006906E2 /* LineLayoutContext.h in Headers */,
FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
E484A33E23055325009ADE6A /* LineLayoutTraversal.h in Headers */,
FFDBC047183D27B700407109 /* LineWidth.h in Headers */,
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (252862 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2019-11-25 17:29:31 UTC (rev 252863)
@@ -94,13 +94,13 @@
auto& inlineItems = formattingState().inlineItems();
auto lineLogicalTop = geometryForBox(root()).contentBoxTop();
unsigned leadingInlineItemIndex = 0;
- Optional<LineLayout::PartialContent> leadingPartialContent;
+ Optional<LineLayoutContext::PartialContent> leadingPartialContent;
auto line = Line { *this, root().style().textAlign(), Line::SkipAlignment::No };
- auto lineLayout = LineLayout { *this, inlineItems };
+ auto lineLayoutContext = LineLayoutContext { *this, inlineItems };
while (leadingInlineItemIndex < inlineItems.size()) {
line.initialize(constraintsForLine(usedHorizontalValues, lineLogicalTop));
- auto lineContent = lineLayout.layout(line, leadingInlineItemIndex, leadingPartialContent);
+ auto lineContent = lineLayoutContext.layoutLine(line, leadingInlineItemIndex, leadingPartialContent);
setDisplayBoxesForLine(lineContent, usedHorizontalValues);
leadingPartialContent = { };
@@ -111,7 +111,7 @@
leadingInlineItemIndex = *lineContent.trailingInlineItemIndex;
// Turn previous line's overflow content length into the next line's leading content partial length.
// "sp<->litcontent" -> overflow length: 10 -> leading partial content length: 10.
- leadingPartialContent = LineLayout::PartialContent { lineContent.trailingPartialContent->length };
+ leadingPartialContent = LineLayoutContext::PartialContent { lineContent.trailingPartialContent->length };
} else
leadingInlineItemIndex = *lineContent.trailingInlineItemIndex + 1;
} else {
@@ -234,11 +234,11 @@
LayoutUnit maximumLineWidth;
unsigned leadingInlineItemIndex = 0;
auto line = Line { *this, root().style().textAlign(), Line::SkipAlignment::Yes };
- auto lineLayout = LineLayout { *this, inlineItems };
+ auto lineLayoutContext = LineLayoutContext { *this, inlineItems };
while (leadingInlineItemIndex < inlineItems.size()) {
// Only the horiztonal available width is constrained when computing intrinsic width.
line.initialize(Line::Constraints { { }, usedHorizontalValues.constraints.width, false, { } });
- auto lineContent = lineLayout.layout(line, leadingInlineItemIndex, { });
+ auto lineContent = lineLayoutContext.layoutLine(line, leadingInlineItemIndex, { });
leadingInlineItemIndex = *lineContent.trailingInlineItemIndex + 1;
LayoutUnit floatsWidth;
@@ -407,7 +407,7 @@
return Line::Constraints { { lineLogicalLeft, lineLogicalTop }, availableWidth, lineIsConstrainedByFloat, quirks().lineHeightConstraints(root()) };
}
-void InlineFormattingContext::setDisplayBoxesForLine(const LineLayout::LineContent& lineContent, const UsedHorizontalValues& usedHorizontalValues)
+void InlineFormattingContext::setDisplayBoxesForLine(const LineLayoutContext::LineContent& lineContent, const UsedHorizontalValues& usedHorizontalValues)
{
auto& formattingState = this->formattingState();
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (252862 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2019-11-25 17:29:31 UTC (rev 252863)
@@ -28,7 +28,7 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FormattingContext.h"
-#include "InlineLineLayout.h"
+#include "LineLayoutContext.h"
#include <wtf/IsoMalloc.h>
namespace WebCore {
@@ -90,7 +90,7 @@
void collectInlineContentIfNeeded();
Line::Constraints constraintsForLine(const UsedHorizontalValues&, const LayoutUnit lineLogicalTop);
- void setDisplayBoxesForLine(const LineLayout::LineContent&, const UsedHorizontalValues&);
+ void setDisplayBoxesForLine(const LineLayoutContext::LineContent&, const UsedHorizontalValues&);
void invalidateFormattingState(const InvalidationState&);
const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp (252862 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp 2019-11-25 17:29:31 UTC (rev 252863)
@@ -47,7 +47,7 @@
return trailingInlineItem.style().whiteSpace() == WhiteSpace::PreWrap && downcast<InlineTextItem>(trailingInlineItem).isWhitespace();
}
-LineBreaker::BreakingContext LineBreaker::breakingContextForInlineContent(const LineLayout::RunList& runs, LayoutUnit logicalWidth, LayoutUnit availableWidth, bool lineIsEmpty)
+LineBreaker::BreakingContext LineBreaker::breakingContextForInlineContent(const LineLayoutContext::RunList& runs, LayoutUnit logicalWidth, LayoutUnit availableWidth, bool lineIsEmpty)
{
if (logicalWidth <= availableWidth)
return { BreakingContext::ContentBreak::Keep, { } };
@@ -87,7 +87,7 @@
return !lineIsEmpty && floatLogicalWidth > availableWidth;
}
-Optional<LineBreaker::BreakingContext::TrailingPartialContent> LineBreaker::wordBreakingBehavior(const LineLayout::RunList& runs, LayoutUnit availableWidth) const
+Optional<LineBreaker::BreakingContext::TrailingPartialContent> LineBreaker::wordBreakingBehavior(const LineLayoutContext::RunList& runs, LayoutUnit availableWidth) const
{
// Check where the overflow occurs and use the corresponding style to figure out the breaking behaviour.
// <span style="word-break: normal">first</span><span style="word-break: break-all">second</span><span style="word-break: normal">third</span>
@@ -120,7 +120,7 @@
return { };
}
-Optional<LineBreaker::SplitLengthAndWidth> LineBreaker::tryBreakingTextRun(const LineLayout::Run overflowRun, LayoutUnit availableWidth) const
+Optional<LineBreaker::SplitLengthAndWidth> LineBreaker::tryBreakingTextRun(const LineLayoutContext::Run overflowRun, LayoutUnit availableWidth) const
{
ASSERT(overflowRun.inlineItem.isText());
auto breakWords = overflowRun.inlineItem.style().wordBreak();
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h (252862 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h 2019-11-25 17:29:31 UTC (rev 252863)
@@ -27,8 +27,8 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
-#include "InlineLineLayout.h"
#include "LayoutUnit.h"
+#include "LineLayoutContext.h"
namespace WebCore {
namespace Layout {
@@ -48,18 +48,18 @@
};
Optional<TrailingPartialContent> trailingPartialContent;
};
- BreakingContext breakingContextForInlineContent(const LineLayout::RunList&, LayoutUnit logicalWidth, LayoutUnit availableWidth, bool lineIsEmpty);
+ BreakingContext breakingContextForInlineContent(const LineLayoutContext::RunList&, LayoutUnit logicalWidth, LayoutUnit availableWidth, bool lineIsEmpty);
bool shouldWrapFloatBox(LayoutUnit floatLogicalWidth, LayoutUnit availableWidth, bool lineIsEmpty);
private:
- Optional<BreakingContext::TrailingPartialContent> wordBreakingBehavior(const LineLayout::RunList&, LayoutUnit availableWidth) const;
+ Optional<BreakingContext::TrailingPartialContent> wordBreakingBehavior(const LineLayoutContext::RunList&, LayoutUnit availableWidth) const;
struct SplitLengthAndWidth {
unsigned length { 0 };
LayoutUnit leftLogicalWidth;
};
- Optional<SplitLengthAndWidth> tryBreakingTextRun(const LineLayout::Run overflowRun, LayoutUnit availableWidth) const;
+ Optional<SplitLengthAndWidth> tryBreakingTextRun(const LineLayoutContext::Run overflowRun, LayoutUnit availableWidth) const;
};
}
Deleted: trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp (252862 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp 2019-11-25 17:29:31 UTC (rev 252863)
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "InlineLineLayout.h"
-
-#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
-
-#include "InlineLineBreaker.h"
-#include "LayoutBox.h"
-#include "TextUtil.h"
-
-namespace WebCore {
-namespace Layout {
-
-static LayoutUnit inlineItemWidth(const FormattingContext& formattingContext, const InlineItem& inlineItem, LayoutUnit contentLogicalLeft)
-{
- if (inlineItem.isForcedLineBreak())
- return 0;
-
- if (is<InlineTextItem>(inlineItem)) {
- auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
- if (auto contentWidth = inlineTextItem.width())
- return *contentWidth;
- auto end = inlineTextItem.isCollapsible() ? inlineTextItem.start() + 1 : inlineTextItem.end();
- return TextUtil::width(inlineTextItem.layoutBox(), inlineTextItem.start(), end, contentLogicalLeft);
- }
-
- auto& layoutBox = inlineItem.layoutBox();
- auto& boxGeometry = formattingContext.geometryForBox(layoutBox);
-
- if (layoutBox.isFloatingPositioned())
- return boxGeometry.marginBoxWidth();
-
- if (layoutBox.replaced())
- return boxGeometry.width();
-
- if (inlineItem.isContainerStart())
- return boxGeometry.marginStart() + boxGeometry.borderLeft() + boxGeometry.paddingLeft().valueOr(0);
-
- if (inlineItem.isContainerEnd())
- return boxGeometry.marginEnd() + boxGeometry.borderRight() + boxGeometry.paddingRight().valueOr(0);
-
- // Non-replaced inline box (e.g. inline-block)
- return boxGeometry.width();
-}
-
-void LineLayout::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth)
-{
- m_uncommittedRuns.append({ inlineItem, logicalWidth });
- m_width += logicalWidth;
-}
-
-void LineLayout::UncommittedContent::reset()
-{
- m_uncommittedRuns.clear();
- m_width = 0;
-}
-
-LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const InlineItems& inlineItems)
- : m_inlineFormattingContext(inlineFormattingContext)
- , m_inlineItems(inlineItems)
-{
-}
-
-LineLayout::LineContent LineLayout::layout(Line& line, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent)
-{
- auto initialize = [&] {
- m_committedInlineItemCount = 0;
- m_uncommittedContent.reset();
- m_leadingPartialTextItem = { };
- m_trailingPartialTextItem = { };
- m_overflowTextLength = { };
- };
- initialize();
- // Iterate through the inline content and place the inline boxes on the current line.
- // Start with the partial leading text from the previous line.
- auto firstNonPartialInlineItemIndex = leadingInlineItemIndex;
- if (leadingPartialContent) {
- // Handle partial inline item (split text from the previous line).
- auto& leadingTextItem = m_inlineItems[leadingInlineItemIndex];
- RELEASE_ASSERT(leadingTextItem->isText());
- // Construct a partial leading inline item.
- ASSERT(!m_leadingPartialTextItem);
- m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right(leadingPartialContent->length);
- if (placeInlineItem(line, *m_leadingPartialTextItem) == IsEndOfLine::Yes)
- return close(line, leadingInlineItemIndex);
- ++firstNonPartialInlineItemIndex;
- }
-
- for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_inlineItems.size(); ++inlineItemIndex) {
- // FIXME: We should not need to re-measure the dropped, uncommitted content when re-using them on the next line.
- if (placeInlineItem(line, *m_inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
- return close(line, leadingInlineItemIndex);
- }
- // Check the uncommitted content whether they fit now that we know we are at a commit boundary.
- if (!m_uncommittedContent.isEmpty())
- processUncommittedContent(line);
- return close(line, leadingInlineItemIndex);
-}
-
-void LineLayout::commitPendingContent(Line& line)
-{
- if (m_uncommittedContent.isEmpty())
- return;
- m_committedInlineItemCount += m_uncommittedContent.size();
- for (auto& uncommittedRun : m_uncommittedContent.runs())
- line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
- m_uncommittedContent.reset();
-}
-
-LineLayout::LineContent LineLayout::close(Line& line, unsigned leadingInlineItemIndex)
-{
- ASSERT(m_committedInlineItemCount || line.hasIntrusiveFloat());
- m_uncommittedContent.reset();
- if (!m_committedInlineItemCount)
- return LineContent { { }, { }, WTFMove(m_floats), line.close(), line.lineBox() };
-
- Optional<PartialContent> overflowContent;
- if (m_overflowTextLength)
- overflowContent = PartialContent { *m_overflowTextLength };
- auto trailingInlineItemIndex = leadingInlineItemIndex + m_committedInlineItemCount - 1;
-
- auto isLastLineWithInlineContent = [&] {
- if (overflowContent)
- return Line::IsLastLineWithInlineContent::No;
- // Skip floats backwards to see if this is going to be the last line with inline content.
- for (auto i = m_inlineItems.size(); i--;) {
- if (!m_inlineItems[i]->isFloat())
- return i == trailingInlineItemIndex ? Line::IsLastLineWithInlineContent::Yes : Line::IsLastLineWithInlineContent::No;
- }
- // There has to be at least one non-float item.
- ASSERT_NOT_REACHED();
- return Line::IsLastLineWithInlineContent::No;
- };
-
- return LineContent { trailingInlineItemIndex, overflowContent, WTFMove(m_floats), line.close(isLastLineWithInlineContent()), line.lineBox() };
-}
-
-LineLayout::IsEndOfLine LineLayout::placeInlineItem(Line& line, const InlineItem& inlineItem)
-{
- auto currentLogicalRight = line.lineBox().logicalRight();
- auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight);
-
- // Floats are special, they are intrusive but they don't really participate in the line layout context.
- if (inlineItem.isFloat()) {
- // FIXME: It gets a bit more complicated when there's some uncommitted content whether they should be added to the current line
- // e.g. text_content<div style="float: left"></div>continuous_text_content
- // Not sure what to do when the float takes up the available space and we've got continuous content. Browser engines don't agree.
- // Let's just commit the pending content and try placing the float for now.
- if (!m_uncommittedContent.isEmpty()) {
- if (processUncommittedContent(line) == IsEndOfLine::Yes)
- return IsEndOfLine::Yes;
- }
- auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
- if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, line.availableWidth() + line.trailingTrimmableWidth(), lineIsConsideredEmpty))
- return IsEndOfLine::Yes;
-
- // This float can sit on the current line.
- auto& floatBox = inlineItem.layoutBox();
- // Shrink available space for current line and move existing inline runs.
- floatBox.isLeftFloatingPositioned() ? line.moveLogicalLeft(itemLogicalWidth) : line.moveLogicalRight(itemLogicalWidth);
- m_floats.append(makeWeakPtr(inlineItem));
- ++m_committedInlineItemCount;
- line.setHasIntrusiveFloat();
- return IsEndOfLine::No;
- }
- // Forced line breaks are also special.
- if (inlineItem.isForcedLineBreak()) {
- auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent(line) : IsEndOfLine::No;
- // When the uncommitted content fits(or the line is empty), add the line break to this line as well.
- if (isEndOfLine == IsEndOfLine::No) {
- m_uncommittedContent.add(inlineItem, itemLogicalWidth);
- commitPendingContent(line);
- }
- return IsEndOfLine::Yes;
- }
- //
- auto isEndOfLine = IsEndOfLine::No;
- if (!m_uncommittedContent.isEmpty() && shouldProcessUncommittedContent(inlineItem))
- isEndOfLine = processUncommittedContent(line);
- // The current item might fit as well.
- if (isEndOfLine == IsEndOfLine::No)
- m_uncommittedContent.add(inlineItem, itemLogicalWidth);
- return isEndOfLine;
-}
-
-LineLayout::IsEndOfLine LineLayout::processUncommittedContent(Line& line)
-{
- // Check if the pending content fits.
- auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
- auto breakingContext = LineBreaker().breakingContextForInlineContent(m_uncommittedContent.runs(), m_uncommittedContent.width(), line.availableWidth(), lineIsConsideredEmpty);
- // The uncommitted content can fully, partially fit the current line (commit/partial commit) or not at all (reset).
- if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep)
- commitPendingContent(line);
- else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Split) {
- ASSERT(breakingContext.trailingPartialContent);
- ASSERT(m_uncommittedContent.runs()[breakingContext.trailingPartialContent->runIndex].inlineItem.isText());
- // Turn the uncommitted trailing run into a partial trailing run.
- auto overflowInlineTextItemIndex = breakingContext.trailingPartialContent->runIndex;
- auto& overflowInlineTextItem = downcast<InlineTextItem>(m_uncommittedContent.runs()[overflowInlineTextItemIndex].inlineItem);
-
- // Construct a partial trailing inline run.
- ASSERT(!m_trailingPartialTextItem);
- auto trailingContentLength = breakingContext.trailingPartialContent->length;
- m_trailingPartialTextItem = overflowInlineTextItem.left(trailingContentLength);
- m_overflowTextLength = overflowInlineTextItem.length() - trailingContentLength;
- // Keep the non-overflow part of the uncommitted runs and add the trailing partial content.
- m_uncommittedContent.trim(overflowInlineTextItemIndex);
- m_uncommittedContent.add(*m_trailingPartialTextItem, breakingContext.trailingPartialContent->logicalWidth);
- commitPendingContent(line);
- } else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Wrap)
- m_uncommittedContent.reset();
- else
- ASSERT_NOT_REACHED();
- return breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep ? IsEndOfLine::No :IsEndOfLine::Yes;
-}
-
-bool LineLayout::shouldProcessUncommittedContent(const InlineItem& inlineItem) const
-{
- // https://drafts.csswg.org/css-text-3/#line-break-details
- // Figure out if the new incoming content puts the uncommitted content on commit boundary.
- // e.g. <span>continuous</span> <- uncomitted content ->
- // [inline container start][text content][inline container end]
- // An incoming <img> box would enable us to commit the "<span>continuous</span>" content
- // while additional text content would not.
- ASSERT(!inlineItem.isFloat() && !inlineItem.isForcedLineBreak());
- ASSERT(!m_uncommittedContent.isEmpty());
-
- auto* lastUncomittedContent = &m_uncommittedContent.runs().last().inlineItem;
- if (inlineItem.isText()) {
- // any content' ' -> whitespace is always a commit boundary.
- if (downcast<InlineTextItem>(inlineItem).isWhitespace())
- return true;
- // texttext -> continuous content.
- // ' 'text -> commit boundary.
- if (lastUncomittedContent->isText())
- return downcast<InlineTextItem>(*lastUncomittedContent).isWhitespace();
- // <span>text -> the inline container start and the text content form an unbreakable continuous content.
- if (lastUncomittedContent->isContainerStart())
- return false;
- // </span>text -> need to check what's before the </span>.
- // text</span>text -> continuous content
- // <img></span>text -> commit bounday
- if (lastUncomittedContent->isContainerEnd()) {
- auto& runs = m_uncommittedContent.runs();
- // text</span><span></span></span>text -> check all the way back until we hit either a box or some text
- for (auto i = m_uncommittedContent.size(); i--;) {
- auto& previousInlineItem = runs[i].inlineItem;
- if (previousInlineItem.isContainerStart() || previousInlineItem.isContainerEnd())
- continue;
- ASSERT(previousInlineItem.isText() || previousInlineItem.isBox());
- lastUncomittedContent = &previousInlineItem;
- break;
- }
- // Did not find any content (e.g. <span></span>text)
- if (lastUncomittedContent->isContainerEnd())
- return false;
- }
- // <img>text -> the inline box is on a commit boundary.
- if (lastUncomittedContent->isBox())
- return true;
- ASSERT_NOT_REACHED();
- }
-
- if (inlineItem.isBox()) {
- // <span><img> -> the inline container start and the content form an unbreakable continuous content.
- if (lastUncomittedContent->isContainerStart())
- return false;
- // </span><img> -> ok to commit the </span>.
- if (lastUncomittedContent->isContainerEnd())
- return true;
- // <img>text and <img><img> -> these combinations are ok to commit.
- if (lastUncomittedContent->isText() || lastUncomittedContent->isBox())
- return true;
- ASSERT_NOT_REACHED();
- }
-
- if (inlineItem.isContainerStart() || inlineItem.isContainerEnd()) {
- // <span><span> or </span><span> -> can't commit the previous content yet.
- if (lastUncomittedContent->isContainerStart() || lastUncomittedContent->isContainerEnd())
- return false;
- // ' '<span> -> let's commit the whitespace
- // text<span> -> but not yet the non-whitespace; we need to know what comes next (e.g. text<span>text or text<span><img>).
- if (lastUncomittedContent->isText())
- return downcast<InlineTextItem>(*lastUncomittedContent).isWhitespace();
- // <img><span> -> it's ok to commit the inline box content.
- // <img></span> -> the inline box and the closing inline container form an unbreakable continuous content.
- if (lastUncomittedContent->isBox())
- return inlineItem.isContainerStart();
- ASSERT_NOT_REACHED();
- }
-
- ASSERT_NOT_REACHED();
- return true;
-}
-
-void LineLayout::UncommittedContent::trim(unsigned newSize)
-{
- for (auto i = m_uncommittedRuns.size(); i--;)
- m_width -= m_uncommittedRuns[i].logicalWidth;
- m_uncommittedRuns.shrink(newSize);
-}
-
-
-}
-}
-
-#endif
Deleted: trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h (252862 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h 2019-11-25 16:19:42 UTC (rev 252862)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h 2019-11-25 17:29:31 UTC (rev 252863)
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
-
-#include "InlineLine.h"
-#include <wtf/IsoMalloc.h>
-
-namespace WebCore {
-namespace Layout {
-
-class LineLayout {
-public:
- LineLayout(const InlineFormattingContext&, const InlineItems&);
-
- struct PartialContent {
- // This will potentially gain some more members.
- unsigned length;
- };
- struct LineContent {
- Optional<unsigned> trailingInlineItemIndex;
- Optional<PartialContent> trailingPartialContent;
- Vector<WeakPtr<InlineItem>> floats;
- const Line::RunList runList;
- const LineBox lineBox;
- };
- LineContent layout(Line&, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent);
-
- struct Run {
- const InlineItem& inlineItem;
- LayoutUnit logicalWidth;
- };
-
- using RunList = Vector<Run, 30>;
-
-private:
- const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
- enum class IsEndOfLine { No, Yes };
- IsEndOfLine placeInlineItem(Line&, const InlineItem&);
- void commitPendingContent(Line&);
- LineContent close(Line&, unsigned leadingInlineItemIndex);
- bool shouldProcessUncommittedContent(const InlineItem&) const;
- IsEndOfLine processUncommittedContent(Line&);
-
- struct UncommittedContent {
- void add(const InlineItem&, LayoutUnit logicalWidth);
- void reset();
- void trim(unsigned newSize);
-
- RunList& runs() { return m_uncommittedRuns; }
- const RunList& runs() const { return m_uncommittedRuns; }
- bool isEmpty() const { return m_uncommittedRuns.isEmpty(); }
- unsigned size() const { return m_uncommittedRuns.size(); }
- LayoutUnit width() const { return m_width; }
-
- private:
- RunList m_uncommittedRuns;
- LayoutUnit m_width;
- };
-
- const InlineFormattingContext& m_inlineFormattingContext;
- const InlineItems& m_inlineItems;
- UncommittedContent m_uncommittedContent;
- unsigned m_committedInlineItemCount { 0 };
- Vector<WeakPtr<InlineItem>> m_floats;
- std::unique_ptr<InlineTextItem> m_leadingPartialTextItem;
- std::unique_ptr<InlineTextItem> m_trailingPartialTextItem;
- Optional<unsigned> m_overflowTextLength;
-};
-
-}
-}
-#endif
Copied: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp (from rev 252862, trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp) (0 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp 2019-11-25 17:29:31 UTC (rev 252863)
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LineLayoutContext.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "InlineLineBreaker.h"
+#include "LayoutBox.h"
+#include "TextUtil.h"
+
+namespace WebCore {
+namespace Layout {
+
+static LayoutUnit inlineItemWidth(const FormattingContext& formattingContext, const InlineItem& inlineItem, LayoutUnit contentLogicalLeft)
+{
+ if (inlineItem.isForcedLineBreak())
+ return 0;
+
+ if (is<InlineTextItem>(inlineItem)) {
+ auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
+ if (auto contentWidth = inlineTextItem.width())
+ return *contentWidth;
+ auto end = inlineTextItem.isCollapsible() ? inlineTextItem.start() + 1 : inlineTextItem.end();
+ return TextUtil::width(inlineTextItem.layoutBox(), inlineTextItem.start(), end, contentLogicalLeft);
+ }
+
+ auto& layoutBox = inlineItem.layoutBox();
+ auto& boxGeometry = formattingContext.geometryForBox(layoutBox);
+
+ if (layoutBox.isFloatingPositioned())
+ return boxGeometry.marginBoxWidth();
+
+ if (layoutBox.replaced())
+ return boxGeometry.width();
+
+ if (inlineItem.isContainerStart())
+ return boxGeometry.marginStart() + boxGeometry.borderLeft() + boxGeometry.paddingLeft().valueOr(0);
+
+ if (inlineItem.isContainerEnd())
+ return boxGeometry.marginEnd() + boxGeometry.borderRight() + boxGeometry.paddingRight().valueOr(0);
+
+ // Non-replaced inline box (e.g. inline-block)
+ return boxGeometry.width();
+}
+
+void LineLayoutContext::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth)
+{
+ m_uncommittedRuns.append({ inlineItem, logicalWidth });
+ m_width += logicalWidth;
+}
+
+void LineLayoutContext::UncommittedContent::reset()
+{
+ m_uncommittedRuns.clear();
+ m_width = 0;
+}
+
+LineLayoutContext::LineLayoutContext(const InlineFormattingContext& inlineFormattingContext, const InlineItems& inlineItems)
+ : m_inlineFormattingContext(inlineFormattingContext)
+ , m_inlineItems(inlineItems)
+{
+}
+
+LineLayoutContext::LineContent LineLayoutContext::layoutLine(Line& line, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent)
+{
+ auto initialize = [&] {
+ m_committedInlineItemCount = 0;
+ m_uncommittedContent.reset();
+ m_leadingPartialTextItem = { };
+ m_trailingPartialTextItem = { };
+ m_overflowTextLength = { };
+ };
+ initialize();
+ // Iterate through the inline content and place the inline boxes on the current line.
+ // Start with the partial leading text from the previous line.
+ auto firstNonPartialInlineItemIndex = leadingInlineItemIndex;
+ if (leadingPartialContent) {
+ // Handle partial inline item (split text from the previous line).
+ auto& leadingTextItem = m_inlineItems[leadingInlineItemIndex];
+ RELEASE_ASSERT(leadingTextItem->isText());
+ // Construct a partial leading inline item.
+ ASSERT(!m_leadingPartialTextItem);
+ m_leadingPartialTextItem = downcast<InlineTextItem>(*leadingTextItem).right(leadingPartialContent->length);
+ if (placeInlineItem(line, *m_leadingPartialTextItem) == IsEndOfLine::Yes)
+ return close(line, leadingInlineItemIndex);
+ ++firstNonPartialInlineItemIndex;
+ }
+
+ for (auto inlineItemIndex = firstNonPartialInlineItemIndex; inlineItemIndex < m_inlineItems.size(); ++inlineItemIndex) {
+ // FIXME: We should not need to re-measure the dropped, uncommitted content when re-using them on the next line.
+ if (placeInlineItem(line, *m_inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
+ return close(line, leadingInlineItemIndex);
+ }
+ // Check the uncommitted content whether they fit now that we know we are at a commit boundary.
+ if (!m_uncommittedContent.isEmpty())
+ processUncommittedContent(line);
+ return close(line, leadingInlineItemIndex);
+}
+
+void LineLayoutContext::commitPendingContent(Line& line)
+{
+ if (m_uncommittedContent.isEmpty())
+ return;
+ m_committedInlineItemCount += m_uncommittedContent.size();
+ for (auto& uncommittedRun : m_uncommittedContent.runs())
+ line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
+ m_uncommittedContent.reset();
+}
+
+LineLayoutContext::LineContent LineLayoutContext::close(Line& line, unsigned leadingInlineItemIndex)
+{
+ ASSERT(m_committedInlineItemCount || line.hasIntrusiveFloat());
+ m_uncommittedContent.reset();
+ if (!m_committedInlineItemCount)
+ return LineContent { { }, { }, WTFMove(m_floats), line.close(), line.lineBox() };
+
+ Optional<PartialContent> overflowContent;
+ if (m_overflowTextLength)
+ overflowContent = PartialContent { *m_overflowTextLength };
+ auto trailingInlineItemIndex = leadingInlineItemIndex + m_committedInlineItemCount - 1;
+
+ auto isLastLineWithInlineContent = [&] {
+ if (overflowContent)
+ return Line::IsLastLineWithInlineContent::No;
+ // Skip floats backwards to see if this is going to be the last line with inline content.
+ for (auto i = m_inlineItems.size(); i--;) {
+ if (!m_inlineItems[i]->isFloat())
+ return i == trailingInlineItemIndex ? Line::IsLastLineWithInlineContent::Yes : Line::IsLastLineWithInlineContent::No;
+ }
+ // There has to be at least one non-float item.
+ ASSERT_NOT_REACHED();
+ return Line::IsLastLineWithInlineContent::No;
+ };
+
+ return LineContent { trailingInlineItemIndex, overflowContent, WTFMove(m_floats), line.close(isLastLineWithInlineContent()), line.lineBox() };
+}
+
+LineLayoutContext::IsEndOfLine LineLayoutContext::placeInlineItem(Line& line, const InlineItem& inlineItem)
+{
+ auto currentLogicalRight = line.lineBox().logicalRight();
+ auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight);
+
+ // Floats are special, they are intrusive but they don't really participate in the line layout context.
+ if (inlineItem.isFloat()) {
+ // FIXME: It gets a bit more complicated when there's some uncommitted content whether they should be added to the current line
+ // e.g. text_content<div style="float: left"></div>continuous_text_content
+ // Not sure what to do when the float takes up the available space and we've got continuous content. Browser engines don't agree.
+ // Let's just commit the pending content and try placing the float for now.
+ if (!m_uncommittedContent.isEmpty()) {
+ if (processUncommittedContent(line) == IsEndOfLine::Yes)
+ return IsEndOfLine::Yes;
+ }
+ auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
+ if (LineBreaker().shouldWrapFloatBox(itemLogicalWidth, line.availableWidth() + line.trailingTrimmableWidth(), lineIsConsideredEmpty))
+ return IsEndOfLine::Yes;
+
+ // This float can sit on the current line.
+ auto& floatBox = inlineItem.layoutBox();
+ // Shrink available space for current line and move existing inline runs.
+ floatBox.isLeftFloatingPositioned() ? line.moveLogicalLeft(itemLogicalWidth) : line.moveLogicalRight(itemLogicalWidth);
+ m_floats.append(makeWeakPtr(inlineItem));
+ ++m_committedInlineItemCount;
+ line.setHasIntrusiveFloat();
+ return IsEndOfLine::No;
+ }
+ // Forced line breaks are also special.
+ if (inlineItem.isForcedLineBreak()) {
+ auto isEndOfLine = !m_uncommittedContent.isEmpty() ? processUncommittedContent(line) : IsEndOfLine::No;
+ // When the uncommitted content fits(or the line is empty), add the line break to this line as well.
+ if (isEndOfLine == IsEndOfLine::No) {
+ m_uncommittedContent.add(inlineItem, itemLogicalWidth);
+ commitPendingContent(line);
+ }
+ return IsEndOfLine::Yes;
+ }
+ //
+ auto isEndOfLine = IsEndOfLine::No;
+ if (!m_uncommittedContent.isEmpty() && shouldProcessUncommittedContent(inlineItem))
+ isEndOfLine = processUncommittedContent(line);
+ // The current item might fit as well.
+ if (isEndOfLine == IsEndOfLine::No)
+ m_uncommittedContent.add(inlineItem, itemLogicalWidth);
+ return isEndOfLine;
+}
+
+LineLayoutContext::IsEndOfLine LineLayoutContext::processUncommittedContent(Line& line)
+{
+ // Check if the pending content fits.
+ auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
+ auto breakingContext = LineBreaker().breakingContextForInlineContent(m_uncommittedContent.runs(), m_uncommittedContent.width(), line.availableWidth(), lineIsConsideredEmpty);
+ // The uncommitted content can fully, partially fit the current line (commit/partial commit) or not at all (reset).
+ if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep)
+ commitPendingContent(line);
+ else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Split) {
+ ASSERT(breakingContext.trailingPartialContent);
+ ASSERT(m_uncommittedContent.runs()[breakingContext.trailingPartialContent->runIndex].inlineItem.isText());
+ // Turn the uncommitted trailing run into a partial trailing run.
+ auto overflowInlineTextItemIndex = breakingContext.trailingPartialContent->runIndex;
+ auto& overflowInlineTextItem = downcast<InlineTextItem>(m_uncommittedContent.runs()[overflowInlineTextItemIndex].inlineItem);
+
+ // Construct a partial trailing inline run.
+ ASSERT(!m_trailingPartialTextItem);
+ auto trailingContentLength = breakingContext.trailingPartialContent->length;
+ m_trailingPartialTextItem = overflowInlineTextItem.left(trailingContentLength);
+ m_overflowTextLength = overflowInlineTextItem.length() - trailingContentLength;
+ // Keep the non-overflow part of the uncommitted runs and add the trailing partial content.
+ m_uncommittedContent.trim(overflowInlineTextItemIndex);
+ m_uncommittedContent.add(*m_trailingPartialTextItem, breakingContext.trailingPartialContent->logicalWidth);
+ commitPendingContent(line);
+ } else if (breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Wrap)
+ m_uncommittedContent.reset();
+ else
+ ASSERT_NOT_REACHED();
+ return breakingContext.contentBreak == LineBreaker::BreakingContext::ContentBreak::Keep ? IsEndOfLine::No :IsEndOfLine::Yes;
+}
+
+bool LineLayoutContext::shouldProcessUncommittedContent(const InlineItem& inlineItem) const
+{
+ // https://drafts.csswg.org/css-text-3/#line-break-details
+ // Figure out if the new incoming content puts the uncommitted content on commit boundary.
+ // e.g. <span>continuous</span> <- uncomitted content ->
+ // [inline container start][text content][inline container end]
+ // An incoming <img> box would enable us to commit the "<span>continuous</span>" content
+ // while additional text content would not.
+ ASSERT(!inlineItem.isFloat() && !inlineItem.isForcedLineBreak());
+ ASSERT(!m_uncommittedContent.isEmpty());
+
+ auto* lastUncomittedContent = &m_uncommittedContent.runs().last().inlineItem;
+ if (inlineItem.isText()) {
+ // any content' ' -> whitespace is always a commit boundary.
+ if (downcast<InlineTextItem>(inlineItem).isWhitespace())
+ return true;
+ // texttext -> continuous content.
+ // ' 'text -> commit boundary.
+ if (lastUncomittedContent->isText())
+ return downcast<InlineTextItem>(*lastUncomittedContent).isWhitespace();
+ // <span>text -> the inline container start and the text content form an unbreakable continuous content.
+ if (lastUncomittedContent->isContainerStart())
+ return false;
+ // </span>text -> need to check what's before the </span>.
+ // text</span>text -> continuous content
+ // <img></span>text -> commit bounday
+ if (lastUncomittedContent->isContainerEnd()) {
+ auto& runs = m_uncommittedContent.runs();
+ // text</span><span></span></span>text -> check all the way back until we hit either a box or some text
+ for (auto i = m_uncommittedContent.size(); i--;) {
+ auto& previousInlineItem = runs[i].inlineItem;
+ if (previousInlineItem.isContainerStart() || previousInlineItem.isContainerEnd())
+ continue;
+ ASSERT(previousInlineItem.isText() || previousInlineItem.isBox());
+ lastUncomittedContent = &previousInlineItem;
+ break;
+ }
+ // Did not find any content (e.g. <span></span>text)
+ if (lastUncomittedContent->isContainerEnd())
+ return false;
+ }
+ // <img>text -> the inline box is on a commit boundary.
+ if (lastUncomittedContent->isBox())
+ return true;
+ ASSERT_NOT_REACHED();
+ }
+
+ if (inlineItem.isBox()) {
+ // <span><img> -> the inline container start and the content form an unbreakable continuous content.
+ if (lastUncomittedContent->isContainerStart())
+ return false;
+ // </span><img> -> ok to commit the </span>.
+ if (lastUncomittedContent->isContainerEnd())
+ return true;
+ // <img>text and <img><img> -> these combinations are ok to commit.
+ if (lastUncomittedContent->isText() || lastUncomittedContent->isBox())
+ return true;
+ ASSERT_NOT_REACHED();
+ }
+
+ if (inlineItem.isContainerStart() || inlineItem.isContainerEnd()) {
+ // <span><span> or </span><span> -> can't commit the previous content yet.
+ if (lastUncomittedContent->isContainerStart() || lastUncomittedContent->isContainerEnd())
+ return false;
+ // ' '<span> -> let's commit the whitespace
+ // text<span> -> but not yet the non-whitespace; we need to know what comes next (e.g. text<span>text or text<span><img>).
+ if (lastUncomittedContent->isText())
+ return downcast<InlineTextItem>(*lastUncomittedContent).isWhitespace();
+ // <img><span> -> it's ok to commit the inline box content.
+ // <img></span> -> the inline box and the closing inline container form an unbreakable continuous content.
+ if (lastUncomittedContent->isBox())
+ return inlineItem.isContainerStart();
+ ASSERT_NOT_REACHED();
+ }
+
+ ASSERT_NOT_REACHED();
+ return true;
+}
+
+void LineLayoutContext::UncommittedContent::trim(unsigned newSize)
+{
+ for (auto i = m_uncommittedRuns.size(); i--;)
+ m_width -= m_uncommittedRuns[i].logicalWidth;
+ m_uncommittedRuns.shrink(newSize);
+}
+
+
+}
+}
+
+#endif
Copied: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h (from rev 252862, trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h) (0 => 252863)
--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h 2019-11-25 17:29:31 UTC (rev 252863)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "InlineLine.h"
+
+namespace WebCore {
+namespace Layout {
+
+class LineLayoutContext {
+public:
+ LineLayoutContext(const InlineFormattingContext&, const InlineItems&);
+
+ struct PartialContent {
+ // This will potentially gain some more members.
+ unsigned length;
+ };
+ struct LineContent {
+ Optional<unsigned> trailingInlineItemIndex;
+ Optional<PartialContent> trailingPartialContent;
+ Vector<WeakPtr<InlineItem>> floats;
+ const Line::RunList runList;
+ const LineBox lineBox;
+ };
+ LineContent layoutLine(Line&, unsigned leadingInlineItemIndex, Optional<PartialContent> leadingPartialContent);
+
+ struct Run {
+ const InlineItem& inlineItem;
+ LayoutUnit logicalWidth;
+ };
+
+ using RunList = Vector<Run, 30>;
+
+private:
+ const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
+ enum class IsEndOfLine { No, Yes };
+ IsEndOfLine placeInlineItem(Line&, const InlineItem&);
+ void commitPendingContent(Line&);
+ LineContent close(Line&, unsigned leadingInlineItemIndex);
+ bool shouldProcessUncommittedContent(const InlineItem&) const;
+ IsEndOfLine processUncommittedContent(Line&);
+
+ struct UncommittedContent {
+ void add(const InlineItem&, LayoutUnit logicalWidth);
+ void reset();
+ void trim(unsigned newSize);
+
+ RunList& runs() { return m_uncommittedRuns; }
+ const RunList& runs() const { return m_uncommittedRuns; }
+ bool isEmpty() const { return m_uncommittedRuns.isEmpty(); }
+ unsigned size() const { return m_uncommittedRuns.size(); }
+ LayoutUnit width() const { return m_width; }
+
+ private:
+ RunList m_uncommittedRuns;
+ LayoutUnit m_width;
+ };
+
+ const InlineFormattingContext& m_inlineFormattingContext;
+ const InlineItems& m_inlineItems;
+ UncommittedContent m_uncommittedContent;
+ unsigned m_committedInlineItemCount { 0 };
+ Vector<WeakPtr<InlineItem>> m_floats;
+ std::unique_ptr<InlineTextItem> m_leadingPartialTextItem;
+ std::unique_ptr<InlineTextItem> m_trailingPartialTextItem;
+ Optional<unsigned> m_overflowTextLength;
+};
+
+}
+}
+#endif