Diff
Modified: trunk/Source/WebCore/ChangeLog (211737 => 211738)
--- trunk/Source/WebCore/ChangeLog 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/ChangeLog 2017-02-06 19:06:39 UTC (rev 211738)
@@ -1,3 +1,38 @@
+2017-02-06 Zalan Bujtas <za...@apple.com>
+
+ Simple line layout: Use simplified text measuring when possible.
+ https://bugs.webkit.org/show_bug.cgi?id=167843
+ <rdar://problem/30364907>
+
+ Reviewed by Antti Koivisto.
+
+ This patch adds a simplified version of text width measuring.
+ Certain type of text runs (no spacing etc) only require a subset of what we
+ currently do in FontCascade::width().
+
+ * platform/graphics/FontCascade.cpp:
+ (WebCore::FontCascade::widthForSimpleText):
+ * platform/graphics/FontCascade.h:
+ * platform/graphics/WidthCache.h:
+ (WebCore::WidthCache::add):
+ (WebCore::WidthCache::addSlowCase):
+ * platform/graphics/WidthIterator.cpp:
+ (WebCore::WidthIterator::advanceInternal):
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::styleDidChange):
+ (WebCore::RenderText::setRenderedText):
+ (WebCore::RenderText::computeCanUseSimplifiedTextMeasuring):
+ * rendering/RenderText.h:
+ (WebCore::RenderText::canUseSimplifiedTextMeasuring):
+ * rendering/SimpleLineLayoutFlowContents.cpp:
+ (WebCore::SimpleLineLayout::initializeSegments):
+ * rendering/SimpleLineLayoutFlowContents.h:
+ * rendering/SimpleLineLayoutTextFragmentIterator.cpp:
+ (WebCore::SimpleLineLayout::TextFragmentIterator::Style::Style):
+ (WebCore::SimpleLineLayout::TextFragmentIterator::TextFragmentIterator):
+ (WebCore::SimpleLineLayout::TextFragmentIterator::textWidth):
+ * rendering/SimpleLineLayoutTextFragmentIterator.h:
+
2017-02-06 Carlos Garcia Campos <cgar...@igalia.com>
Resource usage overlay should ignore mouse events outside bounds by default
Modified: trunk/Source/WebCore/platform/graphics/FontCascade.cpp (211737 => 211738)
--- trunk/Source/WebCore/platform/graphics/FontCascade.cpp 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.cpp 2017-02-06 19:06:39 UTC (rev 211738)
@@ -33,6 +33,9 @@
#include "SurrogatePairAwareTextIterator.h"
#include "TextRun.h"
#include "WidthIterator.h"
+#if USE(CAIRO)
+#include <cairo.h>
+#endif
#include <wtf/MainThread.h>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>
@@ -377,6 +380,37 @@
return result;
}
+float FontCascade::widthForSimpleText(StringView text) const
+{
+ ASSERT(codePath(TextRun(text)) != FontCascade::Complex);
+ float* cacheEntry = m_fonts->widthCache().add(text, std::numeric_limits<float>::quiet_NaN());
+ if (cacheEntry && !std::isnan(*cacheEntry))
+ return *cacheEntry;
+
+ Vector<GlyphBufferGlyph, 16> glyphs;
+ Vector<GlyphBufferAdvance, 16> advances;
+ auto& font = primaryFont();
+ for (unsigned i = 0; i < text.length(); ++i) {
+ auto glyph = glyphDataForCharacter(text[i], false).glyph;
+#if USE(CAIRO)
+ cairo_glyph_t cairoGlyph;
+ cairoGlyph.index = glyph;
+ glyphs.append(cairoGlyph);
+#else
+ glyphs.append(glyph);
+#endif
+ advances.append(FloatSize(font.widthForGlyph(glyph), 0));
+ }
+ font.applyTransforms(&glyphs[0], &advances[0], glyphs.size(), enableKerning(), requiresShaping());
+ float runWidth = 0;
+ for (auto& advance : advances)
+ runWidth += advance.width();
+
+ if (cacheEntry)
+ *cacheEntry = runWidth;
+ return runWidth;
+}
+
GlyphData FontCascade::glyphDataForCharacter(UChar32 c, bool mirror, FontVariant variant) const
{
if (variant == AutoVariant) {
Modified: trunk/Source/WebCore/platform/graphics/FontCascade.h (211737 => 211738)
--- trunk/Source/WebCore/platform/graphics/FontCascade.h 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.h 2017-02-06 19:06:39 UTC (rev 211738)
@@ -139,6 +139,7 @@
DashArray dashesForIntersectionsWithRect(const TextRun&, const FloatPoint& textOrigin, const FloatRect& lineExtents) const;
WEBCORE_EXPORT float width(const TextRun&, HashSet<const Font*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+ float widthForSimpleText(StringView text) const;
std::unique_ptr<TextLayout, TextLayoutDeleter> createLayout(RenderText&, float xPos, bool collapseWhiteSpace) const;
static float width(TextLayout&, unsigned from, unsigned len, HashSet<const Font*>* fallbackFonts = 0);
Modified: trunk/Source/WebCore/platform/graphics/WidthCache.h (211737 => 211738)
--- trunk/Source/WebCore/platform/graphics/WidthCache.h 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/platform/graphics/WidthCache.h 2017-02-06 19:06:39 UTC (rev 211738)
@@ -119,6 +119,21 @@
{
}
+ float* add(StringView text, float entry)
+ {
+ if (MemoryPressureHandler::singleton().isUnderMemoryPressure())
+ return nullptr;
+
+ if (static_cast<unsigned>(text.length()) > SmallStringKey::capacity())
+ return nullptr;
+
+ if (m_countdown > 0) {
+ --m_countdown;
+ return nullptr;
+ }
+ return addSlowCase(text, entry);
+ }
+
float* add(const TextRun& run, float entry, bool hasKerningOrLigatures, bool hasWordSpacingOrLetterSpacing, GlyphOverflow* glyphOverflow)
{
if (MemoryPressureHandler::singleton().isUnderMemoryPressure())
@@ -143,7 +158,7 @@
return 0;
}
- return addSlowCase(run, entry);
+ return addSlowCase(run.text(), entry);
}
void clear()
@@ -153,23 +168,24 @@
}
private:
- float* addSlowCase(const TextRun& run, float entry)
+
+ float* addSlowCase(StringView text, float entry)
{
- int length = run.length();
+ int length = text.length();
bool isNewEntry;
- float *value;
+ float* value;
if (length == 1) {
- SingleCharMap::AddResult addResult = m_singleCharMap.add(run[0], entry);
+ SingleCharMap::AddResult addResult = m_singleCharMap.fastAdd(text[0], entry);
isNewEntry = addResult.isNewEntry;
value = &addResult.iterator->value;
} else {
SmallStringKey smallStringKey;
- if (run.is8Bit())
- smallStringKey = SmallStringKey(run.characters8(), length);
+ if (text.is8Bit())
+ smallStringKey = SmallStringKey(text.characters8(), length);
else
- smallStringKey = SmallStringKey(run.characters16(), length);
+ smallStringKey = SmallStringKey(text.characters16(), length);
- Map::AddResult addResult = m_map.add(smallStringKey, entry);
+ Map::AddResult addResult = m_map.fastAdd(smallStringKey, entry);
isNewEntry = addResult.isNewEntry;
value = &addResult.iterator->value;
}
Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.cpp (211737 => 211738)
--- trunk/Source/WebCore/platform/graphics/WidthIterator.cpp 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.cpp 2017-02-06 19:06:39 UTC (rev 211738)
@@ -172,6 +172,7 @@
template <typename TextIterator>
inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer)
{
+ // The core logic here needs to match SimpleLineLayout::widthForSimpleText()
bool rtl = m_run.rtl();
bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_expansion) && !m_run.spacingDisabled();
Modified: trunk/Source/WebCore/rendering/RenderText.cpp (211737 => 211738)
--- trunk/Source/WebCore/rendering/RenderText.cpp 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/rendering/RenderText.cpp 2017-02-06 19:06:39 UTC (rev 211738)
@@ -257,6 +257,8 @@
if (!oldStyle) {
m_useBackslashAsYenSymbol = computeUseBackslashAsYenSymbol();
needsResetText = m_useBackslashAsYenSymbol;
+ // It should really be computed in the c'tor, but during construction we don't have parent yet -and RenderText style == parent()->style()
+ m_canUseSimplifiedTextMeasuring = computeCanUseSimplifiedTextMeasuring();
} else if (oldStyle->fontCascade().useBackslashAsYenSymbol() != newStyle.fontCascade().useBackslashAsYenSymbol()) {
m_useBackslashAsYenSymbol = computeUseBackslashAsYenSymbol();
needsResetText = true;
@@ -1179,7 +1181,8 @@
m_isAllASCII = m_text.containsOnlyASCII();
m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
-
+ m_canUseSimplifiedTextMeasuring = computeCanUseSimplifiedTextMeasuring();
+
if (m_text != originalText) {
originalTextMap().set(this, originalText);
m_originalTextDiffersFromRendered = true;
@@ -1221,6 +1224,29 @@
characters[revealedCharactersOffset] = characterToReveal;
}
+bool RenderText::computeCanUseSimplifiedTextMeasuring() const
+{
+ if (!m_canUseSimpleFontCodePath)
+ return false;
+
+ auto& font = style().fontCascade();
+ if (font.wordSpacing() || font.letterSpacing())
+ return false;
+
+ // Additional check on the font codepath.
+ TextRun run(m_text);
+ run.setCharacterScanForCodePath(false);
+ if (font.codePath(run) != FontCascade::Simple)
+ return false;
+
+ auto whitespaceIsCollapsed = style().collapseWhiteSpace();
+ for (unsigned i = 0; i < m_text.length(); ++i) {
+ if ((!whitespaceIsCollapsed && m_text[i] == '\t') || m_text[i] == noBreakSpace || m_text[i] >= HiraganaLetterSmallA)
+ return false;
+ }
+ return true;
+}
+
void RenderText::setText(const String& text, bool force)
{
ASSERT(!text.isNull());
Modified: trunk/Source/WebCore/rendering/RenderText.h (211737 => 211738)
--- trunk/Source/WebCore/rendering/RenderText.h 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/rendering/RenderText.h 2017-02-06 19:06:39 UTC (rev 211738)
@@ -171,6 +171,8 @@
LayoutUnit topOfFirstText() const;
bool containsOnlyWhitespace(unsigned from, unsigned len) const;
+
+ bool canUseSimplifiedTextMeasuring() const { return m_canUseSimplifiedTextMeasuring; }
protected:
virtual void computePreferredLogicalWidths(float leadWidth);
@@ -202,6 +204,7 @@
void secureText(UChar mask);
LayoutRect collectSelectionRectsForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>*);
+ bool computeCanUseSimplifiedTextMeasuring() const;
void node() const = delete;
void container() const = delete; // Use parent() instead.
@@ -223,6 +226,7 @@
mutable unsigned m_knownToHaveNoOverflowAndNoFallbackFonts : 1;
unsigned m_useBackslashAsYenSymbol : 1;
unsigned m_originalTextDiffersFromRendered : 1;
+ unsigned m_canUseSimplifiedTextMeasuring : 1;
#if ENABLE(TEXT_AUTOSIZING)
// FIXME: This should probably be part of the text sizing structures in Document instead. That would save some memory.
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp (211737 => 211738)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp 2017-02-06 19:06:39 UTC (rev 211738)
@@ -47,12 +47,13 @@
if (is<RenderText>(child)) {
auto& textChild = downcast<RenderText>(child);
unsigned textLength = textChild.text()->length();
- segments.append(FlowContents::Segment { startPosition, startPosition + textLength, textChild.text(), textChild });
+ segments.append(FlowContents::Segment { startPosition, startPosition + textLength, textChild.text(),
+ textChild, textChild.canUseSimplifiedTextMeasuring() });
startPosition += textLength;
continue;
}
if (is<RenderLineBreak>(child)) {
- segments.append(FlowContents::Segment { startPosition, startPosition, String(), child });
+ segments.append(FlowContents::Segment { startPosition, startPosition, String(), child, true });
continue;
}
ASSERT_NOT_REACHED();
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h (211737 => 211738)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h 2017-02-06 19:06:39 UTC (rev 211738)
@@ -47,6 +47,7 @@
unsigned end;
StringView text;
const RenderObject& renderer;
+ bool canUseSimplifiedTextMeasuring;
};
const Segment& segmentForRun(unsigned start, unsigned end) const;
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.cpp (211737 => 211738)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.cpp 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.cpp 2017-02-06 19:06:39 UTC (rev 211738)
@@ -34,7 +34,7 @@
namespace WebCore {
namespace SimpleLineLayout {
-TextFragmentIterator::Style::Style(const RenderStyle& style)
+TextFragmentIterator::Style::Style(const RenderStyle& style, bool useSimplifiedTextMeasuring)
: font(style.fontCascade())
, textAlign(style.textAlign())
, collapseWhitespace(style.collapseWhiteSpace())
@@ -44,11 +44,11 @@
, breakFirstWordOnOverflow(breakAnyWordOnOverflow || (style.breakWords() && (wrapLines || preserveNewline)))
, breakNBSP(wrapLines && style.nbspMode() == SPACE)
, keepAllWordsForCJK(style.wordBreak() == KeepAllWordBreak)
- , spaceWidth(font.width(TextRun(StringView(&space, 1))))
+ , spaceWidth(useSimplifiedTextMeasuring ? font.widthForSimpleText(StringView(&space, 1)) : font.width(TextRun(StringView(&space, 1))))
, wordSpacing(font.wordSpacing())
, tabWidth(collapseWhitespace ? 0 : style.tabSize())
, shouldHyphenate(style.hyphens() == HyphensAuto && canHyphenate(style.locale()))
- , hyphenStringWidth(shouldHyphenate ? font.width(TextRun(style.hyphenString())) : 0)
+ , hyphenStringWidth(shouldHyphenate ? (useSimplifiedTextMeasuring ? font.widthForSimpleText(style.hyphenString()) : font.width(TextRun(style.hyphenString()))) : 0)
, hyphenLimitBefore(style.hyphenationLimitBefore() < 0 ? 2 : style.hyphenationLimitBefore())
, hyphenLimitAfter(style.hyphenationLimitAfter() < 0 ? 2 : style.hyphenationLimitAfter())
, locale(style.locale())
@@ -61,7 +61,7 @@
: m_flowContents(flow)
, m_currentSegment(m_flowContents.begin())
, m_lineBreakIterator(m_currentSegment->text, flow.style().locale())
- , m_style(flow.style())
+ , m_style(flow.style(), m_currentSegment->canUseSimplifiedTextMeasuring)
{
}
@@ -247,10 +247,15 @@
bool measureWithEndSpace = m_style.collapseWhitespace && segmentTo < segment.text.length() && segment.text[segmentTo] == ' ';
if (measureWithEndSpace)
++segmentTo;
- TextRun run(StringView(segment.text).substring(segmentFrom, segmentTo - segmentFrom), xPosition);
- if (m_style.tabWidth)
- run.setTabSize(true, m_style.tabWidth);
- float width = m_style.font.width(run);
+ float width = 0;
+ if (segment.canUseSimplifiedTextMeasuring)
+ width = m_style.font.widthForSimpleText(StringView(segment.text).substring(segmentFrom, segmentTo - segmentFrom));
+ else {
+ TextRun run(StringView(segment.text).substring(segmentFrom, segmentTo - segmentFrom), xPosition);
+ if (m_style.tabWidth)
+ run.setTabSize(true, m_style.tabWidth);
+ width = m_style.font.width(run);
+ }
if (measureWithEndSpace)
width -= (m_style.spaceWidth + m_style.wordSpacing);
return std::max<float>(0, width);
Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h (211737 => 211738)
--- trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h 2017-02-06 18:59:19 UTC (rev 211737)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h 2017-02-06 19:06:39 UTC (rev 211738)
@@ -105,7 +105,7 @@
std::optional<unsigned> lastHyphenPosition(const TextFragmentIterator::TextFragment& run, unsigned beforeIndex) const;
struct Style {
- explicit Style(const RenderStyle&);
+ explicit Style(const RenderStyle&, bool useSimplifiedTextMeasuring);
const FontCascade& font;
ETextAlign textAlign;