18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FontCache.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FontFallbackList.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FontPlatformData.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FontSelector.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashMap.h>
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/ListHashSet.h>
39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/StdLibExtras.h>
40f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include <wtf/text/StringHash.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF;
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectFontCache* fontCache()
47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return &globalFontCache;
50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectFontCache::FontCache()
53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
55635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
56ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochstruct FontPlatformDataCacheKey {
57ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    WTF_MAKE_FAST_ALLOCATED;
58ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochpublic:
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false,
602bde8e466a4451c7319e3a072d118917957d6554Steve Block                             bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal,
612bde8e466a4451c7319e3a072d118917957d6554Steve Block                             TextOrientation textOrientation = TextOrientationVerticalRight, FontWidthVariant widthVariant = RegularWidth)
626c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        : m_size(size)
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_weight(weight)
646c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        , m_family(family)
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_italic(italic)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_printerFont(isPrinterFont)
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_renderingMode(renderingMode)
68e14391e94c850b8bd03680c23b38978db68687a8John Reck        , m_orientation(orientation)
692bde8e466a4451c7319e3a072d118917957d6554Steve Block        , m_textOrientation(textOrientation)
702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        , m_widthVariant(widthVariant)
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDeletedSize()) { }
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize(); }
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool operator==(const FontPlatformDataCacheKey& other) const
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size &&
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project               m_weight == other.m_weight && m_italic == other.m_italic && m_printerFont == other.m_printerFont &&
812bde8e466a4451c7319e3a072d118917957d6554Steve Block               m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_textOrientation == other.m_textOrientation && m_widthVariant == other.m_widthVariant;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned m_size;
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned m_weight;
866c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    AtomicString m_family;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool m_italic;
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool m_printerFont;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontRenderingMode m_renderingMode;
90e14391e94c850b8bd03680c23b38978db68687a8John Reck    FontOrientation m_orientation;
912bde8e466a4451c7319e3a072d118917957d6554Steve Block    TextOrientation m_textOrientation;
922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FontWidthVariant m_widthVariant;
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectinline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unsigned hashCodes[5] = {
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CaseFoldingHash::hash(fontKey.m_family),
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fontKey.m_size,
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        fontKey.m_weight,
1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        fontKey.m_widthVariant,
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block        static_cast<unsigned>(fontKey.m_textOrientation) << 4 | static_cast<unsigned>(fontKey.m_orientation) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    };
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block    return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct FontPlatformDataCacheKeyHash {
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static unsigned hash(const FontPlatformDataCacheKey& font)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return computeHash(font);
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataCacheKey& b)
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return a == b;
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const bool safeToCompareToEmptyOrDeleted = true;
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstruct FontPlatformDataCacheKeyTraits : WTF::SimpleClassHashTraits<FontPlatformDataCacheKey> { };
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic FontPlatformDataCache* gFontPlatformDataCache = 0;
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const AtomicString& alternateFamilyName(const AtomicString& familyName)
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Alias Courier <-> Courier New
133635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, courier, ("Courier"));
134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, courierNew, ("Courier New"));
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(familyName, courier))
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return courierNew;
137d0825bca7fe65beaee391d30da42e937db621564Steve Block#if !OS(WINDOWS)
1388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // On Windows, Courier New (truetype font) is always present and
1398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Courier is a bitmap font. So, we don't want to map Courier New to
1408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Courier.
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(familyName, courierNew))
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return courier;
1438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Alias Times and Times New Roman.
146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, times, ("Times"));
147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, timesNewRoman, ("Times New Roman"));
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(familyName, times))
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return timesNewRoman;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(familyName, timesNewRoman))
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return times;
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Alias Arial and Helvetica
154635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, arial, ("Arial"));
155635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    DEFINE_STATIC_LOCAL(AtomicString, helvetica, ("Helvetica"));
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(familyName, arial))
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return helvetica;
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(familyName, helvetica))
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return arial;
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
161d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINDOWS)
1628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // On Windows, bitmap fonts are blocked altogether so that we have to
1638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // alias MS Sans Serif (bitmap font) -> Microsoft Sans Serif (truetype font)
1648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    DEFINE_STATIC_LOCAL(AtomicString, msSans, ("MS Sans Serif"));
1658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    DEFINE_STATIC_LOCAL(AtomicString, microsoftSans, ("Microsoft Sans Serif"));
1668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (equalIgnoringCase(familyName, msSans))
1678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return microsoftSans;
1688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Alias MS Serif (bitmap) -> Times New Roman (truetype font). There's no
1708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // 'Microsoft Sans Serif-equivalent' for Serif.
1718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    static AtomicString msSerif("MS Serif");
1728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (equalIgnoringCase(familyName, msSerif))
1738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return timesNewRoman;
1748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
1758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return emptyAtom;
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectFontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription,
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                       const AtomicString& familyName,
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                       bool checkingAlternateName)
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!gFontPlatformDataCache) {
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gFontPlatformDataCache = new FontPlatformDataCache;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        platformInit();
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(),
1892bde8e466a4451c7319e3a072d118917957d6554Steve Block                                 fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(),
1902bde8e466a4451c7319e3a072d118917957d6554Steve Block                                 fontDescription.textOrientation(), fontDescription.widthVariant());
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontPlatformData* result = 0;
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool foundResult;
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (it == gFontPlatformDataCache->end()) {
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = createFontPlatformData(fontDescription, familyName);
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gFontPlatformDataCache->set(key, result);
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        foundResult = result;
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = it->second;
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        foundResult = true;
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!foundResult && !checkingAlternateName) {
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We were unable to find a font.  We have a small set of fonts that we alias to other names,
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // e.g., Arial/Helvetica, Courier/Courier New, etc.  Try looking up the font under the aliased name.
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const AtomicString& alternateName = alternateFamilyName(familyName);
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!alternateName.isEmpty())
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            result = getCachedFontPlatformData(fontDescription, alternateName, true);
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (result)
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name.
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct FontDataCacheKeyHash {
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static unsigned hash(const FontPlatformData& platformData)
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return platformData.hash();
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static bool equal(const FontPlatformData& a, const FontPlatformData& b)
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return a == b;
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const bool safeToCompareToEmptyOrDeleted = true;
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const bool emptyValueIsZero = true;
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const bool needsDestruction = true;
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const FontPlatformData& emptyValue()
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        DEFINE_STATIC_LOCAL(FontPlatformData, key, (0.f, false, false));
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return key;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static void constructDeletedValue(FontPlatformData& slot)
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        new (&slot) FontPlatformData(HashTableDeletedValue);
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static bool isDeletedValue(const FontPlatformData& value)
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return value.isHashTableDeletedValue();
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic FontDataCache* gFontDataCache = 0;
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int cMaxInactiveFontData = 120;  // Pretty Low Threshold
25381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochconst int cTargetInactiveFontData = 100;
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic ListHashSet<const SimpleFontData*>* gInactiveFontData = 0;
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockSimpleFontData* FontCache::getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName)
2578a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block{
2588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, checkingAlternateName);
2598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!platformData)
2608a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return 0;
2618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
2628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return getCachedFontData(platformData);
2638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block}
2648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData)
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!platformData)
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!gFontDataCache) {
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gFontDataCache = new FontDataCache;
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gInactiveFontData = new ListHashSet<const SimpleFontData*>;
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontDataCache::iterator result = gFontDataCache->find(*platformData);
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result == gFontDataCache->end()) {
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformData), 1);
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gFontDataCache->set(*platformData, newValue);
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return newValue.first;
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!result.get()->second.second++) {
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(gInactiveFontData->contains(result.get()->second.first));
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gInactiveFontData->remove(result.get()->second.first);
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result.get()->second.first;
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid FontCache::releaseFontData(const SimpleFontData* fontData)
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(gFontDataCache);
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!fontData->isCustomFont());
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontDataCache::iterator it = gFontDataCache->find(fontData->platformData());
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(it != gFontDataCache->end());
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!--it->second.second) {
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gInactiveFontData->add(fontData);
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (gInactiveFontData->size() > cMaxInactiveFontData)
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            purgeInactiveFontData(gInactiveFontData->size() - cTargetInactiveFontData);
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid FontCache::purgeInactiveFontData(int count)
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!gInactiveFontData)
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static bool isPurging;  // Guard against reentry when e.g. a deleted FontData releases its small caps FontData.
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isPurging)
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    isPurging = true;
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Vector<const SimpleFontData*, 20> fontDataToDelete;
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end();
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin();
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = 0; i < count && it != end; ++it, ++i) {
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const SimpleFontData* fontData = *it.get();
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gFontDataCache->remove(fontData->platformData());
3215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        fontDataToDelete.append(fontData);
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (it == end) {
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Removed everything
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gInactiveFontData->clear();
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (int i = 0; i < count; ++i)
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gInactiveFontData->remove(gInactiveFontData->begin());
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    size_t fontDataToDeleteCount = fontDataToDelete.size();
3335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (size_t i = 0; i < fontDataToDeleteCount; ++i)
3345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        delete fontDataToDelete[i];
3355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (gFontPlatformDataCache) {
3370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        Vector<FontPlatformDataCacheKey> keysToRemove;
3380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        keysToRemove.reserveInitialCapacity(gFontPlatformDataCache->size());
3390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->end();
3400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        for (FontPlatformDataCache::iterator platformData = gFontPlatformDataCache->begin(); platformData != platformDataEnd; ++platformData) {
3410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (platformData->second && !gFontDataCache->contains(*platformData->second))
3420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                keysToRemove.append(platformData->first);
3430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
3440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        size_t keysToRemoveCount = keysToRemove.size();
3460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        for (size_t i = 0; i < keysToRemoveCount; ++i)
3470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            delete gFontPlatformDataCache->take(keysToRemove[i]);
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    isPurging = false;
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectsize_t FontCache::fontDataCount()
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (gFontDataCache)
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return gFontDataCache->size();
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectsize_t FontCache::inactiveFontDataCount()
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (gInactiveFontData)
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return gInactiveFontData->size();
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector)
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3698a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    SimpleFontData* result = 0;
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int startIndex = familyIndex;
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const FontFamily* startFamily = &font.fontDescription().family();
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = 0; startFamily && i < startIndex; i++)
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startFamily = startFamily->next();
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const FontFamily* currFamily = startFamily;
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (currFamily && !result) {
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        familyIndex++;
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (currFamily->family().length()) {
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (fontSelector) {
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                FontData* data = fontSelector->getFontData(font.fontDescription(), currFamily->family());
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (data)
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return data;
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
3848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            result = getCachedFontData(font.fontDescription(), currFamily->family());
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        currFamily = currFamily->next();
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!currFamily)
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        familyIndex = cAllFamiliesScanned;
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!result)
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform.
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Geeza Pro font.
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = getSimilarFontPlatformData(font);
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!result && startIndex == 0) {
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If it's the primary font that we couldn't find, we try the following. In all other cases, we will
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // just use per-character system fallback.
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (fontSelector) {
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Try the user's preferred standard font.
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (FontData* data = fontSelector->getFontData(font.fontDescription(), "-webkit-standard"))
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return data;
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Still no result.  Hand back our last resort fallback font.
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = getLastResortFallbackFont(font.fontDescription());
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    return result;
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic HashSet<FontSelector*>* gClients;
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid FontCache::addClient(FontSelector* client)
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!gClients)
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gClients = new HashSet<FontSelector*>;
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!gClients->contains(client));
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gClients->add(client);
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid FontCache::removeClient(FontSelector* client)
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(gClients);
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(gClients->contains(client));
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gClients->remove(client);
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic unsigned gGeneration = 0;
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunsigned FontCache::generation()
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return gGeneration;
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid FontCache::invalidate()
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!gClients) {
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(!gFontPlatformDataCache);
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (gFontPlatformDataCache) {
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        deleteAllValues(*gFontPlatformDataCache);
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete gFontPlatformDataCache;
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        gFontPlatformDataCache = new FontPlatformDataCache;
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gGeneration++;
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<RefPtr<FontSelector> > clients;
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    size_t numClients = gClients->size();
4578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    clients.reserveInitialCapacity(numClients);
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HashSet<FontSelector*>::iterator end = gClients->end();
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (HashSet<FontSelector*>::iterator it = gClients->begin(); it != end; ++it)
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        clients.append(*it);
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(numClients == clients.size());
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (size_t i = 0; i < numClients; ++i)
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        clients[i]->fontCacheInvalidated();
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    purgeInactiveFontData();
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
470