[LFC][IFC] Make InlineTextItem reusable when 'segment break' behavior changes
https://bugs.webkit.org/show_bug.cgi?id=203184
<rdar://problem/56438945>
Reviewed by Antti Koivisto.
InlineTextItem::isWhitespace should dynamically check for 'preserve new line' behavior. This way we don't have to rebuild the inline item list
when the related style property value changes.
* layout/inlineformatting/InlineTextItem.cpp:
(WebCore::Layout::isWhitespaceCharacter):
(WebCore::Layout::moveToNextNonWhitespacePosition):
(WebCore::Layout::InlineTextItem::createAndAppendTextItems):
(WebCore::Layout::InlineTextItem::createWhitespaceItem):
(WebCore::Layout::InlineTextItem::createNonWhitespaceItem):
(WebCore::Layout::InlineTextItem::createSegmentBreakItem):
(WebCore::Layout::InlineTextItem::createEmptyItem):
(WebCore::Layout::InlineTextItem::InlineTextItem):
(WebCore::Layout::InlineTextItem::split const):
(WebCore::Layout::InlineTextItem::isWhitespace const):
(WebCore::Layout::isSoftLineBreak): Deleted.
* layout/inlineformatting/InlineTextItem.h:
(WebCore::Layout::InlineTextItem::isSegmentBreak const):
(WebCore::Layout::InlineTextItem::isWhitespace const): Deleted.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251330 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 12d8a96..bcb17e7 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,32 @@
2019-10-20 Zalan Bujtas <zalan@apple.com>
+ [LFC][IFC] Make InlineTextItem reusable when 'segment break' behavior changes
+ https://bugs.webkit.org/show_bug.cgi?id=203184
+ <rdar://problem/56438945>
+
+ Reviewed by Antti Koivisto.
+
+ InlineTextItem::isWhitespace should dynamically check for 'preserve new line' behavior. This way we don't have to rebuild the inline item list
+ when the related style property value changes.
+
+ * layout/inlineformatting/InlineTextItem.cpp:
+ (WebCore::Layout::isWhitespaceCharacter):
+ (WebCore::Layout::moveToNextNonWhitespacePosition):
+ (WebCore::Layout::InlineTextItem::createAndAppendTextItems):
+ (WebCore::Layout::InlineTextItem::createWhitespaceItem):
+ (WebCore::Layout::InlineTextItem::createNonWhitespaceItem):
+ (WebCore::Layout::InlineTextItem::createSegmentBreakItem):
+ (WebCore::Layout::InlineTextItem::createEmptyItem):
+ (WebCore::Layout::InlineTextItem::InlineTextItem):
+ (WebCore::Layout::InlineTextItem::split const):
+ (WebCore::Layout::InlineTextItem::isWhitespace const):
+ (WebCore::Layout::isSoftLineBreak): Deleted.
+ * layout/inlineformatting/InlineTextItem.h:
+ (WebCore::Layout::InlineTextItem::isSegmentBreak const):
+ (WebCore::Layout::InlineTextItem::isWhitespace const): Deleted.
+
+2019-10-20 Zalan Bujtas <zalan@apple.com>
+
[LFC][IFC] Move the collapsed bit from InlineItems to runs
https://bugs.webkit.org/show_bug.cgi?id=203183
diff --git a/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp b/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp
index 2c94efb..f79403c 100644
--- a/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp
@@ -33,20 +33,15 @@
namespace WebCore {
namespace Layout {
-static inline bool isWhitespaceCharacter(char character, bool preserveNewline)
+static inline bool isWhitespaceCharacter(char character)
{
- return character == ' ' || character == '\t' || (character == '\n' && !preserveNewline);
+ return character == ' ' || character == '\t';
}
-static inline bool isSoftLineBreak(char character, bool preserveNewline)
-{
- return preserveNewline && character == '\n';
-}
-
-static unsigned moveToNextNonWhitespacePosition(String textContent, unsigned startPosition, bool preserveNewline)
+static unsigned moveToNextNonWhitespacePosition(String textContent, unsigned startPosition)
{
auto nextNonWhiteSpacePosition = startPosition;
- while (nextNonWhiteSpacePosition < textContent.length() && isWhitespaceCharacter(textContent[nextNonWhiteSpacePosition], preserveNewline))
+ while (nextNonWhiteSpacePosition < textContent.length() && isWhitespaceCharacter(textContent[nextNonWhiteSpacePosition]))
++nextNonWhiteSpacePosition;
return nextNonWhiteSpacePosition - startPosition;
}
@@ -89,37 +84,64 @@
{
auto text = inlineBox.textContent();
if (!text.length())
- return inlineContent.append(makeUnique<InlineTextItem>(inlineBox, 0, 0, false));
+ return inlineContent.append(InlineTextItem::createEmptyItem(inlineBox));
auto& style = inlineBox.style();
- auto preserveNewline = style.preserveNewline();
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));
+ auto isSegmentBreakCandidate = [](auto character) {
+ return character == '\n';
+ };
+
+ if (isSegmentBreakCandidate(text[currentPosition])) {
+ inlineContent.append(InlineTextItem::createSegmentBreakItem(inlineBox, currentPosition));
++currentPosition;
continue;
}
- if (isWhitespaceCharacter(text[currentPosition], preserveNewline)) {
- auto length = moveToNextNonWhitespacePosition(text, currentPosition, preserveNewline);
- inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, length, true));
+ if (isWhitespaceCharacter(text[currentPosition])) {
+ auto length = moveToNextNonWhitespacePosition(text, currentPosition);
+ inlineContent.append(InlineTextItem::createWhitespaceItem(inlineBox, currentPosition, length));
currentPosition += length;
continue;
}
auto length = moveToNextBreakablePosition(currentPosition, lineBreakIterator, style);
- inlineContent.append(makeUnique<InlineTextItem>(inlineBox, currentPosition, length, false));
+ inlineContent.append(InlineTextItem::createNonWhitespaceItem(inlineBox, currentPosition, length));
currentPosition += length;
}
}
-InlineTextItem::InlineTextItem(const Box& inlineBox, unsigned start, unsigned length, bool isWhitespace)
+std::unique_ptr<InlineTextItem> InlineTextItem::createWhitespaceItem(const Box& inlineBox, unsigned start, unsigned length)
+{
+ return makeUnique<InlineTextItem>(inlineBox, start, length, TextItemType::Whitespace);
+}
+
+std::unique_ptr<InlineTextItem> InlineTextItem::createNonWhitespaceItem(const Box& inlineBox, unsigned start, unsigned length)
+{
+ return makeUnique<InlineTextItem>(inlineBox, start, length, TextItemType::NonWhitespace);
+}
+
+std::unique_ptr<InlineTextItem> InlineTextItem::createSegmentBreakItem(const Box& inlineBox, unsigned position)
+{
+ return makeUnique<InlineTextItem>(inlineBox, position, 1, TextItemType::SegmentBreak);
+}
+
+std::unique_ptr<InlineTextItem> InlineTextItem::createEmptyItem(const Box& inlineBox)
+{
+ return makeUnique<InlineTextItem>(inlineBox);
+}
+
+InlineTextItem::InlineTextItem(const Box& inlineBox, unsigned start, unsigned length, TextItemType textItemType)
: InlineItem(inlineBox, Type::Text)
, m_start(start)
, m_length(length)
- , m_isWhitespace(isWhitespace)
+ , m_textItemType(textItemType)
+{
+}
+
+InlineTextItem::InlineTextItem(const Box& inlineBox)
+ : InlineItem(inlineBox, Type::Text)
{
}
@@ -127,7 +149,16 @@
{
RELEASE_ASSERT(splitPosition >= this->start());
RELEASE_ASSERT(splitPosition + length <= end());
- return makeUnique<InlineTextItem>(layoutBox(), splitPosition, length, isWhitespace());
+ ASSERT(!isSegmentBreak());
+ ASSERT(m_textItemType != TextItemType::Undefined);
+ return makeUnique<InlineTextItem>(layoutBox(), splitPosition, length, m_textItemType);
+}
+
+bool InlineTextItem::isWhitespace() const
+{
+ if (isSegmentBreak())
+ return !style().preserveNewline();
+ return m_textItemType == TextItemType::Whitespace;
}
}
diff --git a/Source/WebCore/layout/inlineformatting/InlineTextItem.h b/Source/WebCore/layout/inlineformatting/InlineTextItem.h
index 45fa6e1..0a9c305 100644
--- a/Source/WebCore/layout/inlineformatting/InlineTextItem.h
+++ b/Source/WebCore/layout/inlineformatting/InlineTextItem.h
@@ -37,23 +37,36 @@
public:
static void createAndAppendTextItems(InlineItems&, const Box&);
- InlineTextItem(const Box&, unsigned start, unsigned length, bool isWhitespace);
+ static std::unique_ptr<InlineTextItem> createWhitespaceItem(const Box&, unsigned start, unsigned length);
+ static std::unique_ptr<InlineTextItem> createNonWhitespaceItem(const Box&, unsigned start, unsigned length);
+ static std::unique_ptr<InlineTextItem> createSegmentBreakItem(const Box&, unsigned position);
+ static std::unique_ptr<InlineTextItem> createEmptyItem(const Box&);
unsigned start() const { return m_start; }
unsigned end() const { return start() + length(); }
unsigned length() const { return m_length; }
- bool isWhitespace() const { return m_isWhitespace; }
+ bool isWhitespace() const;
bool isCollapsible() const { return isWhitespace() && style().collapseWhiteSpace(); }
+ bool isSegmentBreak() const;
std::unique_ptr<InlineTextItem> split(unsigned splitPosition, unsigned length) const;
+ enum class TextItemType { Undefined, Whitespace, NonWhitespace, SegmentBreak };
+ InlineTextItem(const Box&, unsigned start, unsigned length, TextItemType);
+ InlineTextItem(const Box&);
+
private:
unsigned m_start { 0 };
unsigned m_length { 0 };
- bool m_isWhitespace { false };
+ TextItemType m_textItemType { TextItemType::Undefined };
};
+inline bool InlineTextItem::isSegmentBreak() const
+{
+ return m_textItemType == TextItemType::SegmentBreak;
+}
+
}
}