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; }
bool FontFaceSet::hasForBinding(ScriptState*, FontFace* fontFace, ExceptionState&) const { ASSERT(fontFace); if (!inActiveDocumentContext()) return false; return m_nonCSSConnectedFaces.contains(fontFace) || isCSSConnectedFontFace(fontFace); }
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; }
bool FontFaceSet::has(FontFace* fontFace, ExceptionState& exceptionState) const { if (!inActiveDocumentContext()) return false; if (!fontFace) { exceptionState.ThrowTypeError("The argument is not a FontFace."); return false; } return m_nonCSSConnectedFaces.contains(fontFace) || isCSSConnectedFontFace(fontFace); }
ScriptPromise FontFaceSet::ready(ScriptState* scriptState) { if (!inActiveDocumentContext()) return ScriptPromise(); OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); m_readyResolvers.append(resolver.release()); handlePendingEventsAndPromisesSoon(); return promise; }
void FontFaceSet::clearForBinding(ScriptState*, ExceptionState&) { if (!inActiveDocumentContext() || m_nonCSSConnectedFaces.isEmpty()) return; CSSFontSelector* fontSelector = document()->styleEngine().fontSelector(); FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); for (const auto& fontFace : m_nonCSSConnectedFaces) { fontFaceCache->removeFontFace(fontFace.get(), false); if (fontFace->loadStatus() == FontFace::Loading) removeFromLoadingFonts(fontFace); } m_nonCSSConnectedFaces.clear(); fontSelector->fontFaceInvalidated(); }
void FontFaceSet::clear() { if (!inActiveDocumentContext() || m_nonCSSConnectedFaces.isEmpty()) return; CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); for (ListHashSet<RefPtr<FontFace> >::iterator it = m_nonCSSConnectedFaces.begin(); it != m_nonCSSConnectedFaces.end(); ++it) { fontFaceCache->removeFontFace(it->get(), false); if ((*it)->loadStatus() == FontFace::Loading) removeFromLoadingFonts(*it); } m_nonCSSConnectedFaces.clear(); fontSelector->fontFaceInvalidated(); }
FontFaceSetIterable::IterationSource* FontFaceSet::startIteration(ScriptState*, ExceptionState&) { // Setlike should iterate each item in insertion order, and items should // be keep on up to date. But since blink does not have a way to hook up CSS // modification, take a snapshot here, and make it ordered as follows. WillBeHeapVector<RefPtrWillBeMember<FontFace>> fontFaces; if (inActiveDocumentContext()) { const WillBeHeapListHashSet<RefPtrWillBeMember<FontFace>>& cssConnectedFaces = cssConnectedFontFaceList(); fontFaces.reserveInitialCapacity(cssConnectedFaces.size() + m_nonCSSConnectedFaces.size()); for (const auto& fontFace : cssConnectedFaces) fontFaces.append(fontFace); for (const auto& fontFace : m_nonCSSConnectedFaces) fontFaces.append(fontFace); } return new IterationSource(fontFaces); }
bool FontFaceSet::deleteForBinding(ScriptState*, FontFace* fontFace, ExceptionState&) { ASSERT(fontFace); if (!inActiveDocumentContext()) return false; WillBeHeapListHashSet<RefPtrWillBeMember<FontFace>>::iterator it = m_nonCSSConnectedFaces.find(fontFace); if (it != m_nonCSSConnectedFaces.end()) { m_nonCSSConnectedFaces.remove(it); CSSFontSelector* fontSelector = document()->styleEngine().fontSelector(); fontSelector->fontFaceCache()->removeFontFace(fontFace, false); if (fontFace->loadStatus() == FontFace::Loading) removeFromLoadingFonts(fontFace); fontSelector->fontFaceInvalidated(); return true; } return false; }
PassRefPtrWillBeRawPtr<FontFaceSet> FontFaceSet::addForBinding(ScriptState*, FontFace* fontFace, ExceptionState&) { ASSERT(fontFace); if (!inActiveDocumentContext()) return this; if (m_nonCSSConnectedFaces.contains(fontFace)) return this; if (isCSSConnectedFontFace(fontFace)) return this; CSSFontSelector* fontSelector = document()->styleEngine().fontSelector(); m_nonCSSConnectedFaces.add(fontFace); fontSelector->fontFaceCache()->addFontFace(fontSelector, fontFace, false); if (fontFace->loadStatus() == FontFace::Loading) addToLoadingFonts(fontFace); fontSelector->fontFaceInvalidated(); return this; }
void FontFaceSet::forEachInternal(PassOwnPtr<FontFaceSetForEachCallback> callback, const ScriptValue* thisArg) const { if (!inActiveDocumentContext()) return; const ListHashSet<RefPtr<FontFace> >& cssConnectedFaces = cssConnectedFontFaceList(); Vector<RefPtr<FontFace> > fontFaces; fontFaces.reserveInitialCapacity(cssConnectedFaces.size() + m_nonCSSConnectedFaces.size()); for (ListHashSet<RefPtr<FontFace> >::const_iterator it = cssConnectedFaces.begin(); it != cssConnectedFaces.end(); ++it) fontFaces.append(*it); for (ListHashSet<RefPtr<FontFace> >::const_iterator it = m_nonCSSConnectedFaces.begin(); it != m_nonCSSConnectedFaces.end(); ++it) fontFaces.append(*it); for (size_t i = 0; i < fontFaces.size(); ++i) { FontFace* face = fontFaces[i].get(); if (thisArg) callback->handleItem(*thisArg, face, face, const_cast<FontFaceSet*>(this)); else callback->handleItem(face, face, const_cast<FontFaceSet*>(this)); } }
void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) { if (!inActiveDocumentContext()) return; if (!fontFace) { exceptionState.ThrowTypeError("The argument is not a FontFace."); return; } if (m_nonCSSConnectedFaces.contains(fontFace)) return; if (isCSSConnectedFontFace(fontFace)) { exceptionState.ThrowDOMException(InvalidModificationError, "Cannot add a CSS-connected FontFace."); return; } CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); m_nonCSSConnectedFaces.add(fontFace); fontSelector->fontFaceCache()->addFontFace(fontSelector, fontFace, false); if (fontFace->loadStatus() == FontFace::Loading) addToLoadingFonts(fontFace); fontSelector->fontFaceInvalidated(); }
bool FontFaceSet::remove(FontFace* fontFace, ExceptionState& exceptionState) { if (!inActiveDocumentContext()) return false; if (!fontFace) { exceptionState.ThrowTypeError("The argument is not a FontFace."); return false; } ListHashSet<RefPtr<FontFace> >::iterator it = m_nonCSSConnectedFaces.find(fontFace); if (it != m_nonCSSConnectedFaces.end()) { m_nonCSSConnectedFaces.remove(it); CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); fontSelector->fontFaceCache()->removeFontFace(fontFace, false); if (fontFace->loadStatus() == FontFace::Loading) removeFromLoadingFonts(fontFace); fontSelector->fontFaceInvalidated(); return true; } if (isCSSConnectedFontFace(fontFace)) exceptionState.ThrowDOMException(InvalidModificationError, "Cannot delete a CSS-connected FontFace."); return false; }
unsigned long FontFaceSet::size() const { if (!inActiveDocumentContext()) return m_nonCSSConnectedFaces.size(); return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); }