Esempio n. 1
0
void FontFaceSet::faceFinished(CSSFontFace& face, CSSFontFace::Status newStatus)
{
    if (!face.existingWrapper())
        return;

    auto iterator = m_pendingPromises.find(face.existingWrapper());
    if (iterator == m_pendingPromises.end())
        return;

    for (auto& pendingPromise : iterator->value) {
        if (pendingPromise->hasReachedTerminalState)
            continue;
        if (newStatus == CSSFontFace::Status::Success) {
            if (pendingPromise->hasOneRef()) {
                pendingPromise->promise.resolve(pendingPromise->faces);
                pendingPromise->hasReachedTerminalState = true;
            }
        } else {
            ASSERT(newStatus == CSSFontFace::Status::Failure);
            pendingPromise->promise.reject(NETWORK_ERR);
            pendingPromise->hasReachedTerminalState = true;
        }
    }

    m_pendingPromises.remove(iterator);
}
Esempio n. 2
0
static bool fontFaceComparator(FontTraitsMask desiredTraitsMaskForComparison, const CSSFontFace& first, const CSSFontFace& second)
{
    FontTraitsMask firstTraitsMask = first.traitsMask();
    FontTraitsMask secondTraitsMask = second.traitsMask();

    bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
    bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;

    if (firstHasDesiredStyle != secondHasDesiredStyle)
        return firstHasDesiredStyle;

    if ((desiredTraitsMaskForComparison & FontStyleItalicMask) && !first.isLocalFallback() && !second.isLocalFallback()) {
        // Prefer a font that has indicated that it can only support italics to a font that claims to support
        // all styles. The specialized font is more likely to be the one the author wants used.
        bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask);
        bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask);
        if (firstRequiresItalics != secondRequiresItalics)
            return firstRequiresItalics;
    }

    if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
        return false;
    if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
        return true;

    // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says :
    //   - 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.
    //   - 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.
    //   - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used.
    //   - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used.

    static const unsigned fallbackRuleSets = 9;
    static const unsigned rulesPerSet = 8;
    static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = {
        { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight500Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
        { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
        { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
        { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }
    };

    unsigned ruleSetIndex = 0;
    for (; !(desiredTraitsMaskForComparison & (1 << (FontWeight100Bit + ruleSetIndex))); ruleSetIndex++) { }

    const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];
    for (unsigned i = 0; i < rulesPerSet; ++i) {
        if (secondTraitsMask & weightFallbackRule[i])
            return false;
        if (firstTraitsMask & weightFallbackRule[i])
            return true;
    }

    return false;
}
CSSSegmentedFontFace* CSSFontSelector::getFontFace(const FontDescription& fontDescription, const AtomicString& family)
{
    Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family);
    if (!familyFontFaces || familyFontFaces->isEmpty())
        return 0;

    OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFaceCache = m_fonts.add(family, nullptr).iterator->value;
    if (!segmentedFontFaceCache)
        segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >);

    FontTraitsMask traitsMask = fontDescription.traitsMask();

    RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).iterator->value;
    if (!face) {
        face = CSSSegmentedFontFace::create(this);

        // Collect all matching faces and sort them in order of preference.
        Vector<CSSFontFace*, 32> candidateFontFaces;
        for (int i = familyFontFaces->size() - 1; i >= 0; --i) {
            CSSFontFace* candidate = familyFontFaces->at(i).get();
            unsigned candidateTraitsMask = candidate->traitsMask();
            if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                continue;
            if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                continue;
#if ENABLE(SVG_FONTS)
            // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable
            // of small-caps synthesis and just ignore the font face as a candidate.
            if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask))
                continue;
#endif
            candidateFontFaces.append(candidate);
        }

        if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
            unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
            for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
                CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
                unsigned candidateTraitsMask = candidate->traitsMask();
                if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                    continue;
                if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                    continue;
                candidateFontFaces.append(candidate);
            }
        }

        desiredTraitsMaskForComparison = traitsMask;
        stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces);
        unsigned numCandidates = candidateFontFaces.size();
        for (unsigned i = 0; i < numCandidates; ++i)
            face->appendFontFace(candidateFontFaces[i]);
    }
    return face.get();
}
void CSSSegmentedFontFace::willUseRange(const blink::FontDescription& fontDescription, const blink::FontDataForRangeSet& rangeSet)
{
    // Iterating backwards since later defined unicode-range faces override
    // previously defined ones, according to the CSS3 fonts module.
    // https://drafts.csswg.org/css-fonts/#composite-fonts
    for (FontFaceList::reverse_iterator it = m_fontFaces.rbegin(); it != m_fontFaces.rend(); ++it) {
        CSSFontFace* cssFontFace = (*it)->cssFontFace();
        if (cssFontFace->maybeScheduleFontLoad(fontDescription, rangeSet))
            break;
    }
}
Esempio n. 5
0
void FontFace::adopt(CSSFontFace& newFace)
{
    m_backing->removeClient(*this);
    m_backing = newFace;
    m_backing->addClient(*this);
    newFace.setWrapper(*this);
}
Esempio n. 6
0
void CSSFontFaceSet::add(CSSFontFace& face)
{
    ASSERT(!hasFace(face));

    for (auto* client : m_clients)
        client->fontModified();

    face.addClient(*this);
    m_cache.clear();

    if (face.cssConnection())
        m_faces.insert(m_facesPartitionIndex++, face);
    else
        m_faces.append(face);

    addToFacesLookupTable(face);

    if (face.status() == CSSFontFace::Status::Loading || face.status() == CSSFontFace::Status::TimedOut)
        incrementActiveCount();
}
Esempio n. 7
0
void CSSFontFaceSet::addToFacesLookupTable(CSSFontFace& face)
{
    if (!face.families())
        return;

    for (auto& item : *face.families()) {
        String familyName = CSSFontFaceSet::familyNameFromPrimitive(downcast<CSSPrimitiveValue>(item.get()));
        if (familyName.isEmpty())
            continue;

        auto addResult = m_facesLookupTable.add(familyName, Vector<Ref<CSSFontFace>>());
        auto& familyFontFaces = addResult.iterator->value;
        if (addResult.isNewEntry) {
            // m_locallyInstalledFontFaces grows without bound, eventually encorporating every font installed on the system.
            // This is by design.
            registerLocalFontFacesForFamily(familyName);
            familyFontFaces = { };
        }

        familyFontFaces.append(face);
    }
}
Esempio n. 8
0
void CSSFontFaceSet::remove(const CSSFontFace& face)
{
    m_cache.clear();

    for (auto* client : m_clients)
        client->fontModified();

    if (face.families())
        removeFromFacesLookupTable(face, *face.families());

    for (size_t i = 0; i < m_faces.size(); ++i) {
        if (m_faces[i].ptr() == &face) {
            if (i < m_facesPartitionIndex)
                --m_facesPartitionIndex;
            m_faces[i]->removeClient(*this);
            m_faces.remove(i);
            if (face.status() == CSSFontFace::Status::Loading || face.status() == CSSFontFace::Status::TimedOut)
                decrementActiveCount();
            return;
        }
    }
    ASSERT_NOT_REACHED();
}
Esempio n. 9
0
FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
{
    if (m_fontFaces.isEmpty()) {
        if (familyName.startsWith("-webkit-"))
            return fontDataForGenericFamily(m_document, fontDescription, familyName);
        if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
            return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard");
        return 0;
    }

    String family = familyName.string();

    Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family);
    // If no face was found, then return 0 and let the OS come up with its best match for the name.
    if (!familyFontFaces || familyFontFaces->isEmpty()) {
        // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our
        // settings.
        if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
            return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard");
        return fontDataForGenericFamily(m_document, fontDescription, familyName);
    }

    OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFaceCache = m_fonts.add(family, nullptr).first->second;
    if (!segmentedFontFaceCache)
        segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >);

    FontTraitsMask traitsMask = fontDescription.traitsMask();

    RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).first->second;
    if (!face) {
        face = CSSSegmentedFontFace::create(this);

        // Collect all matching faces and sort them in order of preference.
        Vector<CSSFontFace*, 32> candidateFontFaces;
        for (int i = familyFontFaces->size() - 1; i >= 0; --i) {
            CSSFontFace* candidate = familyFontFaces->at(i).get();
            unsigned candidateTraitsMask = candidate->traitsMask();
            if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                continue;
            if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                continue;
#if ENABLE(SVG_FONTS)
            // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable
            // of small-caps synthesis and just ignore the font face as a candidate.
            if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask))
                continue;
#endif
            candidateFontFaces.append(candidate);
        }

        if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
            unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
            for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
                CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
                unsigned candidateTraitsMask = candidate->traitsMask();
                if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                    continue;
                if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                    continue;
                candidateFontFaces.append(candidate);
            }
        }

        desiredTraitsMaskForComparison = traitsMask;
        stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces);
        unsigned numCandidates = candidateFontFaces.size();
        for (unsigned i = 0; i < numCandidates; ++i)
            face->appendFontFace(candidateFontFaces[i]);
    }

    // We have a face.  Ask it for a font data.  If it cannot produce one, it will fail, and the OS will take over.
    return face->getFontData(fontDescription);
}
Esempio n. 10
0
FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
{
    if (m_fontFaces.isEmpty()) {
        if (familyName.startsWith("-webkit-"))
            return fontDataForGenericFamily(m_document, fontDescription, familyName);
        return 0;
    }

    String family = familyName.string();

#if ENABLE(SVG_FONTS)
    if (fontDescription.smallCaps())
        family += "-webkit-svg-small-caps";
#endif

    Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family);
    // If no face was found, then return 0 and let the OS come up with its best match for the name.
    if (!familyFontFaces || familyFontFaces->isEmpty()) {
        // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our
        // settings.
        return fontDataForGenericFamily(m_document, fontDescription, familyName);
    }

    HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >* segmentedFontFaceCache = m_fonts.get(family);
    if (!segmentedFontFaceCache) {
        segmentedFontFaceCache = new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >;
        m_fonts.set(family, segmentedFontFaceCache);
    }

    FontTraitsMask traitsMask = fontDescription.traitsMask();

    RefPtr<CSSSegmentedFontFace> face = segmentedFontFaceCache->get(traitsMask);

    if (!face) {
        face = CSSSegmentedFontFace::create(this);
        segmentedFontFaceCache->set(traitsMask, face);
        // Collect all matching faces and sort them in order of preference.
        Vector<CSSFontFace*, 32> candidateFontFaces;
        for (int i = familyFontFaces->size() - 1; i >= 0; --i) {
            CSSFontFace* candidate = familyFontFaces->at(i).get();
            unsigned candidateTraitsMask = candidate->traitsMask();
            if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                continue;
            if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                continue;
            candidateFontFaces.append(candidate);
        }

        if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
            unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
            for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
                CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
                unsigned candidateTraitsMask = candidate->traitsMask();
                if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                    continue;
                if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                    continue;
                candidateFontFaces.append(candidate);
            }
        }

        desiredTraitsMaskForComparison = traitsMask;
        std::stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces);
        unsigned numCandidates = candidateFontFaces.size();
        for (unsigned i = 0; i < numCandidates; ++i)
            face->appendFontFace(candidateFontFaces[i]);
    }

    // We have a face.  Ask it for a font data.  If it cannot produce one, it will fail, and the OS will take over.
    return face->getFontData(fontDescription);
}
Esempio n. 11
0
static bool populateFontFaceWithArrayBuffer(CSSFontFace& fontFace, Ref<JSC::ArrayBufferView>&& arrayBufferView)
{
    auto source = std::make_unique<CSSFontFaceSource>(fontFace, String(), nullptr, nullptr, WTFMove(arrayBufferView));
    fontFace.adoptSource(WTFMove(source));
    return false;
}
Esempio n. 12
0
static inline bool compareFontFaces(const CSSFontFace& first, const CSSFontFace& second)
{
    FontTraitsMask firstTraitsMask = first.traitsMask();
    FontTraitsMask secondTraitsMask = second.traitsMask();

    bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
    bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;

    if (firstHasDesiredVariant != secondHasDesiredVariant)
        return firstHasDesiredVariant;

    // We need to check font-variant css property for CSS2.1 compatibility.
    if ((desiredTraitsMaskForComparison & FontVariantSmallCapsMask) && !first.isLocalFallback() && !second.isLocalFallback()) {
        // Prefer a font that has indicated that it can only support small-caps to a font that claims to support
        // all variants.  The specialized font is more likely to be true small-caps and not require synthesis.
        bool firstRequiresSmallCaps = (firstTraitsMask & FontVariantSmallCapsMask) && !(firstTraitsMask & FontVariantNormalMask);
        bool secondRequiresSmallCaps = (secondTraitsMask & FontVariantSmallCapsMask) && !(secondTraitsMask & FontVariantNormalMask);
        if (firstRequiresSmallCaps != secondRequiresSmallCaps)
            return firstRequiresSmallCaps;
    }

    bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
    bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;

    if (firstHasDesiredStyle != secondHasDesiredStyle)
        return firstHasDesiredStyle;

    if ((desiredTraitsMaskForComparison & FontStyleItalicMask) && !first.isLocalFallback() && !second.isLocalFallback()) {
        // Prefer a font that has indicated that it can only support italics to a font that claims to support
        // all styles.  The specialized font is more likely to be the one the author wants used.
        bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask);
        bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask);
        if (firstRequiresItalics != secondRequiresItalics)
            return firstRequiresItalics;
    }

    if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
        return false;
    if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
        return true;

    // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says :
    //   - 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.
    //   - 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.
    //   - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used.
    //   - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used.

    static const unsigned fallbackRuleSets = 9;
    static const unsigned rulesPerSet = 8;
    static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = {
        { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight500Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
        { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
        { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
        { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
        { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }
    };

    unsigned ruleSetIndex = 0;
    unsigned w = FontWeight100Bit;
    while (!(desiredTraitsMaskForComparison & (1 << w))) {
        w++;
        ruleSetIndex++;
    }

    ASSERT_WITH_SECURITY_IMPLICATION(ruleSetIndex < fallbackRuleSets);
    const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];
    for (unsigned i = 0; i < rulesPerSet; ++i) {
        if (secondTraitsMask & weightFallbackRule[i])
            return false;
        if (firstTraitsMask & weightFallbackRule[i])
            return true;
    }

    return false;
}
Esempio n. 13
0
void CSSFontSelector::addFontFaceRule(const CSSFontFaceRuleImpl *fontFaceRule)
{
    // Obtain the font-family property and the src property.  Both must be defined.
    const CSSStyleDeclarationImpl *style = fontFaceRule->style();
    CSSValueImpl *fontFamily = style->getPropertyCSSValue(CSS_PROP_FONT_FAMILY);
    CSSValueImpl *src = style->getPropertyCSSValue(CSS_PROP_SRC);
    CSSValueImpl *unicodeRange = style->getPropertyCSSValue(CSS_PROP_UNICODE_RANGE);

    if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || (unicodeRange && !unicodeRange->isValueList())) {
        return;
    }

    CSSValueListImpl *familyList = static_cast<CSSValueListImpl *>(fontFamily);
    if (!familyList->length()) {
        return;
    }

    CSSValueListImpl *srcList = static_cast<CSSValueListImpl *>(src);
    if (!srcList->length()) {
        return;
    }

//    CSSValueListImpl* rangeList = static_cast<CSSValueListImpl*>(unicodeRange);

    unsigned traitsMask = 0;
    /*
        if (CSSValueImpl* fontStyle = style->getPropertyCSSValue(CSS_PROP_FONT_STYLE)) {

            if (fontStyle->isPrimitiveValue()) {
                CSSValueListImpl* list = new CSSValueListImpl(CSSValueListImpl::Comma);
                list->append(fontStyle);
                fontStyle = list;
            } else if (!fontStyle->isValueList())
                return;

            CSSValueListImpl* styleList = static_cast<CSSValueListImpl*>(fontStyle);
            unsigned numStyles = styleList->length();
            if (!numStyles)
                return;

            for (unsigned i = 0; i < numStyles; ++i) {
                switch (static_cast<CSSPrimitiveValueImpl*>(styleList[i])->getIdent()) {
                    case CSS_ALL:
                        traitsMask |= FontStyleMask;
                        break;
                    case CSS_NORMAL:
                        traitsMask |= FontStyleNormalMask;
                        break;
                    case CSS_ITALIC:
                    case CSS_OBLIQUE:
                        traitsMask |= FontStyleItalicMask;
                        break;
                    default:
                        break;
                }
            }
        } else
            traitsMask |= FontStyleMask;

        if (CSSValueImpl* fontWeight = style->getPropertyCSSValue(CSS_PROP_FONT_WEIGHT)) {
            if (fontWeight->isPrimitiveValue()) {
                CSSValueListImpl* list = new CSSValueListImpl(CSSValueListImpl::Comma);
                list->append(fontWeight);
                fontWeight = list;
            } else if (!fontWeight->isValueList())
                return;

            CSSValueListImpl* weightList = static_cast<CSSValueListImpl*>(fontWeight);
            unsigned numWeights = weightList->length();
            if (!numWeights)
                return;

            for (unsigned i = 0; i < numWeights; ++i) {
                switch (static_cast<CSSPrimitiveValueImpl*>(weightList[i])->getIdent()) {
                    case CSS_VAL_ALL:
                        traitsMask |= FontWeightMask;
                        break;
                    case CSS_VAL_BOLDER:
                    case CSS_VAL_BOLD:
                    case CSS_VAL_700:
                        traitsMask |= FontWeight700Mask;
                        break;
                    case CSS_VAL_NORMAL:
                    case CSS_VAL_400:
                        traitsMask |= FontWeight400Mask;
                        break;
                    case CSS_VAL_900:
                        traitsMask |= FontWeight900Mask;
                        break;
                    case CSS_VAL_800:
                        traitsMask |= FontWeight800Mask;
                        break;
                    case CSS_VAL_600:
                        traitsMask |= FontWeight600Mask;
                        break;
                    case CSS_VAL_500:
                        traitsMask |= FontWeight500Mask;
                        break;
                    case CSS_VAL_300:
                        traitsMask |= FontWeight300Mask;
                        break;
                    case CSS_VAL_LIGHTER:
                    case CSS_VAL_200:
                        traitsMask |= FontWeight200Mask;
                        break;
                    case CSS_VAL_100:
                        traitsMask |= FontWeight100Mask;
                        break;
                    default:
                        break;
                }
            }
        } else
            traitsMask |= FontWeightMask;

        if (CSSValueImpl* fontVariant = style->getPropertyCSSValue(CSS_PROP_FONT_VARIANT)) {
            if (fontVariant->isPrimitiveValue()) {
                CSSValueListImpl* list = new CSSValueListImpl(CSSValueListImpl::Comma);
                list->append(fontVariant);
                fontVariant = list;
            } else if (!fontVariant->isValueList())
                return;

            CSSValueListImpl* variantList = static_cast<CSSValueListImpl*>(fontVariant);
            unsigned numVariants = variantList->length();
            if (!numVariants)
                return;

            for (unsigned i = 0; i < numVariants; ++i) {
                switch (static_cast<CSSPrimitiveValueImpl*>(variantList[i])->getIdent()) {
                    case CSS_VAL_ALL:
                        traitsMask |= FontVariantMask;
                        break;
                    case CSS_VAL_NORMAL:
                        traitsMask |= FontVariantNormalMask;
                        break;
                    case CSS_VAL_SMALL_CAPS:
                        traitsMask |= FontVariantSmallCapsMask;
                        break;
                    default:
                        break;
                }
            }
        } else
            traitsMask |= FontVariantNormalMask;
    */

    // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace.
    CSSFontFace *fontFace = 0;

    const int srcLength = srcList->length();

#if 0
    // ENABLE(SVG_FONTS)
    bool foundSVGFont = false;
#endif
    for (int i = 0; i < srcLength; i++) {
        // An item in the list either specifies a string (local font name) or a URL (remote font to download).
        CSSFontFaceSrcValueImpl *item = static_cast<CSSFontFaceSrcValueImpl *>(srcList->item(i));
        CSSFontFaceSource *source = 0;

#if 0
        // ENABLE(SVG_FONTS)
        foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement();
#endif

        if (!item->isLocal()) {
            if (item->isSupportedFormat() && m_document) {
                source = new CSSFontFaceSource(item->resource(), true /*distant*/);
#if 0
                // ENABLE(SVG_FONTS)
                if (foundSVGFont) {
                    cachedFont->setSVGFont(true);
                }
#endif
            }
        } else {
            source = new CSSFontFaceSource(item->resource());
        }

        if (source) {
#if 0
            // ENABLE(SVG_FONTS)
            source->setSVGFontFaceElement(item->svgFontFaceElement());
#endif
            if (!fontFace) {
                fontFace = new CSSFontFace(static_cast<FontTraitsMask>(traitsMask), this);
            }
            fontFace->addSource(source);
        }
    }

    if (!fontFace || !fontFace->isValid()) {
        delete fontFace;
        return;
    }

    /*
        if (rangeList) {
            unsigned numRanges = rangeList->length();
            for (unsigned i = 0; i < numRanges; i++) {
                CSSUnicodeRangeValueImpl* range = static_cast<CSSUnicodeRangeValueImpl*>(rangeList->item(i));
                fontFace->addRange(range->from(), range->to());
            }
        }
    */

    // Hash under every single family name.
    int familyLength = familyList->length();
    for (int i = 0; i < familyLength; i++) {
        CSSPrimitiveValueImpl *item = static_cast<CSSPrimitiveValueImpl *>(familyList->item(i));
        DOMString familyName;
        if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
            familyName = DOMString(static_cast<FontFamilyValueImpl *>(item)->fontName());
        } else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
            // We need to use the raw text for all the generic family types, since @font-face is a way of actually
            // defining what font to use for those types.
            switch (item->getIdent()) {
            case CSS_VAL_SERIF:
                familyName = "-khtml-serif";
                break;
            case CSS_VAL_SANS_SERIF:
                familyName = "-khtml-sans-serif";
                break;
            case CSS_VAL_CURSIVE:
                familyName = "-khtml-cursive";
                break;
            case CSS_VAL_FANTASY:
                familyName = "-khtml-fantasy";
                break;
            case CSS_VAL_MONOSPACE:
                familyName = "-khtml-monospace";
                break;
            default:
                break;
            }
        }

        if (familyName.isEmpty()) {
            continue;
        }

        fontFace->addFamilyName(familyName);
        m_locallyInstalledFontFaces.insertMulti(familyName.lower(), fontFace);
        fontFace->ref();

#if 0
        // ENABLE(SVG_FONTS)
        // SVG allows several <font> elements with the same font-family, differing only
        // in ie. font-variant. Be sure to pick up the right one - in getFontData below.
        if (foundSVGFont && (traitsMask & FontVariantSmallCapsMask)) {
            familyName += "-webkit-svg-small-caps";
        }
#endif

        /*
                Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(familyName);
                if (!familyFontFaces) {
                    familyFontFaces = new Vector<RefPtr<CSSFontFace> >;
                    m_fontFaces.set(familyName, familyFontFaces);

                    ASSERT(!m_locallyInstalledFontFaces.contains(familyName));
                    Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFaces;

                    Vector<unsigned> locallyInstalledFontsTraitsMasks;
                    fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks);
                    unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size();
                    if (numLocallyInstalledFaces) {
                        familyLocallyInstalledFaces = new Vector<RefPtr<CSSFontFace> >;
                        m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces);

                        for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) {
                            RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]));
                            locallyInstalledFontFace->addSource(new CSSFontFaceSource(familyName));
                            ASSERT(locallyInstalledFontFace->isValid());
                            familyLocallyInstalledFaces->append(locallyInstalledFontFace);
                        }
                    }
                }

                familyFontFaces->append(fontFace);
        */
    }

    // Should be impossible, but in case empty/invalid family name makes it through...
    if (fontFace->refCount() < 1) {
        delete fontFace;
    }
}