Update configs. IGNORE BROKEN CHANGESETS CLOSED TREE NO BUG a=release ba=release
[gecko.git] / gfx / 2d / NativeFontResourceMac.cpp
blob51e5afa4f57d386bfb71b4b8b722f43f908b4e78
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <unordered_map>
8 #include <unordered_set>
9 #include "NativeFontResourceMac.h"
10 #include "UnscaledFontMac.h"
11 #include "Types.h"
13 #include "mozilla/RefPtr.h"
14 #include "mozilla/DataMutex.h"
16 #ifdef MOZ_WIDGET_UIKIT
17 # include <CoreFoundation/CoreFoundation.h>
18 #endif
20 #include "nsIMemoryReporter.h"
22 namespace mozilla {
23 namespace gfx {
25 #define FONT_NAME_MAX 32
26 MOZ_RUNINIT static StaticDataMutex<
27 std::unordered_map<void*, nsAutoCStringN<FONT_NAME_MAX>>>
28 sWeakFontDataMap("WeakFonts");
30 void FontDataDeallocate(void*, void* info) {
31 auto fontMap = sWeakFontDataMap.Lock();
32 fontMap->erase(info);
33 free(info);
36 class NativeFontResourceMacReporter final : public nsIMemoryReporter {
37 ~NativeFontResourceMacReporter() = default;
39 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
40 public:
41 NS_DECL_ISUPPORTS
43 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
44 nsISupports* aData, bool aAnonymize) override {
45 auto fontMap = sWeakFontDataMap.Lock();
47 nsAutoCString path("explicit/gfx/native-font-resource-mac/font(");
49 unsigned int unknownFontIndex = 0;
50 for (auto& i : *fontMap) {
51 nsAutoCString subPath(path);
53 if (aAnonymize) {
54 subPath.AppendPrintf("<anonymized-%p>", this);
55 } else {
56 if (i.second.Length()) {
57 subPath.AppendLiteral("psname=");
58 subPath.Append(i.second);
59 } else {
60 subPath.AppendPrintf("Unknown(%d)", unknownFontIndex);
64 size_t bytes = MallocSizeOf(i.first) + FONT_NAME_MAX;
66 subPath.Append(")");
68 aHandleReport->Callback(""_ns, subPath, KIND_HEAP, UNITS_BYTES, bytes,
69 "Memory used by this native font."_ns, aData);
71 unknownFontIndex++;
73 return NS_OK;
77 NS_IMPL_ISUPPORTS(NativeFontResourceMacReporter, nsIMemoryReporter)
79 void NativeFontResourceMac::RegisterMemoryReporter() {
80 RegisterStrongMemoryReporter(new NativeFontResourceMacReporter);
83 /* static */
84 already_AddRefed<NativeFontResourceMac> NativeFontResourceMac::Create(
85 uint8_t* aFontData, uint32_t aDataLength) {
86 uint8_t* fontData = (uint8_t*)malloc(aDataLength);
87 if (!fontData) {
88 return nullptr;
90 memcpy(fontData, aFontData, aDataLength);
91 CFAllocatorContext context = {0, fontData, nullptr, nullptr,
92 nullptr, nullptr, nullptr, FontDataDeallocate,
93 nullptr};
94 CFAllocatorRef allocator = CFAllocatorCreate(kCFAllocatorDefault, &context);
96 // We create a CFDataRef here that we'l hold until we've determined that we
97 // have a valid font. If and only if we can create a font from the data,
98 // we'll store the font data in our map. Whether or not the font is valid,
99 // we'll later release this CFDataRef.
100 CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, fontData,
101 aDataLength, allocator);
102 if (!data) {
103 free(fontData);
104 return nullptr;
107 CTFontDescriptorRef ctFontDesc =
108 CTFontManagerCreateFontDescriptorFromData(data);
109 if (!ctFontDesc) {
110 CFRelease(data);
111 return nullptr;
114 // creating the CGFontRef via the CTFont avoids the data being held alive
115 // in a cache.
116 CTFontRef ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
118 // Creating the CGFont from the CTFont prevents the font data from being
119 // held in the TDescriptorSource cache. This appears to be true even
120 // if we later create a CTFont from the CGFont.
121 CGFontRef fontRef = CTFontCopyGraphicsFont(ctFont, NULL);
122 CFRelease(ctFont);
124 if (!fontRef) {
125 // Not a valid font; release the structures we've been holding.
126 CFRelease(data);
127 CFRelease(ctFontDesc);
128 return nullptr;
131 // Determine the font name and store it with the font data in the map.
132 nsAutoCStringN<FONT_NAME_MAX> fontName;
134 CFStringRef psname = CGFontCopyPostScriptName(fontRef);
135 if (psname) {
136 const char* cstr = CFStringGetCStringPtr(psname, kCFStringEncodingUTF8);
137 if (cstr) {
138 fontName.Assign(cstr);
139 } else {
140 char buf[FONT_NAME_MAX];
141 if (CFStringGetCString(psname, buf, FONT_NAME_MAX,
142 kCFStringEncodingUTF8)) {
143 fontName.Assign(buf);
146 CFRelease(psname);
150 auto fontMap = sWeakFontDataMap.Lock();
151 void* key = (void*)fontData;
152 fontMap->insert({key, fontName});
154 // It's now safe to release our CFDataRef.
155 CFRelease(data);
157 // passes ownership of fontRef to the NativeFontResourceMac instance
158 RefPtr<NativeFontResourceMac> fontResource =
159 new NativeFontResourceMac(ctFontDesc, fontRef, aDataLength);
161 return fontResource.forget();
164 already_AddRefed<UnscaledFont> NativeFontResourceMac::CreateUnscaledFont(
165 uint32_t aIndex, const uint8_t* aInstanceData,
166 uint32_t aInstanceDataLength) {
167 RefPtr<UnscaledFont> unscaledFont =
168 new UnscaledFontMac(mFontDescRef, mFontRef, true);
170 return unscaledFont.forget();
173 } // namespace gfx
174 } // namespace mozilla