gfxDWriteCommon.cpp (4738B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "gfxDWriteCommon.h" 7 8 #include <unordered_map> 9 10 #include "mozilla/StaticMutex.h" 11 #include "mozilla/gfx/Logging.h" 12 13 class gfxDWriteFontFileStream; 14 15 using namespace mozilla; 16 17 static StaticMutex sFontFileStreamsMutex MOZ_UNANNOTATED; 18 static uint64_t sNextFontFileKey = 0; 19 MOZ_RUNINIT static std::unordered_map<uint64_t, gfxDWriteFontFileStream*> 20 sFontFileStreams; 21 22 IDWriteFontFileLoader* gfxDWriteFontFileLoader::mInstance = nullptr; 23 24 IFACEMETHODIMP_(ULONG) gfxDWriteFontFileStream::Release() { 25 MOZ_ASSERT(0 != mRefCnt, "dup release"); 26 uint32_t count = --mRefCnt; 27 if (count == 0) { 28 // Avoid locking unless necessary. Verify the refcount hasn't changed 29 // while locked. Delete within the scope of the lock when zero. 30 StaticMutexAutoLock lock(sFontFileStreamsMutex); 31 if (0 != mRefCnt) { 32 return mRefCnt; 33 } 34 delete this; 35 } 36 return count; 37 } 38 39 gfxDWriteFontFileStream::gfxDWriteFontFileStream(const uint8_t* aData, 40 uint32_t aLength, 41 uint64_t aFontFileKey) 42 : mFontFileKey(aFontFileKey) { 43 // If this fails, mData will remain empty. That's OK: GetFileSize() 44 // will then return 0, etc., and the font just won't load. 45 if (!mData.AppendElements(aData, aLength, fallible_t())) { 46 NS_WARNING("Failed to store data in gfxDWriteFontFileStream"); 47 } 48 } 49 50 gfxDWriteFontFileStream::~gfxDWriteFontFileStream() { 51 sFontFileStreams.erase(mFontFileKey); 52 } 53 54 HRESULT STDMETHODCALLTYPE 55 gfxDWriteFontFileStream::GetFileSize(UINT64* fileSize) { 56 *fileSize = mData.Length(); 57 return S_OK; 58 } 59 60 HRESULT STDMETHODCALLTYPE 61 gfxDWriteFontFileStream::GetLastWriteTime(UINT64* lastWriteTime) { 62 return E_NOTIMPL; 63 } 64 65 HRESULT STDMETHODCALLTYPE gfxDWriteFontFileStream::ReadFileFragment( 66 const void** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize, 67 void** fragmentContext) { 68 // We are required to do bounds checking. 69 if (fileOffset + fragmentSize > (UINT64)mData.Length()) { 70 return E_FAIL; 71 } 72 // We should be alive for the duration of this. 73 *fragmentStart = &mData[fileOffset]; 74 *fragmentContext = nullptr; 75 return S_OK; 76 } 77 78 void STDMETHODCALLTYPE 79 gfxDWriteFontFileStream::ReleaseFileFragment(void* fragmentContext) {} 80 81 HRESULT STDMETHODCALLTYPE gfxDWriteFontFileLoader::CreateStreamFromKey( 82 const void* fontFileReferenceKey, UINT32 fontFileReferenceKeySize, 83 IDWriteFontFileStream** fontFileStream) { 84 if (!fontFileReferenceKey || !fontFileStream) { 85 return E_POINTER; 86 } 87 88 StaticMutexAutoLock lock(sFontFileStreamsMutex); 89 uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey); 90 auto found = sFontFileStreams.find(fontFileKey); 91 if (found == sFontFileStreams.end()) { 92 *fontFileStream = nullptr; 93 return E_FAIL; 94 } 95 96 found->second->AddRef(); 97 *fontFileStream = found->second; 98 return S_OK; 99 } 100 101 /* static */ 102 HRESULT 103 gfxDWriteFontFileLoader::CreateCustomFontFile( 104 const uint8_t* aFontData, uint32_t aLength, IDWriteFontFile** aFontFile, 105 gfxDWriteFontFileStream** aFontFileStream) { 106 MOZ_ASSERT(aFontFile); 107 MOZ_ASSERT(aFontFileStream); 108 109 RefPtr<IDWriteFactory> factory = gfx::Factory::GetDWriteFactory(); 110 if (!factory) { 111 gfxCriticalError() 112 << "Failed to get DWrite Factory in CreateCustomFontFile."; 113 return E_FAIL; 114 } 115 116 sFontFileStreamsMutex.Lock(); 117 uint64_t fontFileKey = sNextFontFileKey++; 118 RefPtr<gfxDWriteFontFileStream> ffsRef = 119 new gfxDWriteFontFileStream(aFontData, aLength, fontFileKey); 120 sFontFileStreams[fontFileKey] = ffsRef; 121 sFontFileStreamsMutex.Unlock(); 122 123 RefPtr<IDWriteFontFile> fontFile; 124 HRESULT hr = factory->CreateCustomFontFileReference( 125 &fontFileKey, sizeof(fontFileKey), Instance(), getter_AddRefs(fontFile)); 126 if (FAILED(hr)) { 127 NS_WARNING("Failed to load font file from data!"); 128 return hr; 129 } 130 131 fontFile.forget(aFontFile); 132 ffsRef.forget(aFontFileStream); 133 134 return S_OK; 135 } 136 137 size_t gfxDWriteFontFileLoader::SizeOfIncludingThis( 138 MallocSizeOf mallocSizeOf) const { 139 // We are a singleton type that is effective owner of sFontFileStreams. 140 MOZ_ASSERT(this == mInstance); 141 142 size_t sizes = mallocSizeOf(this); 143 144 // We don't have memory-reporting methods for a std::unordered_map, so just 145 // take the size of the actual elements stored for now. 146 sizes += sFontFileStreams.size() * 147 (sizeof(uint64_t) + sizeof(gfxDWriteFontFileStream*)); 148 149 return sizes; 150 }