Diff
Modified: trunk/Source/WebCore/ChangeLog (282269 => 282270)
--- trunk/Source/WebCore/ChangeLog 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/ChangeLog 2021-09-10 15:20:38 UTC (rev 282270)
@@ -1,3 +1,42 @@
+2021-09-10 Antti Koivisto <an...@apple.com>
+
+ Factor painting functions from LegacyInlineTextBox into a class
+ https://bugs.webkit.org/show_bug.cgi?id=230147
+
+ Reviewed by Alan Bujtas.
+
+ Add TextBoxPainter class and move some of the painting functions from LegacyInlineTextBox there.
+
+ This patch is largely mechanical but will make it easier to decouple text painting from the legacy
+ inline boxes in the future.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * rendering/LegacyInlineTextBox.cpp:
+ (WebCore::LegacyInlineTextBox::paint):
+ (WebCore::LegacyInlineTextBox::debugTextShadow const):
+ (WebCore::LegacyInlineTextBox::paintMarkedTexts): Deleted.
+ (WebCore::LegacyInlineTextBox::paintMarkedTextBackground): Deleted.
+ (WebCore::LegacyInlineTextBox::paintMarkedTextForeground): Deleted.
+ (WebCore::LegacyInlineTextBox::paintMarkedTextDecoration): Deleted.
+ (WebCore::LegacyInlineTextBox::paintCompositionBackground): Deleted.
+ (WebCore::LegacyInlineTextBox::debugTextShadow): Deleted.
+ * rendering/LegacyInlineTextBox.h:
+ (WebCore::LegacyInlineTextBox::paintMarkedTexts): Deleted.
+ * rendering/MarkedText.h:
+ * rendering/StyledMarkedText.cpp:
+ (WebCore::resolveStyleForMarkedText):
+ (WebCore::computeStyleForUnmarkedMarkedText):
+ * rendering/StyledMarkedText.h:
+ * rendering/TextBoxPainter.cpp: Added.
+ (WebCore::TextBoxPainter::TextBoxPainter):
+ (WebCore::TextBoxPainter::~TextBoxPainter):
+ (WebCore::TextBoxPainter::paintCompositionBackground):
+ (WebCore::TextBoxPainter::paintBackground):
+ (WebCore::TextBoxPainter::paintForeground):
+ (WebCore::TextBoxPainter::paintDecoration):
+ * rendering/TextBoxPainter.h: Added.
+
2021-09-07 Sergio Villar Senin <svil...@igalia.com>
[css-flexbox] Add support for self-start & self-end css-align-3 positional alignment properties
Modified: trunk/Source/WebCore/Sources.txt (282269 => 282270)
--- trunk/Source/WebCore/Sources.txt 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/Sources.txt 2021-09-10 15:20:38 UTC (rev 282270)
@@ -2282,6 +2282,7 @@
rendering/SelectionRangeData.cpp
rendering/StyledMarkedText.cpp
rendering/TableLayout.cpp
+rendering/TextBoxPainter.cpp
rendering/TextDecorationPainter.cpp
rendering/TextPaintStyle.cpp
rendering/TextPainter.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (282269 => 282270)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-09-10 15:20:38 UTC (rev 282270)
@@ -5225,6 +5225,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 */; };
+ E440DF5626EB53E0004AF06B /* TextBoxPainter.h in Headers */ = {isa = PBXBuildFile; fileRef = E440DF5426EB53DF004AF06B /* TextBoxPainter.h */; };
E440FD5325A4AFDF00F7C849 /* StyledMarkedText.h in Headers */ = {isa = PBXBuildFile; fileRef = E440FD5125A4AFDF00F7C849 /* StyledMarkedText.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, ); }; };
@@ -16291,6 +16292,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>"; };
+ E440DF5426EB53DF004AF06B /* TextBoxPainter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextBoxPainter.h; sourceTree = "<group>"; };
+ E440DF5726EB53EA004AF06B /* TextBoxPainter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextBoxPainter.cpp; sourceTree = "<group>"; };
E440FD5125A4AFDF00F7C849 /* StyledMarkedText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyledMarkedText.h; sourceTree = "<group>"; };
E440FD5425A4AFEE00F7C849 /* StyledMarkedText.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyledMarkedText.cpp; sourceTree = "<group>"; };
E4451077202C7E0100657D33 /* CompiledSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompiledSelector.h; sourceTree = "<group>"; };
@@ -29867,6 +29870,8 @@
A8CFF04C0A154F09000A4234 /* TableLayout.h */,
0F54DCE31881051D003EEDBB /* TextAutoSizing.cpp */,
0F54DCE41881051D003EEDBB /* TextAutoSizing.h */,
+ E440DF5726EB53EA004AF06B /* TextBoxPainter.cpp */,
+ E440DF5426EB53DF004AF06B /* TextBoxPainter.h */,
E447F5B1266CF63D00133F00 /* TextBoxSelectableRange.h */,
582DE3221C30C85400BE02A8 /* TextDecorationPainter.cpp */,
582DE3231C30C85400BE02A8 /* TextDecorationPainter.h */,
@@ -32553,6 +32558,7 @@
318EAD4D1FA91380008CEF86 /* ImageBitmapRenderingContextSettings.h in Headers */,
B2A10B920B3818BD00099AA4 /* ImageBuffer.h in Headers */,
72BAC3AE23E1F0B0008D741C /* ImageBufferBackend.h in Headers */,
+ E440DF5626EB53E0004AF06B /* TextBoxPainter.h in Headers */,
550640B02407587E00AAE045 /* ImageBufferCGBackend.h in Headers */,
2D7705C925528D34001D0C94 /* ImageBufferCGBitmapBackend.h in Headers */,
727A7F3A24078B84004D2931 /* ImageBufferIOSurfaceBackend.h in Headers */,
Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp (282269 => 282270)
--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.cpp 2021-09-10 15:20:38 UTC (rev 282270)
@@ -54,6 +54,7 @@
#include "Settings.h"
#include "StyledMarkedText.h"
#include "Text.h"
+#include "TextBoxPainter.h"
#include "TextBoxSelectableRange.h"
#include "TextDecorationPainter.h"
#include "TextPaintStyle.h"
@@ -184,7 +185,7 @@
return state;
}
-inline const FontCascade& LegacyInlineTextBox::lineFont() const
+const FontCascade& LegacyInlineTextBox::lineFont() const
{
return combinedText() ? combinedText()->textCombineFont() : lineStyle().fontCascade();
}
@@ -213,7 +214,6 @@
return LayoutRect { topPoint, LayoutSize { width, height } };
}
-// FIXME: Share more code with paintMarkedTextBackground().
LayoutRect LegacyInlineTextBox::localSelectionRect(unsigned startPos, unsigned endPos) const
{
auto [clampedStart, clampedEnd] = selectableRange().clamp(startPos, endPos);
@@ -475,12 +475,8 @@
return;
}
- auto* combinedText = this->combinedText();
+ TextBoxPainter textBoxPainter(*this, paintInfo, boxRect);
- bool shouldRotate = !isHorizontal() && !combinedText;
- if (shouldRotate)
- context.concatCTM(rotation(boxRect, Clockwise));
-
// Determine whether or not we have composition underlines to draw.
bool containsComposition = renderer().textNode() && renderer().frame().editor().compositionNode() == renderer().textNode();
bool useCustomUnderlines = containsComposition && renderer().frame().editor().compositionUsesCustomUnderlines();
@@ -489,7 +485,7 @@
// and composition underlines.
if (paintInfo.phase != PaintPhase::Selection && paintInfo.phase != PaintPhase::TextClip && !isPrinting) {
if (containsComposition && !useCustomUnderlines)
- paintCompositionBackground(paintInfo, boxOrigin);
+ textBoxPainter.paintCompositionBackground();
auto selectableRange = this->selectableRange();
@@ -509,7 +505,8 @@
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = StyledMarkedText::coalesceAdjacentWithEqualBackground(styledMarkedTexts);
- paintMarkedTexts(paintInfo, MarkedText::PaintPhase::Background, boxRect, coalescedStyledMarkedTexts);
+ for (auto& markedText : coalescedStyledMarkedTexts)
+ textBoxPainter.paintBackground(markedText);
}
// FIXME: Right now, LegacyInlineTextBoxes never call addRelevantUnpaintedObject() even though they might
@@ -565,7 +562,8 @@
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = StyledMarkedText::coalesceAdjacentWithEqualForeground(styledMarkedTexts);
- paintMarkedTexts(paintInfo, MarkedText::PaintPhase::Foreground, boxRect, coalescedStyledMarkedTexts);
+ for (auto& markedText : coalescedStyledMarkedTexts)
+ textBoxPainter.paintForeground(markedText);
// Paint decorations
auto textDecorations = lineStyle.textDecorationsInEffect();
@@ -604,15 +602,13 @@
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = StyledMarkedText::coalesceAdjacentWithEqualDecorations(styledMarkedTexts);
- paintMarkedTexts(paintInfo, MarkedText::PaintPhase::Decoration, boxRect, coalescedStyledMarkedTexts, textDecorationSelectionClipOutRect);
+ for (auto& markedText : coalescedStyledMarkedTexts)
+ textBoxPainter.paintDecoration(markedText, textDecorationSelectionClipOutRect);
}
// 3. Paint fancy decorations, including composition underlines and platform-specific underlines for spelling errors, grammar errors, et cetera.
if (paintInfo.phase == PaintPhase::Foreground && useCustomUnderlines)
- paintCompositionUnderlines(paintInfo, boxOrigin);
-
- if (shouldRotate)
- context.concatCTM(rotation(boxRect, Counterclockwise));
+ paintCompositionUnderlines(paintInfo, boxOrigin);
}
TextBoxSelectableRange LegacyInlineTextBox::selectableRange() const
@@ -743,185 +739,6 @@
return textOrigin;
}
-void LegacyInlineTextBox::paintMarkedTexts(PaintInfo& paintInfo, MarkedText::PaintPhase phase, const FloatRect& boxRect, const Vector<StyledMarkedText>& markedTexts, const FloatRect& decorationClipOutRect)
-{
- switch (phase) {
- case MarkedText::PaintPhase::Background:
- for (auto& markedText : markedTexts)
- paintMarkedTextBackground(paintInfo, boxRect.location(), markedText.style.backgroundColor, markedText.startOffset, markedText.endOffset);
- return;
- case MarkedText::PaintPhase::Foreground:
- for (auto& markedText : markedTexts)
- paintMarkedTextForeground(paintInfo, boxRect, markedText);
- return;
- case MarkedText::PaintPhase::Decoration:
- for (auto& markedText : markedTexts)
- paintMarkedTextDecoration(paintInfo, boxRect, decorationClipOutRect, markedText);
- return;
- }
-}
-
-void LegacyInlineTextBox::paintMarkedTextBackground(PaintInfo& paintInfo, const FloatPoint& boxOrigin, const Color& color, unsigned clampedStartOffset, unsigned clampedEndOffset, MarkedTextBackgroundStyle style)
-{
- if (clampedStartOffset >= clampedEndOffset)
- return;
-
- GraphicsContext& context = paintInfo.context();
- GraphicsContextStateSaver stateSaver { context };
- updateGraphicsContext(context, TextPaintStyle { color }); // Don't draw text at all!
-
- // Note that if the text is truncated, we let the thing being painted in the truncation
- // draw its own highlight.
- TextRun textRun = createTextRun();
-
- const LegacyRootInlineBox& rootBox = root();
- LayoutUnit selectionBottom = rootBox.selectionBottom();
- LayoutUnit selectionTop = rootBox.selectionTopAdjustedForPrecedingBlock();
-
- // Use same y positioning and height as for selection, so that when the selection and this subrange are on
- // the same word there are no pieces sticking out.
- LayoutUnit deltaY { renderer().style().isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop };
- LayoutUnit selectionHeight = std::max<LayoutUnit>(0, selectionBottom - selectionTop);
-
- LayoutRect selectionRect { LayoutUnit(boxOrigin.x()), LayoutUnit(boxOrigin.y() - deltaY), LayoutUnit(logicalWidth()), selectionHeight };
- lineFont().adjustSelectionRectForText(textRun, selectionRect, clampedStartOffset, clampedEndOffset);
-
- // FIXME: Support painting combined text. See <https://bugs.webkit.org/show_bug.cgi?id=180993>.
- auto backgroundRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr());
- if (style == MarkedTextBackgroundStyle::Rounded) {
- backgroundRect.expand(-1, -1);
- backgroundRect.move(0.5, 0.5);
- context.fillRoundedRect(FloatRoundedRect { backgroundRect, FloatRoundedRect::Radii { 2 } }, color);
- return;
- }
-
- context.fillRect(backgroundRect, color);
-}
-
-void LegacyInlineTextBox::paintMarkedTextForeground(PaintInfo& paintInfo, const FloatRect& boxRect, const StyledMarkedText& markedText)
-{
- if (markedText.startOffset >= markedText.endOffset)
- return;
-
- GraphicsContext& context = paintInfo.context();
- const FontCascade& font = lineFont();
- const RenderStyle& lineStyle = this->lineStyle();
-
- float emphasisMarkOffset = 0;
- std::optional<bool> markExistsAndIsAbove = emphasisMarkExistsAndIsAbove(lineStyle);
- const AtomString& emphasisMark = markExistsAndIsAbove ? lineStyle.textEmphasisMarkString() : nullAtom();
- if (!emphasisMark.isEmpty())
- emphasisMarkOffset = *markExistsAndIsAbove ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fontMetrics().descent() + font.emphasisMarkAscent(emphasisMark);
-
- TextPainter textPainter { context };
- textPainter.setFont(font);
- textPainter.setStyle(markedText.style.textStyles);
- textPainter.setIsHorizontal(isHorizontal());
- if (markedText.style.textShadow) {
- textPainter.setShadow(&markedText.style.textShadow.value());
- if (lineStyle.hasAppleColorFilter())
- textPainter.setShadowColorFilter(&lineStyle.appleColorFilter());
- }
- textPainter.setEmphasisMark(emphasisMark, emphasisMarkOffset, combinedText());
- if (auto* debugShadow = debugTextShadow())
- textPainter.setShadow(debugShadow);
-
- TextRun textRun = createTextRun();
- textPainter.setGlyphDisplayListIfNeeded(*this, paintInfo, font, context, textRun);
-
- GraphicsContextStateSaver stateSaver { context, false };
- if (markedText.type == MarkedText::DraggedContent) {
- stateSaver.save();
- context.setAlpha(markedText.style.alpha);
- }
- // TextPainter wants the box rectangle and text origin of the entire line box.
- textPainter.paintRange(textRun, boxRect, textOriginFromBoxRect(boxRect), markedText.startOffset, markedText.endOffset);
-}
-
-void LegacyInlineTextBox::paintMarkedTextDecoration(PaintInfo& paintInfo, const FloatRect& boxRect, const FloatRect& clipOutRect, const StyledMarkedText& markedText)
-{
- if (m_truncation == cFullTruncation)
- return;
-
- GraphicsContext& context = paintInfo.context();
- updateGraphicsContext(context, markedText.style.textStyles);
-
- bool isCombinedText = combinedText();
- if (isCombinedText)
- context.concatCTM(rotation(boxRect, Clockwise));
-
- // 1. Compute text selection
- unsigned startOffset = markedText.startOffset;
- unsigned endOffset = markedText.endOffset;
- if (startOffset >= endOffset)
- return;
-
- // Note that if the text is truncated, we let the thing being painted in the truncation
- // draw its own decoration.
- TextRun textRun = createTextRun();
-
- // Avoid measuring the text when the entire line box is selected as an optimization.
- FloatRect snappedSelectionRect = boxRect;
- if (startOffset || endOffset != textRun.length()) {
- LayoutRect selectionRect = { boxRect.x(), boxRect.y(), boxRect.width(), boxRect.height() };
- lineFont().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
- snappedSelectionRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr());
- }
-
- // 2. Paint
- auto textDecorations = lineStyle().textDecorationsInEffect();
- textDecorations.add(TextDecorationPainter::textDecorationsInEffectForStyle(markedText.style.textDecorationStyles));
- TextDecorationPainter decorationPainter { context, textDecorations, renderer(), isFirstLine(), lineFont(), markedText.style.textDecorationStyles };
- decorationPainter.setTextRunIterator(LayoutIntegration::textRunFor(this));
- decorationPainter.setWidth(snappedSelectionRect.width());
- decorationPainter.setIsHorizontal(isHorizontal());
- if (markedText.style.textShadow) {
- decorationPainter.setTextShadow(&markedText.style.textShadow.value());
- if (lineStyle().hasAppleColorFilter())
- decorationPainter.setShadowColorFilter(&lineStyle().appleColorFilter());
- }
-
- {
- GraphicsContextStateSaver stateSaver { context, false };
- bool isDraggedContent = markedText.type == MarkedText::DraggedContent;
- if (isDraggedContent || !clipOutRect.isEmpty()) {
- stateSaver.save();
- if (isDraggedContent)
- context.setAlpha(markedText.style.alpha);
- if (!clipOutRect.isEmpty())
- context.clipOut(clipOutRect);
- }
- decorationPainter.paintTextDecoration(textRun.subRun(startOffset, endOffset - startOffset), textOriginFromBoxRect(snappedSelectionRect), snappedSelectionRect.location());
- }
-
- if (isCombinedText)
- context.concatCTM(rotation(boxRect, Counterclockwise));
-}
-
-void LegacyInlineTextBox::paintCompositionBackground(PaintInfo& paintInfo, const FloatPoint& boxOrigin)
-{
- auto selectableRange = this->selectableRange();
-
- if (!renderer().frame().editor().compositionUsesCustomHighlights()) {
- paintMarkedTextBackground(paintInfo, boxOrigin, CompositionHighlight::defaultCompositionFillColor, selectableRange.clamp(renderer().frame().editor().compositionStart()), selectableRange.clamp(renderer().frame().editor().compositionEnd()));
- return;
- }
-
- for (auto& highlight : renderer().frame().editor().customCompositionHighlights()) {
- if (highlight.endOffset <= m_start)
- continue;
-
- if (highlight.startOffset >= end())
- break;
-
- auto [clampedStart, clampedEnd] = selectableRange.clamp(highlight.startOffset, highlight.endOffset);
- paintMarkedTextBackground(paintInfo, boxOrigin, highlight.color, clampedStart, clampedEnd, MarkedTextBackgroundStyle::Rounded);
-
- if (highlight.endOffset > end())
- break;
- }
-}
-
void LegacyInlineTextBox::paintCompositionUnderlines(PaintInfo& paintInfo, const FloatPoint& boxOrigin) const
{
if (m_truncation == cFullTruncation)
@@ -1089,12 +906,12 @@
return RenderBlock::updateSecurityDiscCharacters(lineStyle(), WTFMove(result));
}
-inline const RenderCombineText* LegacyInlineTextBox::combinedText() const
+const RenderCombineText* LegacyInlineTextBox::combinedText() const
{
return lineStyle().hasTextCombine() && is<RenderCombineText>(renderer()) && downcast<RenderCombineText>(renderer()).isCombined() ? &downcast<RenderCombineText>(renderer()) : nullptr;
}
-ShadowData* LegacyInlineTextBox::debugTextShadow()
+const ShadowData* LegacyInlineTextBox::debugTextShadow() const
{
if (!renderer().settings().legacyLineLayoutVisualCoverageEnabled())
return nullptr;
Modified: trunk/Source/WebCore/rendering/LegacyInlineTextBox.h (282269 => 282270)
--- trunk/Source/WebCore/rendering/LegacyInlineTextBox.h 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/rendering/LegacyInlineTextBox.h 2021-09-10 15:20:38 UTC (rev 282270)
@@ -163,26 +163,20 @@
FloatRect calculateDocumentMarkerBounds(const MarkedText&) const;
private:
+ friend class TextBoxPainter;
+
FloatPoint textOriginFromBoxRect(const FloatRect&) const;
- void paintMarkedTexts(PaintInfo&, MarkedText::PaintPhase, const FloatRect& boxRect, const Vector<StyledMarkedText>&, const FloatRect& decorationClipOutRect = { });
-
void paintPlatformDocumentMarker(GraphicsContext&, const FloatPoint& boxOrigin, const MarkedText&);
void paintPlatformDocumentMarkers(GraphicsContext&, const FloatPoint& boxOrigin);
- void paintCompositionBackground(PaintInfo&, const FloatPoint& boxOrigin);
void paintCompositionUnderlines(PaintInfo&, const FloatPoint& boxOrigin) const;
void paintCompositionUnderline(PaintInfo&, const FloatPoint& boxOrigin, const CompositionUnderline&) const;
- enum class MarkedTextBackgroundStyle : bool { Default, Rounded };
- void paintMarkedTextBackground(PaintInfo&, const FloatPoint& boxOrigin, const Color&, unsigned clampedStartOffset, unsigned clampedEndOffset, MarkedTextBackgroundStyle = MarkedTextBackgroundStyle::Default);
- void paintMarkedTextForeground(PaintInfo&, const FloatRect& boxRect, const StyledMarkedText&);
- void paintMarkedTextDecoration(PaintInfo&, const FloatRect& boxRect, const FloatRect& clipOutRect, const StyledMarkedText&);
-
const RenderCombineText* combinedText() const;
const FontCascade& lineFont() const;
- ShadowData* debugTextShadow();
+ const ShadowData* debugTextShadow() const;
String text(bool ignoreCombinedText = false, bool ignoreHyphen = false) const; // The effective text for the run.
TextRun createTextRun(bool ignoreCombinedText = false, bool ignoreHyphen = false) const;
Modified: trunk/Source/WebCore/rendering/StyledMarkedText.cpp (282269 => 282270)
--- trunk/Source/WebCore/rendering/StyledMarkedText.cpp 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/rendering/StyledMarkedText.cpp 2021-09-10 15:20:38 UTC (rev 282270)
@@ -111,7 +111,6 @@
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;
}
Modified: trunk/Source/WebCore/rendering/StyledMarkedText.h (282269 => 282270)
--- trunk/Source/WebCore/rendering/StyledMarkedText.h 2021-09-10 15:19:46 UTC (rev 282269)
+++ trunk/Source/WebCore/rendering/StyledMarkedText.h 2021-09-10 15:20:38 UTC (rev 282270)
@@ -46,7 +46,7 @@
TextPaintStyle textStyles;
TextDecorationPainter::Styles textDecorationStyles;
std::optional<ShadowData> textShadow;
- float alpha;
+ float alpha { 1 };
};
Style style;
Added: trunk/Source/WebCore/rendering/TextBoxPainter.cpp (0 => 282270)
--- trunk/Source/WebCore/rendering/TextBoxPainter.cpp (rev 0)
+++ trunk/Source/WebCore/rendering/TextBoxPainter.cpp 2021-09-10 15:20:38 UTC (rev 282270)
@@ -0,0 +1,230 @@
+/*
+ * 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 "TextBoxPainter.h"
+
+#include "CompositionHighlight.h"
+#include "Editor.h"
+#include "GraphicsContext.h"
+#include "LegacyInlineTextBox.h"
+#include "PaintInfo.h"
+#include "StyledMarkedText.h"
+#include "TextPaintStyle.h"
+#include "TextPainter.h"
+
+namespace WebCore {
+
+TextBoxPainter::TextBoxPainter(const LegacyInlineTextBox& textBox, PaintInfo& paintInfo, const FloatRect& boxRect)
+ : m_textBox(textBox)
+ , m_paintInfo(paintInfo)
+ , m_boxRect(boxRect)
+{
+ bool shouldRotate = !m_textBox.isHorizontal() && !m_textBox.combinedText();
+ if (shouldRotate)
+ m_paintInfo.context().concatCTM(rotation(m_boxRect, Clockwise));
+}
+
+TextBoxPainter::~TextBoxPainter()
+{
+ bool shouldRotate = !m_textBox.isHorizontal() && !m_textBox.combinedText();
+ if (shouldRotate)
+ m_paintInfo.context().concatCTM(rotation(m_boxRect, Counterclockwise));
+}
+
+void TextBoxPainter::paintCompositionBackground()
+{
+ auto selectableRange = m_textBox.selectableRange();
+
+ auto& editor = m_textBox.renderer().frame().editor();
+
+ if (!editor.compositionUsesCustomHighlights()) {
+ auto [clampedStart, clampedEnd] = selectableRange.clamp(editor.compositionStart(), editor.compositionEnd());
+
+ paintBackground(clampedStart, clampedEnd, CompositionHighlight::defaultCompositionFillColor);
+ return;
+ }
+
+ for (auto& highlight : editor.customCompositionHighlights()) {
+ if (highlight.endOffset <= m_textBox.start())
+ continue;
+
+ if (highlight.startOffset >= m_textBox.end())
+ break;
+
+ auto [clampedStart, clampedEnd] = selectableRange.clamp(highlight.startOffset, highlight.endOffset);
+
+ paintBackground(clampedStart, clampedEnd, highlight.color, BackgroundStyle::Rounded);
+
+ if (highlight.endOffset > m_textBox.end())
+ break;
+ }
+}
+
+void TextBoxPainter::paintBackground(const StyledMarkedText& markedText)
+{
+ paintBackground(markedText.startOffset, markedText.endOffset, markedText.style.backgroundColor);
+}
+
+void TextBoxPainter::paintBackground(unsigned startOffset, unsigned endOffset, const Color& color, BackgroundStyle backgroundStyle)
+{
+ if (startOffset >= endOffset)
+ return;
+
+ GraphicsContext& context = m_paintInfo.context();
+ GraphicsContextStateSaver stateSaver { context };
+ updateGraphicsContext(context, TextPaintStyle { color }); // Don't draw text at all!
+
+ // Note that if the text is truncated, we let the thing being painted in the truncation
+ // draw its own highlight.
+ TextRun textRun = m_textBox.createTextRun();
+
+ const LegacyRootInlineBox& rootBox = m_textBox.root();
+ LayoutUnit selectionBottom = rootBox.selectionBottom();
+ LayoutUnit selectionTop = rootBox.selectionTopAdjustedForPrecedingBlock();
+
+ // Use same y positioning and height as for selection, so that when the selection and this subrange are on
+ // the same word there are no pieces sticking out.
+ LayoutUnit deltaY { m_textBox.renderer().style().isFlippedLinesWritingMode() ? selectionBottom - m_textBox.logicalBottom() : m_textBox.logicalTop() - selectionTop };
+ LayoutUnit selectionHeight = std::max<LayoutUnit>(0, selectionBottom - selectionTop);
+
+ LayoutRect selectionRect { LayoutUnit(m_boxRect.x()), LayoutUnit(m_boxRect.y() - deltaY), LayoutUnit(m_textBox.logicalWidth()), selectionHeight };
+ m_textBox.lineFont().adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
+
+ // FIXME: Support painting combined text. See <https://bugs.webkit.org/show_bug.cgi?id=180993>.
+ auto backgroundRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, m_textBox.renderer().document().deviceScaleFactor(), textRun.ltr());
+ if (backgroundStyle == BackgroundStyle::Rounded) {
+ backgroundRect.expand(-1, -1);
+ backgroundRect.move(0.5, 0.5);
+ context.fillRoundedRect(FloatRoundedRect { backgroundRect, FloatRoundedRect::Radii { 2 } }, color);
+ return;
+ }
+
+ context.fillRect(backgroundRect, color);
+}
+
+void TextBoxPainter::paintForeground(const StyledMarkedText& markedText)
+{
+ if (markedText.startOffset >= markedText.endOffset)
+ return;
+
+ GraphicsContext& context = m_paintInfo.context();
+ const FontCascade& font = m_textBox.lineFont();
+ const RenderStyle& lineStyle = m_textBox.lineStyle();
+
+ float emphasisMarkOffset = 0;
+ std::optional<bool> markExistsAndIsAbove = m_textBox.emphasisMarkExistsAndIsAbove(lineStyle);
+ const AtomString& emphasisMark = markExistsAndIsAbove ? lineStyle.textEmphasisMarkString() : nullAtom();
+ if (!emphasisMark.isEmpty())
+ emphasisMarkOffset = *markExistsAndIsAbove ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fontMetrics().descent() + font.emphasisMarkAscent(emphasisMark);
+
+ TextPainter textPainter { context };
+ textPainter.setFont(font);
+ textPainter.setStyle(markedText.style.textStyles);
+ textPainter.setIsHorizontal(m_textBox.isHorizontal());
+ if (markedText.style.textShadow) {
+ textPainter.setShadow(&markedText.style.textShadow.value());
+ if (lineStyle.hasAppleColorFilter())
+ textPainter.setShadowColorFilter(&lineStyle.appleColorFilter());
+ }
+ textPainter.setEmphasisMark(emphasisMark, emphasisMarkOffset, m_textBox.combinedText());
+ if (auto* debugShadow = m_textBox.debugTextShadow())
+ textPainter.setShadow(debugShadow);
+
+ TextRun textRun = m_textBox.createTextRun();
+ textPainter.setGlyphDisplayListIfNeeded(m_textBox, m_paintInfo, font, context, textRun);
+
+ GraphicsContextStateSaver stateSaver { context, false };
+ if (markedText.type == MarkedText::DraggedContent) {
+ stateSaver.save();
+ context.setAlpha(markedText.style.alpha);
+ }
+ // TextPainter wants the box rectangle and text origin of the entire line box.
+ textPainter.paintRange(textRun, m_boxRect, m_textBox.textOriginFromBoxRect(m_boxRect), markedText.startOffset, markedText.endOffset);
+}
+
+void TextBoxPainter::paintDecoration(const StyledMarkedText& markedText, const FloatRect& clipOutRect)
+{
+ if (m_textBox.truncation() == cFullTruncation)
+ return;
+
+ GraphicsContext& context = m_paintInfo.context();
+ const FontCascade& font = m_textBox.lineFont();
+ const RenderStyle& lineStyle = m_textBox.lineStyle();
+
+ updateGraphicsContext(context, markedText.style.textStyles);
+
+ bool isCombinedText = m_textBox.combinedText();
+ if (isCombinedText)
+ context.concatCTM(rotation(m_boxRect, Clockwise));
+
+ // 1. Compute text selection
+ unsigned startOffset = markedText.startOffset;
+ unsigned endOffset = markedText.endOffset;
+ if (startOffset >= endOffset)
+ return;
+
+ // Note that if the text is truncated, we let the thing being painted in the truncation
+ // draw its own decoration.
+ TextRun textRun = m_textBox.createTextRun();
+
+ // Avoid measuring the text when the entire line box is selected as an optimization.
+ FloatRect snappedSelectionRect = m_boxRect;
+ if (startOffset || endOffset != textRun.length()) {
+ LayoutRect selectionRect = { m_boxRect.x(), m_boxRect.y(), m_boxRect.width(), m_boxRect.height() };
+ font.adjustSelectionRectForText(textRun, selectionRect, startOffset, endOffset);
+ snappedSelectionRect = snapRectToDevicePixelsWithWritingDirection(selectionRect, m_textBox.renderer().document().deviceScaleFactor(), textRun.ltr());
+ }
+
+ // 2. Paint
+ auto textDecorations = lineStyle.textDecorationsInEffect();
+ textDecorations.add(TextDecorationPainter::textDecorationsInEffectForStyle(markedText.style.textDecorationStyles));
+ TextDecorationPainter decorationPainter { context, textDecorations, m_textBox.renderer(), m_textBox.isFirstLine(), font, markedText.style.textDecorationStyles };
+ decorationPainter.setTextRunIterator(LayoutIntegration::textRunFor(&m_textBox));
+ decorationPainter.setWidth(snappedSelectionRect.width());
+ decorationPainter.setIsHorizontal(m_textBox.isHorizontal());
+ if (markedText.style.textShadow) {
+ decorationPainter.setTextShadow(&markedText.style.textShadow.value());
+ if (lineStyle.hasAppleColorFilter())
+ decorationPainter.setShadowColorFilter(&lineStyle.appleColorFilter());
+ }
+
+ {
+ GraphicsContextStateSaver stateSaver { context, false };
+ bool isDraggedContent = markedText.type == MarkedText::DraggedContent;
+ if (isDraggedContent || !clipOutRect.isEmpty()) {
+ stateSaver.save();
+ if (isDraggedContent)
+ context.setAlpha(markedText.style.alpha);
+ if (!clipOutRect.isEmpty())
+ context.clipOut(clipOutRect);
+ }
+ decorationPainter.paintTextDecoration(textRun.subRun(startOffset, endOffset - startOffset), m_textBox.textOriginFromBoxRect(snappedSelectionRect), snappedSelectionRect.location());
+ }
+
+ if (isCombinedText)
+ context.concatCTM(rotation(m_boxRect, Counterclockwise));
+}
+
+}
Added: trunk/Source/WebCore/rendering/TextBoxPainter.h (0 => 282270)
--- trunk/Source/WebCore/rendering/TextBoxPainter.h (rev 0)
+++ trunk/Source/WebCore/rendering/TextBoxPainter.h 2021-09-10 15:20:38 UTC (rev 282270)
@@ -0,0 +1,56 @@
+/*
+ * 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 "FloatRect.h"
+
+namespace WebCore {
+
+class FontCascade;
+class LegacyInlineTextBox;
+class RenderCombineText;
+struct PaintInfo;
+struct StyledMarkedText;
+
+class TextBoxPainter {
+public:
+ TextBoxPainter(const LegacyInlineTextBox&, PaintInfo&, const FloatRect& boxRect);
+ ~TextBoxPainter();
+
+ void paintCompositionBackground();
+ void paintBackground(const StyledMarkedText&);
+ void paintForeground(const StyledMarkedText&);
+ void paintDecoration(const StyledMarkedText&, const FloatRect& clipOutRect);
+
+private:
+ enum class BackgroundStyle { Normal, Rounded };
+ void paintBackground(unsigned startOffset, unsigned endOffset, const Color&, BackgroundStyle = BackgroundStyle::Normal);
+
+ const LegacyInlineTextBox& m_textBox;
+ PaintInfo& m_paintInfo;
+ const FloatRect m_boxRect;
+};
+
+}