Diff
Modified: trunk/LayoutTests/ChangeLog (271349 => 271350)
--- trunk/LayoutTests/ChangeLog 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/LayoutTests/ChangeLog 2021-01-10 18:09:09 UTC (rev 271350)
@@ -1,3 +1,21 @@
+2021-01-10 Antti Koivisto <[email protected]>
+
+ [LFC][Integration] Factor marked text style collection code out of InlineTextBox
+ https://bugs.webkit.org/show_bug.cgi?id=220249
+
+ Reviewed by Zalan Bujtas.
+
+ * TestExpectations:
+
+ Mark http/wpt/css/css-highlight-api/highlight-text-cascade.html failing.
+
+ This test requires CSS4 highlight pseudo element inheritance (https://bugs.webkit.org/show_bug.cgi?id=220325)
+ which we (or anyone else) don't support.
+
+ It was passing by accident because the code was getting '::highlight' pseudo element style from a wrong element
+ (containing block instead of inline element) in certain cases. Renderer was found via InlineBox parent() which doesn't
+ match render tree parent in case inline culling optimization is active. The correct way is to use render tree parent.
+
2021-01-09 Zalan Bujtas <[email protected]>
play.google.com: App preview images are clipped
Modified: trunk/LayoutTests/TestExpectations (271349 => 271350)
--- trunk/LayoutTests/TestExpectations 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/LayoutTests/TestExpectations 2021-01-10 18:09:09 UTC (rev 271350)
@@ -4594,3 +4594,5 @@
webkit.org/b/217931 imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-classic.html [ Pass Failure ]
webkit.org/b/217931 imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-module.html [ Pass Failure ]
webkit.org/b/217931 imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-inline-classic.html [ Pass Failure ]
+
+webkit.org/b/220325 http/wpt/css/css-highlight-api/highlight-text-cascade.html [ ImageOnlyFailure ]
Modified: trunk/Source/WebCore/ChangeLog (271349 => 271350)
--- trunk/Source/WebCore/ChangeLog 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/Source/WebCore/ChangeLog 2021-01-10 18:09:09 UTC (rev 271350)
@@ -1,5 +1,38 @@
2021-01-10 Antti Koivisto <[email protected]>
+ [LFC][Integration] Factor marked text style collection code out of InlineTextBox
+ https://bugs.webkit.org/show_bug.cgi?id=220249
+
+ Reviewed by Zalan Bujtas.
+
+ This makes it possible to use the code from LFC painting.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * rendering/InlineTextBox.cpp:
+ (WebCore::InlineTextBox::paint):
+ (WebCore::InlineTextBox::MarkedTextStyle::areBackgroundMarkedTextStylesEqual): Deleted.
+ (WebCore::InlineTextBox::MarkedTextStyle::areForegroundMarkedTextStylesEqual): Deleted.
+ (WebCore::InlineTextBox::MarkedTextStyle::areDecorationMarkedTextStylesEqual): Deleted.
+ (WebCore::InlineTextBox::StyledMarkedText::StyledMarkedText): Deleted.
+ (WebCore::InlineTextBox::computeStyleForUnmarkedMarkedText const): Deleted.
+ (WebCore::InlineTextBox::resolveStyleForMarkedText): Deleted.
+ (WebCore::InlineTextBox::subdivideAndResolveStyle): Deleted.
+ (WebCore::InlineTextBox::coalesceAdjacentMarkedTexts): Deleted.
+ * rendering/InlineTextBox.h:
+ * rendering/MarkedTextStyle.cpp: Added.
+ (WebCore::resolveStyleForMarkedText):
+ (WebCore::computeStyleForUnmarkedMarkedText):
+ (WebCore::subdivideAndResolveStyle):
+ (WebCore::coalesceAdjacentMarkedTexts):
+ * rendering/MarkedTextStyle.h: Added.
+ (WebCore::MarkedTextStyle::areBackgroundMarkedTextStylesEqual):
+ (WebCore::MarkedTextStyle::areForegroundMarkedTextStylesEqual):
+ (WebCore::MarkedTextStyle::areDecorationMarkedTextStylesEqual):
+ (WebCore::StyledMarkedText::StyledMarkedText):
+
+2021-01-10 Antti Koivisto <[email protected]>
+
Remove InlineBox::hasSelectedChildren bit
https://bugs.webkit.org/show_bug.cgi?id=220240
Modified: trunk/Source/WebCore/Sources.txt (271349 => 271350)
--- trunk/Source/WebCore/Sources.txt 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/Source/WebCore/Sources.txt 2021-01-10 18:09:09 UTC (rev 271350)
@@ -2195,6 +2195,7 @@
rendering/LayoutDisallowedScope.cpp
rendering/LayoutRepainter.cpp
rendering/MarkedText.cpp
+rendering/MarkedTextStyle.cpp
rendering/OrderIterator.cpp
rendering/PointerEventsHitRules.cpp
rendering/RenderAttachment.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (271349 => 271350)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-01-10 18:09:09 UTC (rev 271350)
@@ -5090,6 +5090,7 @@
E43A023B17EB370A004CDD25 /* RenderElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E43A023A17EB370A004CDD25 /* RenderElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
E43AF8E71AC5B7EC00CA717E /* CacheValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E43AF8E51AC5B7DD00CA717E /* CacheValidation.h */; settings = {ATTRIBUTES = (Private, ); }; };
E440AA961C68420800A265CC /* ElementAndTextDescendantIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E440AA951C68420800A265CC /* ElementAndTextDescendantIterator.h */; };
+ E440FD5325A4AFDF00F7C849 /* MarkedTextStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = E440FD5125A4AFDF00F7C849 /* MarkedTextStyle.h */; };
E44613A20CD6331000FADA75 /* HTMLAudioElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E44613900CD6331000FADA75 /* HTMLAudioElement.h */; };
E44613A50CD6331000FADA75 /* HTMLMediaElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E44613930CD6331000FADA75 /* HTMLMediaElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
E44613A80CD6331000FADA75 /* HTMLSourceElement.h in Headers */ = {isa = PBXBuildFile; fileRef = E44613960CD6331000FADA75 /* HTMLSourceElement.h */; };
@@ -16232,6 +16233,8 @@
E43AF8E41AC5B7DD00CA717E /* CacheValidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CacheValidation.cpp; sourceTree = "<group>"; };
E43AF8E51AC5B7DD00CA717E /* CacheValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CacheValidation.h; sourceTree = "<group>"; };
E440AA951C68420800A265CC /* ElementAndTextDescendantIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAndTextDescendantIterator.h; sourceTree = "<group>"; };
+ E440FD5125A4AFDF00F7C849 /* MarkedTextStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedTextStyle.h; sourceTree = "<group>"; };
+ E440FD5425A4AFEE00F7C849 /* MarkedTextStyle.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MarkedTextStyle.cpp; sourceTree = "<group>"; };
E4451077202C7E0100657D33 /* CompiledSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompiledSelector.h; sourceTree = "<group>"; };
E446138F0CD6331000FADA75 /* HTMLAudioElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLAudioElement.cpp; sourceTree = "<group>"; };
E44613900CD6331000FADA75 /* HTMLAudioElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLAudioElement.h; sourceTree = "<group>"; };
@@ -29647,6 +29650,8 @@
9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */,
CE1866421F72E5B400A0CAB6 /* MarkedText.cpp */,
CE1866431F72E5B400A0CAB6 /* MarkedText.h */,
+ E440FD5425A4AFEE00F7C849 /* MarkedTextStyle.cpp */,
+ E440FD5125A4AFDF00F7C849 /* MarkedTextStyle.h */,
CDE7FC42181904B1002BBB77 /* OrderIterator.cpp */,
CDE7FC43181904B1002BBB77 /* OrderIterator.h */,
3774ABA30FA21EB400AD7DE9 /* OverlapTestRequestClient.h */,
@@ -33041,6 +33046,7 @@
E44614190CD6826900FADA75 /* JSMediaError.h in Headers */,
CDF756A3215C29E900EFCB50 /* JSMediaKeyEncryptionScheme.h in Headers */,
2D9BF7281DBFDB0D007A7D99 /* JSMediaKeyMessageEvent.h in Headers */,
+ E440FD5325A4AFDF00F7C849 /* MarkedTextStyle.h in Headers */,
2D9BF7291DBFDB10007A7D99 /* JSMediaKeys.h in Headers */,
2D9BF72A1DBFDB13007A7D99 /* JSMediaKeySession.h in Headers */,
CDF4B71E1E01E11A00E235A2 /* JSMediaKeySessionType.h in Headers */,
Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (271349 => 271350)
--- trunk/Source/WebCore/rendering/InlineTextBox.cpp 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp 2021-01-10 18:09:09 UTC (rev 271350)
@@ -40,7 +40,7 @@
#include "HitTestResult.h"
#include "ImageBuffer.h"
#include "InlineTextBoxStyle.h"
-#include "MarkedText.h"
+#include "MarkedTextStyle.h"
#include "Page.h"
#include "PaintInfo.h"
#include "RenderBlock.h"
@@ -433,36 +433,6 @@
return isAbove;
}
-struct InlineTextBox::MarkedTextStyle {
- static bool areBackgroundMarkedTextStylesEqual(const MarkedTextStyle& a, const MarkedTextStyle& b)
- {
- return a.backgroundColor == b.backgroundColor;
- }
- static bool areForegroundMarkedTextStylesEqual(const MarkedTextStyle& a, const MarkedTextStyle& b)
- {
- return a.textStyles == b.textStyles && a.textShadow == b.textShadow && a.alpha == b.alpha;
- }
- static bool areDecorationMarkedTextStylesEqual(const MarkedTextStyle& a, const MarkedTextStyle& b)
- {
- return a.textDecorationStyles == b.textDecorationStyles && a.textShadow == b.textShadow && a.alpha == b.alpha;
- }
-
- Color backgroundColor;
- TextPaintStyle textStyles;
- TextDecorationPainter::Styles textDecorationStyles;
- Optional<ShadowData> textShadow;
- float alpha;
-};
-
-struct InlineTextBox::StyledMarkedText : MarkedText {
- StyledMarkedText(const MarkedText& marker)
- : MarkedText { marker }
- {
- }
-
- MarkedTextStyle style;
-};
-
static MarkedText createMarkedTextFromSelectionInBox(const InlineTextBox& box)
{
auto [selectionStart, selectionEnd] = box.selectionStartEnd();
@@ -544,8 +514,6 @@
bool containsComposition = renderer().textNode() && renderer().frame().editor().compositionNode() == renderer().textNode();
bool useCustomUnderlines = containsComposition && renderer().frame().editor().compositionUsesCustomUnderlines();
- MarkedTextStyle unmarkedStyle = computeStyleForUnmarkedMarkedText(paintInfo);
-
// 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
// and composition underlines.
if (paintInfo.phase != PaintPhase::Selection && paintInfo.phase != PaintPhase::TextClip && !isPrinting) {
@@ -563,7 +531,7 @@
markedTexts.append(WTFMove(selectionMarkedText));
}
#endif
- auto styledMarkedTexts = subdivideAndResolveStyle(markedTexts, unmarkedStyle, paintInfo);
+ auto styledMarkedTexts = subdivideAndResolveStyle(markedTexts, renderer(), isFirstLine(), paintInfo);
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areBackgroundMarkedTextStylesEqual);
@@ -611,7 +579,7 @@
markedTexts.append(WTFMove(selectionMarkedText));
}
- auto styledMarkedTexts = subdivideAndResolveStyle(markedTexts, unmarkedStyle, paintInfo);
+ auto styledMarkedTexts = subdivideAndResolveStyle(markedTexts, renderer(), isFirstLine(), paintInfo);
// ... now remove the selection marked text if we are excluding selection.
if (!isPrinting && paintInfo.paintBehavior.contains(PaintBehavior::ExcludeSelection))
@@ -796,141 +764,6 @@
context.drawDotsForDocumentMarker(bounds, lineStyleForMarkedTextType());
}
-auto InlineTextBox::computeStyleForUnmarkedMarkedText(const PaintInfo& paintInfo) const -> MarkedTextStyle
-{
- auto& lineStyle = this->lineStyle();
-
- MarkedTextStyle style;
- style.textDecorationStyles = TextDecorationPainter::stylesForRenderer(renderer(), lineStyle.textDecorationsInEffect(), isFirstLine());
- style.textStyles = computeTextPaintStyle(renderer().frame(), lineStyle, paintInfo);
- style.textShadow = ShadowData::clone(paintInfo.forceTextColor() ? nullptr : lineStyle.textShadow());
- style.alpha = 1;
- return style;
-}
-
-auto InlineTextBox::resolveStyleForMarkedText(const MarkedText& markedText, const MarkedTextStyle& baseStyle, const PaintInfo& paintInfo) -> StyledMarkedText
-{
- MarkedTextStyle style = baseStyle;
- switch (markedText.type) {
- case MarkedText::Correction:
- case MarkedText::DictationAlternatives:
-#if PLATFORM(IOS_FAMILY)
- // FIXME: See <rdar://problem/8933352>. Also, remove the PLATFORM(IOS_FAMILY)-guard.
- case MarkedText::DictationPhraseWithAlternatives:
-#endif
- case MarkedText::GrammarError:
- case MarkedText::SpellingError:
- case MarkedText::Unmarked:
- break;
- case MarkedText::Highlight:
- if (auto renderStyle = parent()->renderer().getUncachedPseudoStyle({ PseudoId::Highlight, markedText.highlightName }, &parent()->renderer().style())) {
- style.backgroundColor = renderStyle->backgroundColor();
- style.textStyles.fillColor = renderStyle->computedStrokeColor();
- style.textStyles.strokeColor = renderStyle->computedStrokeColor();
-
- auto color = TextDecorationPainter::decorationColor(*renderStyle.get());
- auto decorationStyle = renderStyle->textDecorationStyle();
- auto decorations = renderStyle->textDecorationsInEffect();
-
- if (decorations.contains(TextDecoration::Underline)) {
- style.textDecorationStyles.underlineColor = color;
- style.textDecorationStyles.underlineStyle = decorationStyle;
- }
- if (decorations.contains(TextDecoration::Overline)) {
- style.textDecorationStyles.overlineColor = color;
- style.textDecorationStyles.overlineStyle = decorationStyle;
- }
- if (decorations.contains(TextDecoration::LineThrough)) {
- style.textDecorationStyles.linethroughColor = color;
- style.textDecorationStyles.linethroughStyle = decorationStyle;
- }
- }
- break;
-#if ENABLE(APP_HIGHLIGHTS)
- case MarkedText::AppHighlight: {
- OptionSet<StyleColor::Options> styleColorOptions = { StyleColor::Options::UseSystemAppearance };
- style.backgroundColor = renderer().theme().appHighlightColor(styleColorOptions);
- break;
- }
-#endif
- case MarkedText::DraggedContent:
- style.alpha = 0.25;
- break;
- case MarkedText::Selection: {
- style.textStyles = computeTextSelectionPaintStyle(style.textStyles, renderer(), lineStyle(), paintInfo, style.textShadow);
-
- Color selectionBackgroundColor = renderer().selectionBackgroundColor();
- style.backgroundColor = selectionBackgroundColor;
- if (selectionBackgroundColor.isValid() && selectionBackgroundColor.isVisible() && style.textStyles.fillColor == selectionBackgroundColor)
- style.backgroundColor = selectionBackgroundColor.invertedColorWithAlpha(1.0);
- break;
- }
- case MarkedText::TextMatch: {
- // Text matches always use the light system appearance.
- OptionSet<StyleColor::Options> styleColorOptions = { StyleColor::Options::UseSystemAppearance };
-#if PLATFORM(MAC)
- style.textStyles.fillColor = renderer().theme().systemColor(CSSValueAppleSystemLabel, styleColorOptions);
-#endif
- style.backgroundColor = renderer().theme().textSearchHighlightColor(styleColorOptions);
- break;
- }
- }
- StyledMarkedText styledMarkedText = markedText;
- styledMarkedText.style = WTFMove(style);
- return styledMarkedText;
-}
-
-auto InlineTextBox::subdivideAndResolveStyle(const Vector<MarkedText>& textsToSubdivide, const MarkedTextStyle& baseStyle, const PaintInfo& paintInfo) -> Vector<StyledMarkedText>
-{
- if (textsToSubdivide.isEmpty())
- return { };
-
- auto markedTexts = subdivide(textsToSubdivide);
- ASSERT(!markedTexts.isEmpty());
- if (UNLIKELY(markedTexts.isEmpty()))
- return { };
-
- // Compute frontmost overlapping styled marked texts.
- Vector<StyledMarkedText> frontmostMarkedTexts;
- frontmostMarkedTexts.reserveInitialCapacity(markedTexts.size());
- frontmostMarkedTexts.uncheckedAppend(resolveStyleForMarkedText(markedTexts[0], baseStyle, paintInfo));
- for (auto it = markedTexts.begin() + 1, end = markedTexts.end(); it != end; ++it) {
- StyledMarkedText& previousStyledMarkedText = frontmostMarkedTexts.last();
- if (previousStyledMarkedText.startOffset == it->startOffset && previousStyledMarkedText.endOffset == it->endOffset) {
- // Marked texts completely cover each other.
- previousStyledMarkedText = resolveStyleForMarkedText(*it, previousStyledMarkedText.style, paintInfo);
- continue;
- }
- frontmostMarkedTexts.uncheckedAppend(resolveStyleForMarkedText(*it, baseStyle, paintInfo));
- }
-
- return frontmostMarkedTexts;
-}
-
-auto InlineTextBox::coalesceAdjacentMarkedTexts(const Vector<StyledMarkedText>& textsToCoalesce, MarkedTextStylesEqualityFunction areMarkedTextStylesEqual) -> Vector<StyledMarkedText>
-{
- if (textsToCoalesce.isEmpty())
- return { };
-
- auto areAdjacentMarkedTextsWithSameStyle = [&] (const StyledMarkedText& a, const StyledMarkedText& b) {
- return a.endOffset == b.startOffset && areMarkedTextStylesEqual(a.style, b.style);
- };
-
- Vector<StyledMarkedText> styledMarkedTexts;
- styledMarkedTexts.reserveInitialCapacity(textsToCoalesce.size());
- styledMarkedTexts.uncheckedAppend(textsToCoalesce[0]);
- for (auto it = textsToCoalesce.begin() + 1, end = textsToCoalesce.end(); it != end; ++it) {
- StyledMarkedText& previousStyledMarkedText = styledMarkedTexts.last();
- if (areAdjacentMarkedTextsWithSameStyle(previousStyledMarkedText, *it)) {
- previousStyledMarkedText.endOffset = it->endOffset;
- continue;
- }
- styledMarkedTexts.uncheckedAppend(*it);
- }
-
- return styledMarkedTexts;
-}
-
Vector<MarkedText> InlineTextBox::collectMarkedTextsForDraggedContent()
{
using DraggendContentRange = std::pair<unsigned, unsigned>;
Modified: trunk/Source/WebCore/rendering/InlineTextBox.h (271349 => 271350)
--- trunk/Source/WebCore/rendering/InlineTextBox.h 2021-01-10 12:04:02 UTC (rev 271349)
+++ trunk/Source/WebCore/rendering/InlineTextBox.h 2021-01-10 18:09:09 UTC (rev 271350)
@@ -33,6 +33,7 @@
class TextPainter;
struct CompositionUnderline;
struct MarkedText;
+struct StyledMarkedText;
struct TextPaintStyle;
const unsigned short cNoTruncation = USHRT_MAX;
@@ -164,9 +165,6 @@
FloatRect calculateDocumentMarkerBounds(const MarkedText&) const;
private:
- struct MarkedTextStyle;
- struct StyledMarkedText;
-
enum class TextPaintPhase { Background, Foreground, Decoration };
Vector<MarkedText> collectMarkedTextsForDraggedContent();
@@ -173,13 +171,6 @@
Vector<MarkedText> collectMarkedTextsForDocumentMarkers(TextPaintPhase) const;
Vector<MarkedText> collectMarkedTextsForHighlights(TextPaintPhase) const;
- MarkedTextStyle computeStyleForUnmarkedMarkedText(const PaintInfo&) const;
- StyledMarkedText resolveStyleForMarkedText(const MarkedText&, const MarkedTextStyle& baseStyle, const PaintInfo&);
- Vector<StyledMarkedText> subdivideAndResolveStyle(const Vector<MarkedText>&, const MarkedTextStyle& baseStyle, const PaintInfo&);
-
- using MarkedTextStylesEqualityFunction = bool (*)(const MarkedTextStyle&, const MarkedTextStyle&);
- Vector<StyledMarkedText> coalesceAdjacentMarkedTexts(const Vector<StyledMarkedText>&, MarkedTextStylesEqualityFunction);
-
FloatPoint textOriginFromBoxRect(const FloatRect&) const;
void paintMarkedTexts(PaintInfo&, TextPaintPhase, const FloatRect& boxRect, const Vector<StyledMarkedText>&, const FloatRect& decorationClipOutRect = { });
Added: trunk/Source/WebCore/rendering/MarkedTextStyle.cpp (0 => 271350)
--- trunk/Source/WebCore/rendering/MarkedTextStyle.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/MarkedTextStyle.cpp 2021-01-10 18:09:09 UTC (rev 271350)
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MarkedTextStyle.h"
+
+#include "ElementRuleCollector.h"
+#include "RenderElement.h"
+#include "RenderText.h"
+#include "RenderTheme.h"
+
+namespace WebCore {
+
+static StyledMarkedText resolveStyleForMarkedText(const MarkedText& markedText, const MarkedTextStyle& baseStyle, const RenderText& renderer, const RenderStyle& lineStyle, const PaintInfo& paintInfo)
+{
+ MarkedTextStyle style = baseStyle;
+ switch (markedText.type) {
+ case MarkedText::Correction:
+ case MarkedText::DictationAlternatives:
+#if PLATFORM(IOS_FAMILY)
+ // FIXME: See <rdar://problem/8933352>. Also, remove the PLATFORM(IOS_FAMILY)-guard.
+ case MarkedText::DictationPhraseWithAlternatives:
+#endif
+ case MarkedText::GrammarError:
+ case MarkedText::SpellingError:
+ case MarkedText::Unmarked:
+ break;
+ case MarkedText::Highlight:
+ if (auto renderStyle = renderer.parent()->getUncachedPseudoStyle({ PseudoId::Highlight, markedText.highlightName }, &renderer.style())) {
+ style.backgroundColor = renderStyle->backgroundColor();
+ style.textStyles.fillColor = renderStyle->computedStrokeColor();
+ style.textStyles.strokeColor = renderStyle->computedStrokeColor();
+
+ auto color = TextDecorationPainter::decorationColor(*renderStyle.get());
+ auto decorationStyle = renderStyle->textDecorationStyle();
+ auto decorations = renderStyle->textDecorationsInEffect();
+
+ if (decorations.contains(TextDecoration::Underline)) {
+ style.textDecorationStyles.underlineColor = color;
+ style.textDecorationStyles.underlineStyle = decorationStyle;
+ }
+ if (decorations.contains(TextDecoration::Overline)) {
+ style.textDecorationStyles.overlineColor = color;
+ style.textDecorationStyles.overlineStyle = decorationStyle;
+ }
+ if (decorations.contains(TextDecoration::LineThrough)) {
+ style.textDecorationStyles.linethroughColor = color;
+ style.textDecorationStyles.linethroughStyle = decorationStyle;
+ }
+ }
+ break;
+#if ENABLE(APP_HIGHLIGHTS)
+ case MarkedText::AppHighlight: {
+ OptionSet<StyleColor::Options> styleColorOptions = { StyleColor::Options::UseSystemAppearance };
+ style.backgroundColor = renderer().theme().appHighlightColor(styleColorOptions);
+ break;
+ }
+#endif
+ case MarkedText::DraggedContent:
+ style.alpha = 0.25;
+ break;
+ case MarkedText::Selection: {
+ style.textStyles = computeTextSelectionPaintStyle(style.textStyles, renderer, lineStyle, paintInfo, style.textShadow);
+
+ Color selectionBackgroundColor = renderer.selectionBackgroundColor();
+ style.backgroundColor = selectionBackgroundColor;
+ if (selectionBackgroundColor.isValid() && selectionBackgroundColor.isVisible() && style.textStyles.fillColor == selectionBackgroundColor)
+ style.backgroundColor = selectionBackgroundColor.invertedColorWithAlpha(1.0);
+ break;
+ }
+ case MarkedText::TextMatch: {
+ // Text matches always use the light system appearance.
+ OptionSet<StyleColor::Options> styleColorOptions = { StyleColor::Options::UseSystemAppearance };
+#if PLATFORM(MAC)
+ style.textStyles.fillColor = renderer.theme().systemColor(CSSValueAppleSystemLabel, styleColorOptions);
+#endif
+ style.backgroundColor = renderer.theme().textSearchHighlightColor(styleColorOptions);
+ break;
+ }
+ }
+ StyledMarkedText styledMarkedText = markedText;
+ styledMarkedText.style = WTFMove(style);
+ return styledMarkedText;
+}
+
+static MarkedTextStyle computeStyleForUnmarkedMarkedText(const RenderText& renderer, const RenderStyle& lineStyle, bool isFirstLine, const PaintInfo& paintInfo)
+{
+ MarkedTextStyle style;
+ style.textDecorationStyles = TextDecorationPainter::stylesForRenderer(renderer, lineStyle.textDecorationsInEffect(), isFirstLine);
+ style.textStyles = computeTextPaintStyle(renderer.frame(), lineStyle, paintInfo);
+ style.textShadow = ShadowData::clone(paintInfo.forceTextColor() ? nullptr : lineStyle.textShadow());
+ style.alpha = 1;
+ return style;
+}
+
+Vector<StyledMarkedText> subdivideAndResolveStyle(const Vector<MarkedText>& textsToSubdivide, const RenderText& renderer, bool isFirstLine, const PaintInfo& paintInfo)
+{
+ if (textsToSubdivide.isEmpty())
+ return { };
+
+ auto markedTexts = subdivide(textsToSubdivide);
+ ASSERT(!markedTexts.isEmpty());
+ if (UNLIKELY(markedTexts.isEmpty()))
+ return { };
+
+ auto& lineStyle = isFirstLine ? renderer.firstLineStyle() : renderer.style();
+ auto baseStyle = computeStyleForUnmarkedMarkedText(renderer, lineStyle, isFirstLine, paintInfo);
+
+ // Compute frontmost overlapping styled marked texts.
+ Vector<StyledMarkedText> frontmostMarkedTexts;
+ frontmostMarkedTexts.reserveInitialCapacity(markedTexts.size());
+ frontmostMarkedTexts.uncheckedAppend(resolveStyleForMarkedText(markedTexts[0], baseStyle, renderer, lineStyle, paintInfo));
+ for (auto it = markedTexts.begin() + 1, end = markedTexts.end(); it != end; ++it) {
+ StyledMarkedText& previousStyledMarkedText = frontmostMarkedTexts.last();
+ if (previousStyledMarkedText.startOffset == it->startOffset && previousStyledMarkedText.endOffset == it->endOffset) {
+ // Marked texts completely cover each other.
+ previousStyledMarkedText = resolveStyleForMarkedText(*it, previousStyledMarkedText.style, renderer, lineStyle, paintInfo);
+ continue;
+ }
+ frontmostMarkedTexts.uncheckedAppend(resolveStyleForMarkedText(*it, baseStyle, renderer, lineStyle, paintInfo));
+ }
+
+ return frontmostMarkedTexts;
+}
+
+Vector<StyledMarkedText> coalesceAdjacentMarkedTexts(const Vector<StyledMarkedText>& textsToCoalesce, MarkedTextStylesEqualityFunction areMarkedTextStylesEqual)
+{
+ if (textsToCoalesce.isEmpty())
+ return { };
+
+ auto areAdjacentMarkedTextsWithSameStyle = [&] (const StyledMarkedText& a, const StyledMarkedText& b) {
+ return a.endOffset == b.startOffset && areMarkedTextStylesEqual(a.style, b.style);
+ };
+
+ Vector<StyledMarkedText> styledMarkedTexts;
+ styledMarkedTexts.reserveInitialCapacity(textsToCoalesce.size());
+ styledMarkedTexts.uncheckedAppend(textsToCoalesce[0]);
+ for (auto it = textsToCoalesce.begin() + 1, end = textsToCoalesce.end(); it != end; ++it) {
+ StyledMarkedText& previousStyledMarkedText = styledMarkedTexts.last();
+ if (areAdjacentMarkedTextsWithSameStyle(previousStyledMarkedText, *it)) {
+ previousStyledMarkedText.endOffset = it->endOffset;
+ continue;
+ }
+ styledMarkedTexts.uncheckedAppend(*it);
+ }
+
+ return styledMarkedTexts;
+}
+
+}
Added: trunk/Source/WebCore/rendering/MarkedTextStyle.h (0 => 271350)
--- trunk/Source/WebCore/rendering/MarkedTextStyle.h (rev 0)
+++ trunk/Source/WebCore/rendering/MarkedTextStyle.h 2021-01-10 18:09:09 UTC (rev 271350)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "MarkedText.h"
+#include "ShadowData.h"
+#include "TextDecorationPainter.h"
+#include "TextPaintStyle.h"
+#include <wtf/Optional.h>
+
+namespace WebCore {
+
+class RenderText;
+class RenderedDocumentMarker;
+
+struct MarkedTextStyle {
+ static bool areBackgroundMarkedTextStylesEqual(const MarkedTextStyle& a, const MarkedTextStyle& b)
+ {
+ return a.backgroundColor == b.backgroundColor;
+ }
+ static bool areForegroundMarkedTextStylesEqual(const MarkedTextStyle& a, const MarkedTextStyle& b)
+ {
+ return a.textStyles == b.textStyles && a.textShadow == b.textShadow && a.alpha == b.alpha;
+ }
+ static bool areDecorationMarkedTextStylesEqual(const MarkedTextStyle& a, const MarkedTextStyle& b)
+ {
+ return a.textDecorationStyles == b.textDecorationStyles && a.textShadow == b.textShadow && a.alpha == b.alpha;
+ }
+
+ Color backgroundColor;
+ TextPaintStyle textStyles;
+ TextDecorationPainter::Styles textDecorationStyles;
+ Optional<ShadowData> textShadow;
+ float alpha;
+};
+
+struct StyledMarkedText : MarkedText {
+ StyledMarkedText(const MarkedText& marker)
+ : MarkedText { marker }
+ {
+ }
+
+ MarkedTextStyle style;
+};
+
+Vector<StyledMarkedText> subdivideAndResolveStyle(const Vector<MarkedText>&, const RenderText&, bool isFirstLine, const PaintInfo&);
+
+using MarkedTextStylesEqualityFunction = bool (*)(const MarkedTextStyle&, const MarkedTextStyle&);
+Vector<StyledMarkedText> coalesceAdjacentMarkedTexts(const Vector<StyledMarkedText>&, MarkedTextStylesEqualityFunction);
+
+}