From 652e0bfdf0d75898db241f971155445563948a07 Mon Sep 17 00:00:00 2001 From: Alan Bujtas Date: Fri, 9 Sep 2022 13:56:06 -0700 Subject: [PATCH] [LFC][IFC] Introduce InlineDisplay::Box:isVisible https://bugs.webkit.org/show_bug.cgi?id=244957 Reviewed by Antti Koivisto. Let's propagate RenderStyle::visibility bit to InlineDisplay::Box and combine it with text-overflow truncation. It is used for both painting and hittesting. This patch also flips isVisuallyHidden to isVisible. * Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h: (WebCore::InlineDisplay::Box::Text::partiallyVisibleContentLength const): (WebCore::InlineDisplay::Box::Box): (WebCore::InlineDisplay::Box::isVisible const): (WebCore::InlineDisplay::Box::Text::Text): (WebCore::InlineDisplay::Box::Text::visuallyVisibleLength const): Deleted. (WebCore::InlineDisplay::Box::isVisuallyHidden const): Deleted. * Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp: (WebCore::Layout::InlineDisplayContentBuilder::appendTextDisplayBox): (WebCore::Layout::InlineDisplayContentBuilder::appendAtomicInlineLevelDisplayBox): (WebCore::Layout::InlineDisplayContentBuilder::appendInlineBoxDisplayBox): (WebCore::Layout::InlineDisplayContentBuilder::appendSpanningInlineBoxDisplayBox): (WebCore::Layout::InlineDisplayContentBuilder::appendInlineDisplayBoxAtBidiBoundary): * Source/WebCore/layout/integration/inline/InlineIteratorBoxModernPath.h: (WebCore::InlineIterator::BoxModernPath::selectableRange const): * Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentPainter.cpp: (WebCore::LayoutIntegration::InlineContentPainter::paintDisplayBox): * Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp: (WebCore::LayoutIntegration::LineLayout::hitTest): Canonical link: https://commits.webkit.org/254325@main --- .../inline/display/InlineDisplayBox.h | 21 +++++++------- .../display/InlineDisplayContentBuilder.cpp | 28 ++++++++++++------- .../inline/InlineIteratorBoxModernPath.h | 2 +- .../LayoutIntegrationInlineContentPainter.cpp | 3 +- .../inline/LayoutIntegrationLineLayout.cpp | 3 ++ 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h index bcbc9f385963..49751d0eb0d2 100644 --- a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h +++ b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h @@ -39,12 +39,12 @@ struct Box { struct Text { WTF_MAKE_STRUCT_FAST_ALLOCATED; public: - Text(size_t position, size_t length, const String& originalContent, String adjustedContentToRender = String(), bool hasHyphen = false, std::optional visuallyVisibleLength = std::nullopt); + Text(size_t position, size_t length, const String& originalContent, String adjustedContentToRender = String(), bool hasHyphen = false, std::optional partiallyVisibleContentLength = std::nullopt); size_t start() const { return m_start; } size_t end() const { return start() + length(); } size_t length() const { return m_length; } - std::optional visuallyVisibleLength() const { return m_visuallyVisibleLength; } + std::optional partiallyVisibleContentLength() const { return m_partiallyVisibleContentLength; } StringView originalContent() const { return StringView(m_originalContent).substring(m_start, m_length); } StringView renderedContent() const { return m_adjustedContentToRender.isNull() ? originalContent() : m_adjustedContentToRender; } @@ -55,7 +55,7 @@ struct Box { size_t m_start { 0 }; size_t m_length { 0 }; - std::optional m_visuallyVisibleLength { }; + std::optional m_partiallyVisibleContentLength { }; bool m_hasHyphen { false }; String m_originalContent; String m_adjustedContentToRender; @@ -77,8 +77,7 @@ struct Box { First = 1 << 0, Last = 1 << 1 }; - enum class IsVisuallyHidden : uint8_t { Yes, No, Partially }; - Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const FloatRect&, const FloatRect& inkOverflow, Expansion, std::optional = std::nullopt, bool hasContent = true, IsVisuallyHidden isVisuallyHidden = IsVisuallyHidden::No, OptionSet = { }); + Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const FloatRect&, const FloatRect& inkOverflow, Expansion, std::optional = std::nullopt, bool hasContent = true, bool isFullyTruncated = false, OptionSet = { }); bool isText() const { return m_type == Type::Text || isWordSeparator(); } bool isWordSeparator() const { return m_type == Type::WordSeparator; } @@ -100,7 +99,7 @@ struct Box { bool isHorizontal() const { return style().isHorizontalWritingMode(); } bool hasContent() const { return m_hasContent; } - IsVisuallyHidden isVisuallyHidden() const { return m_isVisuallyHidden; } + bool isVisible() const { return !m_isFullyTruncated && style().visibility() == Visibility::Visible; } const FloatRect& visualRectIgnoringBlockDirection() const { return m_unflippedVisualRect; } const FloatRect& inkOverflow() const { return m_inkOverflow; } @@ -186,12 +185,12 @@ struct Box { bool m_hasContent : 1; bool m_isFirstForLayoutBox : 1; bool m_isLastForLayoutBox : 1; - IsVisuallyHidden m_isVisuallyHidden { IsVisuallyHidden::No }; + bool m_isFullyTruncated : 1; Expansion m_expansion; std::optional m_text; }; -inline Box::Box(size_t lineIndex, Type type, const Layout::Box& layoutBox, UBiDiLevel bidiLevel, const FloatRect& physicalRect, const FloatRect& inkOverflow, Expansion expansion, std::optional text, bool hasContent, IsVisuallyHidden isVisuallyHidden, OptionSet positionWithinInlineLevelBox) +inline Box::Box(size_t lineIndex, Type type, const Layout::Box& layoutBox, UBiDiLevel bidiLevel, const FloatRect& physicalRect, const FloatRect& inkOverflow, Expansion expansion, std::optional text, bool hasContent, bool isFullyTruncated, OptionSet positionWithinInlineLevelBox) : m_lineIndex(lineIndex) , m_type(type) , m_layoutBox(layoutBox) @@ -201,16 +200,16 @@ inline Box::Box(size_t lineIndex, Type type, const Layout::Box& layoutBox, UBiDi , m_hasContent(hasContent) , m_isFirstForLayoutBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::First)) , m_isLastForLayoutBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::Last)) - , m_isVisuallyHidden(isVisuallyHidden) + , m_isFullyTruncated(isFullyTruncated) , m_expansion(expansion) , m_text(text) { } -inline Box::Text::Text(size_t start, size_t length, const String& originalContent, String adjustedContentToRender, bool hasHyphen, std::optional visuallyVisibleLength) +inline Box::Text::Text(size_t start, size_t length, const String& originalContent, String adjustedContentToRender, bool hasHyphen, std::optional partiallyVisibleContentLength) : m_start(start) , m_length(length) - , m_visuallyVisibleLength(visuallyVisibleLength) + , m_partiallyVisibleContentLength(partiallyVisibleContentLength) , m_hasHyphen(hasHyphen) , m_originalContent(originalContent) , m_adjustedContentToRender(adjustedContentToRender) diff --git a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp index 65f4f4903086..358e6ac88891 100644 --- a/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp +++ b/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayContentBuilder.cpp @@ -186,7 +186,9 @@ void InlineDisplayContentBuilder::appendTextDisplayBox(const Line::Run& lineRun, auto adjustedContentToRender = [&] { return text->needsHyphen ? makeString(StringView(content).substring(text->start, text->length), style.hyphenString()) : String(); }; - auto isVisuallyHidden = !lineRun.isTruncated() ? InlineDisplay::Box::IsVisuallyHidden::No : !text->partiallyVisibleContent.has_value() ? InlineDisplay::Box::IsVisuallyHidden::Yes : InlineDisplay::Box::IsVisuallyHidden::Partially; + auto isFullyTruncated = lineRun.isTruncated() && !text->partiallyVisibleContent; + auto partiallyVisibleContentLength = !isFullyTruncated && text->partiallyVisibleContent ? std::make_optional(text->partiallyVisibleContent->length): std::nullopt; + boxes.append({ m_lineIndex , lineRun.isWordSeparator() ? InlineDisplay::Box::Type::WordSeparator : InlineDisplay::Box::Type::Text , layoutBox @@ -194,9 +196,9 @@ void InlineDisplayContentBuilder::appendTextDisplayBox(const Line::Run& lineRun, , textRunRect , inkOverflow() , lineRun.expansion() - , InlineDisplay::Box::Text { text->start, text->length, content, adjustedContentToRender(), text->needsHyphen, isVisuallyHidden == InlineDisplay::Box::IsVisuallyHidden::Partially ? std::make_optional(text->partiallyVisibleContent->length) : std::nullopt } + , InlineDisplay::Box::Text { text->start, text->length, content, adjustedContentToRender(), text->needsHyphen, partiallyVisibleContentLength } , true - , isVisuallyHidden + , isFullyTruncated , { } }); } @@ -243,13 +245,15 @@ void InlineDisplayContentBuilder::appendAtomicInlineLevelDisplayBox(const Line:: ASSERT(lineRun.layoutBox().isAtomicInlineLevelBox()); auto& layoutBox = lineRun.layoutBox(); + auto& style = !m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(); auto inkOverflow = [&] { auto inkOverflow = FloatRect { borderBoxRect }; - computeInkOverflowForInlineLevelBox(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow); + computeInkOverflowForInlineLevelBox(style, inkOverflow); // Atomic inline box contribute to their inline box parents ink overflow at all times (e.g. ). m_contentHasInkOverflow = m_contentHasInkOverflow || &layoutBox.parent() != &root(); return inkOverflow; }; + boxes.append({ m_lineIndex , InlineDisplay::Box::Type::AtomicInlineLevelBox , layoutBox @@ -259,7 +263,7 @@ void InlineDisplayContentBuilder::appendAtomicInlineLevelDisplayBox(const Line:: , lineRun.expansion() , { } , true - , lineRun.isTruncated() ? InlineDisplay::Box::IsVisuallyHidden::Yes : InlineDisplay::Box::IsVisuallyHidden::No + , lineRun.isTruncated() }); // Note that inline boxes are relative to the line and their top position can be negative. // Atomic inline boxes are all set. Their margin/border/content box geometries are already computed. We just have to position them here. @@ -310,11 +314,13 @@ void InlineDisplayContentBuilder::appendInlineBoxDisplayBox(const Line::Run& lin return; } + auto& style = !m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(); auto inkOverflow = [&] { auto inkOverflow = FloatRect { inlineBoxBorderBox }; - m_contentHasInkOverflow = computeInkOverflowForInlineBox(inlineBox, !m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow) || m_contentHasInkOverflow; + m_contentHasInkOverflow = computeInkOverflowForInlineBox(inlineBox, style, inkOverflow) || m_contentHasInkOverflow; return inkOverflow; }; + ASSERT(inlineBox.isFirstBox()); boxes.append({ m_lineIndex , InlineDisplay::Box::Type::NonRootInlineBox @@ -325,7 +331,7 @@ void InlineDisplayContentBuilder::appendInlineBoxDisplayBox(const Line::Run& lin , { } , { } , inlineBox.hasContent() - , lineRun.isTruncated() ? InlineDisplay::Box::IsVisuallyHidden::Yes : InlineDisplay::Box::IsVisuallyHidden::No + , lineRun.isTruncated() , isFirstLastBox(inlineBox) }); // This inline box showed up first on this line. @@ -336,14 +342,16 @@ void InlineDisplayContentBuilder::appendSpanningInlineBoxDisplayBox(const Line:: { ASSERT(lineRun.layoutBox().isInlineBox()); ASSERT(inlineBox.isInlineBox()); + ASSERT(!inlineBox.isFirstBox()); auto& layoutBox = lineRun.layoutBox(); + auto& style = !m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(); auto inkOverflow = [&] { auto inkOverflow = FloatRect { inlineBoxBorderBox }; - m_contentHasInkOverflow = computeInkOverflowForInlineBox(inlineBox, !m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow) || m_contentHasInkOverflow; + m_contentHasInkOverflow = computeInkOverflowForInlineBox(inlineBox, style, inkOverflow) || m_contentHasInkOverflow; return inkOverflow; }; - ASSERT(!inlineBox.isFirstBox()); + boxes.append({ m_lineIndex , InlineDisplay::Box::Type::NonRootInlineBox , layoutBox @@ -353,7 +361,7 @@ void InlineDisplayContentBuilder::appendSpanningInlineBoxDisplayBox(const Line:: , { } , { } , inlineBox.hasContent() - , lineRun.isTruncated() ? InlineDisplay::Box::IsVisuallyHidden::Yes : InlineDisplay::Box::IsVisuallyHidden::No + , lineRun.isTruncated() , isFirstLastBox(inlineBox) }); // Middle or end of the inline box. Let's stretch the box as needed. diff --git a/Source/WebCore/layout/integration/inline/InlineIteratorBoxModernPath.h b/Source/WebCore/layout/integration/inline/InlineIteratorBoxModernPath.h index 8764d5e0292b..7ac7b28f5560 100644 --- a/Source/WebCore/layout/integration/inline/InlineIteratorBoxModernPath.h +++ b/Source/WebCore/layout/integration/inline/InlineIteratorBoxModernPath.h @@ -73,7 +73,7 @@ class BoxModernPath { length(), box().text()->hasHyphen() ? box().style().hyphenString().length() : 0, box().isLineBreak(), - box().text()->visuallyVisibleLength() + box().text()->partiallyVisibleContentLength() }; } diff --git a/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentPainter.cpp b/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentPainter.cpp index 6bde5c5f7220..b7fc4e4a1f23 100644 --- a/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentPainter.cpp +++ b/Source/WebCore/layout/integration/inline/LayoutIntegrationInlineContentPainter.cpp @@ -67,8 +67,7 @@ void InlineContentPainter::paintDisplayBox(const InlineDisplay::Box& box) return m_damageRect.maxY() > rect.y() && m_damageRect.y() < rect.maxY(); }; - auto isVisuallyHidden = box.isVisuallyHidden() == InlineDisplay::Box::IsVisuallyHidden::Yes || box.style().visibility() != Visibility::Visible; - if (isVisuallyHidden || box.isLineBreak()) + if (!box.isVisible() || box.isLineBreak()) return; if (box.isInlineBox()) { diff --git a/Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp b/Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp index a92037b81be3..16ae341a0d4d 100644 --- a/Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp +++ b/Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp @@ -806,6 +806,9 @@ bool LineLayout::hitTest(const HitTestRequest& request, HitTestResult& result, c LayerPaintScope layerPaintScope(m_boxTree, layerRenderer); for (auto& box : makeReversedRange(boxRange)) { + if (!box.isVisible()) + continue; + auto& renderer = m_boxTree.rendererForLayoutBox(box.layoutBox()); if (!layerPaintScope.includes(box))