Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / CSSFontSelector.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
3  *           (C) 2007, 2008 Nikolas Zimmermann <zimmermann@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 "RuntimeEnabledFeatures.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/fetch/FontResource.h"
37 #include "core/fetch/ResourceFetcher.h"
38 #include "core/loader/FrameLoader.h"
39 #include "core/frame/Frame.h"
40 #include "core/frame/Settings.h"
41 #include "platform/fonts/FontCache.h"
42 #include "platform/fonts/SimpleFontData.h"
43 #include "wtf/text/AtomicString.h"
44
45 using namespace std;
46
47 namespace WebCore {
48
49 FontLoader::FontLoader(ResourceFetcher* resourceFetcher)
50     : m_beginLoadingTimer(this, &FontLoader::beginLoadTimerFired)
51     , m_resourceFetcher(resourceFetcher)
52 {
53 }
54
55 void FontLoader::addFontToBeginLoading(FontResource* fontResource)
56 {
57     if (!m_resourceFetcher || !fontResource->stillNeedsLoad())
58         return;
59
60     m_fontsToBeginLoading.append(fontResource);
61     // FIXME: Use RequestCountTracker??!!
62     // Increment the request count now, in order to prevent didFinishLoad from being dispatched
63     // after this font has been requested but before it began loading. Balanced by
64     // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().
65     m_resourceFetcher->incrementRequestCount(fontResource);
66     m_beginLoadingTimer.startOneShot(0);
67 }
68
69 void FontLoader::beginLoadTimerFired(Timer<WebCore::FontLoader>*)
70 {
71     loadPendingFonts();
72 }
73
74 void FontLoader::loadPendingFonts()
75 {
76     ASSERT(m_resourceFetcher);
77
78     Vector<ResourcePtr<FontResource> > fontsToBeginLoading;
79     fontsToBeginLoading.swap(m_fontsToBeginLoading);
80
81     for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
82         fontsToBeginLoading[i]->beginLoadIfNeeded(m_resourceFetcher);
83         // Balances incrementRequestCount() in beginLoadingFontSoon().
84         m_resourceFetcher->decrementRequestCount(fontsToBeginLoading[i].get());
85     }
86 }
87
88 void FontLoader::clearResourceFetcher()
89 {
90     if (!m_resourceFetcher) {
91         ASSERT(m_fontsToBeginLoading.isEmpty());
92         return;
93     }
94
95     m_beginLoadingTimer.stop();
96
97     for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) {
98         // Balances incrementRequestCount() in beginLoadingFontSoon().
99         m_resourceFetcher->decrementRequestCount(m_fontsToBeginLoading[i].get());
100     }
101
102     m_fontsToBeginLoading.clear();
103     m_resourceFetcher = 0;
104 }
105
106 CSSFontSelector::CSSFontSelector(Document* document)
107     : m_document(document)
108     , m_fontLoader(document->fetcher())
109     , m_genericFontFamilySettings(document->frame()->settings()->genericFontFamilySettings())
110 {
111     // FIXME: An old comment used to say there was no need to hold a reference to m_document
112     // because "we are guaranteed to be destroyed before the document". But there does not
113     // seem to be any such guarantee.
114
115     ASSERT(m_document);
116     ASSERT(m_document->frame());
117     FontCache::fontCache()->addClient(this);
118     FontFaceSet::from(document)->addFontFacesToFontFaceCache(&m_fontFaceCache, this);
119 }
120
121 CSSFontSelector::~CSSFontSelector()
122 {
123     clearDocument();
124     FontCache::fontCache()->removeClient(this);
125 }
126
127 void CSSFontSelector::registerForInvalidationCallbacks(CSSFontSelectorClient* client)
128 {
129     m_clients.add(client);
130 }
131
132 void CSSFontSelector::unregisterForInvalidationCallbacks(CSSFontSelectorClient* client)
133 {
134     m_clients.remove(client);
135 }
136
137 void CSSFontSelector::dispatchInvalidationCallbacks()
138 {
139     Vector<CSSFontSelectorClient*> clients;
140     copyToVector(m_clients, clients);
141     for (size_t i = 0; i < clients.size(); ++i)
142         clients[i]->fontsNeedUpdate(this);
143 }
144
145 void CSSFontSelector::fontLoaded()
146 {
147     dispatchInvalidationCallbacks();
148 }
149
150 void CSSFontSelector::fontCacheInvalidated()
151 {
152     dispatchInvalidationCallbacks();
153 }
154
155 static AtomicString familyNameFromSettings(const GenericFontFamilySettings& settings, const FontDescription& fontDescription, const AtomicString& genericFamilyName)
156 {
157     UScriptCode script = fontDescription.script();
158
159     if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
160         return settings.standard(script);
161
162 #if OS(ANDROID)
163     return FontCache::getGenericFamilyNameForScript(genericFamilyName, script);
164 #else
165     if (genericFamilyName == FontFamilyNames::webkit_serif)
166         return settings.serif(script);
167     if (genericFamilyName == FontFamilyNames::webkit_sans_serif)
168         return settings.sansSerif(script);
169     if (genericFamilyName == FontFamilyNames::webkit_cursive)
170         return settings.cursive(script);
171     if (genericFamilyName == FontFamilyNames::webkit_fantasy)
172         return settings.fantasy(script);
173     if (genericFamilyName == FontFamilyNames::webkit_monospace)
174         return settings.fixed(script);
175     if (genericFamilyName == FontFamilyNames::webkit_pictograph)
176         return settings.pictograph(script);
177     if (genericFamilyName == FontFamilyNames::webkit_standard)
178         return settings.standard(script);
179 #endif
180     return emptyAtom;
181 }
182
183 PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
184 {
185     if (CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, familyName))
186         return face->getFontData(fontDescription);
187
188     // Try to return the correct font based off our settings, in case we were handed the generic font family name.
189     AtomicString settingsFamilyName = familyNameFromSettings(m_genericFontFamilySettings, fontDescription, familyName);
190     if (settingsFamilyName.isEmpty())
191         return 0;
192
193     return FontCache::fontCache()->getFontData(fontDescription, settingsFamilyName);
194 }
195
196 void CSSFontSelector::willUseFontData(const FontDescription& fontDescription, const AtomicString& family)
197 {
198     CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, family);
199     if (face)
200         face->willUseFontData(fontDescription);
201 }
202
203 void CSSFontSelector::clearDocument()
204 {
205     m_fontLoader.clearResourceFetcher();
206     m_document = 0;
207 }
208
209 void CSSFontSelector::beginLoadingFontSoon(FontResource* font)
210 {
211     m_fontLoader.addFontToBeginLoading(font);
212 }
213
214 void CSSFontSelector::loadPendingFonts()
215 {
216     m_fontLoader.loadPendingFonts();
217 }
218
219 void CSSFontSelector::updateGenericFontFamilySettings(Document& document)
220 {
221     ASSERT(document.settings());
222     m_genericFontFamilySettings = document.settings()->genericFontFamilySettings();
223 }
224
225 }