Changeset 141990 in webkit


Ignore:
Timestamp:
Feb 6, 2013 5:09:01 AM (11 years ago)
Author:
akling@apple.com
Message:

Optimize GlyphPage for case where all glyphs are available in the same font.
<http://webkit.org/b/108835>
<rdar://problem/13157042>

Reviewed by Antti Koivisto.

Let GlyphPage begin optimistically assuming that all its glyphs will be represented in
the same SimpleFontData*. In this (very common) case, only keep a single SimpleFontData*.

If glyphs from multiple fonts are mixed in one page, an array of per-glyph SimpleFontData*
is allocated transparently.

4.98 MB progression on Membuster3.

  • platform/graphics/GlyphPageTreeNode.cpp:

(WebCore::GlyphPageTreeNode::initializePage):

  • platform/graphics/GlyphPage.h:

(WebCore::GlyphPage::createUninitialized):
(WebCore::GlyphPage::createZeroedSystemFallbackPage):
(WebCore::GlyphPage::createCopiedSystemFallbackPage):

There are now three ways of constructing a GlyphPage, two of them are only used for
creating system fallback pages.

(WebCore::GlyphPage::setGlyphDataForIndex):

Hold off creating a SimpleFontData* array until we're sure there are two different
SimpleFontData* backing the glyphs in this page.
We don't store font data for glyph #0, instead we let the getters always return null for it.

(WebCore::GlyphPage::~GlyphPage):

Free the SimpleFontData* array if needed.

(WebCore::GlyphPage::glyphDataForCharacter):
(WebCore::GlyphPage::glyphDataForIndex):
(WebCore::GlyphPage::fontDataForCharacter):

The font data for glyph #0 is always a null pointer now.

(WebCore::GlyphPage::clearForFontData):

Updated for new storage format.

  • rendering/svg/SVGTextRunRenderingContext.cpp:

(WebCore::SVGTextRunRenderingContext::glyphDataForCharacter):

Fix bug where non-zero glyph was temporarily associated with null font data,
which triggered the new assertion in setGlyphDataForIndex().

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r141989 r141990  
     12013-02-06  Andreas Kling  <akling@apple.com>
     2
     3        Optimize GlyphPage for case where all glyphs are available in the same font.
     4        <http://webkit.org/b/108835>
     5        <rdar://problem/13157042>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Let GlyphPage begin optimistically assuming that all its glyphs will be represented in
     10        the same SimpleFontData*. In this (very common) case, only keep a single SimpleFontData*.
     11
     12        If glyphs from multiple fonts are mixed in one page, an array of per-glyph SimpleFontData*
     13        is allocated transparently.
     14
     15        4.98 MB progression on Membuster3.
     16
     17        * platform/graphics/GlyphPageTreeNode.cpp:
     18        (WebCore::GlyphPageTreeNode::initializePage):
     19        * platform/graphics/GlyphPage.h:
     20        (WebCore::GlyphPage::createUninitialized):
     21        (WebCore::GlyphPage::createZeroedSystemFallbackPage):
     22        (WebCore::GlyphPage::createCopiedSystemFallbackPage):
     23
     24            There are now three ways of constructing a GlyphPage, two of them are only used for
     25            creating system fallback pages.
     26
     27        (WebCore::GlyphPage::setGlyphDataForIndex):
     28
     29            Hold off creating a SimpleFontData* array until we're sure there are two different
     30            SimpleFontData* backing the glyphs in this page.
     31            We don't store font data for glyph #0, instead we let the getters always return null for it.
     32
     33        (WebCore::GlyphPage::~GlyphPage):
     34
     35            Free the SimpleFontData* array if needed.
     36
     37        (WebCore::GlyphPage::glyphDataForCharacter):
     38        (WebCore::GlyphPage::glyphDataForIndex):
     39        (WebCore::GlyphPage::fontDataForCharacter):
     40
     41            The font data for glyph #0 is always a null pointer now.
     42
     43        (WebCore::GlyphPage::clearForFontData):
     44
     45            Updated for new storage format.
     46
     47        * rendering/svg/SVGTextRunRenderingContext.cpp:
     48        (WebCore::SVGTextRunRenderingContext::glyphDataForCharacter):
     49
     50            Fix bug where non-zero glyph was temporarily associated with null font data,
     51            which triggered the new assertion in setGlyphDataForIndex().
     52
    1532013-02-06  Pavel Feldman  <pfeldman@chromium.org>
    254
  • trunk/Source/WebCore/platform/graphics/GlyphPage.h

    r141976 r141990  
    11/*
    2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
    44 *
     
    3434#include <wtf/PassRefPtr.h>
    3535#include <wtf/RefCounted.h>
     36#include <wtf/RefPtr.h>
    3637#include <wtf/unicode/Unicode.h>
    3738
     
    6364class GlyphPage : public RefCounted<GlyphPage> {
    6465public:
    65     static PassRefPtr<GlyphPage> create(GlyphPageTreeNode* owner)
    66     {
    67         return adoptRef(new GlyphPage(owner));
     66    static PassRefPtr<GlyphPage> createUninitialized(GlyphPageTreeNode* owner)
     67    {
     68        return adoptRef(new GlyphPage(owner, false));
     69    }
     70
     71    static PassRefPtr<GlyphPage> createZeroedSystemFallbackPage(GlyphPageTreeNode* owner)
     72    {
     73        return adoptRef(new GlyphPage(owner, true));
     74    }
     75
     76    PassRefPtr<GlyphPage> createCopiedSystemFallbackPage(GlyphPageTreeNode* owner) const
     77    {
     78        RefPtr<GlyphPage> page = GlyphPage::createUninitialized(owner);
     79        memcpy(page->m_glyphs, m_glyphs, sizeof(m_glyphs));
     80        page->m_fontDataForAllGlyphs = m_fontDataForAllGlyphs;
     81        if (m_perGlyphFontData) {
     82            page->m_perGlyphFontData = static_cast<const SimpleFontData**>(fastMalloc(size * sizeof(SimpleFontData*)));
     83            memcpy(page->m_perGlyphFontData, m_perGlyphFontData, size * sizeof(SimpleFontData*));
     84        }
     85        return page.release();
     86    }
     87
     88    ~GlyphPage()
     89    {
     90        if (m_perGlyphFontData)
     91            fastFree(m_perGlyphFontData);
    6892    }
    6993
     
    7397    GlyphData glyphDataForCharacter(UChar32 c) const
    7498    {
    75         unsigned index = indexForCharacter(c);
    76         return GlyphData(m_glyphs[index], m_glyphFontData[index]);
     99        return glyphDataForIndex(indexForCharacter(c));
    77100    }
    78101
     
    80103    {
    81104        ASSERT_WITH_SECURITY_IMPLICATION(index < size);
    82         return GlyphData(m_glyphs[index], m_glyphFontData[index]);
     105        Glyph glyph = m_glyphs[index];
     106        if (UNLIKELY(!glyph))
     107            return GlyphData(0, 0);
     108        if (UNLIKELY(!!m_perGlyphFontData))
     109            return GlyphData(glyph, m_perGlyphFontData[index]);
     110        return GlyphData(glyph, m_fontDataForAllGlyphs);
    83111    }
    84112
     
    91119    const SimpleFontData* fontDataForCharacter(UChar32 c) const
    92120    {
    93         return m_glyphFontData[indexForCharacter(c)];
     121        return glyphDataForIndex(indexForCharacter(c)).fontData;
    94122    }
    95123
     
    99127    }
    100128
    101     void setGlyphDataForIndex(unsigned index, Glyph g, const SimpleFontData* f)
     129    void setGlyphDataForIndex(unsigned index, Glyph glyph, const SimpleFontData* fontData)
    102130    {
    103131        ASSERT_WITH_SECURITY_IMPLICATION(index < size);
    104         m_glyphs[index] = g;
    105         m_glyphFontData[index] = f;
     132        m_glyphs[index] = glyph;
     133
     134        // GlyphPage getters will always return a null SimpleFontData* for glyph #0, so don't worry about the pointer for them.
     135        if (!glyph)
     136            return;
     137
     138        // A glyph index without a font data pointer makes no sense.
     139        ASSERT(fontData);
     140
     141        if (m_perGlyphFontData) {
     142            m_perGlyphFontData[index] = fontData;
     143            return;
     144        }
     145
     146        if (!m_fontDataForAllGlyphs)
     147            m_fontDataForAllGlyphs = fontData;
     148
     149        if (m_fontDataForAllGlyphs == fontData)
     150            return;
     151
     152        // This GlyphPage houses glyphs from multiple fonts, transition to an array of SimpleFontData pointers.
     153        const SimpleFontData* oldFontData = m_fontDataForAllGlyphs;
     154        m_perGlyphFontData = static_cast<const SimpleFontData**>(fastMalloc(size * sizeof(SimpleFontData*)));
     155        for (unsigned i = 0; i < size; ++i)
     156            m_perGlyphFontData[i] = oldFontData;
     157        m_perGlyphFontData[index] = fontData;
    106158    }
    107159
     
    110162        setGlyphDataForIndex(index, glyphData.glyph, glyphData.fontData);
    111163    }
    112    
    113     void copyFrom(const GlyphPage& other)
    114     {
    115         memcpy(m_glyphs, other.m_glyphs, sizeof(m_glyphs));
    116         memcpy(m_glyphFontData, other.m_glyphFontData, sizeof(m_glyphFontData));
    117     }
    118 
    119     void clear()
    120     {
    121         memset(m_glyphs, 0, sizeof(m_glyphs));
    122         memset(m_glyphFontData, 0, sizeof(m_glyphFontData));
    123     }
    124164
    125165    void clearForFontData(const SimpleFontData* fontData)
    126166    {
     167        if (!m_perGlyphFontData) {
     168            if (m_fontDataForAllGlyphs == fontData) {
     169                memset(m_glyphs, 0, sizeof(m_glyphs));
     170                m_fontDataForAllGlyphs = 0;
     171            }
     172            return;
     173        }
    127174        for (size_t i = 0; i < size; ++i) {
    128             if (m_glyphFontData[i] == fontData) {
     175            if (m_perGlyphFontData[i] == fontData) {
    129176                m_glyphs[i] = 0;
    130                 m_glyphFontData[i] = 0;
     177                m_perGlyphFontData[i] = 0;
    131178            }
    132179        }
     
    139186
    140187private:
    141     GlyphPage(GlyphPageTreeNode* owner)
    142         : m_owner(owner)
    143     {
    144     }
    145 
    146     // Separate arrays, rather than array of GlyphData, to save space.
     188    GlyphPage(GlyphPageTreeNode* owner, bool clearGlyphs)
     189        : m_fontDataForAllGlyphs(0)
     190        , m_perGlyphFontData(0)
     191        , m_owner(owner)
     192    {
     193        if (clearGlyphs)
     194            memset(m_glyphs, 0, sizeof(m_glyphs));
     195    }
     196
     197    const SimpleFontData* m_fontDataForAllGlyphs;
     198    const SimpleFontData** m_perGlyphFontData;
     199
     200    GlyphPageTreeNode* m_owner;
    147201    Glyph m_glyphs[size];
    148     const SimpleFontData* m_glyphFontData[size];
    149 
    150     GlyphPageTreeNode* m_owner;
    151202};
    152203
    153204} // namespace WebCore
    154205
    155 #endif // GlyphPageTreeNode_h
     206#endif // GlyphPage_h
  • trunk/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp

    r141976 r141990  
    201201                }
    202202            }
    203            
    204             m_page = GlyphPage::create(this);
     203
     204            m_page = GlyphPage::createUninitialized(this);
    205205
    206206            // Now that we have a buffer full of characters, we want to get back an array
     
    226226                    if (from < static_cast<int>(GlyphPage::size) && to > 0) {
    227227                        if (haveGlyphs && !scratchPage) {
    228                             scratchPage = GlyphPage::create(this);
     228                            scratchPage = GlyphPage::createUninitialized(this);
    229229                            pageToFill = scratchPage.get();
    230230                        }
     
    280280            } else {
    281281                // Combine the parent's glyphs and ours to form a new more complete page.
    282                 m_page = GlyphPage::create(this);
     282                m_page = GlyphPage::createUninitialized(this);
    283283
    284284                // Overlay the parent page on the fallback page. Check if the fallback font
     
    301301        }
    302302    } else {
    303         m_page = GlyphPage::create(this);
    304303        // System fallback. Initialized with the parent's page here, as individual
    305304        // entries may use different fonts depending on character. If the Font
     
    307306        // ask the system for the best font to use and fill that glyph in for us.
    308307        if (parentPage)
    309             m_page->copyFrom(*parentPage);
     308            m_page = parentPage->createCopiedSystemFallbackPage(this);
    310309        else
    311             m_page->clear();
     310            m_page = GlyphPage::createZeroedSystemFallbackPage(this);
    312311    }
    313312}
  • trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp

    r133897 r141990  
    231231    // Even though our GlyphPage contains an entry for eg. glyph "a", it's not compatible. So we have to temporarily
    232232    // remove the glyph data information from the GlyphPage, and retry the lookup, which handles font fallbacks correctly.
    233     page->setGlyphDataForCharacter(character, glyphData.glyph, 0);
     233    page->setGlyphDataForCharacter(character, 0, 0);
    234234
    235235    // Assure that the font fallback glyph selection worked, aka. the fallbackGlyphData font data is not the same as before.
Note: See TracChangeset for help on using the changeset viewer.