Diff
Modified: trunk/Source/WebCore/ChangeLog (230543 => 230544)
--- trunk/Source/WebCore/ChangeLog 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/ChangeLog 2018-04-11 20:29:49 UTC (rev 230544)
@@ -1,3 +1,87 @@
+2018-04-11 Said Abou-Hallawa <[email protected]>
+
+ Cache glyphs (using display lists) when painting at high frequency
+ https://bugs.webkit.org/show_bug.cgi?id=178750
+ <rdar://problem/35201729>
+
+ Reviewed by Antti Koivisto.
+
+ This patch adds support for caching of glyph drawing commands when painting
+ at high frequency. Caching the glyph drawing will be done using DisplayLists.
+
+ GlyphDisplayListCache is basically a hash map which maps InlineTextBox
+ or SimpleLineLayout::Run to DisplayList. Before adding a new entry to it
+ we have to check whether the conditions for caching the glyph DisplayList
+ are met or not. If no entry is found for a given run, a new DisplayList
+ is created and a new entry is add to the cache.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * page/MemoryRelease.cpp:
+ (WebCore::releaseNoncriticalMemory): Make GlyphDisplayListCache respond
+ to memory pressure.
+
+ * platform/graphics/FontCascade.cpp:
+ (WebCore::FontCascade::displayListForTextRun const):
+ * platform/graphics/FontCascade.h:
+ (WebCore::FontCascade::displayListForTextRun):
+ Record the drawing of a glyph run into a DisplayList.
+
+ * rendering/GlyphDisplayListCache.h: Added.
+ (WebCore::GlyphDisplayListCache::singleton):
+ (WebCore::GlyphDisplayListCache::get):
+ (WebCore::GlyphDisplayListCache::remove):
+ (WebCore::GlyphDisplayListCache::clear):
+ (WebCore::GlyphDisplayListCache::size const):
+ (WebCore::GlyphDisplayListCache::sizeInBytes const):
+ A simple cache for the TextRun DisplayList. Adding a new entry in the
+ cache happens under restricted conditions. So this cache is not expected
+ to grow much.
+
+ * rendering/InlineTextBox.cpp:
+ (WebCore::InlineTextBox::~InlineTextBox):
+ (WebCore::InlineTextBox::paint):
+ (WebCore::InlineTextBox::paintMarkedTexts):
+ (WebCore::InlineTextBox::paintMarkedTextBackground):
+ (WebCore::InlineTextBox::paintMarkedTextForeground):
+ (WebCore::InlineTextBox::paintMarkedTextDecoration):
+ (WebCore::InlineTextBox::paintCompositionBackground):
+ (WebCore::InlineTextBox::paintCompositionUnderlines const):
+ (WebCore::InlineTextBox::paintCompositionUnderline const):
+ * rendering/InlineTextBox.h:
+ (WebCore::InlineTextBox::paintMarkedTexts):
+ InlineTextBox::paintMarkedTextForeground() now requires PaintInfo to know
+ whether the entry in the GlyphDisplayListCache should be removed or not.
+ Change all the GraphicsContext arguments to be PaintInfo.
+
+ * rendering/SimpleLineLayout.cpp:
+ (WebCore::SimpleLineLayout::Layout::~Layout):
+ * rendering/SimpleLineLayout.h:
+ * rendering/SimpleLineLayoutFunctions.cpp:
+ (WebCore::SimpleLineLayout::paintFlow):
+ (WebCore::SimpleLineLayout::simpleLineLayoutWillBeDeleted):
+ * rendering/SimpleLineLayoutFunctions.h:
+ * rendering/SimpleLineLayoutResolver.h:
+ (WebCore::SimpleLineLayout::RunResolver::Run::simpleRun const):
+ Implement the glyph caching for SimpleLineLayout::Run.
+
+ * rendering/TextPainter.cpp:
+ (WebCore::TextPainter::paintTextOrEmphasisMarks): If the DisplayList is
+ available, replay it back into the GraphicsContext. Make sure to reset to
+ the DisplayList pointer to nullptr after painting.
+
+ (WebCore::TextPainter::clearGlyphDisplayLists):
+ (WebCore::TextPainter::shouldUseGlyphDisplayList): Check whether we should
+ use DisplayList to the draw glyph run.
+
+ * rendering/TextPainter.h:
+ (WebCore::TextPainter::setGlyphDisplayListIfNeeded): Check whether we should
+ should use DisplayList to the draw glyph run and if we should, ensure first
+ the DisplayList is cached and set it in the TextPainter so it uses it when
+ the run is painted.
+
+ (WebCore::TextPainter::removeGlyphDisplayList): Remove the cached DisplayList
+ entry for a glyph layout run.
+
2018-04-11 Brent Fulgham <[email protected]>
GraphicsLayerCA::createPlatformCALayer always disables extended color in its backing store
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (230543 => 230544)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-04-11 20:29:49 UTC (rev 230544)
@@ -8254,6 +8254,7 @@
555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = "<group>"; };
5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = "<group>"; };
+ 5597FCCB2076C06800D35BB0 /* GlyphDisplayListCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlyphDisplayListCache.h; sourceTree = "<group>"; };
55A336F61D8209F40022C4C7 /* NativeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeImage.h; sourceTree = "<group>"; };
55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBackingStore.h; sourceTree = "<group>"; };
55AF14E31EAAC59B0026EEAA /* UTIRegistry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UTIRegistry.cpp; sourceTree = "<group>"; };
@@ -25478,6 +25479,7 @@
9A528E8117D7F52F00AA9518 /* FloatingObjects.cpp */,
9A528E8217D7F52F00AA9518 /* FloatingObjects.h */,
935C477409AC4D8D00A6AAB4 /* GapRects.h */,
+ 5597FCCB2076C06800D35BB0 /* GlyphDisplayListCache.h */,
E112F4701E3A85F200D6CDFD /* Grid.cpp */,
E112F46F1E3A85D800D6CDFD /* Grid.h */,
E12DE7151E4B748700F9ACCF /* GridTrackSizingAlgorithm.cpp */,
Modified: trunk/Source/WebCore/page/MemoryRelease.cpp (230543 => 230544)
--- trunk/Source/WebCore/page/MemoryRelease.cpp 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/page/MemoryRelease.cpp 2018-04-11 20:29:49 UTC (rev 230544)
@@ -46,6 +46,7 @@
#include "ScrollingThread.h"
#include "StyleScope.h"
#include "StyledElement.h"
+#include "TextPainter.h"
#include "WorkerThread.h"
#include <wtf/FastMalloc.h>
#include <wtf/SystemTracing.h>
@@ -64,6 +65,7 @@
FontDescription::invalidateCaches();
clearWidthCaches();
+ TextPainter::clearGlyphDisplayLists();
for (auto* document : Document::allDocuments())
document->clearSelectorQueryCache();
Modified: trunk/Source/WebCore/platform/graphics/FontCascade.cpp (230543 => 230544)
--- trunk/Source/WebCore/platform/graphics/FontCascade.cpp 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.cpp 2018-04-11 20:29:49 UTC (rev 230544)
@@ -26,6 +26,7 @@
#include "CharacterProperties.h"
#include "ComplexTextController.h"
+#include "DisplayListRecorder.h"
#include "FloatRect.h"
#include "FontCache.h"
#include "GlyphBuffer.h"
@@ -305,6 +306,32 @@
drawEmphasisMarksForComplexText(context, run, mark, point, from, destination);
}
+std::unique_ptr<DisplayList::DisplayList> FontCascade::displayListForTextRun(GraphicsContext& context, const TextRun& run, unsigned from, std::optional<unsigned> to, CustomFontNotReadyAction customFontNotReadyAction) const
+{
+ ASSERT(!context.paintingDisabled());
+ unsigned destination = to.value_or(run.length());
+
+ // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
+ CodePath codePathToUse = codePath(run);
+ if (codePathToUse != Complex && (enableKerning() || requiresShaping()) && (from || destination != run.length()))
+ codePathToUse = Complex;
+
+ GlyphBuffer glyphBuffer;
+ float startX = glyphBufferForTextRun(codePathToUse, run, from, destination, glyphBuffer);
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return nullptr;
+
+ std::unique_ptr<DisplayList::DisplayList> displayList = std::make_unique<DisplayList::DisplayList>();
+ GraphicsContext recordingContext([&](GraphicsContext& displayListContext) {
+ return std::make_unique<DisplayList::Recorder>(displayListContext, *displayList, context.state(), FloatRect(), AffineTransform());
+ });
+
+ FloatPoint startPoint(startX, 0);
+ drawGlyphBuffer(recordingContext, glyphBuffer, startPoint, customFontNotReadyAction);
+ return displayList;
+}
+
float FontCascade::widthOfTextRange(const TextRun& run, unsigned from, unsigned to, HashSet<const Font*>* fallbackFonts, float* outWidthBeforeRange, float* outWidthAfterRange) const
{
ASSERT(from <= to);
Modified: trunk/Source/WebCore/platform/graphics/FontCascade.h (230543 => 230544)
--- trunk/Source/WebCore/platform/graphics/FontCascade.h 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -48,6 +48,10 @@
class TextLayout;
class TextRun;
+namespace DisplayList {
+class DisplayList;
+}
+
struct GlyphData;
struct GlyphOverflow {
@@ -197,6 +201,8 @@
WeakPtr<FontCascade> createWeakPtr() const { return m_weakPtrFactory.createWeakPtr(*const_cast<FontCascade*>(this)); }
+ std::unique_ptr<DisplayList::DisplayList> displayListForTextRun(GraphicsContext&, const TextRun&, unsigned from = 0, std::optional<unsigned> to = { }, CustomFontNotReadyAction = CustomFontNotReadyAction::DoNotPaintIfFontNotReady) const;
+
private:
enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
Added: trunk/Source/WebCore/rendering/GlyphDisplayListCache.h (0 => 230544)
--- trunk/Source/WebCore/rendering/GlyphDisplayListCache.h (rev 0)
+++ trunk/Source/WebCore/rendering/GlyphDisplayListCache.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 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. ``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
+ * 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 "DisplayList.h"
+#include "FontCascade.h"
+#include "Logging.h"
+#include "TextRun.h"
+#include <wtf/HashMap.h>
+#include <wtf/MemoryPressureHandler.h>
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+template<typename LayoutRun>
+class GlyphDisplayListCache {
+public:
+ GlyphDisplayListCache() = default;
+
+ static GlyphDisplayListCache& singleton()
+ {
+ static NeverDestroyed<GlyphDisplayListCache> cache;
+ return cache;
+ }
+
+ DisplayList::DisplayList* get(const LayoutRun& run, const FontCascade& font, GraphicsContext& context, const TextRun& textRun)
+ {
+ if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
+ if (!m_glyphRunMap.isEmpty()) {
+ LOG(MemoryPressure, "GlyphDisplayListCache::%s - Under memory pressure - size: %d - sizeInBytes: %ld", __FUNCTION__, size(), sizeInBytes());
+ clear();
+ }
+ return nullptr;
+ }
+
+ if (auto displayList = m_glyphRunMap.get(&run))
+ return displayList;
+
+ if (auto displayList = font.displayListForTextRun(context, textRun))
+ return m_glyphRunMap.add(&run, WTFMove(displayList)).iterator->value.get();
+
+ return nullptr;
+ }
+
+ void remove(const LayoutRun& run)
+ {
+ m_glyphRunMap.remove(&run);
+ }
+
+ void clear()
+ {
+ m_glyphRunMap.clear();
+ }
+
+ unsigned size() const
+ {
+ return m_glyphRunMap.size();
+ }
+
+ size_t sizeInBytes() const
+ {
+ size_t sizeInBytes = 0;
+ for (const auto& entry : m_glyphRunMap)
+ sizeInBytes += entry.value->sizeInBytes();
+ return sizeInBytes;
+ }
+
+private:
+ using GlyphRunMap = HashMap<const LayoutRun*, std::unique_ptr<DisplayList::DisplayList>>;
+ GlyphRunMap m_glyphRunMap;
+};
+
+}
Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (230543 => 230544)
--- trunk/Source/WebCore/rendering/InlineTextBox.cpp 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp 2018-04-11 20:29:49 UTC (rev 230544)
@@ -73,6 +73,7 @@
{
if (!knownToHaveNoOverflow() && gTextBoxesWithOverflow)
gTextBoxesWithOverflow->remove(this);
+ TextPainter::removeGlyphDisplayList(*this);
}
void InlineTextBox::markDirty(bool dirty)
@@ -503,7 +504,7 @@
// and composition underlines.
if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
if (containsComposition && !useCustomUnderlines)
- paintCompositionBackground(context, boxOrigin);
+ paintCompositionBackground(paintInfo, boxOrigin);
Vector<MarkedText> markedTexts = collectMarkedTextsForDocumentMarkers(TextPaintPhase::Background);
#if ENABLE(TEXT_SELECTION)
@@ -518,7 +519,7 @@
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areBackgroundMarkedTextStylesEqual);
- paintMarkedTexts(context, TextPaintPhase::Background, boxRect, coalescedStyledMarkedTexts);
+ paintMarkedTexts(paintInfo, TextPaintPhase::Background, boxRect, coalescedStyledMarkedTexts);
}
// FIXME: Right now, InlineTextBoxes never call addRelevantUnpaintedObject() even though they might
@@ -564,7 +565,7 @@
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areForegroundMarkedTextStylesEqual);
- paintMarkedTexts(context, TextPaintPhase::Foreground, boxRect, coalescedStyledMarkedTexts);
+ paintMarkedTexts(paintInfo, TextPaintPhase::Foreground, boxRect, coalescedStyledMarkedTexts);
// Paint decorations
TextDecoration textDecorations = lineStyle.textDecorationsInEffect();
@@ -601,7 +602,7 @@
// Coalesce styles of adjacent marked texts to minimize the number of drawing commands.
auto coalescedStyledMarkedTexts = coalesceAdjacentMarkedTexts(styledMarkedTexts, &MarkedTextStyle::areDecorationMarkedTextStylesEqual);
- paintMarkedTexts(context, TextPaintPhase::Decoration, boxRect, coalescedStyledMarkedTexts, textDecorationSelectionClipOutRect);
+ paintMarkedTexts(paintInfo, TextPaintPhase::Decoration, boxRect, coalescedStyledMarkedTexts, textDecorationSelectionClipOutRect);
}
// 3. Paint fancy decorations, including composition underlines and platform-specific underlines for spelling errors, grammar errors, et cetera.
@@ -609,7 +610,7 @@
paintPlatformDocumentMarkers(context, boxOrigin);
if (useCustomUnderlines)
- paintCompositionUnderlines(context, boxOrigin);
+ paintCompositionUnderlines(paintInfo, boxOrigin);
}
if (shouldRotate)
@@ -943,29 +944,30 @@
return textOrigin;
}
-void InlineTextBox::paintMarkedTexts(GraphicsContext& context, TextPaintPhase phase, const FloatRect& boxRect, const Vector<StyledMarkedText>& markedTexts, const FloatRect& decorationClipOutRect)
+void InlineTextBox::paintMarkedTexts(PaintInfo& paintInfo, TextPaintPhase phase, const FloatRect& boxRect, const Vector<StyledMarkedText>& markedTexts, const FloatRect& decorationClipOutRect)
{
switch (phase) {
case TextPaintPhase::Background:
for (auto& markedText : markedTexts)
- paintMarkedTextBackground(context, boxRect.location(), markedText.style.backgroundColor, markedText.startOffset, markedText.endOffset);
+ paintMarkedTextBackground(paintInfo, boxRect.location(), markedText.style.backgroundColor, markedText.startOffset, markedText.endOffset);
return;
case TextPaintPhase::Foreground:
for (auto& markedText : markedTexts)
- paintMarkedTextForeground(context, boxRect, markedText);
+ paintMarkedTextForeground(paintInfo, boxRect, markedText);
return;
case TextPaintPhase::Decoration:
for (auto& markedText : markedTexts)
- paintMarkedTextDecoration(context, boxRect, decorationClipOutRect, markedText);
+ paintMarkedTextDecoration(paintInfo, boxRect, decorationClipOutRect, markedText);
return;
}
}
-void InlineTextBox::paintMarkedTextBackground(GraphicsContext& context, const FloatPoint& boxOrigin, const Color& color, unsigned clampedStartOffset, unsigned clampedEndOffset)
+void InlineTextBox::paintMarkedTextBackground(PaintInfo& paintInfo, const FloatPoint& boxOrigin, const Color& color, unsigned clampedStartOffset, unsigned clampedEndOffset)
{
if (clampedStartOffset >= clampedEndOffset)
return;
+ GraphicsContext& context = paintInfo.context();
GraphicsContextStateSaver stateSaver { context };
updateGraphicsContext(context, TextPaintStyle { color }); // Don't draw text at all!
@@ -989,11 +991,12 @@
context.fillRect(snapRectToDevicePixelsWithWritingDirection(selectionRect, renderer().document().deviceScaleFactor(), textRun.ltr()), color);
}
-void InlineTextBox::paintMarkedTextForeground(GraphicsContext& context, const FloatRect& boxRect, const StyledMarkedText& markedText)
+void InlineTextBox::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();
@@ -1012,6 +1015,9 @@
textPainter.setShadow(&markedText.style.textShadow.value());
textPainter.setEmphasisMark(emphasisMark, emphasisMarkOffset, combinedText());
+ TextRun textRun = createTextRun();
+ textPainter.setGlyphDisplayListIfNeeded(*this, paintInfo, font, context, textRun);
+
GraphicsContextStateSaver stateSaver { context, false };
if (markedText.type == MarkedText::DraggedContent) {
stateSaver.save();
@@ -1018,14 +1024,15 @@
context.setAlpha(markedText.style.alpha);
}
// TextPainter wants the box rectangle and text origin of the entire line box.
- textPainter.paintRange(createTextRun(), boxRect, textOriginFromBoxRect(boxRect), markedText.startOffset, markedText.endOffset);
+ textPainter.paintRange(textRun, boxRect, textOriginFromBoxRect(boxRect), markedText.startOffset, markedText.endOffset);
}
-void InlineTextBox::paintMarkedTextDecoration(GraphicsContext& context, const FloatRect& boxRect, const FloatRect& clipOutRect, const StyledMarkedText& markedText)
+void InlineTextBox::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();
@@ -1073,12 +1080,12 @@
context.concatCTM(rotation(boxRect, Counterclockwise));
}
-void InlineTextBox::paintCompositionBackground(GraphicsContext& context, const FloatPoint& boxOrigin)
+void InlineTextBox::paintCompositionBackground(PaintInfo& paintInfo, const FloatPoint& boxOrigin)
{
- paintMarkedTextBackground(context, boxOrigin, Color::compositionFill, clampedOffset(renderer().frame().editor().compositionStart()), clampedOffset(renderer().frame().editor().compositionEnd()));
+ paintMarkedTextBackground(paintInfo, boxOrigin, Color::compositionFill, clampedOffset(renderer().frame().editor().compositionStart()), clampedOffset(renderer().frame().editor().compositionEnd()));
}
-void InlineTextBox::paintCompositionUnderlines(GraphicsContext& context, const FloatPoint& boxOrigin) const
+void InlineTextBox::paintCompositionUnderlines(PaintInfo& paintInfo, const FloatPoint& boxOrigin) const
{
if (m_truncation == cFullTruncation)
return;
@@ -1095,7 +1102,7 @@
break; // Underline is completely after this run, bail. A later run will paint it.
// Underline intersects this run. Paint it.
- paintCompositionUnderline(context, boxOrigin, underline);
+ paintCompositionUnderline(paintInfo, boxOrigin, underline);
if (underline.endOffset > end() + 1)
break; // Underline also runs into the next run. Bail now, no more marker advancement.
@@ -1109,7 +1116,7 @@
start = logicalWidth - width - start;
}
-void InlineTextBox::paintCompositionUnderline(GraphicsContext& context, const FloatPoint& boxOrigin, const CompositionUnderline& underline) const
+void InlineTextBox::paintCompositionUnderline(PaintInfo& paintInfo, const FloatPoint& boxOrigin, const CompositionUnderline& underline) const
{
if (m_truncation == cFullTruncation)
return;
@@ -1150,6 +1157,7 @@
start += 1;
width -= 2;
+ GraphicsContext& context = paintInfo.context();
context.setStrokeColor(underline.compositionUnderlineColor == CompositionUnderlineColor::TextColor ? renderer().style().visitedDependentColor(CSSPropertyWebkitTextFillColor) : underline.color);
context.setStrokeThickness(lineThickness);
context.drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logicalHeight() - lineThickness), width, renderer().document().printing());
Modified: trunk/Source/WebCore/rendering/InlineTextBox.h (230543 => 230544)
--- trunk/Source/WebCore/rendering/InlineTextBox.h 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/InlineTextBox.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -168,18 +168,18 @@
FloatPoint textOriginFromBoxRect(const FloatRect&) const;
- void paintMarkedTexts(GraphicsContext&, TextPaintPhase, const FloatRect& boxRect, const Vector<StyledMarkedText>&, const FloatRect& decorationClipOutRect = { });
+ void paintMarkedTexts(PaintInfo&, TextPaintPhase, 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(GraphicsContext&, const FloatPoint& boxOrigin);
- void paintCompositionUnderlines(GraphicsContext&, const FloatPoint& boxOrigin) const;
- void paintCompositionUnderline(GraphicsContext&, const FloatPoint& boxOrigin, const CompositionUnderline&) const;
+ void paintCompositionBackground(PaintInfo&, const FloatPoint& boxOrigin);
+ void paintCompositionUnderlines(PaintInfo&, const FloatPoint& boxOrigin) const;
+ void paintCompositionUnderline(PaintInfo&, const FloatPoint& boxOrigin, const CompositionUnderline&) const;
- void paintMarkedTextBackground(GraphicsContext&, const FloatPoint& boxOrigin, const Color&, unsigned clampedStartOffset, unsigned clampedEndOffset);
- void paintMarkedTextForeground(GraphicsContext&, const FloatRect& boxRect, const StyledMarkedText&);
- void paintMarkedTextDecoration(GraphicsContext&, const FloatRect& boxRect, const FloatRect& clipOutRect, const StyledMarkedText&);
+ void paintMarkedTextBackground(PaintInfo&, const FloatPoint& boxOrigin, const Color&, unsigned clampedStartOffset, unsigned clampedEndOffset);
+ 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;
Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (230543 => 230544)
--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp 2018-04-11 20:29:49 UTC (rev 230544)
@@ -978,5 +978,10 @@
memcpy(m_runs, runVector.data(), m_runCount * sizeof(Run));
}
+Layout::~Layout()
+{
+ simpleLineLayoutWillBeDeleted(*this);
}
+
}
+}
Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.h (230543 => 230544)
--- trunk/Source/WebCore/rendering/SimpleLineLayout.h 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -81,6 +81,8 @@
using SimpleLineStruts = Vector<SimpleLineStrut, 4>;
static std::unique_ptr<Layout> create(const RunVector&, unsigned lineCount);
+ ~Layout();
+
unsigned lineCount() const { return m_lineCount; }
unsigned runCount() const { return m_runCount; }
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp (230543 => 230544)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp 2018-04-11 20:29:49 UTC (rev 230544)
@@ -120,6 +120,8 @@
TextRun textRun { run.hasHyphen() ? textWithHyphen : run.text(), 0, run.expansion(), run.expansionBehavior() };
textRun.setTabSize(!style.collapseWhiteSpace(), style.tabSize());
FloatPoint textOrigin { rect.x() + paintOffset.x(), roundToDevicePixel(run.baselinePosition() + paintOffset.y(), deviceScaleFactor) };
+
+ textPainter.setGlyphDisplayListIfNeeded(run.simpleRun(), paintInfo, style.fontCascade(), paintInfo.context(), textRun);
textPainter.paint(textRun, rect, textOrigin);
if (textDecorationPainter) {
textDecorationPainter->setWidth(rect.width());
@@ -261,6 +263,12 @@
return flowContents.segmentForPosition(position).renderer;
}
+void simpleLineLayoutWillBeDeleted(const Layout& layout)
+{
+ for (unsigned i = 0; i < layout.runCount(); ++i)
+ TextPainter::removeGlyphDisplayList(layout.runAt(i));
+}
+
#if ENABLE(TREE_DEBUGGING)
static void printPrefix(TextStream& stream, int& printedCharacters, int depth)
{
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.h (230543 => 230544)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.h 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -66,6 +66,8 @@
const RenderObject& rendererForPosition(const FlowContents&, unsigned);
+void simpleLineLayoutWillBeDeleted(const Layout&);
+
#if ENABLE(TREE_DEBUGGING)
void outputLineLayoutForFlow(WTF::TextStream&, const RenderBlockFlow&, const Layout&, int depth);
#endif
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h (230543 => 230544)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -56,6 +56,7 @@
String textWithHyphen() const;
bool isEndOfLine() const;
bool hasHyphen() const { return m_iterator.simpleRun().hasHyphen; }
+ const SimpleLineLayout::Run& simpleRun() const { return m_iterator.simpleRun(); }
unsigned lineIndex() const;
Modified: trunk/Source/WebCore/rendering/TextPainter.cpp (230543 => 230544)
--- trunk/Source/WebCore/rendering/TextPainter.cpp 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/TextPainter.cpp 2018-04-11 20:29:49 UTC (rev 230544)
@@ -23,9 +23,11 @@
#include "config.h"
#include "TextPainter.h"
+#include "DisplayListReplayer.h"
#include "GraphicsContext.h"
#include "InlineTextBox.h"
#include "RenderCombineText.h"
+#include "RenderLayer.h"
#include "ShadowData.h"
#include <wtf/NeverDestroyed.h>
@@ -98,10 +100,18 @@
float emphasisMarkOffset, const FloatPoint& textOrigin, unsigned startOffset, unsigned endOffset)
{
ASSERT(startOffset < endOffset);
- if (emphasisMark.isEmpty())
+ if (!emphasisMark.isEmpty())
+ m_context.drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + FloatSize(0, emphasisMarkOffset), startOffset, endOffset);
+ else if (startOffset || endOffset < textRun.length() || !m_glyphDisplayList)
m_context.drawText(font, textRun, textOrigin, startOffset, endOffset);
- else
- m_context.drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + FloatSize(0, emphasisMarkOffset), startOffset, endOffset);
+ else {
+ // Replaying back a whole cached glyph run to the GraphicsContext.
+ m_context.translate(textOrigin);
+ DisplayList::Replayer replayer(m_context, *m_glyphDisplayList);
+ replayer.replay();
+ m_context.translate(-textOrigin);
+ }
+ m_glyphDisplayList = nullptr;
}
void TextPainter::paintTextWithShadows(const ShadowData* shadow, const FontCascade& font, const TextRun& textRun, const FloatRect& boxRect, const FloatPoint& textOrigin,
@@ -195,4 +205,15 @@
paintTextAndEmphasisMarksIfNeeded(textRun, boxRect, textOrigin, start, end, m_style, m_shadow);
}
+void TextPainter::clearGlyphDisplayLists()
+{
+ GlyphDisplayListCache<InlineTextBox>::singleton().clear();
+ GlyphDisplayListCache<SimpleLineLayout::Run>::singleton().clear();
+}
+
+bool TextPainter::shouldUseGlyphDisplayList(const PaintInfo& paintInfo)
+{
+ return !paintInfo.context().paintingDisabled() && paintInfo.enclosingSelfPaintingLayer() && paintInfo.enclosingSelfPaintingLayer()->paintingFrequently();
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/TextPainter.h (230543 => 230544)
--- trunk/Source/WebCore/rendering/TextPainter.h 2018-04-11 20:02:29 UTC (rev 230543)
+++ trunk/Source/WebCore/rendering/TextPainter.h 2018-04-11 20:29:49 UTC (rev 230544)
@@ -24,6 +24,7 @@
#include "AffineTransform.h"
#include "FloatRect.h"
+#include "GlyphDisplayListCache.h"
#include "TextFlags.h"
#include "TextPaintStyle.h"
#include <wtf/text/AtomicString.h>
@@ -58,6 +59,21 @@
void paint(const TextRun&, const FloatRect& boxRect, const FloatPoint& textOrigin);
void paintRange(const TextRun&, const FloatRect& boxRect, const FloatPoint& textOrigin, unsigned start, unsigned end);
+ template<typename LayoutRun>
+ void setGlyphDisplayListIfNeeded(const LayoutRun& run, const PaintInfo& paintInfo, const FontCascade& font, GraphicsContext& context, const TextRun& textRun)
+ {
+ if (!TextPainter::shouldUseGlyphDisplayList(paintInfo))
+ TextPainter::removeGlyphDisplayList(run);
+ else
+ m_glyphDisplayList = GlyphDisplayListCache<LayoutRun>::singleton().get(run, font, context, textRun);
+ }
+
+ template<typename LayoutRun>
+ static void removeGlyphDisplayList(const LayoutRun& run) { GlyphDisplayListCache<LayoutRun>::singleton().remove(run); }
+
+ static void clearGlyphDisplayLists();
+ static bool shouldUseGlyphDisplayList(const PaintInfo&);
+
private:
void paintTextOrEmphasisMarks(const FontCascade&, const TextRun&, const AtomicString& emphasisMark, float emphasisMarkOffset,
const FloatPoint& textOrigin, unsigned startOffset, unsigned endOffset);
@@ -74,6 +90,7 @@
const RenderCombineText* m_combinedText { nullptr };
float m_emphasisMarkOffset { 0 };
bool m_textBoxIsHorizontal { true };
+ DisplayList::DisplayList* m_glyphDisplayList { nullptr };
};
inline void TextPainter::setEmphasisMark(const AtomicString& mark, float offset, const RenderCombineText* combinedText)