Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
      3  *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "core/css/CSSFontSelector.h"
     29 
     30 #include "core/css/CSSFontSelectorClient.h"
     31 #include "core/css/CSSSegmentedFontFace.h"
     32 #include "core/css/CSSValueList.h"
     33 #include "core/css/FontFaceSet.h"
     34 #include "core/css/resolver/StyleResolver.h"
     35 #include "core/dom/Document.h"
     36 #include "core/frame/LocalFrame.h"
     37 #include "core/frame/Settings.h"
     38 #include "core/loader/FrameLoader.h"
     39 #include "platform/RuntimeEnabledFeatures.h"
     40 #include "platform/fonts/FontCache.h"
     41 #include "platform/fonts/SimpleFontData.h"
     42 #include "wtf/text/AtomicString.h"
     43 
     44 namespace blink {
     45 
     46 CSSFontSelector::CSSFontSelector(Document* document)
     47     : m_document(document)
     48     , m_fontLoader(FontLoader::create(this, document->fetcher()))
     49     , m_genericFontFamilySettings(document->frame()->settings()->genericFontFamilySettings())
     50 {
     51     // FIXME: An old comment used to say there was no need to hold a reference to m_document
     52     // because "we are guaranteed to be destroyed before the document". But there does not
     53     // seem to be any such guarantee.
     54 
     55     ASSERT(m_document);
     56     ASSERT(m_document->frame());
     57     FontCache::fontCache()->addClient(this);
     58     FontFaceSet::from(*document)->addFontFacesToFontFaceCache(&m_fontFaceCache, this);
     59 }
     60 
     61 CSSFontSelector::~CSSFontSelector()
     62 {
     63 #if !ENABLE(OILPAN)
     64     clearDocument();
     65     FontCache::fontCache()->removeClient(this);
     66 #endif
     67 }
     68 
     69 void CSSFontSelector::registerForInvalidationCallbacks(CSSFontSelectorClient* client)
     70 {
     71     m_clients.add(client);
     72 }
     73 
     74 #if !ENABLE(OILPAN)
     75 void CSSFontSelector::unregisterForInvalidationCallbacks(CSSFontSelectorClient* client)
     76 {
     77     m_clients.remove(client);
     78 }
     79 #endif
     80 
     81 void CSSFontSelector::dispatchInvalidationCallbacks()
     82 {
     83     WillBeHeapVector<RawPtrWillBeMember<CSSFontSelectorClient> > clients;
     84     copyToVector(m_clients, clients);
     85     for (size_t i = 0; i < clients.size(); ++i)
     86         clients[i]->fontsNeedUpdate(this);
     87 }
     88 
     89 void CSSFontSelector::fontFaceInvalidated()
     90 {
     91     dispatchInvalidationCallbacks();
     92 }
     93 
     94 void CSSFontSelector::fontCacheInvalidated()
     95 {
     96     dispatchInvalidationCallbacks();
     97 }
     98 
     99 static AtomicString familyNameFromSettings(const GenericFontFamilySettings& settings, const FontDescription& fontDescription, const AtomicString& genericFamilyName)
    100 {
    101 #if OS(ANDROID)
    102     if (fontDescription.genericFamily() == FontDescription::StandardFamily)
    103         return FontCache::getGenericFamilyNameForScript(FontFamilyNames::webkit_standard, fontDescription);
    104 
    105     if (genericFamilyName.startsWith("-webkit-"))
    106         return FontCache::getGenericFamilyNameForScript(genericFamilyName, fontDescription);
    107 #else
    108     UScriptCode script = fontDescription.script();
    109     if (fontDescription.genericFamily() == FontDescription::StandardFamily)
    110         return settings.standard(script);
    111     if (genericFamilyName == FontFamilyNames::webkit_serif)
    112         return settings.serif(script);
    113     if (genericFamilyName == FontFamilyNames::webkit_sans_serif)
    114         return settings.sansSerif(script);
    115     if (genericFamilyName == FontFamilyNames::webkit_cursive)
    116         return settings.cursive(script);
    117     if (genericFamilyName == FontFamilyNames::webkit_fantasy)
    118         return settings.fantasy(script);
    119     if (genericFamilyName == FontFamilyNames::webkit_monospace)
    120         return settings.fixed(script);
    121     if (genericFamilyName == FontFamilyNames::webkit_pictograph)
    122         return settings.pictograph(script);
    123     if (genericFamilyName == FontFamilyNames::webkit_standard)
    124         return settings.standard(script);
    125 #endif
    126     return emptyAtom;
    127 }
    128 
    129 PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
    130 {
    131     if (CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, familyName))
    132         return face->getFontData(fontDescription);
    133 
    134     // Try to return the correct font based off our settings, in case we were handed the generic font family name.
    135     AtomicString settingsFamilyName = familyNameFromSettings(m_genericFontFamilySettings, fontDescription, familyName);
    136     if (settingsFamilyName.isEmpty())
    137         return nullptr;
    138 
    139     return FontCache::fontCache()->getFontData(fontDescription, settingsFamilyName);
    140 }
    141 
    142 void CSSFontSelector::willUseFontData(const FontDescription& fontDescription, const AtomicString& family, UChar32 character)
    143 {
    144     CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, family);
    145     if (face)
    146         face->willUseFontData(fontDescription, character);
    147 }
    148 
    149 bool CSSFontSelector::isPlatformFontAvailable(const FontDescription& fontDescription, const AtomicString& passedFamily)
    150 {
    151     AtomicString family = familyNameFromSettings(m_genericFontFamilySettings, fontDescription, passedFamily);
    152     if (family.isEmpty())
    153         family = passedFamily;
    154     return FontCache::fontCache()->isPlatformFontAvailable(fontDescription, family);
    155 }
    156 
    157 #if !ENABLE(OILPAN)
    158 void CSSFontSelector::clearDocument()
    159 {
    160     m_fontLoader->clearResourceFetcherAndFontSelector();
    161     m_document = nullptr;
    162     m_fontFaceCache.clearAll();
    163 }
    164 #endif
    165 
    166 void CSSFontSelector::updateGenericFontFamilySettings(Document& document)
    167 {
    168     if (!document.settings())
    169         return;
    170     m_genericFontFamilySettings = document.settings()->genericFontFamilySettings();
    171     // Need to increment FontFaceCache version to update RenderStyles.
    172     m_fontFaceCache.incrementVersion();
    173 }
    174 
    175 void CSSFontSelector::trace(Visitor* visitor)
    176 {
    177 #if ENABLE(OILPAN)
    178     visitor->trace(m_document);
    179     visitor->trace(m_fontFaceCache);
    180     visitor->trace(m_clients);
    181     visitor->trace(m_fontLoader);
    182 #endif
    183     FontSelector::trace(visitor);
    184 }
    185 
    186 }
    187