Diff
Modified: trunk/Source/WebCore/ChangeLog (251328 => 251329)
--- trunk/Source/WebCore/ChangeLog 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/ChangeLog 2019-10-20 14:56:32 UTC (rev 251329)
@@ -1,3 +1,37 @@
+2019-10-20 Zalan Bujtas <za...@apple.com>
+
+ [LFC][IFC] Move the collapsed bit from InlineItems to runs
+ https://bugs.webkit.org/show_bug.cgi?id=203183
+
+ Reviewed by Antti Koivisto.
+ <rdar://problem/56437181>
+
+ Let's not store the collapsed bit on the InlineTextItem. All we need to know is whether the InlineTextItem content is collapsible or not.
+ Also when only the white-space property changes (going from preserve whitespace to not and vice versa) we don't actually need to rebuild the
+ InlinItem list since they don't carry any layout dependent information.
+ This patch also fixes leading/trailing content preservation.
+
+ * layout/inlineformatting/InlineLine.cpp:
+ (WebCore::Layout::Line::Run::canBeExtended const):
+ (WebCore::Layout::shouldPreserveTrailingContent):
+ (WebCore::Layout::shouldPreserveLeadingContent):
+ (WebCore::Layout::Line::appendTextContent):
+ * layout/inlineformatting/InlineLine.h:
+ (WebCore::Layout::Line::Run::isCollapsed const):
+ (WebCore::Layout::Line::Run::setIsCollapsed):
+ * layout/inlineformatting/InlineLineLayout.cpp:
+ (WebCore::Layout::inlineItemWidth):
+ * layout/inlineformatting/InlineTextItem.cpp:
+ (WebCore::Layout::InlineTextItem::createAndAppendTextItems):
+ (WebCore::Layout::InlineTextItem::InlineTextItem):
+ (WebCore::Layout::InlineTextItem::split const):
+ * layout/inlineformatting/InlineTextItem.h:
+ (WebCore::Layout::InlineTextItem::isCollapsible const):
+ (WebCore::Layout::InlineTextItem::isCollapsed const): Deleted.
+ * layout/inlineformatting/text/TextUtil.cpp:
+ (WebCore::Layout::TextUtil::isTrimmableContent): Deleted.
+ * layout/inlineformatting/text/TextUtil.h:
+
2019-10-19 Chris Dumez <cdu...@apple.com>
FileReader should not prevent entering the back/forward cache
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLine.cpp 2019-10-20 14:56:32 UTC (rev 251329)
@@ -54,7 +54,10 @@
{
if (!isText())
return false;
- return !downcast<InlineTextItem>(m_inlineItem).isCollapsed() && !isVisuallyEmpty();
+ // Non-collapsed text runs can be merged into one continuous run.
+ if (isVisuallyEmpty())
+ return false;
+ return !isCollapsed();
}
Line::Line(const InlineFormattingContext& inlineFormattingContext, const InitialConstraints& initialConstraints, Optional<TextAlignMode> horizontalAlignment, SkipAlignment skipAlignment)
@@ -79,6 +82,22 @@
return !(boxGeometry.horizontalBorder() || (boxGeometry.horizontalPadding() && boxGeometry.horizontalPadding().value()));
}
+static bool shouldPreserveTrailingContent(const InlineTextItem& inlineTextItem)
+{
+ if (!inlineTextItem.isWhitespace())
+ return true;
+ auto whitespace = inlineTextItem.style().whiteSpace();
+ return whitespace == WhiteSpace::Pre || whitespace == WhiteSpace::PreWrap;
+}
+
+static bool shouldPreserveLeadingContent(const InlineTextItem& inlineTextItem)
+{
+ if (!inlineTextItem.isWhitespace())
+ return true;
+ auto whitespace = inlineTextItem.style().whiteSpace();
+ return whitespace == WhiteSpace::Pre || whitespace == WhiteSpace::PreWrap || whitespace == WhiteSpace::BreakSpaces;
+}
+
bool Line::isVisuallyEmpty() const
{
// FIXME: This should be cached instead -as the inline items are being added.
@@ -324,7 +343,7 @@
void Line::appendTextContent(const InlineTextItem& inlineItem, LayoutUnit logicalWidth)
{
- auto isTrimmable = TextUtil::isTrimmableContent(inlineItem);
+ auto isTrimmable = !shouldPreserveTrailingContent(inlineItem);
if (!isTrimmable)
m_trimmableContent.clear();
@@ -334,18 +353,22 @@
ASSERT(!logicalWidth);
return true;
}
- if (!isTrimmable)
- return false;
// Leading whitespace.
if (m_runList.isEmpty())
- return true;
- // Check if the last item is trimmable as well.
- for (int index = m_runList.size() - 1; index >= 0; --index) {
- auto& run = m_runList[index];
+ return !shouldPreserveLeadingContent(inlineItem);
+
+ if (!inlineItem.isCollapsible())
+ return false;
+ // Check if the last item is collapsed as well.
+ for (auto i = m_runList.size(); i--;) {
+ auto& run = m_runList[i];
if (run->isBox())
return false;
+ // When the previous text run is collapsed, this collapsible run collapses completely.
if (run->isText())
- return run->isWhitespace() && run->layoutBox().style().collapseWhiteSpace();
+ return run->isCollapsed();
+ // Collapsing works across inline containers: "<span> </span> " <- the trailing whitespace collapses completely.
+ // Not that when the inline container has preserve whitespace style, "<span style="white-space: pre"> </span> " <- this whitespace stays around.
ASSERT(run->isContainerStart() || run->isContainerEnd());
}
return true;
@@ -359,11 +382,15 @@
logicalRect.setHeight(inlineItemContentHeight(inlineItem));
}
+ auto collapseRun = inlineItem.isCollapsible();
auto contentStart = inlineItem.start();
- auto contentLength = inlineItem.isCollapsed() ? 1 : inlineItem.length();
+ auto contentLength = collapseRun ? 1 : inlineItem.length();
auto textContent = inlineItem.layoutBox().textContent().substring(contentStart, contentLength);
auto lineItem = makeUnique<Run>(inlineItem, Display::Run { inlineItem.style(), logicalRect, Display::Run::TextContext { contentStart, contentLength, textContent } });
+
auto isVisuallyEmpty = willCollapseCompletely();
+ if (collapseRun)
+ lineItem->setIsCollapsed();
if (isVisuallyEmpty)
lineItem->setVisuallyIsEmpty();
else if (isTrimmable)
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLine.h (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLine.h 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLine.h 2019-10-20 14:56:32 UTC (rev 251329)
@@ -74,6 +74,7 @@
const Display::Rect& logicalRect() const { return m_displayRun.logicalRect(); }
bool isVisuallyEmpty() const { return m_isVisuallyEmpty; }
+ bool isCollapsed() const { return m_isCollapsed; }
bool isText() const { return m_inlineItem.isText(); }
bool isBox() const { return m_inlineItem.isBox(); }
@@ -90,6 +91,7 @@
void expand(const Run&);
void setVisuallyIsEmpty() { m_isVisuallyEmpty = true; }
+ void setIsCollapsed() { m_isCollapsed = true; }
bool isWhitespace() const;
bool canBeExtended() const;
@@ -96,6 +98,7 @@
const InlineItem& m_inlineItem;
Display::Run m_displayRun;
+ bool m_isCollapsed { false };
bool m_isVisuallyEmpty { false };
};
using RunList = Vector<std::unique_ptr<Run>>;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp 2019-10-20 14:56:32 UTC (rev 251329)
@@ -41,7 +41,7 @@
if (is<InlineTextItem>(inlineItem)) {
auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
- auto end = inlineTextItem.isCollapsed() ? inlineTextItem.start() + 1 : inlineTextItem.end();
+ auto end = inlineTextItem.isCollapsible() ? inlineTextItem.start() + 1 : inlineTextItem.end();
return TextUtil::width(inlineTextItem.layoutBox(), inlineTextItem.start(), end, contentLogicalLeft);
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp 2019-10-20 14:56:32 UTC (rev 251329)
@@ -89,40 +89,37 @@
{
auto text = inlineBox.textContent();
if (!text.length())
- return inlineContent.append(makeUnique<InlineTextItem>(inlineBox, 0, 0, false, false));
+ return inlineContent.append(makeUnique<InlineTextItem>(inlineBox, 0, 0, false));
auto& style = inlineBox.style();
auto preserveNewline = style.preserveNewline();
- auto collapseWhiteSpace = style.collapseWhiteSpace();
LazyLineBreakIterator lineBreakIterator(text);
unsigned currentPosition = 0;
while (currentPosition < text.length()) {
// Soft linebreak?
if (isSoftLineBreak(text[currentPosition], preserveNewline)) {
- inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, 1, true, false));
+ inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, 1, true));
++currentPosition;
continue;
}
if (isWhitespaceCharacter(text[currentPosition], preserveNewline)) {
auto length = moveToNextNonWhitespacePosition(text, currentPosition, preserveNewline);
- auto isCollapsed = collapseWhiteSpace && length > 1;
- inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, length, true, isCollapsed));
+ inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, length, true));
currentPosition += length;
continue;
}
auto length = moveToNextBreakablePosition(currentPosition, lineBreakIterator, style);
- inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, length, false, false));
+ inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, length, false));
currentPosition += length;
}
}
-InlineTextItem::InlineTextItem(const Box& inlineBox, unsigned start, unsigned length, bool isWhitespace, bool isCollapsed)
+InlineTextItem::InlineTextItem(const Box& inlineBox, unsigned start, unsigned length, bool isWhitespace)
: InlineItem(inlineBox, Type::Text)
, m_start(start)
, m_length(length)
, m_isWhitespace(isWhitespace)
- , m_isCollapsed(isCollapsed)
{
}
@@ -130,7 +127,7 @@
{
RELEASE_ASSERT(splitPosition >= this->start());
RELEASE_ASSERT(splitPosition + length <= end());
- return makeUnique<InlineTextItem>(layoutBox(), splitPosition, length, isWhitespace(), isCollapsed());
+ return makeUnique<InlineTextItem>(layoutBox(), splitPosition, length, isWhitespace());
}
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h 2019-10-20 14:56:32 UTC (rev 251329)
@@ -37,7 +37,7 @@
public:
static void createAndAppendTextItems(InlineItems&, const Box&);
- InlineTextItem(const Box&, unsigned start, unsigned length, bool isWhitespace, bool isCollapsed);
+ InlineTextItem(const Box&, unsigned start, unsigned length, bool isWhitespace);
unsigned start() const { return m_start; }
unsigned end() const { return start() + length(); }
@@ -44,7 +44,7 @@
unsigned length() const { return m_length; }
bool isWhitespace() const { return m_isWhitespace; }
- bool isCollapsed() const { return m_isCollapsed; }
+ bool isCollapsible() const { return isWhitespace() && style().collapseWhiteSpace(); }
std::unique_ptr<InlineTextItem> split(unsigned splitPosition, unsigned length) const;
@@ -52,7 +52,6 @@
unsigned m_start { 0 };
unsigned m_length { 0 };
bool m_isWhitespace { false };
- bool m_isCollapsed { false };
};
}
Modified: trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp 2019-10-20 14:56:32 UTC (rev 251329)
@@ -89,14 +89,6 @@
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();
-}
-
TextUtil::SplitData TextUtil::split(const Box& inlineBox, unsigned startPosition, unsigned length, LayoutUnit textWidth, LayoutUnit availableWidth, LayoutUnit contentLogicalLeft)
{
// FIXME This should take hypens into account.
Modified: trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h (251328 => 251329)
--- trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h 2019-10-19 23:50:32 UTC (rev 251328)
+++ trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h 2019-10-20 14:56:32 UTC (rev 251329)
@@ -36,7 +36,6 @@
public:
static LayoutUnit width(const Box&, unsigned from, unsigned to, LayoutUnit contentLogicalLeft);
static Optional<unsigned> hyphenPositionBefore(const InlineItem&, unsigned from, unsigned length);
- static bool isTrimmableContent(const InlineItem&);
struct SplitData {
unsigned start { 0 };
unsigned length { 0 };