hb-directwrite.hh (5725B)
1 /* 2 * This is part of HarfBuzz, a text shaping library. 3 * 4 * Permission is hereby granted, without written agreement and without 5 * license or royalty fees, to use, copy, modify, and distribute this 6 * software and its documentation for any purpose, provided that the 7 * above copyright notice and the following two paragraphs appear in 8 * all copies of this software. 9 * 10 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 11 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 12 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 13 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 14 * DAMAGE. 15 * 16 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 17 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 18 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 19 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 20 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 21 * 22 * Author(s): Behdad Esfahbod 23 */ 24 25 26 #ifndef HB_DIRECTWRITE_HH 27 #define HB_DIRECTWRITE_HH 28 29 #include "hb.hh" 30 31 #include "hb-directwrite.h" 32 33 #include "hb-mutex.hh" 34 #include "hb-map.hh" 35 36 /* 37 * DirectWrite font stream helpers 38 */ 39 40 // Have a look at to NativeFontResourceDWrite.cpp in Mozilla 41 42 43 /* Declare object creator for dynamic support of DWRITE */ 44 typedef HRESULT (WINAPI *t_DWriteCreateFactory)( 45 DWRITE_FACTORY_TYPE factoryType, 46 REFIID iid, 47 IUnknown **factory 48 ); 49 50 class DWriteFontFileLoader : public IDWriteFontFileLoader 51 { 52 private: 53 hb_reference_count_t mRefCount; 54 hb_mutex_t mutex; 55 hb_hashmap_t<uint64_t, IDWriteFontFileStream *> mFontStreams; 56 uint64_t mNextFontFileKey = 0; 57 public: 58 DWriteFontFileLoader () 59 { 60 mRefCount.init (); 61 } 62 63 uint64_t RegisterFontFileStream (IDWriteFontFileStream *fontFileStream) 64 { 65 fontFileStream->AddRef (); 66 hb_lock_t lock {mutex}; 67 mFontStreams.set (mNextFontFileKey, fontFileStream); 68 return mNextFontFileKey++; 69 } 70 void UnregisterFontFileStream (uint64_t fontFileKey) 71 { 72 hb_lock_t lock {mutex}; 73 IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey); 74 if (stream) 75 { 76 mFontStreams.del (fontFileKey); 77 stream->Release (); 78 } 79 } 80 81 // IUnknown interface 82 IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) 83 { return S_OK; } 84 IFACEMETHOD_ (ULONG, AddRef) () 85 { 86 return mRefCount.inc () + 1; 87 } 88 IFACEMETHOD_ (ULONG, Release) () 89 { 90 signed refCount = mRefCount.dec () - 1; 91 assert (refCount >= 0); 92 if (refCount) 93 return refCount; 94 delete this; 95 return 0; 96 } 97 98 // IDWriteFontFileLoader methods 99 virtual HRESULT STDMETHODCALLTYPE 100 CreateStreamFromKey (void const* fontFileReferenceKey, 101 uint32_t fontFileReferenceKeySize, 102 OUT IDWriteFontFileStream** fontFileStream) 103 { 104 if (fontFileReferenceKeySize != sizeof (uint64_t)) 105 return E_INVALIDARG; 106 uint64_t fontFileKey = * (uint64_t *) fontFileReferenceKey; 107 IDWriteFontFileStream *stream = mFontStreams.get (fontFileKey); 108 if (!stream) 109 return E_FAIL; 110 stream->AddRef (); 111 *fontFileStream = stream; 112 return S_OK; 113 } 114 115 virtual ~DWriteFontFileLoader() 116 { 117 for (auto v : mFontStreams.values ()) 118 v->Release (); 119 } 120 }; 121 122 class DWriteFontFileStream : public IDWriteFontFileStream 123 { 124 private: 125 hb_reference_count_t mRefCount; 126 hb_blob_t *mBlob; 127 uint8_t *mData; 128 unsigned mSize; 129 DWriteFontFileLoader *mLoader; 130 public: 131 uint64_t fontFileKey; 132 public: 133 DWriteFontFileStream (hb_blob_t *blob); 134 135 // IUnknown interface 136 IFACEMETHOD (QueryInterface) (IID const& iid, OUT void** ppObject) 137 { return S_OK; } 138 IFACEMETHOD_ (ULONG, AddRef) () 139 { 140 return mRefCount.inc () + 1; 141 } 142 IFACEMETHOD_ (ULONG, Release) () 143 { 144 signed refCount = mRefCount.dec () - 1; 145 assert (refCount >= 0); 146 if (refCount) 147 return refCount; 148 delete this; 149 return 0; 150 } 151 152 // IDWriteFontFileStream methods 153 virtual HRESULT STDMETHODCALLTYPE 154 ReadFileFragment (void const** fragmentStart, 155 UINT64 fileOffset, 156 UINT64 fragmentSize, 157 OUT void** fragmentContext) 158 { 159 // We are required to do bounds checking. 160 if (fileOffset + fragmentSize > mSize) return E_FAIL; 161 162 // truncate the 64 bit fileOffset to size_t sized index into mData 163 size_t index = static_cast<size_t> (fileOffset); 164 165 // We should be alive for the duration of this. 166 *fragmentStart = &mData[index]; 167 *fragmentContext = nullptr; 168 return S_OK; 169 } 170 171 virtual void STDMETHODCALLTYPE 172 ReleaseFileFragment (void* fragmentContext) {} 173 174 virtual HRESULT STDMETHODCALLTYPE 175 GetFileSize (OUT UINT64* fileSize) 176 { 177 *fileSize = mSize; 178 return S_OK; 179 } 180 181 virtual HRESULT STDMETHODCALLTYPE 182 GetLastWriteTime (OUT UINT64* lastWriteTime) { return E_NOTIMPL; } 183 184 virtual ~DWriteFontFileStream(); 185 }; 186 187 struct hb_directwrite_global_t 188 { 189 hb_directwrite_global_t () 190 { 191 HRESULT hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), 192 (IUnknown**) &dwriteFactory); 193 194 if (unlikely (hr != S_OK)) 195 return; 196 197 fontFileLoader = new DWriteFontFileLoader (); 198 dwriteFactory->RegisterFontFileLoader (fontFileLoader); 199 200 success = true; 201 } 202 ~hb_directwrite_global_t () 203 { 204 if (fontFileLoader) 205 fontFileLoader->Release (); 206 if (dwriteFactory) 207 dwriteFactory->Release (); 208 } 209 210 bool success = false; 211 IDWriteFactory *dwriteFactory; 212 DWriteFontFileLoader *fontFileLoader; 213 }; 214 215 216 HB_INTERNAL hb_directwrite_global_t * 217 get_directwrite_global (); 218 219 HB_INTERNAL IDWriteFontFace * 220 dw_face_create (hb_blob_t *blob, unsigned index); 221 222 223 #endif /* HB_DIRECTWRITE_HH */