WebKit Bugzilla
Attachment 370849 Details for
Bug 198332
: [LFC][IFC] Move Line class to a dedicated file
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198332-20190529080640.patch (text/plain), 37.40 KB, created by
zalan
on 2019-05-29 08:06:44 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2019-05-29 08:06:44 PDT
Size:
37.40 KB
patch
obsolete
>Subversion Revision: 245776 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 88fececca45aa74012ab4342060b69ff9f0c8180..dd4203cfe642293cd9e0c7ae6b62a06eeffbc918 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,51 @@ >+2019-05-29 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][IFC] Move Line class to a dedicated file >+ https://bugs.webkit.org/show_bug.cgi?id=198332 >+ <rdar://problem/51221403> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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-27 Zalan Bujtas <zalan@apple.com> > > [LFC][IFC] Decouple line layout and processing inline runs. >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index ca248f3eba6144ed468157443b707be72a423d58..11eb486c727e25e5f7156026ea117db765aa07e0 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -1348,6 +1348,7 @@ layout/inlineformatting/InlineFormattingContextGeometry.cpp > 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 >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index cee0d4c0a5b8091c0a321b2cfc0d6d742943cfe5..4f827b0db8701fd71b09adf96a32ba357c8edc1e 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -2012,6 +2012,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, ); }; }; >@@ -9116,6 +9117,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>"; }; >@@ -16369,6 +16372,8 @@ > 115CFA9A208BC140001E6991 /* inlineformatting */ = { > isa = PBXGroup; > children = ( >+ 6F0CD694229ED32700C5994E /* InlineLine.h */, >+ 6F0CD692229ED31900C5994E /* InlineLine.cpp */, > 6FE7DDDD20EC6E8B008B5B4E /* text */, > 6F7CA3C9208C2B2E002F29AB /* InlineFormattingContext.cpp */, > 6F7CA3C8208C2B2E002F29AB /* InlineFormattingContext.h */, >@@ -28162,6 +28167,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 */, >diff --git a/Source/WebCore/layout/displaytree/DisplayRun.h b/Source/WebCore/layout/displaytree/DisplayRun.h >index 63929036083c40b039f9dec4933f6142a74da1b0..7ae3b409d76116f2e9d13cc31eb6e56063b1076f 100644 >--- a/Source/WebCore/layout/displaytree/DisplayRun.h >+++ b/Source/WebCore/layout/displaytree/DisplayRun.h >@@ -27,6 +27,7 @@ > > #if ENABLE(LAYOUT_FORMATTING_CONTEXT) > >+#include "DisplayRect.h" > #include "InlineItem.h" > #include "LayoutUnit.h" > #include "TextFlags.h" >diff --git a/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp b/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp >index 10eb208809d5250e78970225a928f883d0b8de09..8186329d11fa5a686811a904a1fbd90cb889b50b 100644 >--- a/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp >+++ b/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp >@@ -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 @@ void InlineFormattingContext::LineLayout::initializeLine(Line& line, LayoutUnit > > 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 @@ LayoutUnit InlineFormattingContext::LineLayout::computedIntrinsicWidth(LayoutUni > trimmableTrailingWidth = { }; > lineLogicalRight = { }; > } >- if (isTrimmableContent(*inlineItem)) { >+ if (TextUtil::isTrimmableContent(*inlineItem)) { > // Skip leading whitespace. > if (!lineLogicalRight) > continue; >diff --git a/Source/WebCore/layout/inlineformatting/InlineLine.cpp b/Source/WebCore/layout/inlineformatting/InlineLine.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..c27bea3f7fda3834aef2f6cec52930955bd146e1 >--- /dev/null >+++ b/Source/WebCore/layout/inlineformatting/InlineLine.cpp >@@ -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 >diff --git a/Source/WebCore/layout/inlineformatting/InlineLine.h b/Source/WebCore/layout/inlineformatting/InlineLine.h >new file mode 100644 >index 0000000000000000000000000000000000000000..38665cb351b21a7ffa28ef140d5e318279f27a8e >--- /dev/null >+++ b/Source/WebCore/layout/inlineformatting/InlineLine.h >@@ -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 >diff --git a/Source/WebCore/layout/inlineformatting/InlineTextItem.h b/Source/WebCore/layout/inlineformatting/InlineTextItem.h >index 2874f28a31dcd00abede8897574513cbe29e16de..c7d8f34a4b60c1f9264385cf3f0702dfc5a5314a 100644 >--- a/Source/WebCore/layout/inlineformatting/InlineTextItem.h >+++ b/Source/WebCore/layout/inlineformatting/InlineTextItem.h >@@ -27,6 +27,7 @@ > > #if ENABLE(LAYOUT_FORMATTING_CONTEXT) > >+#include "InlineFormattingState.h" > #include "InlineItem.h" > > namespace WebCore { >diff --git a/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp b/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp >index c139eaba757696d3c876f444dcc97fec7c3a63eb..efe74b5a045d6ac5968469663b2a32d8e58d9299 100644 >--- a/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp >+++ b/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp >@@ -89,6 +89,14 @@ LayoutUnit TextUtil::fixedPitchWidth(String text, const RenderStyle& style, unsi > 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 >diff --git a/Source/WebCore/layout/inlineformatting/text/TextUtil.h b/Source/WebCore/layout/inlineformatting/text/TextUtil.h >index d0fea6ad1ddd729d74f9bdfb1bc9d21c987d2e0c..5cf77bee2ca0a98944b7767b375115d760406406 100644 >--- a/Source/WebCore/layout/inlineformatting/text/TextUtil.h >+++ b/Source/WebCore/layout/inlineformatting/text/TextUtil.h >@@ -36,6 +36,7 @@ class TextUtil { > 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);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198332
: 370849