diff options
Diffstat (limited to 'gfx/thebes/gfxDWriteCommon.cpp')
-rw-r--r-- | gfx/thebes/gfxDWriteCommon.cpp | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/gfx/thebes/gfxDWriteCommon.cpp b/gfx/thebes/gfxDWriteCommon.cpp new file mode 100644 index 000000000..3047818bb --- /dev/null +++ b/gfx/thebes/gfxDWriteCommon.cpp @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gfxDWriteCommon.h" + +#include <unordered_map> + +#include "mozilla/Atomics.h" +#include "mozilla/gfx/Logging.h" + +static mozilla::Atomic<uint64_t> sNextFontFileKey; +static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams; + +IDWriteFontFileLoader* gfxDWriteFontFileLoader::mInstance = nullptr; + +class gfxDWriteFontFileStream final : public IDWriteFontFileStream +{ +public: + /** + * Used by the FontFileLoader to create a new font stream, + * this font stream is created from data in memory. The memory + * passed may be released after object creation, it will be + * copied internally. + * + * @param aData Font data + */ + gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData, + uint64_t aFontFileKey); + ~gfxDWriteFontFileStream(); + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) + { + if (iid == __uuidof(IDWriteFontFileStream)) { + *ppObject = static_cast<IDWriteFontFileStream*>(this); + return S_OK; + } + else if (iid == __uuidof(IUnknown)) { + *ppObject = static_cast<IUnknown*>(this); + return S_OK; + } + else { + return E_NOINTERFACE; + } + } + + IFACEMETHOD_(ULONG, AddRef)() + { + NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt"); + ++mRefCnt; + return mRefCnt; + } + + IFACEMETHOD_(ULONG, Release)() + { + NS_PRECONDITION(0 != mRefCnt, "dup release"); + --mRefCnt; + if (mRefCnt == 0) { + delete this; + return 0; + } + return mRefCnt; + } + + // IDWriteFontFileStream methods + virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + OUT void** fragmentContext); + + virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext); + + virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize); + + virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime); + +private: + FallibleTArray<uint8_t> mData; + nsAutoRefCnt mRefCnt; + uint64_t mFontFileKey; +}; + +gfxDWriteFontFileStream::gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData, + uint64_t aFontFileKey) + : mFontFileKey(aFontFileKey) +{ + mData.SwapElements(*aData); +} + +gfxDWriteFontFileStream::~gfxDWriteFontFileStream() +{ + sFontFileStreams.erase(mFontFileKey); +} + +HRESULT STDMETHODCALLTYPE +gfxDWriteFontFileStream::GetFileSize(UINT64 *fileSize) +{ + *fileSize = mData.Length(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +gfxDWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE +gfxDWriteFontFileStream::ReadFileFragment(const void **fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + void **fragmentContext) +{ + // We are required to do bounds checking. + if (fileOffset + fragmentSize > (UINT64)mData.Length()) { + return E_FAIL; + } + // We should be alive for the duration of this. + *fragmentStart = &mData[fileOffset]; + *fragmentContext = nullptr; + return S_OK; +} + +void STDMETHODCALLTYPE +gfxDWriteFontFileStream::ReleaseFileFragment(void *fragmentContext) +{ +} + +HRESULT STDMETHODCALLTYPE +gfxDWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + IDWriteFontFileStream **fontFileStream) +{ + if (!fontFileReferenceKey || !fontFileStream) { + return E_POINTER; + } + + uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey); + auto found = sFontFileStreams.find(fontFileKey); + if (found == sFontFileStreams.end()) { + *fontFileStream = nullptr; + return E_FAIL; + } + + found->second->AddRef(); + *fontFileStream = found->second; + return S_OK; +} + +/* static */ +HRESULT +gfxDWriteFontFileLoader::CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData, + IDWriteFontFile** aFontFile, + IDWriteFontFileStream** aFontFileStream) +{ + MOZ_ASSERT(aFontFile); + MOZ_ASSERT(aFontFileStream); + + IDWriteFactory *factory = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory(); + if (!factory) { + gfxCriticalError() << "Failed to get DWrite Factory in CreateCustomFontFile."; + return E_FAIL; + } + + uint64_t fontFileKey = sNextFontFileKey++; + RefPtr<IDWriteFontFileStream> ffsRef = new gfxDWriteFontFileStream(&aFontData, fontFileKey); + sFontFileStreams[fontFileKey] = ffsRef; + + RefPtr<IDWriteFontFile> fontFile; + HRESULT hr = factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey), Instance(), getter_AddRefs(fontFile)); + if (FAILED(hr)) { + NS_WARNING("Failed to load font file from data!"); + return hr; + } + + fontFile.forget(aFontFile); + ffsRef.forget(aFontFileStream); + + return S_OK; +} |