Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: webkit/pending/FontCache.cpp

Issue 6500: Cleaning up the unfork (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/pending/FontCache.h ('k') | webkit/pending/FontDescription.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
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 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "config.h"
31 #include "FontCache.h"
32
33 #include "Font.h"
34 #include "FontFallbackList.h"
35 #include "FontPlatformData.h"
36 #include "FontSelector.h"
37 #include "StringHash.h"
38 #include <wtf/HashMap.h>
39 #include <wtf/ListHashSet.h>
40
41 using namespace WTF;
42
43 namespace WebCore {
44
45 struct FontPlatformDataCacheKey {
46 FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsign ed size = 0, unsigned weight = 0, bool italic = false,
47 bool isPrinterFont = false, FontRenderingMode rende ringMode = NormalRenderingMode)
48 : m_family(family)
49 , m_size(size)
50 , m_weight(weight)
51 , m_italic(italic)
52 , m_printerFont(isPrinterFont)
53 , m_renderingMode(renderingMode)
54 {
55 }
56
57 FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDelete dSize()) { }
58 bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize (); }
59
60 bool operator==(const FontPlatformDataCacheKey& other) const
61 {
62 return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_ size &&
63 m_weight == other.m_weight && m_italic == other.m_italic && m_pri nterFont == other.m_printerFont &&
64 m_renderingMode == other.m_renderingMode;
65 }
66
67 AtomicString m_family;
68 unsigned m_size;
69 unsigned m_weight;
70 bool m_italic;
71 bool m_printerFont;
72 FontRenderingMode m_renderingMode;
73
74 private:
75 static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
76 };
77
78 inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
79 {
80 unsigned hashCodes[4] = {
81 CaseFoldingHash::hash(fontKey.m_family),
82 fontKey.m_size,
83 fontKey.m_weight,
84 static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fon tKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
85 };
86 return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(h ashCodes) / sizeof(UChar));
87 }
88
89 struct FontPlatformDataCacheKeyHash {
90 static unsigned hash(const FontPlatformDataCacheKey& font)
91 {
92 return computeHash(font);
93 }
94
95 static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataC acheKey& b)
96 {
97 return a == b;
98 }
99
100 static const bool safeToCompareToEmptyOrDeleted = true;
101 };
102
103 struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataC acheKey> {
104 static const bool emptyValueIsZero = true;
105 static const FontPlatformDataCacheKey& emptyValue()
106 {
107 static FontPlatformDataCacheKey key(nullAtom);
108 return key;
109 }
110 static void constructDeletedValue(FontPlatformDataCacheKey& slot)
111 {
112 new (&slot) FontPlatformDataCacheKey(HashTableDeletedValue);
113 }
114 static bool isDeletedValue(const FontPlatformDataCacheKey& value)
115 {
116 return value.isHashTableDeletedValue();
117 }
118 };
119
120 typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCac heKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
121
122 static FontPlatformDataCache* gFontPlatformDataCache = 0;
123
124 FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo ntDescription,
125 const AtomicString& famil yName,
126 bool checkingAlternateNam e)
127 {
128 if (!gFontPlatformDataCache) {
129 gFontPlatformDataCache = new FontPlatformDataCache;
130 platformInit();
131 }
132
133 FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize() , fontDescription.weight(), fontDescription.italic(),
134 fontDescription.usePrinterFont(), fontDescripti on.renderingMode());
135 FontPlatformData* result = 0;
136 bool foundResult;
137 FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
138 if (it == gFontPlatformDataCache->end()) {
139 result = createFontPlatformData(fontDescription, familyName);
140 gFontPlatformDataCache->set(key, result);
141 foundResult = result;
142 } else {
143 result = it->second;
144 foundResult = true;
145 }
146
147 if (!foundResult && !checkingAlternateName) {
148 // We were unable to find a font. We have a small set of fonts that we alias to other names,
149 // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name.
150 const AtomicString& alternateName = alternateFamilyName(familyName);
151 if (!alternateName.isEmpty())
152 result = getCachedFontPlatformData(fontDescription, alternateName, t rue);
153 if (result)
154 gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name.
155 }
156
157 return result;
158 }
159
160 struct FontDataCacheKeyHash {
161 static unsigned hash(const FontPlatformData& platformData)
162 {
163 return platformData.hash();
164 }
165
166 static bool equal(const FontPlatformData& a, const FontPlatformData& b)
167 {
168 return a == b;
169 }
170
171 static const bool safeToCompareToEmptyOrDeleted = true;
172 };
173
174 struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
175 static const bool emptyValueIsZero = true;
176 static const bool needsDestruction = true;
177 static const FontPlatformData& emptyValue()
178 {
179 static FontPlatformData key;
180 return key;
181 }
182 static void constructDeletedValue(FontPlatformData& slot)
183 {
184 new (&slot) FontPlatformData(HashTableDeletedValue);
185 }
186 static bool isDeletedValue(const FontPlatformData& value)
187 {
188 return value.isHashTableDeletedValue();
189 }
190 };
191
192 typedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCache KeyHash, FontDataCacheKeyTraits> FontDataCache;
193
194 static FontDataCache* gFontDataCache = 0;
195
196 const int cMaxInactiveFontData = 120; // Pretty Low Threshold
197 const float cTargetInactiveFontData = 100;
198 static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0;
199
200 SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformDat a)
201 {
202 if (!platformData)
203 return 0;
204
205 if (!gFontDataCache) {
206 gFontDataCache = new FontDataCache;
207 gInactiveFontData = new ListHashSet<const SimpleFontData*>;
208 }
209
210 FontDataCache::iterator result = gFontDataCache->find(*platformData);
211 if (result == gFontDataCache->end()) {
212 pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformDat a), 1);
213 gFontDataCache->set(*platformData, newValue);
214 return newValue.first;
215 }
216 if (!result.get()->second.second++) {
217 ASSERT(gInactiveFontData->contains(result.get()->second.first));
218 gInactiveFontData->remove(result.get()->second.first);
219 }
220
221 return result.get()->second.first;
222 }
223
224 void FontCache::releaseFontData(const SimpleFontData* fontData)
225 {
226 ASSERT(gFontDataCache);
227 ASSERT(!fontData->isCustomFont());
228
229 FontDataCache::iterator it = gFontDataCache->find(fontData->platformData());
230 ASSERT(it != gFontDataCache->end());
231
232 if (!--it->second.second) {
233 gInactiveFontData->add(fontData);
234 if (gInactiveFontData->size() > cMaxInactiveFontData)
235 purgeInactiveFontData(gInactiveFontData->size() - cTargetInactiveFon tData);
236 }
237 }
238
239 void FontCache::purgeInactiveFontData(int count)
240 {
241 if (!gInactiveFontData)
242 return;
243
244 static bool isPurging; // Guard against reentry when e.g. a deleted FontDat a releases its small caps FontData.
245 if (isPurging)
246 return;
247
248 isPurging = true;
249
250 ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end();
251 ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin() ;
252 for (int i = 0; i < count && it != end; ++it, ++i) {
253 const SimpleFontData* fontData = *it.get();
254 gFontDataCache->remove(fontData->platformData());
255 delete fontData;
256 }
257
258 if (it == end) {
259 // Removed everything
260 gInactiveFontData->clear();
261 } else {
262 for (int i = 0; i < count; ++i)
263 gInactiveFontData->remove(gInactiveFontData->begin());
264 }
265
266 Vector<FontPlatformDataCacheKey> keysToRemove;
267 keysToRemove.reserveCapacity(gFontPlatformDataCache->size());
268 FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->en d();
269 for (FontPlatformDataCache::iterator platformData = gFontPlatformDataCache-> begin(); platformData != platformDataEnd; ++platformData) {
270 if (platformData->second && !gFontDataCache->contains(*platformData->sec ond))
271 keysToRemove.append(platformData->first);
272 }
273
274 size_t keysToRemoveCount = keysToRemove.size();
275 for (size_t i = 0; i < keysToRemoveCount; ++i)
276 delete gFontPlatformDataCache->take(keysToRemove[i]);
277
278 isPurging = false;
279 }
280
281 size_t FontCache::fontDataCount()
282 {
283 if (gFontDataCache)
284 return gFontDataCache->size();
285 return 0;
286 }
287
288 size_t FontCache::inactiveFontDataCount()
289 {
290 if (gInactiveFontData)
291 return gInactiveFontData->size();
292 return 0;
293 }
294
295 const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontS elector* fontSelector)
296 {
297 FontPlatformData* result = 0;
298
299 int startIndex = familyIndex;
300 const FontFamily* startFamily = &font.fontDescription().family();
301 for (int i = 0; startFamily && i < startIndex; i++)
302 startFamily = startFamily->next();
303 const FontFamily* currFamily = startFamily;
304 while (currFamily && !result) {
305 familyIndex++;
306 if (currFamily->family().length()) {
307 if (fontSelector) {
308 FontData* data = fontSelector->getFontData(font.fontDescription( ), currFamily->family());
309 if (data)
310 return data;
311 }
312 result = getCachedFontPlatformData(font.fontDescription(), currFamil y->family());
313 }
314 currFamily = currFamily->next();
315 }
316
317 if (!currFamily)
318 familyIndex = cAllFamiliesScanned;
319
320 if (!result)
321 // We didn't find a font. Try to find a similar font using our own speci fic knowledge about our platform.
322 // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the
323 // Geeza Pro font.
324 result = getSimilarFontPlatformData(font);
325
326 if (!result && startIndex == 0) {
327 // If it's the primary font that we couldn't find, we try the following. In all other cases, we will
328 // just use per-character system fallback.
329
330 if (fontSelector) {
331 // Try the user's preferred standard font.
332 if (FontData* data = fontSelector->getFontData(font.fontDescription( ), "-webkit-standard"))
333 return data;
334 }
335
336 // Still no result. Hand back our last resort fallback font.
337 result = getLastResortFallbackFont(font.fontDescription());
338 }
339
340 // Now that we have a result, we need to go from FontPlatformData -> FontDat a.
341 return getCachedFontData(result);
342 }
343
344 static HashSet<FontSelector*>* gClients;
345
346 void FontCache::addClient(FontSelector* client)
347 {
348 if (!gClients)
349 gClients = new HashSet<FontSelector*>;
350
351 ASSERT(!gClients->contains(client));
352 gClients->add(client);
353 }
354
355 void FontCache::removeClient(FontSelector* client)
356 {
357 ASSERT(gClients);
358 ASSERT(gClients->contains(client));
359
360 gClients->remove(client);
361 }
362
363 static unsigned gGeneration = 0;
364
365 unsigned FontCache::generation()
366 {
367 return gGeneration;
368 }
369
370 void FontCache::invalidate()
371 {
372 if (!gClients) {
373 ASSERT(!gFontPlatformDataCache);
374 return;
375 }
376
377 if (gFontPlatformDataCache) {
378 deleteAllValues(*gFontPlatformDataCache);
379 delete gFontPlatformDataCache;
380 gFontPlatformDataCache = new FontPlatformDataCache;
381 }
382
383 gGeneration++;
384
385 Vector<RefPtr<FontSelector> > clients;
386 size_t numClients = gClients->size();
387 clients.reserveCapacity(numClients);
388 HashSet<FontSelector*>::iterator end = gClients->end();
389 for (HashSet<FontSelector*>::iterator it = gClients->begin(); it != end; ++i t)
390 clients.append(*it);
391
392 ASSERT(numClients == clients.size());
393 for (size_t i = 0; i < numClients; ++i)
394 clients[i]->fontCacheInvalidated();
395
396 purgeInactiveFontData();
397 }
398
399 } // namespace WebCore
OLDNEW
« no previous file with comments | « webkit/pending/FontCache.h ('k') | webkit/pending/FontDescription.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698