This patch modifies RenderText so that it scans all of its characters up front to
determine whether or not the simple code path can be used for measurement/rendering
of the text for the whole run.
TextRun now has an additional field that indicates that the character scan is not
required, since the entire RenderText is known to be simple. This boolean is set
when constructing the TextRun from the places that make TextRuns from RenderTexts.
The character scan has been refactored into a static Font method so that it can be
called by RenderText. The scan of individual TextRuns is also done using the same method
so that the code is shared.
Reviewed by Dan Bernstein.
* platform/graphics/Font.cpp:
(WebCore::Font::codePath):
(WebCore::Font::characterRangeCodePath):
* platform/graphics/Font.h:
* platform/graphics/TextRun.h:
(WebCore::TextRun::TextRun):
(WebCore::TextRun::characterScanForCodePath):
(WebCore::TextRun::setCharacterScanForCodePath):
(TextRun):
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::constructTextRun):
* rendering/RenderBlockLineLayout.cpp:
(WebCore::textWidth):
* rendering/RenderText.cpp:
(WebCore::RenderText::RenderText):
(WebCore::RenderText::widthFromCache):
(WebCore::RenderText::setTextInternal):
(WebCore::RenderText::width):
(WebCore::RenderText::computeCanUseSimpleFontCodePath):
(WebCore):
* rendering/RenderText.h:
(RenderText):
(WebCore::RenderText::canUseSimpleFontCodePath):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@114032
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-04-12 David Hyatt <hyatt@apple.com>
+
+ https://bugs.webkit.org/show_bug.cgi?id=83817
+
+ This patch modifies RenderText so that it scans all of its characters up front to
+ determine whether or not the simple code path can be used for measurement/rendering
+ of the text for the whole run.
+
+ TextRun now has an additional field that indicates that the character scan is not
+ required, since the entire RenderText is known to be simple. This boolean is set
+ when constructing the TextRun from the places that make TextRuns from RenderTexts.
+
+ The character scan has been refactored into a static Font method so that it can be
+ called by RenderText. The scan of individual TextRuns is also done using the same method
+ so that the code is shared.
+
+ Reviewed by Dan Bernstein.
+
+ * platform/graphics/Font.cpp:
+ (WebCore::Font::codePath):
+ (WebCore::Font::characterRangeCodePath):
+ * platform/graphics/Font.h:
+ * platform/graphics/TextRun.h:
+ (WebCore::TextRun::TextRun):
+ (WebCore::TextRun::characterScanForCodePath):
+ (WebCore::TextRun::setCharacterScanForCodePath):
+ (TextRun):
+ * rendering/InlineTextBox.cpp:
+ (WebCore::InlineTextBox::constructTextRun):
+ * rendering/RenderBlockLineLayout.cpp:
+ (WebCore::textWidth):
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::RenderText):
+ (WebCore::RenderText::widthFromCache):
+ (WebCore::RenderText::setTextInternal):
+ (WebCore::RenderText::width):
+ (WebCore::RenderText::computeCanUseSimpleFontCodePath):
+ (WebCore):
+ * rendering/RenderText.h:
+ (RenderText):
+ (WebCore::RenderText::canUseSimpleFontCodePath):
+
2012-04-12 Levi Weintraub <leviw@chromium.org>
Make AccessibilityObject::size non-virtual and fix platform accessibility code's LayoutUnit usage
if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
return Complex;
+
+ if (run.length() > 1 && typesettingFeatures())
+ return Complex;
- CodePath result = Simple;
+ if (!run.characterScanForCodePath())
+ return Simple;
+
+ // Start from 0 since drawing and highlighting also measure the characters before run->from.
+ return characterRangeCodePath(run.characters(), run.length());
+}
- // Start from 0 since drawing and highlighting also measure the characters before run->from
+Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned len)
+{
// FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we
// can't simply use UnicodeCharacter Property/class because some characters
// are not 'combining', but still need to go to the complex path.
// Alternatively, we may as well consider binary search over a sorted
// list of ranges.
- for (int i = 0; i < run.length(); i++) {
- const UChar c = run[i];
+ CodePath result = Simple;
+ for (unsigned i = 0; i < len; i++) {
+ const UChar c = characters[i];
if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
continue;
if (c <= 0x2E9)
if (c <= 0xDBFF) {
// High surrogate
- if (i == run.length() - 1)
+ if (i == len - 1)
continue;
- UChar next = run[++i];
+ UChar next = characters[++i];
if (!U16_IS_TRAIL(next))
continue;
if (c <= 0xFE2F)
return Complex;
}
-
- if (run.length() > 1 && typesettingFeatures())
- return Complex;
-
return result;
}
enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
CodePath codePath(const TextRun&) const;
-
+ static CodePath characterRangeCodePath(const UChar*, unsigned len);
+
private:
enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
typedef unsigned RoundingHacks;
- TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, RoundingHacks roundingHacks = RunRounding | WordRounding)
+ TextRun(const UChar* c, int len, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_characters(c)
, m_charactersLength(len)
, m_len(len)
, m_allowTabs(allowTabs)
, m_direction(direction)
, m_directionalOverride(directionalOverride)
+ , m_characterScanForCodePath(characterScanForCodePath)
, m_applyRunRounding((roundingHacks & RunRounding) && s_allowsRoundingHacks)
, m_applyWordRounding((roundingHacks & WordRounding) && s_allowsRoundingHacks)
, m_disableSpacing(false)
{
}
- TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, RoundingHacks roundingHacks = RunRounding | WordRounding)
+ TextRun(const String& s, bool allowTabs = false, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
: m_characters(s.characters())
, m_charactersLength(s.length())
, m_len(s.length())
, m_allowTabs(allowTabs)
, m_direction(direction)
, m_directionalOverride(directionalOverride)
+ , m_characterScanForCodePath(characterScanForCodePath)
, m_applyRunRounding((roundingHacks & RunRounding) && s_allowsRoundingHacks)
, m_applyWordRounding((roundingHacks & WordRounding) && s_allowsRoundingHacks)
, m_disableSpacing(false)
bool rtl() const { return m_direction == RTL; }
bool ltr() const { return m_direction == LTR; }
bool directionalOverride() const { return m_directionalOverride; }
+ bool characterScanForCodePath() const { return m_characterScanForCodePath; }
bool applyRunRounding() const { return m_applyRunRounding; }
bool applyWordRounding() const { return m_applyWordRounding; }
bool spacingDisabled() const { return m_disableSpacing; }
void disableRoundingHacks() { m_applyRunRounding = m_applyWordRounding = false; }
void setDirection(TextDirection direction) { m_direction = direction; }
void setDirectionalOverride(bool override) { m_directionalOverride = override; }
+ void setCharacterScanForCodePath(bool scan) { m_characterScanForCodePath = scan; }
class RenderingContext : public RefCounted<RenderingContext> {
public:
bool m_allowTabs;
TextDirection m_direction;
bool m_directionalOverride; // Was this direction set by an override character.
+ bool m_characterScanForCodePath;
bool m_applyRunRounding;
bool m_applyWordRounding;
bool m_disableSpacing;
ASSERT(maximumLength >= length);
- TextRun run(characters, length, textRenderer->allowTabs(), textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder);
+ TextRun run(characters, length, textRenderer->allowTabs(), textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer->canUseSimpleFontCodePath());
if (textRunNeedsRenderingContext(font))
run.setRenderingContext(SVGTextRunRenderingContext::create(textRenderer));
run.setCharactersLength(text->textLength() - from);
ASSERT(run.charactersLength() >= run.length());
+ run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
run.setAllowTabs(!collapseWhiteSpace);
run.setXPos(xPos);
return font.width(run);
, m_linesDirty(false)
, m_containsReversedText(false)
, m_isAllASCII(m_text.containsOnlyASCII())
+ , m_canUseSimpleFontCodePath(computeCanUseSimpleFontCodePath())
, m_knownToHaveNoOverflowAndNoFallbackFonts(false)
, m_needsTranscoding(false)
{
run.setCharactersLength(textLength() - start);
ASSERT(run.charactersLength() >= run.length());
+ run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
run.setAllowTabs(allowTabs());
run.setXPos(xPos);
return f.width(run, fallbackFonts, glyphOverflow);
ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n'));
m_isAllASCII = m_text.containsOnlyASCII();
+ m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
}
void RenderText::secureText(UChar mask)
run.setCharactersLength(textLength() - from);
ASSERT(run.charactersLength() >= run.length());
+ run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
run.setAllowTabs(allowTabs());
run.setXPos(xPos);
w = f.width(run, fallbackFonts, glyphOverflow);
return result;
}
+bool RenderText::computeCanUseSimpleFontCodePath() const
+{
+ if (isAllASCII())
+ return true;
+ return Font::characterRangeCodePath(characters(), length()) == Font::Simple;
+}
+
#ifndef NDEBUG
void RenderText::checkConsistency() const
virtual void computePreferredLogicalWidths(float leadWidth);
bool isAllCollapsibleWhitespace();
-
+
+ bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; }
bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; }
void removeAndDestroyTextBoxes();
private:
void computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow&);
+ bool computeCanUseSimpleFontCodePath() const;
+
// Make length() private so that callers that have a RenderText*
// will use the more efficient textLength() instead, while
// callers with a RenderObject* can continue to use length().
// or removed).
bool m_containsReversedText : 1;
bool m_isAllASCII : 1;
+ bool m_canUseSimpleFontCodePath : 1;
mutable bool m_knownToHaveNoOverflowAndNoFallbackFonts : 1;
bool m_needsTranscoding : 1;
};