Diff
Modified: trunk/Source/WebCore/ChangeLog (245849 => 245850)
--- trunk/Source/WebCore/ChangeLog 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/ChangeLog 2019-05-29 16:07:19 UTC (rev 245850)
@@ -1,3 +1,51 @@
+2019-05-29 Zalan Bujtas <[email protected]>
+
+ [LFC][IFC] Move Line class to a dedicated file
+ https://bugs.webkit.org/show_bug.cgi?id=198332
+ <rdar://problem/51221403>
+
+ Reviewed by Antti Koivisto.
+
+ An upcoming refactoring requires the Line class to be in a .h.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * layout/displaytree/DisplayRun.h:
+ * layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
+ (WebCore::Layout::InlineFormattingContext::LineLayout::initializeLine const):
+ (WebCore::Layout::InlineFormattingContext::LineLayout::computedIntrinsicWidth const):
+ (WebCore::Layout::halfLeadingMetrics): Deleted.
+ (WebCore::Layout::Line::availableWidth const): Deleted.
+ (WebCore::Layout::Line::contentLogicalRight const): Deleted.
+ (WebCore::Layout::Line::contentLogicalWidth const): Deleted.
+ (WebCore::Layout::Line::logicalTop const): Deleted.
+ (WebCore::Layout::Line::logicalLeft const): Deleted.
+ (WebCore::Layout::Line::logicalRight const): Deleted.
+ (WebCore::Layout::Line::logicalBottom const): Deleted.
+ (WebCore::Layout::Line::logicalWidth const): Deleted.
+ (WebCore::Layout::Line::logicalHeight const): Deleted.
+ (WebCore::Layout::Line::LineItem::LineItem): Deleted.
+ (WebCore::Layout::Line::Line): Deleted.
+ (WebCore::Layout::Line::reset): Deleted.
+ (WebCore::Layout::Line::close): Deleted.
+ (WebCore::Layout::Line::removeTrailingTrimmableContent): Deleted.
+ (WebCore::Layout::Line::moveLogicalLeft): Deleted.
+ (WebCore::Layout::Line::moveLogicalRight): Deleted.
+ (WebCore::Layout::isTrimmableContent): Deleted.
+ (WebCore::Layout::Line::trailingTrimmableWidth const): Deleted.
+ (WebCore::Layout::Line::hasContent const): Deleted.
+ (WebCore::Layout::Line::appendNonBreakableSpace): Deleted.
+ (WebCore::Layout::Line::appendInlineContainerStart): Deleted.
+ (WebCore::Layout::Line::appendInlineContainerEnd): Deleted.
+ (WebCore::Layout::Line::appendTextContent): Deleted.
+ (WebCore::Layout::Line::appendNonReplacedInlineBox): Deleted.
+ (WebCore::Layout::Line::appendReplacedInlineBox): Deleted.
+ (WebCore::Layout::Line::appendHardLineBreak): Deleted.
+ * layout/inlineformatting/InlineTextItem.h:
+ * layout/inlineformatting/text/TextUtil.cpp:
+ (WebCore::Layout::TextUtil::isTrimmableContent):
+ * layout/inlineformatting/text/TextUtil.h:
+
2019-05-29 Ludovico de Nittis <[email protected]>
PlatformEventKeyboardGtk still uses old key aliases
Modified: trunk/Source/WebCore/Sources.txt (245849 => 245850)
--- trunk/Source/WebCore/Sources.txt 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/Sources.txt 2019-05-29 16:07:19 UTC (rev 245850)
@@ -1349,6 +1349,7 @@
layout/inlineformatting/InlineFormattingContextLineLayout.cpp
layout/inlineformatting/InlineFormattingState.cpp
layout/inlineformatting/InlineInvalidation.cpp
+layout/inlineformatting/InlineLine.cpp
layout/inlineformatting/InlineLineBreaker.cpp
layout/inlineformatting/InlineTextItem.cpp
layout/inlineformatting/text/TextUtil.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (245849 => 245850)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-05-29 16:07:19 UTC (rev 245850)
@@ -2016,6 +2016,7 @@
6ED878C5147493F4004C3597 /* RenderTableCaption.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED878C3147493F4004C3597 /* RenderTableCaption.h */; };
6ED8C37A183BFF8C009E53BD /* BoxShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED8C378183BFF8C009E53BD /* BoxShape.h */; settings = {ATTRIBUTES = (Private, ); }; };
6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */; };
+ 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, ); }; };
6F222B761AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */; };
6F3E1F622136142000A65A08 /* FloatBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F3E1F612136141700A65A08 /* FloatBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9127,6 +9128,8 @@
6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLContextAttributes.cpp; sourceTree = "<group>"; };
6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLContextAttributes.h; sourceTree = "<group>"; };
6F0830DF20B46951008A945B /* BlockFormattingContextGeometry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockFormattingContextGeometry.cpp; sourceTree = "<group>"; };
+ 6F0CD692229ED31900C5994E /* InlineLine.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineLine.cpp; sourceTree = "<group>"; };
+ 6F0CD694229ED32700C5994E /* InlineLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineLine.h; sourceTree = "<group>"; };
6F1CC1DC225F8B4100720AD2 /* InlineTextItem.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineTextItem.cpp; sourceTree = "<group>"; };
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>"; };
@@ -16380,6 +16383,8 @@
115CFA9A208BC140001E6991 /* inlineformatting */ = {
isa = PBXGroup;
children = (
+ 6F0CD694229ED32700C5994E /* InlineLine.h */,
+ 6F0CD692229ED31900C5994E /* InlineLine.cpp */,
6FE7DDDD20EC6E8B008B5B4E /* text */,
6F7CA3C9208C2B2E002F29AB /* InlineFormattingContext.cpp */,
6F7CA3C8208C2B2E002F29AB /* InlineFormattingContext.h */,
@@ -28180,6 +28185,7 @@
714C7C661FDAD2A100F2BEE1 /* AnimationPlaybackEvent.h in Headers */,
714C7C671FDAD2A900F2BEE1 /* AnimationPlaybackEventInit.h in Headers */,
71025ECD1F99F0CE004A250C /* AnimationTimeline.h in Headers */,
+ 6F0CD695229ED32700C5994E /* InlineLine.h in Headers */,
0F580FAF149800D400FB5BD8 /* AnimationUtilities.h in Headers */,
57152B5A21CB3E88000C37CA /* ApduCommand.h in Headers */,
57152B5C21CC1902000C37CA /* ApduResponse.h in Headers */,
Modified: trunk/Source/WebCore/layout/displaytree/DisplayRun.h (245849 => 245850)
--- trunk/Source/WebCore/layout/displaytree/DisplayRun.h 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/layout/displaytree/DisplayRun.h 2019-05-29 16:07:19 UTC (rev 245850)
@@ -27,6 +27,7 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+#include "DisplayRect.h"
#include "InlineItem.h"
#include "LayoutUnit.h"
#include "TextFlags.h"
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp (245849 => 245850)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp 2019-05-29 16:07:19 UTC (rev 245850)
@@ -31,6 +31,7 @@
#include "FloatingContext.h"
#include "FloatingState.h"
#include "InlineFormattingState.h"
+#include "InlineLine.h"
#include "InlineLineBreaker.h"
#include "LayoutBox.h"
#include "LayoutContainer.h"
@@ -40,296 +41,6 @@
namespace WebCore {
namespace Layout {
-struct UsedHeightAndDepth {
- LayoutUnit height;
- LayoutUnit depth;
-};
-
-static UsedHeightAndDepth halfLeadingMetrics(const FontMetrics& fontMetrics, LayoutUnit lineLogicalHeight)
-{
- auto ascent = fontMetrics.ascent();
- auto descent = fontMetrics.descent();
- // 10.8.1 Leading and half-leading
- auto leading = lineLogicalHeight - (ascent + descent);
- // Inline tree is all integer based.
- auto adjustedAscent = std::max((ascent + leading / 2).floor(), 0);
- auto adjustedDescent = std::max((descent + leading / 2).ceil(), 0);
- return { adjustedAscent, adjustedDescent };
-}
-
-class Line {
-public:
- Line(const LayoutState&);
-
- void reset(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimumLineHeight, LayoutUnit baselineOffset);
-
- struct LineItem {
- LineItem(Display::Run, const InlineItem&, bool isCollapsed, bool canBeExtended);
-
- // Relative to the baseline.
- Display::Run inlineRun;
- const InlineItem& inlineItem;
- bool isCollapsed { false };
- bool canBeExtended { false };
- };
-
- using LineItems = Vector<std::unique_ptr<LineItem>>;
- const LineItems& close();
-
- void appendTextContent(const InlineTextItem&, LayoutSize);
- void appendNonReplacedInlineBox(const InlineItem&, LayoutSize);
- void appendReplacedInlineBox(const InlineItem&, LayoutSize);
- void appendInlineContainerStart(const InlineItem&);
- void appendInlineContainerEnd(const InlineItem&);
- void appendHardLineBreak(const InlineItem&);
-
- bool hasContent() const;
-
- LayoutUnit trailingTrimmableWidth() const;
-
- void moveLogicalLeft(LayoutUnit);
- void moveLogicalRight(LayoutUnit);
-
- LayoutUnit availableWidth() const { return logicalWidth() - contentLogicalWidth(); }
-
- LayoutUnit contentLogicalRight() const { return logicalLeft() + contentLogicalWidth(); }
- LayoutUnit contentLogicalWidth() const { return m_contentLogicalWidth; }
-
- LayoutUnit logicalTop() const { return m_logicalTopLeft.y(); }
- LayoutUnit logicalLeft() const { return m_logicalTopLeft.x(); }
- LayoutUnit logicalRight() const { return logicalLeft() + logicalWidth(); }
- LayoutUnit logicalBottom() const { return logicalTop() + logicalHeight(); }
- LayoutUnit logicalWidth() const { return m_lineLogicalWidth; }
- LayoutUnit logicalHeight() const { return m_logicalHeight.height + m_logicalHeight.depth; }
-
-private:
- void appendNonBreakableSpace(const InlineItem&, const Display::Rect& logicalRect);
- void removeTrailingTrimmableContent();
-
- const LayoutState& m_layoutState;
- LineItems m_lineItems;
- ListHashSet<LineItem*> m_trimmableContent;
-
- LayoutPoint m_logicalTopLeft;
- LayoutUnit m_contentLogicalWidth;
-
- UsedHeightAndDepth m_logicalHeight;
- LayoutUnit m_lineLogicalWidth;
-};
-
-Line::LineItem::LineItem(Display::Run inlineRun, const InlineItem& inlineItem, bool isCollapsed, bool canBeExtended)
- : inlineRun(inlineRun)
- , inlineItem(inlineItem)
- , isCollapsed(isCollapsed)
- , canBeExtended(canBeExtended)
-{
-}
-
-Line::Line(const LayoutState& layoutState)
- : m_layoutState(layoutState)
-{
-}
-
-void Line::reset(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimumHeight, LayoutUnit baselineOffset)
-{
- m_logicalTopLeft = topLeft;
- m_lineLogicalWidth = availableWidth;
- m_logicalHeight = { baselineOffset, minimumHeight - baselineOffset };
-
- m_contentLogicalWidth = { };
-
- m_lineItems.clear();
- m_trimmableContent.clear();
-}
-
-const Line::LineItems& Line::close()
-{
- removeTrailingTrimmableContent();
- // Convert inline run geometry from relative to the baseline to relative to logical top.
- for (auto& lineItem : m_lineItems) {
- auto adjustedLogicalTop = lineItem->inlineRun.logicalTop() + m_logicalHeight.height + m_logicalTopLeft.y();
- lineItem->inlineRun.setLogicalTop(adjustedLogicalTop);
- }
- return m_lineItems;
-}
-
-void Line::removeTrailingTrimmableContent()
-{
- // Collapse trimmable trailing content
- LayoutUnit trimmableWidth;
- for (auto* trimmableRun : m_trimmableContent) {
- trimmableRun->isCollapsed = true;
- trimmableWidth += trimmableRun->inlineRun.logicalWidth();
- }
- m_contentLogicalWidth -= trimmableWidth;
-}
-
-void Line::moveLogicalLeft(LayoutUnit delta)
-{
- if (!delta)
- return;
- ASSERT(delta > 0);
- // Shrink the line and move the items.
- m_logicalTopLeft.move(delta, 0);
- m_lineLogicalWidth -= delta;
- for (auto& lineItem : m_lineItems)
- lineItem->inlineRun.moveHorizontally(delta);
-}
-
-void Line::moveLogicalRight(LayoutUnit delta)
-{
- ASSERT(delta > 0);
- m_lineLogicalWidth -= delta;
-}
-
-static bool isTrimmableContent(const InlineItem& inlineItem)
-{
- if (!is<InlineTextItem>(inlineItem))
- return false;
- auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
- return inlineTextItem.isWhitespace() && inlineTextItem.style().collapseWhiteSpace();
-}
-
-LayoutUnit Line::trailingTrimmableWidth() const
-{
- LayoutUnit trimmableWidth;
- for (auto* trimmableRun : m_trimmableContent)
- trimmableWidth += trimmableRun->inlineRun.logicalWidth();
- return trimmableWidth;
-}
-
-bool Line::hasContent() const
-{
- // Return false for empty containers like <span></span>.
- if (m_lineItems.isEmpty())
- return false;
- for (auto& lineItem : m_lineItems) {
- if (lineItem->inlineItem.isContainerStart() || lineItem->inlineItem.isContainerEnd())
- continue;
- if (!lineItem->isCollapsed)
- return true;
- }
- return false;
-}
-
-void Line::appendNonBreakableSpace(const InlineItem& inlineItem, const Display::Rect& logicalRect)
-{
- m_lineItems.append(std::make_unique<LineItem>(Display::Run { logicalRect }, inlineItem, false, false));
- m_contentLogicalWidth += inlineItem.width();
-}
-
-void Line::appendInlineContainerStart(const InlineItem& inlineItem)
-{
- auto& layoutBox = inlineItem.layoutBox();
- auto& style = layoutBox.style();
- auto& fontMetrics = style.fontMetrics();
-
- auto alignAndAdjustLineHeight = [&] {
- LayoutUnit inlineBoxHeight = style.computedLineHeight();
-
- auto halfLeading = halfLeadingMetrics(fontMetrics, inlineBoxHeight);
- if (halfLeading.depth > 0)
- m_logicalHeight.depth = std::max(m_logicalHeight.depth, halfLeading.depth);
- if (halfLeading.height > 0)
- m_logicalHeight.height = std::max(m_logicalHeight.height, halfLeading.height);
- };
-
- alignAndAdjustLineHeight();
- auto& displayBox = m_layoutState.displayBoxForLayoutBox(layoutBox);
- auto containerHeight = fontMetrics.height() + displayBox.verticalBorder() + displayBox.verticalPadding().valueOr(0);
- auto logicalTop = -fontMetrics.ascent() - displayBox.borderTop() - displayBox.paddingTop().valueOr(0);
- auto logicalRect = Display::Rect { logicalTop, contentLogicalRight(), inlineItem.width(), containerHeight };
- appendNonBreakableSpace(inlineItem, logicalRect);
-}
-
-void Line::appendInlineContainerEnd(const InlineItem& inlineItem)
-{
- // This is really just a placeholder to mark the end of the inline level container.
- auto logicalRect = Display::Rect { 0, contentLogicalRight(), inlineItem.width(), 0 };
- appendNonBreakableSpace(inlineItem, logicalRect);
-}
-
-void Line::appendTextContent(const InlineTextItem& inlineItem, LayoutSize runSize)
-{
- auto isTrimmable = isTrimmableContent(inlineItem);
- if (!isTrimmable)
- m_trimmableContent.clear();
-
- auto shouldCollapseCompletely = [&] {
- if (!isTrimmable)
- return false;
- // Leading whitespace.
- if (m_lineItems.isEmpty())
- return true;
- // Check if the last item is trimmable as well.
- for (int index = m_lineItems.size() - 1; index >= 0; --index) {
- auto& inlineItem = m_lineItems[index]->inlineItem;
- if (inlineItem.isBox())
- return false;
- if (inlineItem.isText())
- return inlineItem.isText() && isTrimmableContent(downcast<InlineTextItem>(inlineItem));
- ASSERT(inlineItem.isContainerStart() || inlineItem.isContainerEnd());
- }
- return true;
- };
-
- // Collapsed line items don't contribute to the line width.
- auto isCompletelyCollapsed = shouldCollapseCompletely();
- auto canBeExtended = !isCompletelyCollapsed && !inlineItem.isCollapsed();
- auto logicalRect = Display::Rect { -inlineItem.style().fontMetrics().ascent(), contentLogicalRight(), runSize.width(), runSize.height() };
- auto textContext = Display::Run::TextContext { inlineItem.start(), inlineItem.isCollapsed() ? 1 : inlineItem.length() };
- auto displayRun = Display::Run(logicalRect, textContext);
-
- auto lineItem = std::make_unique<LineItem>(displayRun, inlineItem, isCompletelyCollapsed, canBeExtended);
- if (isTrimmable)
- m_trimmableContent.add(lineItem.get());
-
- m_lineItems.append(WTFMove(lineItem));
- m_contentLogicalWidth += isCompletelyCollapsed ? LayoutUnit() : runSize.width();
-}
-
-void Line::appendNonReplacedInlineBox(const InlineItem& inlineItem, LayoutSize runSize)
-{
- auto alignAndAdjustLineHeight = [&] {
- auto inlineBoxHeight = runSize.height();
- // FIXME: We need to look inside the inline-block's formatting context and check the lineboxes (if any) to be able to baseline align.
- if (inlineItem.layoutBox().establishesInlineFormattingContext()) {
- if (inlineBoxHeight == logicalHeight())
- return;
- // FIXME: This fails when the line height difference comes from font-size diff.
- m_logicalHeight.depth = std::max<LayoutUnit>(0, m_logicalHeight.depth);
- m_logicalHeight.height = std::max(inlineBoxHeight, m_logicalHeight.height);
- return;
- }
- // 0 descent -> baseline aligment for now.
- m_logicalHeight.depth = std::max<LayoutUnit>(0, m_logicalHeight.depth);
- m_logicalHeight.height = std::max(inlineBoxHeight, m_logicalHeight.height);
- };
-
- alignAndAdjustLineHeight();
- auto& displayBox = m_layoutState.displayBoxForLayoutBox(inlineItem.layoutBox());
- auto logicalTop = -runSize.height();
- auto horizontalMargin = displayBox.horizontalMargin();
- auto logicalRect = Display::Rect { logicalTop, contentLogicalRight() + horizontalMargin.start, runSize.width(), runSize.height() };
-
- m_lineItems.append(std::make_unique<LineItem>(Display::Run { logicalRect }, inlineItem, false, false));
- m_contentLogicalWidth += (runSize.width() + horizontalMargin.start + horizontalMargin.end);
- m_trimmableContent.clear();
-}
-
-void Line::appendReplacedInlineBox(const InlineItem& inlineItem, LayoutSize runSize)
-{
- // FIXME Surely replaced boxes behave differently.
- appendNonReplacedInlineBox(inlineItem, runSize);
-}
-
-void Line::appendHardLineBreak(const InlineItem& inlineItem)
-{
- auto ascent = inlineItem.layoutBox().style().fontMetrics().ascent();
- auto logicalRect = Display::Rect { -ascent, contentLogicalRight(), { }, logicalHeight() };
- m_lineItems.append(std::make_unique<LineItem>(Display::Run { logicalRect }, inlineItem, false, false));
-}
-
struct UncommittedContent {
void add(InlineItem&);
void reset();
@@ -395,7 +106,7 @@
auto& formattingRootStyle = m_formattingRoot.style();
auto mimimumLineHeight = formattingRootStyle.computedLineHeight();
- auto baselineOffset = halfLeadingMetrics(formattingRootStyle.fontMetrics(), mimimumLineHeight).height;
+ auto baselineOffset = Line::halfLeadingMetrics(formattingRootStyle.fontMetrics(), mimimumLineHeight).height;
line.reset({ lineLogicalLeft, lineLogicalTop }, availableWidth, mimimumLineHeight, baselineOffset);
}
@@ -491,7 +202,7 @@
trimmableTrailingWidth = { };
lineLogicalRight = { };
}
- if (isTrimmableContent(*inlineItem)) {
+ if (TextUtil::isTrimmableContent(*inlineItem)) {
// Skip leading whitespace.
if (!lineLogicalRight)
continue;
Added: trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp (0 => 245850)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp 2019-05-29 16:07:19 UTC (rev 245850)
@@ -0,0 +1,254 @@
+/*
+ * 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 "InlineLine.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+namespace Layout {
+
+Line::LineItem::LineItem(Display::Run inlineRun, const InlineItem& inlineItem, bool isCollapsed, bool canBeExtended)
+ : inlineRun(inlineRun)
+ , inlineItem(inlineItem)
+ , isCollapsed(isCollapsed)
+ , canBeExtended(canBeExtended)
+{
+}
+
+Line::Line(const LayoutState& layoutState)
+ : m_layoutState(layoutState)
+{
+}
+
+void Line::reset(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimumHeight, LayoutUnit baselineOffset)
+{
+ m_logicalTopLeft = topLeft;
+ m_lineLogicalWidth = availableWidth;
+ m_logicalHeight = { baselineOffset, minimumHeight - baselineOffset };
+
+ m_contentLogicalWidth = { };
+
+ m_lineItems.clear();
+ m_trimmableContent.clear();
+}
+
+const Line::LineItems& Line::close()
+{
+ removeTrailingTrimmableContent();
+ // Convert inline run geometry from relative to the baseline to relative to logical top.
+ for (auto& lineItem : m_lineItems) {
+ auto adjustedLogicalTop = lineItem->inlineRun.logicalTop() + m_logicalHeight.height + m_logicalTopLeft.y();
+ lineItem->inlineRun.setLogicalTop(adjustedLogicalTop);
+ }
+ return m_lineItems;
+}
+
+void Line::removeTrailingTrimmableContent()
+{
+ // Collapse trimmable trailing content
+ LayoutUnit trimmableWidth;
+ for (auto* trimmableRun : m_trimmableContent) {
+ trimmableRun->isCollapsed = true;
+ trimmableWidth += trimmableRun->inlineRun.logicalWidth();
+ }
+ m_contentLogicalWidth -= trimmableWidth;
+}
+
+void Line::moveLogicalLeft(LayoutUnit delta)
+{
+ if (!delta)
+ return;
+ ASSERT(delta > 0);
+ // Shrink the line and move the items.
+ m_logicalTopLeft.move(delta, 0);
+ m_lineLogicalWidth -= delta;
+ for (auto& lineItem : m_lineItems)
+ lineItem->inlineRun.moveHorizontally(delta);
+}
+
+void Line::moveLogicalRight(LayoutUnit delta)
+{
+ ASSERT(delta > 0);
+ m_lineLogicalWidth -= delta;
+}
+
+LayoutUnit Line::trailingTrimmableWidth() const
+{
+ LayoutUnit trimmableWidth;
+ for (auto* trimmableRun : m_trimmableContent)
+ trimmableWidth += trimmableRun->inlineRun.logicalWidth();
+ return trimmableWidth;
+}
+
+bool Line::hasContent() const
+{
+ // Return false for empty containers like <span></span>.
+ if (m_lineItems.isEmpty())
+ return false;
+ for (auto& lineItem : m_lineItems) {
+ if (lineItem->inlineItem.isContainerStart() || lineItem->inlineItem.isContainerEnd())
+ continue;
+ if (!lineItem->isCollapsed)
+ return true;
+ }
+ return false;
+}
+
+void Line::appendNonBreakableSpace(const InlineItem& inlineItem, const Display::Rect& logicalRect)
+{
+ m_lineItems.append(std::make_unique<LineItem>(Display::Run { logicalRect }, inlineItem, false, false));
+ m_contentLogicalWidth += inlineItem.width();
+}
+
+void Line::appendInlineContainerStart(const InlineItem& inlineItem)
+{
+ auto& layoutBox = inlineItem.layoutBox();
+ auto& style = layoutBox.style();
+ auto& fontMetrics = style.fontMetrics();
+
+ auto alignAndAdjustLineHeight = [&] {
+ LayoutUnit inlineBoxHeight = style.computedLineHeight();
+
+ auto halfLeading = halfLeadingMetrics(fontMetrics, inlineBoxHeight);
+ if (halfLeading.depth > 0)
+ m_logicalHeight.depth = std::max(m_logicalHeight.depth, halfLeading.depth);
+ if (halfLeading.height > 0)
+ m_logicalHeight.height = std::max(m_logicalHeight.height, halfLeading.height);
+ };
+
+ alignAndAdjustLineHeight();
+ auto& displayBox = m_layoutState.displayBoxForLayoutBox(layoutBox);
+ auto containerHeight = fontMetrics.height() + displayBox.verticalBorder() + displayBox.verticalPadding().valueOr(0);
+ auto logicalTop = -fontMetrics.ascent() - displayBox.borderTop() - displayBox.paddingTop().valueOr(0);
+ auto logicalRect = Display::Rect { logicalTop, contentLogicalRight(), inlineItem.width(), containerHeight };
+ appendNonBreakableSpace(inlineItem, logicalRect);
+}
+
+void Line::appendInlineContainerEnd(const InlineItem& inlineItem)
+{
+ // This is really just a placeholder to mark the end of the inline level container.
+ auto logicalRect = Display::Rect { 0, contentLogicalRight(), inlineItem.width(), 0 };
+ appendNonBreakableSpace(inlineItem, logicalRect);
+}
+
+void Line::appendTextContent(const InlineTextItem& inlineItem, LayoutSize runSize)
+{
+ auto isTrimmable = TextUtil::isTrimmableContent(inlineItem);
+ if (!isTrimmable)
+ m_trimmableContent.clear();
+
+ auto shouldCollapseCompletely = [&] {
+ if (!isTrimmable)
+ return false;
+ // Leading whitespace.
+ if (m_lineItems.isEmpty())
+ return true;
+ // Check if the last item is trimmable as well.
+ for (int index = m_lineItems.size() - 1; index >= 0; --index) {
+ auto& inlineItem = m_lineItems[index]->inlineItem;
+ if (inlineItem.isBox())
+ return false;
+ if (inlineItem.isText())
+ return TextUtil::isTrimmableContent(inlineItem);
+ ASSERT(inlineItem.isContainerStart() || inlineItem.isContainerEnd());
+ }
+ return true;
+ };
+
+ // Collapsed line items don't contribute to the line width.
+ auto isCompletelyCollapsed = shouldCollapseCompletely();
+ auto canBeExtended = !isCompletelyCollapsed && !inlineItem.isCollapsed();
+ auto logicalRect = Display::Rect { -inlineItem.style().fontMetrics().ascent(), contentLogicalRight(), runSize.width(), runSize.height() };
+ auto textContext = Display::Run::TextContext { inlineItem.start(), inlineItem.isCollapsed() ? 1 : inlineItem.length() };
+ auto displayRun = Display::Run(logicalRect, textContext);
+
+ auto lineItem = std::make_unique<LineItem>(displayRun, inlineItem, isCompletelyCollapsed, canBeExtended);
+ if (isTrimmable)
+ m_trimmableContent.add(lineItem.get());
+
+ m_lineItems.append(WTFMove(lineItem));
+ m_contentLogicalWidth += isCompletelyCollapsed ? LayoutUnit() : runSize.width();
+}
+
+void Line::appendNonReplacedInlineBox(const InlineItem& inlineItem, LayoutSize runSize)
+{
+ auto alignAndAdjustLineHeight = [&] {
+ auto inlineBoxHeight = runSize.height();
+ // FIXME: We need to look inside the inline-block's formatting context and check the lineboxes (if any) to be able to baseline align.
+ if (inlineItem.layoutBox().establishesInlineFormattingContext()) {
+ if (inlineBoxHeight == logicalHeight())
+ return;
+ // FIXME: This fails when the line height difference comes from font-size diff.
+ m_logicalHeight.depth = std::max<LayoutUnit>(0, m_logicalHeight.depth);
+ m_logicalHeight.height = std::max(inlineBoxHeight, m_logicalHeight.height);
+ return;
+ }
+ // 0 descent -> baseline aligment for now.
+ m_logicalHeight.depth = std::max<LayoutUnit>(0, m_logicalHeight.depth);
+ m_logicalHeight.height = std::max(inlineBoxHeight, m_logicalHeight.height);
+ };
+
+ alignAndAdjustLineHeight();
+ auto& displayBox = m_layoutState.displayBoxForLayoutBox(inlineItem.layoutBox());
+ auto logicalTop = -runSize.height();
+ auto horizontalMargin = displayBox.horizontalMargin();
+ auto logicalRect = Display::Rect { logicalTop, contentLogicalRight() + horizontalMargin.start, runSize.width(), runSize.height() };
+
+ m_lineItems.append(std::make_unique<LineItem>(Display::Run { logicalRect }, inlineItem, false, false));
+ m_contentLogicalWidth += (runSize.width() + horizontalMargin.start + horizontalMargin.end);
+ m_trimmableContent.clear();
+}
+
+void Line::appendReplacedInlineBox(const InlineItem& inlineItem, LayoutSize runSize)
+{
+ // FIXME Surely replaced boxes behave differently.
+ appendNonReplacedInlineBox(inlineItem, runSize);
+}
+
+void Line::appendHardLineBreak(const InlineItem& inlineItem)
+{
+ auto ascent = inlineItem.layoutBox().style().fontMetrics().ascent();
+ auto logicalRect = Display::Rect { -ascent, contentLogicalRight(), { }, logicalHeight() };
+ m_lineItems.append(std::make_unique<LineItem>(Display::Run { logicalRect }, inlineItem, false, false));
+}
+
+Line::UsedHeightAndDepth Line::halfLeadingMetrics(const FontMetrics& fontMetrics, LayoutUnit lineLogicalHeight)
+{
+ auto ascent = fontMetrics.ascent();
+ auto descent = fontMetrics.descent();
+ // 10.8.1 Leading and half-leading
+ auto leading = lineLogicalHeight - (ascent + descent);
+ // Inline tree is all integer based.
+ auto adjustedAscent = std::max((ascent + leading / 2).floor(), 0);
+ auto adjustedDescent = std::max((descent + leading / 2).ceil(), 0);
+ return { adjustedAscent, adjustedDescent };
+}
+
+}
+}
+
+#endif
Added: trunk/Source/WebCore/layout/inlineformatting/InlineLine.h (0 => 245850)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLine.h (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLine.h 2019-05-29 16:07:19 UTC (rev 245850)
@@ -0,0 +1,104 @@
+/*
+ * 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 "DisplayRun.h"
+#include "InlineItem.h"
+
+namespace WebCore {
+namespace Layout {
+
+class Line {
+public:
+ Line(const LayoutState&);
+
+ void reset(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimumLineHeight, LayoutUnit baselineOffset);
+
+ struct LineItem {
+ LineItem(Display::Run, const InlineItem&, bool isCollapsed, bool canBeExtended);
+
+ // Relative to the baseline.
+ Display::Run inlineRun;
+ const InlineItem& inlineItem;
+ bool isCollapsed { false };
+ bool canBeExtended { false };
+ };
+
+ using LineItems = Vector<std::unique_ptr<LineItem>>;
+ const LineItems& close();
+
+ void appendTextContent(const InlineTextItem&, LayoutSize);
+ void appendNonReplacedInlineBox(const InlineItem&, LayoutSize);
+ void appendReplacedInlineBox(const InlineItem&, LayoutSize);
+ void appendInlineContainerStart(const InlineItem&);
+ void appendInlineContainerEnd(const InlineItem&);
+ void appendHardLineBreak(const InlineItem&);
+
+ bool hasContent() const;
+
+ LayoutUnit trailingTrimmableWidth() const;
+
+ void moveLogicalLeft(LayoutUnit);
+ void moveLogicalRight(LayoutUnit);
+
+ LayoutUnit availableWidth() const { return logicalWidth() - contentLogicalWidth(); }
+
+ LayoutUnit contentLogicalRight() const { return logicalLeft() + contentLogicalWidth(); }
+ LayoutUnit contentLogicalWidth() const { return m_contentLogicalWidth; }
+
+ LayoutUnit logicalTop() const { return m_logicalTopLeft.y(); }
+ LayoutUnit logicalLeft() const { return m_logicalTopLeft.x(); }
+ LayoutUnit logicalRight() const { return logicalLeft() + logicalWidth(); }
+ LayoutUnit logicalBottom() const { return logicalTop() + logicalHeight(); }
+ LayoutUnit logicalWidth() const { return m_lineLogicalWidth; }
+ LayoutUnit logicalHeight() const { return m_logicalHeight.height + m_logicalHeight.depth; }
+
+ struct UsedHeightAndDepth {
+ LayoutUnit height;
+ LayoutUnit depth;
+ };
+ static UsedHeightAndDepth halfLeadingMetrics(const FontMetrics&, LayoutUnit lineLogicalHeight);
+
+private:
+ void appendNonBreakableSpace(const InlineItem&, const Display::Rect& logicalRect);
+ void removeTrailingTrimmableContent();
+
+ const LayoutState& m_layoutState;
+ LineItems m_lineItems;
+ ListHashSet<LineItem*> m_trimmableContent;
+
+ LayoutPoint m_logicalTopLeft;
+ LayoutUnit m_contentLogicalWidth;
+
+ UsedHeightAndDepth m_logicalHeight;
+ LayoutUnit m_lineLogicalWidth;
+};
+
+}
+}
+#endif
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h (245849 => 245850)
--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h 2019-05-29 16:07:19 UTC (rev 245850)
@@ -27,6 +27,7 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+#include "InlineFormattingState.h"
#include "InlineItem.h"
namespace WebCore {
Modified: trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp (245849 => 245850)
--- trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp 2019-05-29 16:07:19 UTC (rev 245850)
@@ -89,6 +89,14 @@
return width;
}
+bool TextUtil::isTrimmableContent(const InlineItem& inlineItem)
+{
+ if (!is<InlineTextItem>(inlineItem))
+ return false;
+ auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
+ return inlineTextItem.isWhitespace() && inlineTextItem.style().collapseWhiteSpace();
}
+
}
+}
#endif
Modified: trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h (245849 => 245850)
--- trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h 2019-05-29 13:07:02 UTC (rev 245849)
+++ trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h 2019-05-29 16:07:19 UTC (rev 245850)
@@ -36,6 +36,7 @@
public:
static LayoutUnit width(const InlineBox&, unsigned from, unsigned to, LayoutUnit contentLogicalLeft);
static Optional<unsigned> hyphenPositionBefore(const InlineItem&, unsigned from, unsigned length);
+ static bool isTrimmableContent(const InlineItem&);
private:
static LayoutUnit fixedPitchWidth(String, const RenderStyle&, unsigned from, unsigned to, LayoutUnit contentLogicalLeft);