Bug 1866777 - Disable test_race_cache_with_network.js on windows opt for frequent...
[gecko.git] / gfx / thebes / gfxDWriteCommon.cpp
blobee81f15680ef5d6702e895646a4666d5d348a026
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/. */
6 #include "gfxDWriteCommon.h"
8 #include <unordered_map>
10 #include "mozilla/Atomics.h"
11 #include "mozilla/StaticMutex.h"
12 #include "mozilla/gfx/Logging.h"
14 class gfxDWriteFontFileStream;
16 static mozilla::StaticMutex sFontFileStreamsMutex MOZ_UNANNOTATED;
17 static uint64_t sNextFontFileKey = 0;
18 static std::unordered_map<uint64_t, gfxDWriteFontFileStream*> sFontFileStreams;
20 IDWriteFontFileLoader* gfxDWriteFontFileLoader::mInstance = nullptr;
22 class gfxDWriteFontFileStream final : public IDWriteFontFileStream {
23 public:
24 /**
25 * Used by the FontFileLoader to create a new font stream,
26 * this font stream is created from data in memory. The memory
27 * passed may be released after object creation, it will be
28 * copied internally.
30 * @param aData Font data
32 gfxDWriteFontFileStream(const uint8_t* aData, uint32_t aLength,
33 uint64_t aFontFileKey);
34 ~gfxDWriteFontFileStream();
36 // IUnknown interface
37 IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) {
38 if (iid == __uuidof(IDWriteFontFileStream)) {
39 *ppObject = static_cast<IDWriteFontFileStream*>(this);
40 return S_OK;
41 } else if (iid == __uuidof(IUnknown)) {
42 *ppObject = static_cast<IUnknown*>(this);
43 return S_OK;
44 } else {
45 return E_NOINTERFACE;
49 IFACEMETHOD_(ULONG, AddRef)() {
50 MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
51 return ++mRefCnt;
54 IFACEMETHOD_(ULONG, Release)() {
55 MOZ_ASSERT(0 != mRefCnt, "dup release");
56 uint32_t count = --mRefCnt;
57 if (count == 0) {
58 // Avoid locking unless necessary. Verify the refcount hasn't changed
59 // while locked. Delete within the scope of the lock when zero.
60 mozilla::StaticMutexAutoLock lock(sFontFileStreamsMutex);
61 if (0 != mRefCnt) {
62 return mRefCnt;
64 delete this;
66 return count;
69 // IDWriteFontFileStream methods
70 virtual HRESULT STDMETHODCALLTYPE
71 ReadFileFragment(void const** fragmentStart, UINT64 fileOffset,
72 UINT64 fragmentSize, OUT void** fragmentContext);
74 virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext);
76 virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize);
78 virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime);
80 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
81 return mData.ShallowSizeOfExcludingThis(mallocSizeOf);
84 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
85 return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
88 private:
89 FallibleTArray<uint8_t> mData;
90 mozilla::Atomic<uint32_t> mRefCnt;
91 uint64_t mFontFileKey;
94 gfxDWriteFontFileStream::gfxDWriteFontFileStream(const uint8_t* aData,
95 uint32_t aLength,
96 uint64_t aFontFileKey)
97 : mFontFileKey(aFontFileKey) {
98 // If this fails, mData will remain empty. That's OK: GetFileSize()
99 // will then return 0, etc., and the font just won't load.
100 if (!mData.AppendElements(aData, aLength, mozilla::fallible_t())) {
101 NS_WARNING("Failed to store data in gfxDWriteFontFileStream");
105 gfxDWriteFontFileStream::~gfxDWriteFontFileStream() {
106 sFontFileStreams.erase(mFontFileKey);
109 HRESULT STDMETHODCALLTYPE
110 gfxDWriteFontFileStream::GetFileSize(UINT64* fileSize) {
111 *fileSize = mData.Length();
112 return S_OK;
115 HRESULT STDMETHODCALLTYPE
116 gfxDWriteFontFileStream::GetLastWriteTime(UINT64* lastWriteTime) {
117 return E_NOTIMPL;
120 HRESULT STDMETHODCALLTYPE gfxDWriteFontFileStream::ReadFileFragment(
121 const void** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize,
122 void** fragmentContext) {
123 // We are required to do bounds checking.
124 if (fileOffset + fragmentSize > (UINT64)mData.Length()) {
125 return E_FAIL;
127 // We should be alive for the duration of this.
128 *fragmentStart = &mData[fileOffset];
129 *fragmentContext = nullptr;
130 return S_OK;
133 void STDMETHODCALLTYPE
134 gfxDWriteFontFileStream::ReleaseFileFragment(void* fragmentContext) {}
136 HRESULT STDMETHODCALLTYPE gfxDWriteFontFileLoader::CreateStreamFromKey(
137 const void* fontFileReferenceKey, UINT32 fontFileReferenceKeySize,
138 IDWriteFontFileStream** fontFileStream) {
139 if (!fontFileReferenceKey || !fontFileStream) {
140 return E_POINTER;
143 mozilla::StaticMutexAutoLock lock(sFontFileStreamsMutex);
144 uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey);
145 auto found = sFontFileStreams.find(fontFileKey);
146 if (found == sFontFileStreams.end()) {
147 *fontFileStream = nullptr;
148 return E_FAIL;
151 found->second->AddRef();
152 *fontFileStream = found->second;
153 return S_OK;
156 /* static */
157 HRESULT
158 gfxDWriteFontFileLoader::CreateCustomFontFile(
159 const uint8_t* aFontData, uint32_t aLength, IDWriteFontFile** aFontFile,
160 IDWriteFontFileStream** aFontFileStream) {
161 MOZ_ASSERT(aFontFile);
162 MOZ_ASSERT(aFontFileStream);
164 RefPtr<IDWriteFactory> factory = mozilla::gfx::Factory::GetDWriteFactory();
165 if (!factory) {
166 gfxCriticalError()
167 << "Failed to get DWrite Factory in CreateCustomFontFile.";
168 return E_FAIL;
171 sFontFileStreamsMutex.Lock();
172 uint64_t fontFileKey = sNextFontFileKey++;
173 RefPtr<gfxDWriteFontFileStream> ffsRef =
174 new gfxDWriteFontFileStream(aFontData, aLength, fontFileKey);
175 sFontFileStreams[fontFileKey] = ffsRef;
176 sFontFileStreamsMutex.Unlock();
178 RefPtr<IDWriteFontFile> fontFile;
179 HRESULT hr = factory->CreateCustomFontFileReference(
180 &fontFileKey, sizeof(fontFileKey), Instance(), getter_AddRefs(fontFile));
181 if (FAILED(hr)) {
182 NS_WARNING("Failed to load font file from data!");
183 return hr;
186 fontFile.forget(aFontFile);
187 ffsRef.forget(aFontFileStream);
189 return S_OK;
192 size_t gfxDWriteFontFileLoader::SizeOfIncludingThis(
193 mozilla::MallocSizeOf mallocSizeOf) const {
194 size_t sizes = mallocSizeOf(this);
196 // We are a singleton type that is effective owner of sFontFileStreams.
197 MOZ_ASSERT(this == mInstance);
198 for (const auto& entry : sFontFileStreams) {
199 gfxDWriteFontFileStream* fileStream = entry.second;
200 sizes += fileStream->SizeOfIncludingThis(mallocSizeOf);
203 return sizes;