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