Diff
Modified: trunk/Source/WebCore/ChangeLog (254749 => 254750)
--- trunk/Source/WebCore/ChangeLog 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/ChangeLog 2020-01-17 16:24:33 UTC (rev 254750)
@@ -1,3 +1,30 @@
+2020-01-17 Zalan Bujtas <[email protected]>
+
+ [LFC][IFC] Optimize LineBuilder::appendTextContent for the most common inline content
+ https://bugs.webkit.org/show_bug.cgi?id=206397
+ <rdar://problem/58671338>
+
+ Reviewed by Antti Koivisto.
+
+ ~2% progression on PerformanceTests/Layout/line-layout-simple.html.
+
+ * layout/inlineformatting/InlineLineBuilder.cpp:
+ (WebCore::Layout::LineBuilder::LineBuilder):
+ (WebCore::Layout::shouldPreserveLeadingContent):
+ (WebCore::Layout::LineBuilder::appendTextContent):
+ (WebCore::Layout::LineBuilder::appendLineBreak):
+ (WebCore::Layout::LineBuilder::InlineItemRun::InlineItemRun):
+ * layout/inlineformatting/InlineLineBuilder.h:
+ (WebCore::Layout::LineBuilder::InlineItemRun::setIsCollapsed): Deleted.
+ * layout/inlineformatting/InlineTextItem.cpp:
+ (WebCore::Layout::InlineTextItem::InlineTextItem):
+ * layout/inlineformatting/InlineTextItem.h:
+ (WebCore::Layout::InlineTextItem::isCollapsible const):
+ * layout/inlineformatting/text/TextUtil.cpp:
+ (WebCore::Layout::TextUtil::shouldPreserveTrailingWhitespace): Deleted.
+ * layout/inlineformatting/text/TextUtil.h:
+ (WebCore::Layout::TextUtil::shouldPreserveTrailingWhitespace):
+
2020-01-17 Antti Koivisto <[email protected]>
[LFC][IFC] Allocate InlineItems in a vector
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineItem.cpp (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/InlineItem.cpp 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineItem.cpp 2020-01-17 16:24:33 UTC (rev 254750)
@@ -38,6 +38,7 @@
uint8_t enum1;
uint8_t enum2;
bool widthBool;
+ bool isCollapsible;
InlineLayoutUnit width;
unsigned start;
unsigned length;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineItem.h (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/InlineItem.h 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineItem.h 2020-01-17 16:24:33 UTC (rev 254750)
@@ -60,6 +60,7 @@
enum class TextItemType : uint8_t { Undefined, Whitespace, NonWhitespace };
TextItemType m_textItemType { TextItemType::Undefined };
bool m_hasWidth { false };
+ bool m_isCollapsible { false };
InlineLayoutUnit m_width { };
unsigned m_length { 0 };
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp 2020-01-17 16:24:33 UTC (rev 254750)
@@ -189,6 +189,7 @@
, m_collapsibleContent(m_inlineItemRuns)
, m_horizontalAlignment(horizontalAlignment)
, m_isIntrinsicSizing(intrinsicSizing == IntrinsicSizing::Yes)
+ , m_shouldIgnoreTrailingLetterSpacing(RuntimeEnabledFeatures::sharedFeatures().layoutFormattingContextIntegrationEnabled())
{
}
@@ -220,7 +221,7 @@
m_lineIsVisuallyEmptyBeforeCollapsibleContent = { };
}
-static bool shouldPreserveLeadingContent(const InlineTextItem& inlineTextItem)
+static inline bool shouldPreserveLeadingContent(const InlineTextItem& inlineTextItem)
{
if (!inlineTextItem.isWhitespace())
return true;
@@ -635,15 +636,12 @@
void LineBuilder::appendTextContent(const InlineTextItem& inlineItem, InlineLayoutUnit logicalWidth)
{
+ auto isCollapsible = inlineItem.isCollapsible();
auto willCollapseCompletely = [&] {
- if (!inlineItem.isCollapsible())
+ if (!isCollapsible)
return false;
- // Leading whitespace.
- if (m_inlineItemRuns.isEmpty())
- return !shouldPreserveLeadingContent(inlineItem);
// Check if the last item is collapsed as well.
- for (auto i = m_inlineItemRuns.size(); i--;) {
- auto& run = m_inlineItemRuns[i];
+ for (auto& run : WTF::makeReversedRange(m_inlineItemRuns)) {
if (run.isBox())
return false;
// https://drafts.csswg.org/css-text-3/#white-space-phase-1
@@ -655,34 +653,27 @@
return run.isCollapsible();
ASSERT(run.isContainerStart() || run.isContainerEnd());
}
- return true;
+ // Leading whitespace.
+ return !shouldPreserveLeadingContent(inlineItem);
};
auto collapsesToZeroAdvanceWidth = willCollapseCompletely();
- auto collapsedRun = inlineItem.isCollapsible() && inlineItem.length() > 1;
- auto contentStart = inlineItem.start();
+ logicalWidth = collapsesToZeroAdvanceWidth ? 0 : logicalWidth;
+ auto collapsedRun = isCollapsible && inlineItem.length() > 1;
auto contentLength = collapsedRun ? 1 : inlineItem.length();
- m_inlineItemRuns.append({ inlineItem, contentLogicalWidth(), logicalWidth, Display::Run::TextContext { contentStart, contentLength, inlineItem.layoutBox().textContext()->content } });
- auto& lineRun = m_inlineItemRuns.last();
+ m_inlineItemRuns.append({ inlineItem, contentLogicalWidth(), logicalWidth, collapsedRun, collapsesToZeroAdvanceWidth, Display::Run::TextContext { inlineItem.start(), contentLength, inlineItem.layoutBox().textContext()->content } });
+ m_lineBox.expandHorizontally(logicalWidth);
- if (collapsesToZeroAdvanceWidth)
- lineRun.setCollapsesToZeroAdvanceWidth();
-
- if (collapsedRun)
- lineRun.setIsCollapsed();
-
- m_lineBox.expandHorizontally(lineRun.logicalWidth());
-
- // Existing trailing collapsible content can only be expanded if the current run is fully collapsible.
- auto collapsibleListNeedsReset = !m_collapsibleContent.isEmpty() && !lineRun.isCollapsibleWhitespace();
- if (collapsibleListNeedsReset)
- m_collapsibleContent.reset();
- auto isCollapsible = lineRun.isCollapsibleWhitespace() || lineRun.hasTrailingLetterSpacing();
- if (isCollapsible) {
+ if (isCollapsible && !TextUtil::shouldPreserveTrailingWhitespace(inlineItem.style())) {
// If we ever collapse this content, we need to know if the line visibility state needs to be recomputed.
if (m_collapsibleContent.isEmpty())
m_lineIsVisuallyEmptyBeforeCollapsibleContent = isVisuallyEmpty();
m_collapsibleContent.append(m_inlineItemRuns.size() - 1);
+ } else {
+ // Existing trailing collapsible content can only be expanded if the current run is fully collapsible.
+ m_collapsibleContent.reset();
+ if (!m_shouldIgnoreTrailingLetterSpacing && !inlineItem.isWhitespace() && inlineItem.style().letterSpacing() > 0)
+ m_collapsibleContent.append(m_inlineItemRuns.size() - 1);
}
}
@@ -710,7 +701,7 @@
// Soft line breaks (preserved new line characters) require inline text boxes for compatibility reasons.
ASSERT(inlineItem.isSoftLineBreak());
auto& softLineBreakItem = downcast<InlineSoftLineBreakItem>(inlineItem);
- m_inlineItemRuns.append({ softLineBreakItem, contentLogicalWidth(), 0_lu, Display::Run::TextContext { softLineBreakItem.position(), 1, softLineBreakItem.layoutBox().textContext()->content } });
+ m_inlineItemRuns.append({ softLineBreakItem, contentLogicalWidth(), 0_lu, false, false, Display::Run::TextContext { softLineBreakItem.position(), 1, softLineBreakItem.layoutBox().textContext()->content } });
}
void LineBuilder::adjustBaselineAndLineHeight(const Run& run)
@@ -964,14 +955,23 @@
return 0_lu;
}
-LineBuilder::InlineItemRun::InlineItemRun(const InlineItem& inlineItem, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, WTF::Optional<Display::Run::TextContext> textContext)
+LineBuilder::InlineItemRun::InlineItemRun(const InlineItem& inlineItem, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth)
: m_inlineItem(inlineItem)
, m_logicalLeft(logicalLeft)
, m_logicalWidth(logicalWidth)
- , m_textContext(textContext)
{
}
+LineBuilder::InlineItemRun::InlineItemRun(const InlineItem& inlineItem, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, bool isCollapsed, bool isCollapsedToZeroAdvanceWidth, Display::Run::TextContext&& textContext)
+ : m_inlineItem(inlineItem)
+ , m_logicalLeft(logicalLeft)
+ , m_logicalWidth(logicalWidth)
+ , m_textContext(WTFMove(textContext))
+ , m_isCollapsed(isCollapsed)
+ , m_collapsedToZeroAdvanceWidth(isCollapsedToZeroAdvanceWidth)
+{
+}
+
bool LineBuilder::InlineItemRun::isCollapsibleWhitespace() const
{
// Return true if the "end-of-line spaces" can be removed.
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h 2020-01-17 16:24:33 UTC (rev 254750)
@@ -161,7 +161,8 @@
class InlineItemRun {
public:
- InlineItemRun(const InlineItem&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, WTF::Optional<Display::Run::TextContext> = WTF::nullopt);
+ InlineItemRun(const InlineItem&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, bool isCollapsed, bool isCollapsedToZeroAdvanceWidth, Display::Run::TextContext&&);
+ InlineItemRun(const InlineItem&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth);
const Box& layoutBox() const { return m_inlineItem.layoutBox(); }
const RenderStyle& style() const { return layoutBox().style(); }
@@ -176,7 +177,6 @@
bool isLineBreak() const { return m_inlineItem.isLineBreak(); }
InlineItem::Type type() const { return m_inlineItem.type(); }
- void setIsCollapsed() { m_isCollapsed = true; }
bool isCollapsed() const { return m_isCollapsed; }
void moveHorizontally(InlineLayoutUnit offset) { m_logicalLeft += offset; }
@@ -242,6 +242,7 @@
bool m_hasIntrusiveFloat { false };
Display::LineBox m_lineBox;
Optional<bool> m_lineIsVisuallyEmptyBeforeCollapsibleContent;
+ bool m_shouldIgnoreTrailingLetterSpacing { false };
};
inline void LineBuilder::CollapsibleContent::reset()
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h 2020-01-17 16:24:33 UTC (rev 254750)
@@ -46,7 +46,7 @@
unsigned length() const { return m_length; }
bool isWhitespace() const { return m_textItemType == TextItemType::Whitespace; }
- bool isCollapsible() const { return isWhitespace() && style().collapseWhiteSpace(); }
+ bool isCollapsible() const { return m_isCollapsible; }
Optional<InlineLayoutUnit> width() const { return m_hasWidth ? makeOptional(m_width) : Optional<InlineLayoutUnit> { }; }
bool isEmptyContent() const;
@@ -80,6 +80,7 @@
m_startOrPosition = start;
m_length = length;
m_hasWidth = !!width;
+ m_isCollapsible = textItemType == TextItemType::Whitespace && inlineBox.style().collapseWhiteSpace();
m_width = width.valueOr(0);
m_textItemType = textItemType;
}
Modified: trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.cpp 2020-01-17 16:24:33 UTC (rev 254750)
@@ -128,12 +128,6 @@
return { startPosition, right - startPosition, leftSideWidth };
}
-bool TextUtil::shouldPreserveTrailingWhitespace(const RenderStyle& style)
-{
- auto whitespace = style.whiteSpace();
- return whitespace == WhiteSpace::Pre || whitespace == WhiteSpace::PreWrap || whitespace == WhiteSpace::BreakSpaces;
-}
-
unsigned TextUtil::findNextBreakablePosition(LazyLineBreakIterator& lineBreakIterator, unsigned startPosition, const RenderStyle& style)
{
auto keepAllWordsForCJK = style.wordBreak() == WordBreak::KeepAll;
Modified: trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h (254749 => 254750)
--- trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h 2020-01-17 16:16:03 UTC (rev 254749)
+++ trunk/Source/WebCore/layout/inlineformatting/text/TextUtil.h 2020-01-17 16:24:33 UTC (rev 254750)
@@ -56,6 +56,12 @@
static InlineLayoutUnit fixedPitchWidth(const StringView&, const RenderStyle&, unsigned from, unsigned to, InlineLayoutUnit contentLogicalLeft);
};
+inline bool TextUtil::shouldPreserveTrailingWhitespace(const RenderStyle& style)
+{
+ auto whitespace = style.whiteSpace();
+ return whitespace == WhiteSpace::Pre || whitespace == WhiteSpace::PreWrap || whitespace == WhiteSpace::BreakSpaces;
}
+
}
+}
#endif