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