| /* | |
| * This is part of HarfBuzz, a text shaping library. | |
| * | |
| * Permission is hereby granted, without written agreement and without | |
| * license or royalty fees, to use, copy, modify, and distribute this | |
| * software and its documentation for any purpose, provided that the | |
| * above copyright notice and the following two paragraphs appear in | |
| * all copies of this software. | |
| * | |
| * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | |
| * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | |
| * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | |
| * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | |
| * DAMAGE. | |
| * | |
| * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | |
| * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
| * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | |
| * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | |
| * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
| * | |
| * Author(s): Behdad Esfahbod | |
| */ | |
| #ifndef HB_DIRECTWRITE_HH | |
| #define HB_DIRECTWRITE_HH | |
| #include "hb.hh" | |
| #include "hb-directwrite.h" | |
| #include "hb-mutex.hh" | |
| #include "hb-map.hh" | |
| /* | |
| * DirectWrite font stream helpers | |
| */ | |
| // Have a look at to NativeFontResourceDWrite.cpp in Mozilla | |
| /* Declare object creator for dynamic support of DWRITE */ | |
| typedef HRESULT (WINAPI *t_DWriteCreateFactory)( | |
| DWRITE_FACTORY_TYPE factoryType, | |
| REFIID iid, | |
| IUnknown **factory | |
| ); | |
| class DWriteFontFileLoader : public IDWriteFontFileLoader | |
| { | |
| private: | |
| hb_reference_count_t mRefCount; | |
| hb_mutex_t mutex; | |
| hb_hashmap_t<uint64_t, IDWriteFontFileStream *> mFontStreams; | |
| uint64_t mNextFontFileKey = 0; | |
| public: | |
| DWriteFontFileLoader () | |
| { | |
| mRefCount.init (); | |
| } | |
| uint64_t RegisterFontFileStream (IDWriteFontFileStream *fontFileStream) | |
| { | |
| fontFileStream->AddRef (); | |
| hb_lock_t lock {mutex}; | |
| mFontStreams.set (mNextFontFileKey, fontFileStream); | |
| return mNextFontFileKey++; | |
| } | |
| void UnregisterFontFileStream (uint64_t fontFileKey) | |
| { | |
| hb_lock_t lock {mutex}; | |
| IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey); | |
| if (stream) | |
| { | |
| mFontStreams.del (fontFileKey); | |
| stream->Release (); | |
| } | |
| } | |
| // IUnknown interface | |
| IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) | |
| { return S_OK; } | |
| IFACEMETHOD_ (ULONG, AddRef) () | |
| { | |
| return mRefCount.inc () + 1; | |
| } | |
| IFACEMETHOD_ (ULONG, Release) () | |
| { | |
| signed refCount = mRefCount.dec () - 1; | |
| assert (refCount >= 0); | |
| if (refCount) | |
| return refCount; | |
| delete this; | |
| return 0; | |
| } | |
| // IDWriteFontFileLoader methods | |
| virtual HRESULT STDMETHODCALLTYPE | |
| CreateStreamFromKey (void const* fontFileReferenceKey, | |
| uint32_t fontFileReferenceKeySize, | |
| OUT IDWriteFontFileStream** fontFileStream) | |
| { | |
| if (fontFileReferenceKeySize != sizeof (uint64_t)) | |
| return E_INVALIDARG; | |
| uint64_t fontFileKey = * (uint64_t *) fontFileReferenceKey; | |
| IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey); | |
| if (!stream) | |
| return E_FAIL; | |
| stream->AddRef (); | |
| *fontFileStream = stream; | |
| return S_OK; | |
| } | |
| virtual ~DWriteFontFileLoader() | |
| { | |
| for (auto v : mFontStreams.values ()) | |
| v->Release (); | |
| } | |
| }; | |
| class DWriteFontFileStream : public IDWriteFontFileStream | |
| { | |
| private: | |
| hb_reference_count_t mRefCount; | |
| hb_blob_t *mBlob; | |
| uint8_t *mData; | |
| unsigned mSize; | |
| DWriteFontFileLoader *mLoader; | |
| public: | |
| uint64_t fontFileKey; | |
| public: | |
| DWriteFontFileStream (hb_blob_t *blob); | |
| // IUnknown interface | |
| IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) | |
| { return S_OK; } | |
| IFACEMETHOD_ (ULONG, AddRef) () | |
| { | |
| return mRefCount.inc () + 1; | |
| } | |
| IFACEMETHOD_ (ULONG, Release) () | |
| { | |
| signed refCount = mRefCount.dec () - 1; | |
| assert (refCount >= 0); | |
| if (refCount) | |
| return refCount; | |
| delete this; | |
| return 0; | |
| } | |
| // IDWriteFontFileStream methods | |
| virtual HRESULT STDMETHODCALLTYPE | |
| ReadFileFragment (void const** fragmentStart, | |
| UINT64 fileOffset, | |
| UINT64 fragmentSize, | |
| OUT void** fragmentContext) | |
| { | |
| // We are required to do bounds checking. | |
| if (fileOffset + fragmentSize > mSize) return E_FAIL; | |
| // truncate the 64 bit fileOffset to size_t sized index into mData | |
| size_t index = static_cast<size_t> (fileOffset); | |
| // We should be alive for the duration of this. | |
| *fragmentStart = &mData[index]; | |
| *fragmentContext = nullptr; | |
| return S_OK; | |
| } | |
| virtual void STDMETHODCALLTYPE | |
| ReleaseFileFragment (void* fragmentContext) {} | |
| virtual HRESULT STDMETHODCALLTYPE | |
| GetFileSize (OUT UINT64* fileSize) | |
| { | |
| *fileSize = mSize; | |
| return S_OK; | |
| } | |
| virtual HRESULT STDMETHODCALLTYPE | |
| GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; } | |
| virtual ~DWriteFontFileStream(); | |
| }; | |
| struct hb_directwrite_global_t | |
| { | |
| hb_directwrite_global_t () | |
| { | |
| HRESULT hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), | |
| (IUnknown**) &dwriteFactory); | |
| if (unlikely (hr != S_OK)) | |
| return; | |
| fontFileLoader = new DWriteFontFileLoader (); | |
| dwriteFactory->RegisterFontFileLoader (fontFileLoader); | |
| success = true; | |
| } | |
| ~hb_directwrite_global_t () | |
| { | |
| if (fontFileLoader) | |
| fontFileLoader->Release (); | |
| if (dwriteFactory) | |
| dwriteFactory->Release (); | |
| } | |
| bool success = false; | |
| IDWriteFactory *dwriteFactory; | |
| DWriteFontFileLoader *fontFileLoader; | |
| }; | |
| HB_INTERNAL hb_directwrite_global_t * | |
| get_directwrite_global (); | |
| HB_INTERNAL IDWriteFontFace * | |
| dw_face_create (hb_blob_t *blob, unsigned index); | |
| #endif /* HB_DIRECTWRITE_HH */ |