Changeset 31324 in webkit


Ignore:
Timestamp:
Mar 26, 2008 12:22:01 PM (16 years 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 edited

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
Note: See TracChangeset for help on using the changeset viewer.