~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/css/CSSFontSelector.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

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