Title: [287493] trunk/Source/WebCore
Revision
287493
Author
[email protected]
Date
2021-12-31 06:21:02 -0800 (Fri, 31 Dec 2021)

Log Message

[LFC][IFC] Take grapheme clusters into account when keeping the first "character" on the line
https://bugs.webkit.org/show_bug.cgi?id=234758

Reviewed by Antti Koivisto.

When dealing with complex fonts, we have to start looking beyond code points and taking
larger cluster of code units into account.

This patch is in preparation for enabling complex font codepath.

* layout/formattingContexts/inline/InlineContentBreaker.cpp:
(WebCore::Layout::InlineContentBreaker::processOverflowingContent const):
* layout/formattingContexts/inline/text/TextUtil.cpp:
(WebCore::Layout::TextUtil::firstUserPerceivedCharacterLength): user-perceived character is a unicode term.
see https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
* layout/formattingContexts/inline/text/TextUtil.h:
* layout/integration/LayoutIntegrationBoxTree.cpp:
(WebCore::LayoutIntegration::BoxTree::buildTree):
* layout/layouttree/LayoutInlineTextBox.cpp:
(WebCore::Layout::InlineTextBox::InlineTextBox):
(WebCore::Layout::m_canUseSimpleFontCodePath):
(WebCore::Layout::m_canUseSimplifiedContentMeasuring): Deleted.
* layout/layouttree/LayoutInlineTextBox.h:
(WebCore::Layout::InlineTextBox::canUseSimpleFontCodePath const):
* layout/layouttree/LayoutTreeBuilder.cpp:
(WebCore::Layout::TreeBuilder::createTextBox):
(WebCore::Layout::TreeBuilder::createLayoutBox):
* layout/layouttree/LayoutTreeBuilder.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (287492 => 287493)


--- trunk/Source/WebCore/ChangeLog	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/ChangeLog	2021-12-31 14:21:02 UTC (rev 287493)
@@ -1,3 +1,34 @@
+2021-12-31  Alan Bujtas  <[email protected]>
+
+        [LFC][IFC] Take grapheme clusters into account when keeping the first "character" on the line
+        https://bugs.webkit.org/show_bug.cgi?id=234758
+
+        Reviewed by Antti Koivisto.
+
+        When dealing with complex fonts, we have to start looking beyond code points and taking
+        larger cluster of code units into account.
+
+        This patch is in preparation for enabling complex font codepath.
+
+        * layout/formattingContexts/inline/InlineContentBreaker.cpp:
+        (WebCore::Layout::InlineContentBreaker::processOverflowingContent const):
+        * layout/formattingContexts/inline/text/TextUtil.cpp:
+        (WebCore::Layout::TextUtil::firstUserPerceivedCharacterLength): user-perceived character is a unicode term.
+        see https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
+        * layout/formattingContexts/inline/text/TextUtil.h:
+        * layout/integration/LayoutIntegrationBoxTree.cpp:
+        (WebCore::LayoutIntegration::BoxTree::buildTree):
+        * layout/layouttree/LayoutInlineTextBox.cpp:
+        (WebCore::Layout::InlineTextBox::InlineTextBox):
+        (WebCore::Layout::m_canUseSimpleFontCodePath):
+        (WebCore::Layout::m_canUseSimplifiedContentMeasuring): Deleted.
+        * layout/layouttree/LayoutInlineTextBox.h:
+        (WebCore::Layout::InlineTextBox::canUseSimpleFontCodePath const):
+        * layout/layouttree/LayoutTreeBuilder.cpp:
+        (WebCore::Layout::TreeBuilder::createTextBox):
+        (WebCore::Layout::TreeBuilder::createLayoutBox):
+        * layout/layouttree/LayoutTreeBuilder.h:
+
 2021-12-30  Jean-Yves Avenard  <[email protected]>
 
         SharedBuffer::takeData() is still dangerous

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp (287492 => 287493)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp	2021-12-31 14:21:02 UTC (rev 287493)
@@ -208,26 +208,17 @@
                 auto leadingTextRunIndex = *firstTextRunIndex(continuousContent);
                 auto& leadingTextRun = continuousContent.runs()[leadingTextRunIndex];
                 auto& inlineTextItem = downcast<InlineTextItem>(leadingTextRun.inlineItem);
-                auto firstCodePointLength = [&]() -> size_t {
-                    auto textContent = inlineTextItem.inlineTextBox().content();
-                    if (textContent.is8Bit())
-                        return 1;
-                    UChar32 character;
-                    size_t endOfCodePoint = 0;
-                    U16_NEXT(textContent.characters16(), endOfCodePoint, textContent.length(), character);
-                    return endOfCodePoint;
-                }();
+                auto firstCharacterLength = TextUtil::firstUserPerceivedCharacterLength(inlineTextItem);
+                ASSERT(firstCharacterLength > 0);
 
-                if (inlineTextItem.length() <= firstCodePointLength) {
-                    if (continuousContent.runs().size() == 1) {
-                        // Let's return single, leading text items as is.
+                if (inlineTextItem.length() <= firstCharacterLength) {
+                    if (continuousContent.runs().size() == 1)
                         return Result { Result::Action::Keep, IsEndOfLine::Yes };
-                    }
                     return Result { Result::Action::Break, IsEndOfLine::Yes, Result::PartialTrailingContent { leadingTextRunIndex, { } } };
                 }
 
-                auto firstCodePointWidth = TextUtil::width(inlineTextItem, leadingTextRun.style.fontCascade(), inlineTextItem.start(), inlineTextItem.start() + firstCodePointLength, lineStatus.contentLogicalRight);
-                return Result { Result::Action::Break, IsEndOfLine::Yes, Result::PartialTrailingContent { leadingTextRunIndex, PartialRun { firstCodePointLength, firstCodePointWidth } } };
+                auto firstCharacterWidth = TextUtil::width(inlineTextItem, leadingTextRun.style.fontCascade(), inlineTextItem.start(), inlineTextItem.start() + firstCharacterLength, lineStatus.contentLogicalRight);
+                return Result { Result::Action::Break, IsEndOfLine::Yes, Result::PartialTrailingContent { leadingTextRunIndex, PartialRun { firstCharacterLength, firstCharacterWidth } } };
             }
             if (trailingContent->overflows && lineStatus.hasContent) {
                 // We managed to break a run with overflow but the line already has content. Let's wrap it to the next line.

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp (287492 => 287493)


--- trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp	2021-12-31 14:21:02 UTC (rev 287493)
@@ -36,6 +36,7 @@
 #include "RenderBox.h"
 #include "RenderStyle.h"
 #include "SurrogatePairAwareTextIterator.h"
+#include <wtf/text/TextBreakIterator.h>
 
 namespace WebCore {
 namespace Layout {
@@ -274,6 +275,27 @@
     return false;
 }
 
+size_t TextUtil::firstUserPerceivedCharacterLength(const InlineTextItem& inlineTextItem)
+{
+    auto& inlineTextBox = inlineTextItem.inlineTextBox();
+    auto textContent = inlineTextBox.content();
+    RELEASE_ASSERT(!textContent.isEmpty());
+
+    if (textContent.is8Bit())
+        return 1;
+    if (inlineTextBox.canUseSimpleFontCodePath()) {
+        UChar32 character;
+        size_t endOfCodePoint = 0;
+        U16_NEXT(textContent.characters16(), endOfCodePoint, textContent.length(), character);
+        return endOfCodePoint;
+    }
+    auto graphemeClustersIterator = NonSharedCharacterBreakIterator { textContent };
+    auto nextPosition = ubrk_following(graphemeClustersIterator, inlineTextItem.start());
+    if (nextPosition == UBRK_DONE)
+        return inlineTextItem.length();
+    return nextPosition - inlineTextItem.start();
 }
+
 }
+}
 #endif

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.h (287492 => 287493)


--- trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.h	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.h	2021-12-31 14:21:02 UTC (rev 287493)
@@ -65,6 +65,8 @@
     static bool shouldPreserveNewline(const Box&);
     static bool isWrappingAllowed(const RenderStyle&);
     static bool containsStrongDirectionalityText(StringView);
+
+    static size_t firstUserPerceivedCharacterLength(const InlineTextItem&);
 };
 
 }

Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationBoxTree.cpp (287492 => 287493)


--- trunk/Source/WebCore/layout/integration/LayoutIntegrationBoxTree.cpp	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationBoxTree.cpp	2021-12-31 14:21:02 UTC (rev 287493)
@@ -98,7 +98,7 @@
             auto style = RenderStyle::createAnonymousStyleWithDisplay(textRenderer.style(), DisplayType::Inline);
             auto text = style.textSecurity() == TextSecurity::None ? textRenderer.text() : RenderBlock::updateSecurityDiscCharacters(style, textRenderer.text());
             auto useSimplifiedTextMeasuring = textRenderer.canUseSimplifiedTextMeasuring() && (!firstLineStyle || firstLineStyle->fontCascade() == style.fontCascade());
-            return makeUnique<Layout::InlineTextBox>(text, useSimplifiedTextMeasuring, WTFMove(style), WTFMove(firstLineStyle));
+            return makeUnique<Layout::InlineTextBox>(text, useSimplifiedTextMeasuring, textRenderer.canUseSimpleFontCodePath(), WTFMove(style), WTFMove(firstLineStyle));
         }
 
         auto style = RenderStyle::clone(childRenderer.style());

Modified: trunk/Source/WebCore/layout/layouttree/LayoutInlineTextBox.cpp (287492 => 287493)


--- trunk/Source/WebCore/layout/layouttree/LayoutInlineTextBox.cpp	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/layouttree/LayoutInlineTextBox.cpp	2021-12-31 14:21:02 UTC (rev 287493)
@@ -36,10 +36,11 @@
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(InlineTextBox);
 
-InlineTextBox::InlineTextBox(String content, bool canUseSimplifiedContentMeasuring, RenderStyle&& style, std::unique_ptr<RenderStyle>&& firstLineStyle)
+InlineTextBox::InlineTextBox(String content, bool canUseSimplifiedContentMeasuring, bool canUseSimpleFontCodePath, RenderStyle&& style, std::unique_ptr<RenderStyle>&& firstLineStyle)
     : Box({ }, WTFMove(style), WTFMove(firstLineStyle), Box::InlineTextBoxFlag)
     , m_content(content)
     , m_canUseSimplifiedContentMeasuring(canUseSimplifiedContentMeasuring)
+    , m_canUseSimpleFontCodePath(canUseSimpleFontCodePath)
 {
     setIsAnonymous();
 }

Modified: trunk/Source/WebCore/layout/layouttree/LayoutInlineTextBox.h (287492 => 287493)


--- trunk/Source/WebCore/layout/layouttree/LayoutInlineTextBox.h	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/layouttree/LayoutInlineTextBox.h	2021-12-31 14:21:02 UTC (rev 287493)
@@ -37,16 +37,18 @@
 class InlineTextBox : public Box {
     WTF_MAKE_ISO_ALLOCATED(InlineTextBox);
 public:
-    InlineTextBox(String, bool canUseSimplifiedContentMeasuring, RenderStyle&&, std::unique_ptr<RenderStyle>&& firstLineStyle = nullptr);
+    InlineTextBox(String, bool canUseSimplifiedContentMeasuring, bool canUseSimpleFontCodePath, RenderStyle&&, std::unique_ptr<RenderStyle>&& firstLineStyle = nullptr);
     virtual ~InlineTextBox() = default;
 
     String content() const { return m_content; }
     // FIXME: This should not be a box's property.
     bool canUseSimplifiedContentMeasuring() const { return m_canUseSimplifiedContentMeasuring; }
+    bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; }
 
 private:
     String m_content;
     bool m_canUseSimplifiedContentMeasuring { false };
+    bool m_canUseSimpleFontCodePath { true };
 };
 
 }

Modified: trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp (287492 => 287493)


--- trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp	2021-12-31 14:21:02 UTC (rev 287493)
@@ -132,9 +132,9 @@
     return makeUnique<ReplacedBox>(elementAttributes, WTFMove(style));
 }
 
-std::unique_ptr<Box> TreeBuilder::createTextBox(String text, bool canUseSimplifiedTextMeasuring, RenderStyle&& style)
+std::unique_ptr<Box> TreeBuilder::createTextBox(String text, bool canUseSimplifiedTextMeasuring, bool canUseSimpleFontCodePath,  RenderStyle&& style)
 {
-    return makeUnique<InlineTextBox>(text, canUseSimplifiedTextMeasuring, WTFMove(style));
+    return makeUnique<InlineTextBox>(text, canUseSimplifiedTextMeasuring, canUseSimpleFontCodePath, WTFMove(style));
 }
 
 std::unique_ptr<Box> TreeBuilder::createLineBreakBox(bool isOptional, RenderStyle&& style)
@@ -171,9 +171,9 @@
         String text = textRenderer.text();
         auto useSimplifiedTextMeasuring = canUseSimplifiedTextMeasuring(text, parentContainer.style().fontCascade(), parentContainer.style().collapseWhiteSpace());
         if (parentContainer.style().display() == DisplayType::Inline)
-            childLayoutBox = createTextBox(text, useSimplifiedTextMeasuring, RenderStyle::clone(parentContainer.style()));
+            childLayoutBox = createTextBox(text, useSimplifiedTextMeasuring, textRenderer.canUseSimpleFontCodePath(), RenderStyle::clone(parentContainer.style()));
         else
-            childLayoutBox = createTextBox(text, useSimplifiedTextMeasuring, RenderStyle::createAnonymousStyleWithDisplay(parentContainer.style(), DisplayType::Inline));
+            childLayoutBox = createTextBox(text, useSimplifiedTextMeasuring, textRenderer.canUseSimpleFontCodePath(), RenderStyle::createAnonymousStyleWithDisplay(parentContainer.style(), DisplayType::Inline));
     } else {
         auto& renderer = downcast<RenderElement>(childRenderer);
         auto displayType = renderer.style().display();

Modified: trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.h (287492 => 287493)


--- trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.h	2021-12-31 10:11:40 UTC (rev 287492)
+++ trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.h	2021-12-31 14:21:02 UTC (rev 287493)
@@ -67,7 +67,7 @@
     std::unique_ptr<Box> createLayoutBox(const ContainerBox& parentContainer, const RenderObject& childRenderer);
 
     std::unique_ptr<Box> createReplacedBox(std::optional<Box::ElementAttributes>, RenderStyle&&);
-    std::unique_ptr<Box> createTextBox(String text, bool canUseSimplifiedTextMeasuring, RenderStyle&&);
+    std::unique_ptr<Box> createTextBox(String text, bool canUseSimplifiedTextMeasuring, bool canUseSimpleFontCodePath, RenderStyle&&);
     std::unique_ptr<Box> createLineBreakBox(bool isOptional, RenderStyle&&);
     std::unique_ptr<ContainerBox> createContainer(std::optional<Box::ElementAttributes>, RenderStyle&&);
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to