diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/css/FontFaceSet.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/css/FontFaceSet.cpp')
-rw-r--r-- | Source/WebCore/css/FontFaceSet.cpp | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/Source/WebCore/css/FontFaceSet.cpp b/Source/WebCore/css/FontFaceSet.cpp new file mode 100644 index 000000000..5b5268b7f --- /dev/null +++ b/Source/WebCore/css/FontFaceSet.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FontFaceSet.h" + +#include "Document.h" +#include "ExceptionCodeDescription.h" +#include "FontFace.h" +#include "JSDOMBinding.h" +#include "JSDOMCoreException.h" +#include "JSFontFace.h" +#include "JSFontFaceSet.h" + +namespace WebCore { + +Ref<FontFaceSet> FontFaceSet::create(Document& document, const Vector<RefPtr<FontFace>>& initialFaces) +{ + Ref<FontFaceSet> result = adoptRef(*new FontFaceSet(document, initialFaces)); + result->suspendIfNeeded(); + return result; +} + +Ref<FontFaceSet> FontFaceSet::create(Document& document, CSSFontFaceSet& backing) +{ + Ref<FontFaceSet> result = adoptRef(*new FontFaceSet(document, backing)); + result->suspendIfNeeded(); + return result; +} + +FontFaceSet::FontFaceSet(Document& document, const Vector<RefPtr<FontFace>>& initialFaces) + : ActiveDOMObject(&document) + , m_backing(CSSFontFaceSet::create()) +{ + m_backing->addClient(*this); + for (auto& face : initialFaces) + add(*face); +} + +FontFaceSet::FontFaceSet(Document& document, CSSFontFaceSet& backing) + : ActiveDOMObject(&document) + , m_backing(backing) +{ + m_backing->addClient(*this); +} + +FontFaceSet::~FontFaceSet() +{ + m_backing->removeClient(*this); +} + +FontFaceSet::Iterator::Iterator(FontFaceSet& set) + : m_target(set) +{ +} + +RefPtr<FontFace> FontFaceSet::Iterator::next() +{ + if (m_index == m_target->size()) + return nullptr; + return m_target->backing()[m_index++].wrapper(); +} + +FontFaceSet::PendingPromise::PendingPromise(LoadPromise&& promise) + : promise(WTFMove(promise)) +{ +} + +FontFaceSet::PendingPromise::~PendingPromise() +{ +} + +bool FontFaceSet::has(FontFace& face) const +{ + return m_backing->hasFace(face.backing()); +} + +size_t FontFaceSet::size() const +{ + return m_backing->faceCount(); +} + +FontFaceSet& FontFaceSet::add(FontFace& face) +{ + if (!m_backing->hasFace(face.backing())) + m_backing->add(face.backing()); + return *this; +} + +bool FontFaceSet::remove(FontFace& face) +{ + bool result = m_backing->hasFace(face.backing()); + if (result) + m_backing->remove(face.backing()); + return result; +} + +void FontFaceSet::clear() +{ + while (m_backing->faceCount()) + m_backing->remove(m_backing.get()[0]); +} + +void FontFaceSet::load(const String& font, const String& text, LoadPromise&& promise) +{ + auto matchingFacesResult = m_backing->matchingFaces(font, text); + if (matchingFacesResult.hasException()) { + promise.reject(matchingFacesResult.releaseException()); + return; + } + auto matchingFaces = matchingFacesResult.releaseReturnValue(); + + if (matchingFaces.isEmpty()) { + promise.resolve({ }); + return; + } + + for (auto& face : matchingFaces) + face.get().load(); + + for (auto& face : matchingFaces) { + if (face.get().status() == CSSFontFace::Status::Failure) { + promise.reject(NETWORK_ERR); + return; + } + } + + auto pendingPromise = PendingPromise::create(WTFMove(promise)); + bool waiting = false; + + for (auto& face : matchingFaces) { + pendingPromise->faces.append(face.get().wrapper()); + if (face.get().status() == CSSFontFace::Status::Success) + continue; + waiting = true; + ASSERT(face.get().existingWrapper()); + m_pendingPromises.add(face.get().existingWrapper(), Vector<Ref<PendingPromise>>()).iterator->value.append(pendingPromise.copyRef()); + } + + if (!waiting) + pendingPromise->promise.resolve(pendingPromise->faces); +} + +ExceptionOr<bool> FontFaceSet::check(const String& family, const String& text) +{ + return m_backing->check(family, text); +} + +void FontFaceSet::registerReady(ReadyPromise&& promise) +{ + ASSERT(!m_promise); + if (m_isReady) { + promise.resolve(*this); + return; + } + m_promise = WTFMove(promise); +} + +auto FontFaceSet::status() const -> LoadStatus +{ + switch (m_backing->status()) { + case CSSFontFaceSet::Status::Loading: + return LoadStatus::Loading; + case CSSFontFaceSet::Status::Loaded: + return LoadStatus::Loaded; + } + ASSERT_NOT_REACHED(); + return LoadStatus::Loaded; +} + +bool FontFaceSet::canSuspendForDocumentSuspension() const +{ + return m_backing->status() == CSSFontFaceSet::Status::Loaded; +} + +void FontFaceSet::startedLoading() +{ + // FIXME: Fire a "loading" event asynchronously. + m_isReady = false; +} + +void FontFaceSet::completedLoading() +{ + if (m_promise) + std::exchange(m_promise, std::nullopt)->resolve(*this); + m_isReady = true; +} + +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); +} + +} |