https://bugs.webkit.org/show_bug.cgi?id=83817
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Apr 2012 21:06:50 +0000 (21:06 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Apr 2012 21:06:50 +0000 (21:06 +0000)
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

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/Font.cpp
Source/WebCore/platform/graphics/Font.h
Source/WebCore/platform/graphics/TextRun.h
Source/WebCore/rendering/InlineTextBox.cpp
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RenderText.cpp
Source/WebCore/rendering/RenderText.h

index f6810ea..f19327e 100644 (file)
@@ -1,3 +1,45 @@
+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
index bd396d5..de74a2b 100644 (file)
@@ -266,17 +266,27 @@ Font::CodePath Font::codePath(const TextRun& run) const
 
     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) 
@@ -383,10 +393,10 @@ Font::CodePath Font::codePath(const TextRun& run) const
         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;
 
@@ -418,10 +428,6 @@ Font::CodePath Font::codePath(const TextRun& run) const
         if (c <= 0xFE2F)
             return Complex;
     }
-
-    if (run.length() > 1 && typesettingFeatures())
-        return Complex;
-
     return result;
 }
 
index 09ed180..5b73404 100644 (file)
@@ -193,7 +193,8 @@ public:
 
     enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
     CodePath codePath(const TextRun&) const;
-
+    static CodePath characterRangeCodePath(const UChar*, unsigned len);
+    
 private:
     enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
 
index 029c708..78f7f9c 100644 (file)
@@ -58,7 +58,7 @@ public:
 
     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)
@@ -71,13 +71,14 @@ public:
         , 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())
@@ -90,6 +91,7 @@ public:
         , 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)
@@ -122,6 +124,7 @@ public:
     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; }
@@ -130,6 +133,7 @@ public:
     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:
@@ -167,6 +171,7 @@ private:
     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;
index 154ce81..784f5c7 100644 (file)
@@ -1325,7 +1325,7 @@ TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, co
 
     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));
 
index 0dd2463..e90d92f 100755 (executable)
@@ -1947,6 +1947,7 @@ static inline float textWidth(RenderText* text, unsigned from, unsigned len, con
     run.setCharactersLength(text->textLength() - from);
     ASSERT(run.charactersLength() >= run.length());
 
+    run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
     run.setAllowTabs(!collapseWhiteSpace);
     run.setXPos(xPos);
     return font.width(run);
index b359d4a..1eef320 100644 (file)
@@ -146,6 +146,7 @@ RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
      , m_linesDirty(false)
      , m_containsReversedText(false)
      , m_isAllASCII(m_text.containsOnlyASCII())
+     , m_canUseSimpleFontCodePath(computeCanUseSimpleFontCodePath())
      , m_knownToHaveNoOverflowAndNoFallbackFonts(false)
      , m_needsTranscoding(false)
 {
@@ -760,6 +761,7 @@ ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
     run.setCharactersLength(textLength() - start);
     ASSERT(run.charactersLength() >= run.length());
 
+    run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
     run.setAllowTabs(allowTabs());
     run.setXPos(xPos);
     return f.width(run, fallbackFonts, glyphOverflow);
@@ -1330,6 +1332,7 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
     ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n'));
 
     m_isAllASCII = m_text.containsOnlyASCII();
+    m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
 }
 
 void RenderText::secureText(UChar mask)
@@ -1473,6 +1476,7 @@ float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos,
         run.setCharactersLength(textLength() - from);
         ASSERT(run.charactersLength() >= run.length());
 
+        run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
         run.setAllowTabs(allowTabs());
         run.setXPos(xPos);
         w = f.width(run, fallbackFonts, glyphOverflow);
@@ -1793,6 +1797,13 @@ int RenderText::nextOffset(int current) const
     return result;
 }
 
+bool RenderText::computeCanUseSimpleFontCodePath() const
+{
+    if (isAllASCII())
+        return true;
+    return Font::characterRangeCodePath(characters(), length()) == Font::Simple;
+}
+
 #ifndef NDEBUG
 
 void RenderText::checkConsistency() const
index 750bb8e..70f7c3e 100644 (file)
@@ -129,7 +129,8 @@ public:
 
     virtual void computePreferredLogicalWidths(float leadWidth);
     bool isAllCollapsibleWhitespace();
-    
+
+    bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; }
     bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; }
 
     void removeAndDestroyTextBoxes();
@@ -148,6 +149,8 @@ protected:
 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().
@@ -186,6 +189,7 @@ private:
                            // or removed).
     bool m_containsReversedText : 1;
     bool m_isAllASCII : 1;
+    bool m_canUseSimpleFontCodePath : 1;
     mutable bool m_knownToHaveNoOverflowAndNoFallbackFonts : 1;
     bool m_needsTranscoding : 1;
 };