REGRESSION: svg/custom/use-instanceRoot-event-listeners.xhtml & svg/custom/pointer...
[WebKit-https.git] / Source / WebCore / 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 "CSSFontSelector.h"
29
30 #include "CachedFont.h"
31 #include "CSSFontFace.h"
32 #include "CSSFontFaceRule.h"
33 #include "CSSFontFaceSource.h"
34 #include "CSSFontFaceSrcValue.h"
35 #include "CSSMutableStyleDeclaration.h"
36 #include "CSSPrimitiveValue.h"
37 #include "CSSPropertyNames.h"
38 #include "CSSSegmentedFontFace.h"
39 #include "CSSStyleSelector.h"
40 #include "CSSUnicodeRangeValue.h"
41 #include "CSSValueKeywords.h"
42 #include "CSSValueList.h"
43 #include "CachedResourceLoader.h"
44 #include "Document.h"
45 #include "FontCache.h"
46 #include "FontFamilyValue.h"
47 #include "Frame.h"
48 #include "RenderObject.h"
49 #include "Settings.h"
50 #include "SimpleFontData.h"
51 #include "WebKitFontFamilyNames.h"
52 #include <wtf/text/AtomicString.h>
53
54 #if ENABLE(SVG)
55 #include "SVGFontFaceElement.h"
56 #include "SVGNames.h"
57 #endif
58
59 using namespace std;
60
61 namespace WebCore {
62
63 CSSFontSelector::CSSFontSelector(Document* document)
64     : m_document(document)
65     , m_beginLoadingTimer(this, &CSSFontSelector::beginLoadTimerFired)
66 {
67     // FIXME: An old comment used to say there was no need to hold a reference to m_document
68     // because "we are guaranteed to be destroyed before the document". But there does not
69     // seem to be any such guarantee.
70
71     ASSERT(m_document);
72     fontCache()->addClient(this);
73 }
74
75 CSSFontSelector::~CSSFontSelector()
76 {
77     clearDocument();
78     fontCache()->removeClient(this);
79 }
80
81 bool CSSFontSelector::isEmpty() const
82 {
83     return m_fonts.isEmpty();
84 }
85
86 void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule)
87 {
88     // Obtain the font-family property and the src property.  Both must be defined.
89     const CSSMutableStyleDeclaration* style = fontFaceRule->style();
90     RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSSPropertyFontFamily);
91     RefPtr<CSSValue> src = style->getPropertyCSSValue(CSSPropertySrc);
92     RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSSPropertyUnicodeRange);
93     if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || (unicodeRange && !unicodeRange->isValueList()))
94         return;
95
96     CSSValueList* familyList = static_cast<CSSValueList*>(fontFamily.get());
97     if (!familyList->length())
98         return;
99
100     CSSValueList* srcList = static_cast<CSSValueList*>(src.get());
101     if (!srcList->length())
102         return;
103
104     CSSValueList* rangeList = static_cast<CSSValueList*>(unicodeRange.get());
105
106     unsigned traitsMask = 0;
107
108     if (RefPtr<CSSValue> fontStyle = style->getPropertyCSSValue(CSSPropertyFontStyle)) {
109         if (fontStyle->isPrimitiveValue()) {
110             RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
111             list->append(fontStyle);
112             fontStyle = list;
113         } else if (!fontStyle->isValueList())
114             return;
115
116         CSSValueList* styleList = static_cast<CSSValueList*>(fontStyle.get());
117         unsigned numStyles = styleList->length();
118         if (!numStyles)
119             return;
120
121         for (unsigned i = 0; i < numStyles; ++i) {
122             switch (static_cast<CSSPrimitiveValue*>(styleList->itemWithoutBoundsCheck(i))->getIdent()) {
123                 case CSSValueAll:
124                     traitsMask |= FontStyleMask;
125                     break;
126                 case CSSValueNormal:
127                     traitsMask |= FontStyleNormalMask;
128                     break;
129                 case CSSValueItalic:
130                 case CSSValueOblique:
131                     traitsMask |= FontStyleItalicMask;
132                     break;
133                 default:
134                     break;
135             }
136         }
137     } else
138         traitsMask |= FontStyleMask;
139
140     if (RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight)) {
141         if (fontWeight->isPrimitiveValue()) {
142             RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
143             list->append(fontWeight);
144             fontWeight = list;
145         } else if (!fontWeight->isValueList())
146             return;
147
148         CSSValueList* weightList = static_cast<CSSValueList*>(fontWeight.get());
149         unsigned numWeights = weightList->length();
150         if (!numWeights)
151             return;
152
153         for (unsigned i = 0; i < numWeights; ++i) {
154             switch (static_cast<CSSPrimitiveValue*>(weightList->itemWithoutBoundsCheck(i))->getIdent()) {
155                 case CSSValueAll:
156                     traitsMask |= FontWeightMask;
157                     break;
158                 case CSSValueBolder:
159                 case CSSValueBold:
160                 case CSSValue700:
161                     traitsMask |= FontWeight700Mask;
162                     break;
163                 case CSSValueNormal:
164                 case CSSValue400:
165                     traitsMask |= FontWeight400Mask;
166                     break;
167                 case CSSValue900:
168                     traitsMask |= FontWeight900Mask;
169                     break;
170                 case CSSValue800:
171                     traitsMask |= FontWeight800Mask;
172                     break;
173                 case CSSValue600:
174                     traitsMask |= FontWeight600Mask;
175                     break;
176                 case CSSValue500:
177                     traitsMask |= FontWeight500Mask;
178                     break;
179                 case CSSValue300:
180                     traitsMask |= FontWeight300Mask;
181                     break;
182                 case CSSValueLighter:
183                 case CSSValue200:
184                     traitsMask |= FontWeight200Mask;
185                     break;
186                 case CSSValue100:
187                     traitsMask |= FontWeight100Mask;
188                     break;
189                 default:
190                     break;
191             }
192         }
193     } else
194         traitsMask |= FontWeightMask;
195
196     if (RefPtr<CSSValue> fontVariant = style->getPropertyCSSValue(CSSPropertyFontVariant)) {
197         if (fontVariant->isPrimitiveValue()) {
198             RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
199             list->append(fontVariant);
200             fontVariant = list;
201         } else if (!fontVariant->isValueList())
202             return;
203
204         CSSValueList* variantList = static_cast<CSSValueList*>(fontVariant.get());
205         unsigned numVariants = variantList->length();
206         if (!numVariants)
207             return;
208
209         for (unsigned i = 0; i < numVariants; ++i) {
210             switch (static_cast<CSSPrimitiveValue*>(variantList->itemWithoutBoundsCheck(i))->getIdent()) {
211                 case CSSValueAll:
212                     traitsMask |= FontVariantMask;
213                     break;
214                 case CSSValueNormal:
215                     traitsMask |= FontVariantNormalMask;
216                     break;
217                 case CSSValueSmallCaps:
218                     traitsMask |= FontVariantSmallCapsMask;
219                     break;
220                 default:
221                     break;
222             }
223         }
224     } else
225         traitsMask |= FontVariantMask;
226
227     // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace.
228     RefPtr<CSSFontFace> fontFace;
229
230     int srcLength = srcList->length();
231
232     bool foundSVGFont = false;
233
234     for (int i = 0; i < srcLength; i++) {
235         // An item in the list either specifies a string (local font name) or a URL (remote font to download).
236         CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->itemWithoutBoundsCheck(i));
237         OwnPtr<CSSFontFaceSource> source;
238
239 #if ENABLE(SVG_FONTS)
240         foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement();
241 #endif
242         if (!item->isLocal()) {
243             Settings* settings = m_document ? m_document->frame() ? m_document->frame()->settings() : 0 : 0;
244             bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled());
245             if (allowDownloading && item->isSupportedFormat() && m_document) {
246                 CachedFont* cachedFont = item->cachedFont(m_document);
247                 if (cachedFont) {
248                     source = adoptPtr(new CSSFontFaceSource(item->resource(), cachedFont));
249 #if ENABLE(SVG_FONTS)
250                     if (foundSVGFont)
251                         source->setHasExternalSVGFont(true);
252 #endif
253                 }
254             }
255         } else {
256             source = adoptPtr(new CSSFontFaceSource(item->resource()));
257         }
258
259         if (!fontFace)
260             fontFace = CSSFontFace::create(static_cast<FontTraitsMask>(traitsMask));
261
262         if (source) {
263 #if ENABLE(SVG_FONTS)
264             source->setSVGFontFaceElement(item->svgFontFaceElement());
265 #endif
266             fontFace->addSource(source.release());
267         }
268     }
269
270     ASSERT(fontFace);
271
272     if (fontFace && !fontFace->isValid())
273         return;
274
275     if (rangeList) {
276         unsigned numRanges = rangeList->length();
277         for (unsigned i = 0; i < numRanges; i++) {
278             CSSUnicodeRangeValue* range = static_cast<CSSUnicodeRangeValue*>(rangeList->itemWithoutBoundsCheck(i));
279             fontFace->addRange(range->from(), range->to());
280         }
281     }
282
283     // Hash under every single family name.
284     int familyLength = familyList->length();
285     for (int i = 0; i < familyLength; i++) {
286         CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->itemWithoutBoundsCheck(i));
287         String familyName;
288         if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING)
289             familyName = static_cast<FontFamilyValue*>(item)->familyName();
290         else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
291             // We need to use the raw text for all the generic family types, since @font-face is a way of actually
292             // defining what font to use for those types.
293             String familyName;
294             switch (item->getIdent()) {
295                 case CSSValueSerif:
296                     familyName = serifFamily;
297                     break;
298                 case CSSValueSansSerif:
299                     familyName = sansSerifFamily;
300                     break;
301                 case CSSValueCursive:
302                     familyName = cursiveFamily;
303                     break;
304                 case CSSValueFantasy:
305                     familyName = fantasyFamily;
306                     break;
307                 case CSSValueMonospace:
308                     familyName = monospaceFamily;
309                     break;
310                 case CSSValueWebkitPictograph:
311                     familyName = pictographFamily;
312                     break;
313                 default:
314                     break;
315             }
316         }
317
318         if (familyName.isEmpty())
319             continue;
320
321         OwnPtr<Vector<RefPtr<CSSFontFace> > >& familyFontFaces = m_fontFaces.add(familyName, nullptr).first->second;
322         if (!familyFontFaces) {
323             familyFontFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >);
324
325             ASSERT(!m_locallyInstalledFontFaces.contains(familyName));
326
327             Vector<unsigned> locallyInstalledFontsTraitsMasks;
328             fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks);
329             if (unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size()) {
330                 OwnPtr<Vector<RefPtr<CSSFontFace> > > familyLocallyInstalledFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >);
331
332                 for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) {
333                     RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]), true);
334                     locallyInstalledFontFace->addSource(adoptPtr(new CSSFontFaceSource(familyName)));
335                     ASSERT(locallyInstalledFontFace->isValid());
336                     familyLocallyInstalledFaces->append(locallyInstalledFontFace);
337                 }
338
339                 m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces.release());
340             }
341         }
342
343         familyFontFaces->append(fontFace);
344     }
345 }
346
347 void CSSFontSelector::registerForInvalidationCallbacks(FontSelectorClient* client)
348 {
349     m_clients.add(client);
350 }
351
352 void CSSFontSelector::unregisterForInvalidationCallbacks(FontSelectorClient* client)
353 {
354     m_clients.remove(client);
355 }
356
357 void CSSFontSelector::dispatchInvalidationCallbacks()
358 {
359     Vector<FontSelectorClient*> clients;
360     copyToVector(m_clients, clients);
361     for (size_t i = 0; i < clients.size(); ++i)
362         clients[i]->fontsNeedUpdate(this);
363
364     // FIXME: Make Document a FontSelectorClient so that it can simply register for invalidation callbacks.
365     if (!m_document)
366         return;
367     if (CSSStyleSelector* styleSelector = m_document->styleSelectorIfExists())
368         styleSelector->invalidateMatchedDeclarationCache();
369     if (m_document->inPageCache() || !m_document->renderer())
370         return;
371     m_document->scheduleForcedStyleRecalc();
372 }
373
374 void CSSFontSelector::fontLoaded()
375 {
376     dispatchInvalidationCallbacks();
377 }
378
379 void CSSFontSelector::fontCacheInvalidated()
380 {
381     dispatchInvalidationCallbacks();
382 }
383
384 static FontData* fontDataForGenericFamily(Document* document, const FontDescription& fontDescription, const AtomicString& familyName)
385 {
386     if (!document || !document->frame())
387         return 0;
388
389     const Settings* settings = document->frame()->settings();
390     if (!settings)
391         return 0;
392
393     AtomicString genericFamily;
394     UScriptCode script = fontDescription.script();
395
396     if (familyName == serifFamily)
397          genericFamily = settings->serifFontFamily(script);
398     else if (familyName == sansSerifFamily)
399          genericFamily = settings->sansSerifFontFamily(script);
400     else if (familyName == cursiveFamily)
401          genericFamily = settings->cursiveFontFamily(script);
402     else if (familyName == fantasyFamily)
403          genericFamily = settings->fantasyFontFamily(script);
404     else if (familyName == monospaceFamily)
405          genericFamily = settings->fixedFontFamily(script);
406     else if (familyName == pictographFamily)
407          genericFamily = settings->pictographFontFamily(script);
408     else if (familyName == standardFamily)
409          genericFamily = settings->standardFontFamily(script);
410
411     if (!genericFamily.isEmpty())
412         return fontCache()->getCachedFontData(fontDescription, genericFamily);
413
414     return 0;
415 }
416
417 static FontTraitsMask desiredTraitsMaskForComparison;
418
419 static inline bool compareFontFaces(CSSFontFace* first, CSSFontFace* second)
420 {
421     FontTraitsMask firstTraitsMask = first->traitsMask();
422     FontTraitsMask secondTraitsMask = second->traitsMask();
423
424     bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
425     bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
426
427     if (firstHasDesiredVariant != secondHasDesiredVariant)
428         return firstHasDesiredVariant;
429
430     if ((desiredTraitsMaskForComparison & FontVariantSmallCapsMask) && !first->isLocalFallback() && !second->isLocalFallback()) {
431         // Prefer a font that has indicated that it can only support small-caps to a font that claims to support
432         // all variants.  The specialized font is more likely to be true small-caps and not require synthesis.
433         bool firstRequiresSmallCaps = (firstTraitsMask & FontVariantSmallCapsMask) && !(firstTraitsMask & FontVariantNormalMask);
434         bool secondRequiresSmallCaps = (secondTraitsMask & FontVariantSmallCapsMask) && !(secondTraitsMask & FontVariantNormalMask);
435         if (firstRequiresSmallCaps != secondRequiresSmallCaps)
436             return firstRequiresSmallCaps;
437     }
438
439     bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
440     bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
441
442     if (firstHasDesiredStyle != secondHasDesiredStyle)
443         return firstHasDesiredStyle;
444
445     if ((desiredTraitsMaskForComparison & FontStyleItalicMask) && !first->isLocalFallback() && !second->isLocalFallback()) {
446         // Prefer a font that has indicated that it can only support italics to a font that claims to support
447         // all styles.  The specialized font is more likely to be the one the author wants used.
448         bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask);
449         bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask);
450         if (firstRequiresItalics != secondRequiresItalics)
451             return firstRequiresItalics;
452     }
453
454     if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
455         return false;
456     if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
457         return true;
458
459     // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#q46 says: "If there are fewer then 9 weights in the family, the default algorithm
460     // for filling the "holes" is as follows. If '500' is unassigned, it will be assigned the same font as '400'. If any of the values '600',
461     // '700', '800', or '900' remains unassigned, they are assigned to the same face as the next darker assigned keyword, if any, or the next
462     // lighter one otherwise. If any of '300', '200', or '100' remains unassigned, it is assigned to the next lighter assigned keyword, if any,
463     // or the next darker otherwise."
464     // For '400', we made up our own rule (which then '500' follows).
465
466     static const unsigned fallbackRuleSets = 9;
467     static const unsigned rulesPerSet = 8;
468     static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = {
469         { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
470         { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
471         { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
472         { FontWeight500Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask },
473         { FontWeight400Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask },
474         { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
475         { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
476         { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
477         { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }
478     };
479
480     unsigned ruleSetIndex = 0;
481     unsigned w = FontWeight100Bit;
482     while (!(desiredTraitsMaskForComparison & (1 << w))) {
483         w++;
484         ruleSetIndex++;
485     }
486
487     ASSERT(ruleSetIndex < fallbackRuleSets);
488     const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];
489     for (unsigned i = 0; i < rulesPerSet; ++i) {
490         if (secondTraitsMask & weightFallbackRule[i])
491             return false;
492         if (firstTraitsMask & weightFallbackRule[i])
493             return true;
494     }
495
496     return false;
497 }
498
499 FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
500 {
501     if (m_fontFaces.isEmpty()) {
502         if (familyName.startsWith("-webkit-"))
503             return fontDataForGenericFamily(m_document, fontDescription, familyName);
504         if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
505             return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard");
506         return 0;
507     }
508
509     String family = familyName.string();
510
511     Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family);
512     // If no face was found, then return 0 and let the OS come up with its best match for the name.
513     if (!familyFontFaces || familyFontFaces->isEmpty()) {
514         // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our
515         // settings.
516         if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
517             return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard");
518         return fontDataForGenericFamily(m_document, fontDescription, familyName);
519     }
520
521     OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFaceCache = m_fonts.add(family, nullptr).first->second;
522     if (!segmentedFontFaceCache)
523         segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >);
524
525     FontTraitsMask traitsMask = fontDescription.traitsMask();
526
527     RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).first->second;
528     if (!face) {
529         face = CSSSegmentedFontFace::create(this);
530
531         // Collect all matching faces and sort them in order of preference.
532         Vector<CSSFontFace*, 32> candidateFontFaces;
533         for (int i = familyFontFaces->size() - 1; i >= 0; --i) {
534             CSSFontFace* candidate = familyFontFaces->at(i).get();
535             unsigned candidateTraitsMask = candidate->traitsMask();
536             if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
537                 continue;
538             if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
539                 continue;
540 #if ENABLE(SVG_FONTS)
541             // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable
542             // of small-caps synthesis and just ignore the font face as a candidate.
543             if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask))
544                 continue;
545 #endif
546             candidateFontFaces.append(candidate);
547         }
548
549         if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
550             unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
551             for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
552                 CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
553                 unsigned candidateTraitsMask = candidate->traitsMask();
554                 if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
555                     continue;
556                 if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
557                     continue;
558                 candidateFontFaces.append(candidate);
559             }
560         }
561
562         desiredTraitsMaskForComparison = traitsMask;
563         stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces);
564         unsigned numCandidates = candidateFontFaces.size();
565         for (unsigned i = 0; i < numCandidates; ++i)
566             face->appendFontFace(candidateFontFaces[i]);
567     }
568
569     // We have a face.  Ask it for a font data.  If it cannot produce one, it will fail, and the OS will take over.
570     return face->getFontData(fontDescription);
571 }
572
573 void CSSFontSelector::clearDocument()
574 {
575     if (!m_document) {
576         ASSERT(!m_beginLoadingTimer.isActive());
577         ASSERT(m_fontsToBeginLoading.isEmpty());
578         return;
579     }
580
581     m_beginLoadingTimer.stop();
582
583     CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
584     for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) {
585         // Balances incrementRequestCount() in beginLoadingFontSoon().
586         cachedResourceLoader->decrementRequestCount(m_fontsToBeginLoading[i].get());
587     }
588
589     m_fontsToBeginLoading.clear();
590
591     m_document = 0;
592 }
593
594 void CSSFontSelector::beginLoadingFontSoon(CachedFont* font)
595 {
596     if (!m_document)
597         return;
598
599     m_fontsToBeginLoading.append(font);
600     // Increment the request count now, in order to prevent didFinishLoad from being dispatched
601     // after this font has been requested but before it began loading. Balanced by
602     // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().
603     m_document->cachedResourceLoader()->incrementRequestCount(font);
604     m_beginLoadingTimer.startOneShot(0);
605 }
606
607 void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*)
608 {
609     Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading;
610     fontsToBeginLoading.swap(m_fontsToBeginLoading);
611
612     CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
613     for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
614         fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader);
615         // Balances incrementRequestCount() in beginLoadingFontSoon().
616         cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get());
617     }
618     // Ensure that if the request count reaches zero, the frame loader will know about it.
619     cachedResourceLoader->loadDone();
620 }
621
622 }