Exemplo n.º 1
0
CSSSegmentedFontFace* FontFaceCache::get(const FontDescription& fontDescription, const AtomicString& family)
{
    TraitsMap* familyFontFaces = m_fontFaces.get(family);
    if (!familyFontFaces || familyFontFaces->isEmpty())
        return 0;

    FamilyToTraitsMap::AddResult traitsResult = m_fonts.add(family, nullptr);
    if (!traitsResult.storedValue->value)
        traitsResult.storedValue->value = adoptPtr(new TraitsMap);

    FontTraits traits = fontDescription.traits();
    TraitsMap::AddResult faceResult = traitsResult.storedValue->value->add(traits.bitfield(), nullptr);
    if (!faceResult.storedValue->value) {
        for (TraitsMap::const_iterator i = familyFontFaces->begin(); i != familyFontFaces->end(); ++i) {
            CSSSegmentedFontFace* candidate = i->value.get();
            FontTraits candidateTraits = candidate->traits();
            if (traits.style() == FontStyleNormal && candidateTraits.style() != FontStyleNormal)
                continue;
            if (traits.variant() == FontVariantNormal && candidateTraits.variant() != FontVariantNormal)
                continue;
            if (!faceResult.storedValue->value || compareFontFaces(candidate, faceResult.storedValue->value.get(), traits))
                faceResult.storedValue->value = candidate;
        }
    }
    return faceResult.storedValue->value.get();
}
Exemplo n.º 2
0
bool FontFaceSet::check(const String& fontString, const String& text, ExceptionState& exceptionState)
{
    if (!inActiveDocumentContext())
        return false;

    Font font;
    if (!resolveFontStyle(fontString, font)) {
        exceptionState.ThrowDOMException(SyntaxError, "Could not resolve '" + fontString + "' as a font.");
        return false;
    }

    CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector();
    FontFaceCache* fontFaceCache = fontSelector->fontFaceCache();

    bool hasLoadedFaces = false;
    for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) {
        CSSSegmentedFontFace* face = fontFaceCache->get(font.fontDescription(), f->family());
        if (face) {
            if (!face->checkFont(nullToSpace(text)))
                return false;
            hasLoadedFaces = true;
        }
    }
    if (hasLoadedFaces)
        return true;
    for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) {
        if (fontSelector->isPlatformFontAvailable(font.fontDescription(), f->family()))
            return true;
    }
    return false;
}
Exemplo n.º 3
0
ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontString, const String& text)
{
    if (!inActiveDocumentContext())
        return ScriptPromise();

    Font font;
    if (!resolveFontStyle(fontString, font)) {
        ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
        ScriptPromise promise = resolver->promise();
        resolver->reject(DOMException::create(SyntaxError, "Could not resolve '" + fontString + "' as a font."));
        return promise;
    }

    FontFaceCache* fontFaceCache = document()->styleEngine().fontSelector()->fontFaceCache();
    FontFaceArray faces;
    for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) {
        CSSSegmentedFontFace* segmentedFontFace = fontFaceCache->get(font.fontDescription(), f->family());
        if (segmentedFontFace)
            segmentedFontFace->match(text, faces);
    }

    RefPtrWillBeRawPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(faces, scriptState);
    ScriptPromise promise = resolver->promise();
    resolver->loadFonts(executionContext()); // After this, resolver->promise() may return null.
    return promise;
}
Exemplo n.º 4
0
bool FontLoader::checkFont(const String& fontString, const String&)
{
    // FIXME: The second parameter (text) is ignored.
    FontCascade font;
    if (!resolveFontStyle(fontString, font))
        return false;
    for (unsigned i = 0; i < font.familyCount(); i++) {
        CSSSegmentedFontFace* face = m_document->fontSelector().getFontFace(font.fontDescription(), font.familyAt(i));
        if (!face || !face->checkFont())
            return false;
    }
    return true;
}
Exemplo n.º 5
0
FontRanges CSSFontSelector::fontRangesForFamily(const FontDescription& fontDescription, const AtomicString& familyName)
{
    // FIXME: The spec (and Firefox) says user specified generic families (sans-serif etc.) should be resolved before the @font-face lookup too.
    bool resolveGenericFamilyFirst = familyName == standardFamily;

    AtomicString familyForLookup = resolveGenericFamilyFirst ? resolveGenericFamily(m_document, fontDescription, familyName) : familyName;
    CSSSegmentedFontFace* face = getFontFace(fontDescription, familyForLookup);
    if (!face) {
        if (!resolveGenericFamilyFirst)
            familyForLookup = resolveGenericFamily(m_document, fontDescription, familyName);
        return FontRanges(FontCache::singleton().fontForFamily(fontDescription, familyForLookup));
    }

    return face->fontRanges(fontDescription);
}
Exemplo n.º 6
0
CSSSegmentedFontFace* CSSFontSelector::getFontFace(const FontDescription& fontDescription, const AtomicString& family)
{
    HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >* 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) {
        for (HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >::const_iterator i = familyFontFaces->begin(); i != familyFontFaces->end(); ++i) {
            CSSSegmentedFontFace* candidate = i->value.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
            if (!face || compareFontFaces(candidate, face.get(), traitsMask))
                face = candidate;
        }

        if (Vector<RefPtr<CSSSegmentedFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
            unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
            for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
                CSSSegmentedFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
                unsigned candidateTraitsMask = candidate->traitsMask();
                if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
                    continue;
                if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
                    continue;
                if (!face || compareFontFaces(candidate, face.get(), traitsMask))
                    face = candidate;
            }
        }
    }
    return face.get();
}
Exemplo n.º 7
0
Vector<std::reference_wrapper<CSSFontFace>> CSSFontFaceSet::matchingFaces(const String& font, const String&, ExceptionCode& ec)
{
    Vector<std::reference_wrapper<CSSFontFace>> result;
    Ref<MutableStyleProperties> style = MutableStyleProperties::create();
    auto parseResult = CSSParser::parseValue(style.ptr(), CSSPropertyFont, font, true, CSSStrictMode, nullptr);
    if (parseResult == CSSParser::ParseResult::Error) {
        ec = SYNTAX_ERR;
        return result;
    }

    FontTraitsMask fontTraitsMask;
    if (auto maskOptional = computeFontTraitsMask(style.get()))
        fontTraitsMask = maskOptional.value();
    else {
        ec = SYNTAX_ERR;
        return result;
    }

    RefPtr<CSSValue> family = style->getPropertyCSSValue(CSSPropertyFontFamily);
    if (!is<CSSValueList>(family.get())) {
        ec = SYNTAX_ERR;
        return result;
    }
    CSSValueList& familyList = downcast<CSSValueList>(*family);

    HashSet<AtomicString> uniqueFamilies;
    for (auto& family : familyList) {
        const CSSPrimitiveValue& primitive = downcast<CSSPrimitiveValue>(family.get());
        if (!primitive.isFontFamily())
            continue;
        uniqueFamilies.add(primitive.fontFamily().familyName);
    }

    for (auto& family : uniqueFamilies) {
        CSSSegmentedFontFace* faces = getFontFace(fontTraitsMask, family);
        if (!faces)
            continue;
        for (auto& constituentFace : faces->constituentFaces())
            result.append(constituentFace.get());
    }

    return result;
}
Exemplo n.º 8
0
void FontLoader::loadFont(const Dictionary& params)
{
    // FIXME: The text member of params is ignored.
    String fontString;
    if (!params.get("font", fontString))
        return;
    FontCascade font;
    if (!resolveFontStyle(fontString, font))
        return;
    RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(params, *this, font);
    m_numLoadingFromJS += callback->familyCount();

    for (unsigned i = 0; i < font.familyCount(); i++) {
        CSSSegmentedFontFace* face = m_document->fontSelector().getFontFace(font.fontDescription(), font.familyAt(i));
        if (!face) {
            if (callback)
                callback->notifyError();
            continue;
        }
        face->loadFont(font.fontDescription(), callback);
    }
}
Exemplo n.º 9
0
PassRefPtr<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;
    }

    CSSSegmentedFontFace* face = getFontFace(fontDescription, familyName);
    // If no face was found, then return 0 and let the OS come up with its best match for the name.
    if (!face) {
        // 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);
    }

    // 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);
}
Exemplo n.º 10
0
void CSSFontSelector::willUseFontData(const FontDescription& fontDescription, const AtomicString& family)
{
    CSSSegmentedFontFace* face = getFontFace(fontDescription, family);
    if (face)
        face->willUseFontData(fontDescription);
}
Exemplo n.º 11
0
void CSSFontSelector::willUseFontData(const FontDescription& fontDescription, const AtomicString& family, UChar32 character)
{
    CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, family);
    if (face)
        face->willUseFontData(fontDescription, character);
}