Changeset 31324

Show
Ignore:
Timestamp:
03/26/08 12:22:01 (20 months ago)
Author:
mjs@apple.com
Message:

WebCore:

2008-03-26 Maciej Stachowiak < mjs@apple.com>

Reviewed by Darin.

  • svg/SVGFont.cpp: (WebCore::SVGTextRunWalker::walk):
  • svg/SVGFontElement.cpp: (WebCore::SVGFontElement::SVGFontElement): (WebCore::SVGFontElement::addGlyphToCache): (WebCore::SVGFontElement::removeGlyphFromCache): (WebCore::SVGFontElement::ensureGlyphCache): (WebCore::SVGFontElement::getGlyphIdentifiersForString):
  • svg/SVGFontElement.h:
  • svg/SVGGlyphElement.h: (WebCore::SVGGlyphIdentifier::SVGGlyphIdentifier):
  • svg/SVGGlyphMap.h: Added. New radix tree based glyph map. (WebCore::GlyphMapNode::GlyphMapNode): (WebCore::SVGGlyphMap::SVGGlyphMap): (WebCore::SVGGlyphMap::add): (WebCore::SVGGlyphMap::compareGlyphPriority): (WebCore::SVGGlyphMap::get): (WebCore::SVGGlyphMap::clear):

LayoutTests:

2008-03-26 Maciej Stachowiak < mjs@apple.com>

Reviewed by Darin.

These test cases were already checking for this exact bug and now
render correctly.


  • platform/mac/svg/W3C-SVG-1.1/fonts-glyph-02-t-expected.txt:
  • platform/mac/svg/W3C-SVG-1.1/fonts-glyph-04-t-expected.txt:
Location:
trunk
Files:
1 added
8 modified

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r31316 r31324  
    1 2008-03-26  Eric Seidel  <eric@webkit.org> 
     12008-03-26  Maciej Stachowiak  <mjs@apple.com> 
     2 
     3        Reviewed by Darin. 
     4 
     5        - test updates for "SVG multichar glyph matching matches longest instead of first (affects Acid3 test 79)" 
     6        http://bugs.webkit.org/show_bug.cgi?id=18118 
     7 
     8        These test cases were already checking for this exact bug and now 
     9        render correctly. 
     10         
     11        * platform/mac/svg/W3C-SVG-1.1/fonts-glyph-02-t-expected.txt: 
     12        * platform/mac/svg/W3C-SVG-1.1/fonts-glyph-04-t-expected.txt: 
     13 
     14o2008-03-26  Eric Seidel  <eric@webkit.org> 
    215 
    316        Reviewed by darin. 
  • trunk/LayoutTests/platform/mac/svg/W3C-SVG-1.1/fonts-glyph-02-t-expected.txt

    r30635 r31324  
    33layer at (0,0) size 480x360 
    44  RenderSVGRoot {svg} at (0.50,0.50) size 479x359 
    5     RenderSVGContainer {g} at (100,36) size 209x180 
     5    RenderSVGContainer {g} at (100,36) size 210x180 
    66      RenderSVGHiddenContainer {defs} at (0,0) size 0x0 
    7       RenderSVGContainer {g} at (100,36) size 184x80 
    8         RenderSVGText {text} at (100,100) size 184x80 contains 1 chunk(s) 
    9           RenderSVGInlineText {#text} at (0,-64) size 184x80 
    10             chunk 1 text run 1 at (100.00,100.00) startOffset 0 endOffset 5 width 184.00 RTL: "\x{69A} \x{69A}\x{69A}\x{69A}" 
    11       RenderSVGContainer {g} at (100,136) size 209x80 
    12         RenderSVGText {text} at (100,200) size 209x80 contains 1 chunk(s) 
    13           RenderSVGInlineText {#text} at (0,-64) size 209x80 
    14             chunk 1 text run 1 at (100.00,200.00) startOffset 0 endOffset 5 width 223.92 RTL: "\x{62E} \x{62E}\x{62E}\x{62E}" 
     7      RenderSVGContainer {g} at (100,36) size 200x80 
     8        RenderSVGText {text} at (100,100) size 200x80 contains 1 chunk(s) 
     9          RenderSVGInlineText {#text} at (0,-64) size 200x80 
     10            chunk 1 text run 1 at (100.00,100.00) startOffset 0 endOffset 5 width 200.00 RTL: "\x{69A} \x{69A}\x{69A}\x{69A}" 
     11      RenderSVGContainer {g} at (100,136) size 210x80 
     12        RenderSVGText {text} at (100,200) size 210x80 contains 1 chunk(s) 
     13          RenderSVGInlineText {#text} at (0,-64) size 210x80 
     14            chunk 1 text run 1 at (100.00,200.00) startOffset 0 endOffset 5 width 209.92 RTL: "\x{62E} \x{62E}\x{62E}\x{62E}" 
    1515    RenderSVGText {text} at (10,340) size 264x46 contains 1 chunk(s) 
    1616      RenderSVGInlineText {#text} at (0,-36) size 264x46 
  • trunk/LayoutTests/platform/mac/svg/W3C-SVG-1.1/fonts-glyph-04-t-expected.txt

    r31310 r31324  
    33layer at (0,0) size 480x360 
    44  RenderSVGRoot {svg} at (0.50,0.50) size 479x359 
    5     RenderSVGContainer {g} at (100,60) size 25x150 
     5    RenderSVGContainer {g} at (100,60) size 64x150 
    66      RenderSVGHiddenContainer {defs} at (0,0) size 0x0 
    7       RenderSVGText {text} at (100,100) size 25x50 contains 1 chunk(s) 
    8         RenderSVGInlineText {#text} at (0,-40) size 25x50 
    9           chunk 1 text run 1 at (100.00,100.00) startOffset 0 endOffset 3 width 25.00: "ffl" 
     7      RenderSVGText {text} at (100,100) size 64x50 contains 1 chunk(s) 
     8        RenderSVGInlineText {#text} at (0,-40) size 64x50 
     9          chunk 1 text run 1 at (100.00,100.00) startOffset 0 endOffset 3 width 64.00: "ffl" 
    1010      RenderSVGText {text} at (100,200) size 25x50 contains 1 chunk(s) 
    1111        RenderSVGInlineText {#text} at (0,-40) size 25x50 
  • trunk/WebCore/ChangeLog

    r31323 r31324  
     12008-03-26  Maciej Stachowiak  <mjs@apple.com> 
     2 
     3        Reviewed by Darin. 
     4 
     5        - fixed "SVG multichar glyph matching matches longest instead of first (affects Acid3 test 79)" 
     6        http://bugs.webkit.org/show_bug.cgi?id=18118 
     7 
     8        * svg/SVGFont.cpp: 
     9        (WebCore::SVGTextRunWalker::walk): 
     10        * svg/SVGFontElement.cpp: 
     11        (WebCore::SVGFontElement::SVGFontElement): 
     12        (WebCore::SVGFontElement::addGlyphToCache): 
     13        (WebCore::SVGFontElement::removeGlyphFromCache): 
     14        (WebCore::SVGFontElement::ensureGlyphCache): 
     15        (WebCore::SVGFontElement::getGlyphIdentifiersForString): 
     16        * svg/SVGFontElement.h: 
     17        * svg/SVGGlyphElement.h: 
     18        (WebCore::SVGGlyphIdentifier::SVGGlyphIdentifier): 
     19        * svg/SVGGlyphMap.h: Added. New radix tree based glyph map. 
     20        (WebCore::GlyphMapNode::GlyphMapNode): 
     21        (WebCore::SVGGlyphMap::SVGGlyphMap): 
     22        (WebCore::SVGGlyphMap::add): 
     23        (WebCore::SVGGlyphMap::compareGlyphPriority): 
     24        (WebCore::SVGGlyphMap::get): 
     25        (WebCore::SVGGlyphMap::clear): 
     26 
    1272008-03-26  David Hyatt  <hyatt@apple.com> 
    228 
  • trunk/WebCore/svg/SVGFont.cpp

    r31310 r31324  
    3030#include "SVGFontData.h" 
    3131#include "SVGGlyphElement.h" 
     32#include "SVGGlyphMap.h" 
    3233#include "SVGFontElement.h" 
    3334#include "SVGFontFaceElement.h" 
     
    242243        ASSERT(to - from == run.length()); 
    243244 
    244         int maximumHashKeyLength = m_fontElement->maximumHashKeyLength(); 
    245         ASSERT(maximumHashKeyLength >= 0); 
    246  
    247245        Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(String(run.data(from), run.length()), run.rtl())); 
    248246 
     
    256254            // We have to check wheter the current character & the next character define a ligature. This needs to be 
    257255            // extended to the n-th next character (where n is 'characterLookupRange'), to check for any possible ligature. 
    258             characterLookupRange = maximumHashKeyLength + i >= endOfScanRange ? endOfScanRange - i : maximumHashKeyLength; 
    259  
    260             // FIXME: instead of checking from longest string to shortest, this should really scan in order 
    261             // of the glyphs and pick the first match 
    262             while (characterLookupRange > 0 && !foundGlyph) { 
    263                 String lookupString(run.data(run.rtl() ? run.length() - (i + characterLookupRange) : i), characterLookupRange); 
    264  
    265                 Vector<SVGGlyphIdentifier> glyphs = m_fontElement->glyphIdentifiersForString(lookupString); 
    266                 Vector<SVGGlyphIdentifier>::iterator it = glyphs.begin(); 
    267                 Vector<SVGGlyphIdentifier>::iterator end = glyphs.end(); 
    268  
    269                 for (; it != end; ++it) { 
    270                     identifier = *it; 
    271  
    272                     unsigned int startPosition = run.rtl() ? run.length() - (i + lookupString.length()) : i; 
    273                     unsigned int endPosition = startPosition + lookupString.length(); 
    274  
    275                     if (identifier.isValid && isCompatibleGlyph(identifier, isVerticalText, language, chars, startPosition, endPosition)) { 
    276                         ASSERT(characterLookupRange > 0); 
    277                         i += characterLookupRange - 1; 
    278                         m_walkerData.charsConsumed += characterLookupRange; 
    279  
    280                         foundGlyph = true; 
    281                         SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData); 
    282                         break; 
    283                     } 
     256            characterLookupRange = endOfScanRange - i; 
     257 
     258            String lookupString(run.data(run.rtl() ? run.length() - (i + characterLookupRange) : i), characterLookupRange); 
     259 
     260            Vector<SVGGlyphIdentifier> glyphs; 
     261            m_fontElement->getGlyphIdentifiersForString(lookupString, glyphs); 
     262            Vector<SVGGlyphIdentifier>::iterator it = glyphs.begin(); 
     263            Vector<SVGGlyphIdentifier>::iterator end = glyphs.end(); 
     264             
     265            for (; it != end; ++it) { 
     266                identifier = *it; 
     267                 
     268                unsigned int startPosition = run.rtl() ? run.length() - (i + lookupString.length()) : i; 
     269                unsigned int endPosition = startPosition + lookupString.length(); 
     270                 
     271                if (identifier.isValid && isCompatibleGlyph(identifier, isVerticalText, language, chars, startPosition, endPosition)) { 
     272                    ASSERT(characterLookupRange > 0); 
     273                    i += identifier.nameLength - 1; 
     274                    m_walkerData.charsConsumed += identifier.nameLength; 
     275                     
     276                    foundGlyph = true; 
     277                    SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData); 
     278                    break; 
    284279                } 
    285  
    286                 characterLookupRange--; 
    287280            } 
    288281 
     282             
    289283            if (!foundGlyph) { 
    290284                ++m_walkerData.charsConsumed; 
  • trunk/WebCore/svg/SVGFontElement.cpp

    r29663 r31324  
    3737SVGFontElement::SVGFontElement(const QualifiedName& tagName, Document* doc) 
    3838    : SVGStyledElement(tagName, doc) 
    39     , m_maximumHashKeyLength(0) 
     39    , m_isGlyphCacheValid(false) 
    4040{ 
    4141} 
     
    4747void SVGFontElement::addGlyphToCache(SVGGlyphElement* glyphElement) 
    4848{ 
    49     ASSERT(glyphElement); 
    50  
    51     String glyphString = glyphElement->getAttribute(unicodeAttr); 
    52     if (glyphString.isEmpty()) // No unicode property, means that glyph will be used in <altGlyph> situations! 
    53         return; 
    54  
    55     SVGGlyphIdentifier identifier = glyphElement->buildGlyphIdentifier(); 
    56     identifier.isValid = true; 
    57  
    58     if (glyphString.length() > m_maximumHashKeyLength) 
    59         m_maximumHashKeyLength = glyphString.length(); 
    60  
    61     GlyphHashMap::iterator glyphsIt = m_glyphMap.find(glyphString); 
    62     if (glyphsIt == m_glyphMap.end()) { 
    63         Vector<SVGGlyphIdentifier> glyphs; 
    64         glyphs.append(identifier); 
    65  
    66         m_glyphMap.add(glyphString, glyphs); 
    67     } else { 
    68         Vector<SVGGlyphIdentifier>& glyphs = (*glyphsIt).second; 
    69         glyphs.append(identifier); 
    70     } 
     49    if (m_isGlyphCacheValid) 
     50        m_glyphMap.clear(); 
     51    m_isGlyphCacheValid = false; 
    7152} 
    7253 
    7354void SVGFontElement::removeGlyphFromCache(SVGGlyphElement* glyphElement) 
    7455{ 
    75     ASSERT(glyphElement); 
    76  
    77     String glyphString = glyphElement->getAttribute(unicodeAttr); 
    78     if (glyphString.isEmpty()) // No unicode property, means that glyph will be used in <altGlyph> situations! 
    79         return; 
    80  
    81     GlyphHashMap::iterator glyphsIt = m_glyphMap.find(glyphString); 
    82     ASSERT(glyphsIt != m_glyphMap.end()); 
    83  
    84     Vector<SVGGlyphIdentifier>& glyphs = (*glyphsIt).second; 
    85  
    86     if (glyphs.size() == 1) 
    87         m_glyphMap.remove(glyphString); 
    88     else { 
    89         SVGGlyphIdentifier identifier = glyphElement->buildGlyphIdentifier(); 
    90         identifier.isValid = true; 
    91  
    92         Vector<SVGGlyphIdentifier>::iterator it = glyphs.begin(); 
    93         Vector<SVGGlyphIdentifier>::iterator end = glyphs.end(); 
    94  
    95         unsigned int position = 0; 
    96         for (; it != end; ++it) { 
    97             if ((*it) == identifier) 
    98                 break; 
    99  
    100             position++; 
    101         } 
    102  
    103         ASSERT(position < glyphs.size()); 
    104         glyphs.remove(position); 
    105     } 
    106  
    107     // If we remove a glyph from cache, whose unicode property length is equal to 
    108     // m_maximumHashKeyLength then we need to recalculate the hash key length, because there 
    109     // is either no more glyph with that length, or there are still more glyphs with the maximum length. 
    110     if (glyphString.length() == m_maximumHashKeyLength) { 
    111         m_maximumHashKeyLength = 0; 
    112  
    113         GlyphHashMap::iterator it = m_glyphMap.begin(); 
    114         GlyphHashMap::iterator end = m_glyphMap.end(); 
    115  
    116         for (; it != end; ++it) { 
    117             if ((*it).first.length() > m_maximumHashKeyLength) 
    118                 m_maximumHashKeyLength = (*it).first.length(); 
    119         } 
    120     } 
     56    if (m_isGlyphCacheValid) 
     57        m_glyphMap.clear(); 
     58    m_isGlyphCacheValid = false; 
    12159} 
    12260 
     
    13169} 
    13270 
    133 const Vector<SVGGlyphIdentifier>& SVGFontElement::glyphIdentifiersForString(const String& string) const 
     71void SVGFontElement::ensureGlyphCache() const 
    13472{ 
    135     GlyphHashMap::const_iterator it = m_glyphMap.find(string); 
    136     if (it == m_glyphMap.end()) { 
    137         static Vector<SVGGlyphIdentifier> s_emptyGlyphList; 
    138         return s_emptyGlyphList; 
     73    if (m_isGlyphCacheValid) 
     74        return; 
     75 
     76    for (Node* child = firstChild(); child; child = child->nextSibling()) { 
     77        if (child->hasTagName(glyphTag)) { 
     78            SVGGlyphElement* glyph = static_cast<SVGGlyphElement*>(child); 
     79            String unicode = glyph->getAttribute(unicodeAttr); 
     80            if (unicode.length()) 
     81                m_glyphMap.add(unicode, glyph->buildGlyphIdentifier()); 
     82        } 
    13983    } 
     84         
     85    m_isGlyphCacheValid = true; 
     86} 
    14087 
    141     return (*it).second; 
     88void SVGFontElement::getGlyphIdentifiersForString(const String& string, Vector<SVGGlyphIdentifier>& glyphs) const 
     89{ 
     90    ensureGlyphCache(); 
     91    m_glyphMap.get(string, glyphs); 
    14292} 
    14393 
  • trunk/WebCore/svg/SVGFontElement.h

    r29663 r31324  
    2525#include "SVGExternalResourcesRequired.h" 
    2626#include "SVGGlyphElement.h" 
     27#include "SVGGlyphMap.h" 
    2728#include "SVGStyledElement.h" 
    2829 
     
    4243        void removeGlyphFromCache(SVGGlyphElement*); 
    4344 
    44         const Vector<SVGGlyphIdentifier>& glyphIdentifiersForString(const String&) const; 
    45  
    46         // Returns the longest hash key length (the 'unicode' property value with the 
    47         // highest amount of characters) - ie. for <glyph unicode="ffl"/> it will return 3. 
    48         unsigned int maximumHashKeyLength() const { return m_maximumHashKeyLength; } 
     45        void getGlyphIdentifiersForString(const String&, Vector<SVGGlyphIdentifier>&) const; 
    4946 
    5047        SVGMissingGlyphElement* firstMissingGlyphElement() const; 
    5148 
    5249    private: 
    53         typedef HashMap<String, Vector<SVGGlyphIdentifier> > GlyphHashMap; 
    54         GlyphHashMap m_glyphMap; 
     50        void ensureGlyphCache() const; 
    5551 
    56         unsigned int m_maximumHashKeyLength; 
     52        mutable SVGGlyphMap m_glyphMap; 
     53        mutable bool m_isGlyphCacheValid; 
    5754    }; 
    5855 
  • trunk/WebCore/svg/SVGGlyphElement.h

    r31310 r31324  
    5252        SVGGlyphIdentifier() 
    5353            : isValid(false) 
    54             , priority(0) 
    5554            , orientation(Both) 
    5655            , arabicForm(None) 
     56            , priority(0) 
     57            , nameLength(0) 
    5758            , horizontalAdvanceX(0.0f) 
    5859            , verticalOriginX(0.0f) 
     
    8485 
    8586        bool isValid : 1; 
    86         int priority; 
    8787 
    8888        Orientation orientation : 2; 
    8989        ArabicForm arabicForm : 3; 
     90        int priority; 
     91        size_t nameLength; 
    9092        String glyphName; 
    9193