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_set>
8 #include "NativeFontResourceMac.h"
9 #include "UnscaledFontMac.h"
12 #include "mozilla/RefPtr.h"
13 #include "mozilla/DataMutex.h"
15 #ifdef MOZ_WIDGET_UIKIT
16 # include <CoreFoundation/CoreFoundation.h>
19 #include "nsIMemoryReporter.h"
20 #include "nsCocoaFeatures.h"
25 #define FONT_NAME_MAX 32
26 static StaticDataMutex
<std::unordered_map
<void*, nsAutoCStringN
<FONT_NAME_MAX
>>>
27 sWeakFontDataMap("WeakFonts");
29 void FontDataDeallocate(void*, void* info
) {
30 auto fontMap
= sWeakFontDataMap
.Lock();
35 class NativeFontResourceMacReporter final
: public nsIMemoryReporter
{
36 ~NativeFontResourceMacReporter() = default;
38 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf
)
42 NS_IMETHOD
CollectReports(nsIHandleReportCallback
* aHandleReport
,
43 nsISupports
* aData
, bool aAnonymize
) override
{
44 auto fontMap
= sWeakFontDataMap
.Lock();
46 nsAutoCString
path("explicit/gfx/native-font-resource-mac/font(");
48 unsigned int unknownFontIndex
= 0;
49 for (auto& i
: *fontMap
) {
50 nsAutoCString
subPath(path
);
53 subPath
.AppendPrintf("<anonymized-%p>", this);
55 if (i
.second
.Length()) {
56 subPath
.AppendLiteral("psname=");
57 subPath
.Append(i
.second
);
59 subPath
.AppendPrintf("Unknown(%d)", unknownFontIndex
);
63 size_t bytes
= MallocSizeOf(i
.first
) + FONT_NAME_MAX
;
67 aHandleReport
->Callback(""_ns
, subPath
, KIND_HEAP
, UNITS_BYTES
, bytes
,
68 "Memory used by this native font."_ns
, aData
);
76 NS_IMPL_ISUPPORTS(NativeFontResourceMacReporter
, nsIMemoryReporter
)
78 void NativeFontResourceMac::RegisterMemoryReporter() {
79 RegisterStrongMemoryReporter(new NativeFontResourceMacReporter
);
83 already_AddRefed
<NativeFontResourceMac
> NativeFontResourceMac::Create(
84 uint8_t* aFontData
, uint32_t aDataLength
) {
85 uint8_t* fontData
= (uint8_t*)malloc(aDataLength
);
89 memcpy(fontData
, aFontData
, aDataLength
);
90 CFAllocatorContext context
= {0, fontData
, nullptr, nullptr,
91 nullptr, nullptr, nullptr, FontDataDeallocate
,
93 CFAllocatorRef allocator
= CFAllocatorCreate(kCFAllocatorDefault
, &context
);
95 // We create a CFDataRef here that we'l hold until we've determined that we
96 // have a valid font. If and only if we can create a font from the data,
97 // we'll store the font data in our map. Whether or not the font is valid,
98 // we'll later release this CFDataRef.
99 CFDataRef data
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, fontData
,
100 aDataLength
, allocator
);
106 CTFontDescriptorRef ctFontDesc
=
107 CTFontManagerCreateFontDescriptorFromData(data
);
113 // creating the CGFontRef via the CTFont avoids the data being held alive
115 CTFontRef ctFont
= CTFontCreateWithFontDescriptor(ctFontDesc
, 0, NULL
);
117 // Creating the CGFont from the CTFont prevents the font data from being
118 // held in the TDescriptorSource cache. This appears to be true even
119 // if we later create a CTFont from the CGFont.
120 CGFontRef fontRef
= CTFontCopyGraphicsFont(ctFont
, NULL
);
124 // Not a valid font; release the structures we've been holding.
126 CFRelease(ctFontDesc
);
130 // Determine the font name and store it with the font data in the map.
131 nsAutoCStringN
<FONT_NAME_MAX
> fontName
;
133 CFStringRef psname
= CGFontCopyPostScriptName(fontRef
);
135 const char* cstr
= CFStringGetCStringPtr(psname
, kCFStringEncodingUTF8
);
137 fontName
.Assign(cstr
);
139 char buf
[FONT_NAME_MAX
];
140 if (CFStringGetCString(psname
, buf
, FONT_NAME_MAX
,
141 kCFStringEncodingUTF8
)) {
142 fontName
.Assign(buf
);
149 auto fontMap
= sWeakFontDataMap
.Lock();
150 void* key
= (void*)fontData
;
151 fontMap
->insert({key
, fontName
});
153 // It's now safe to release our CFDataRef.
156 // passes ownership of fontRef to the NativeFontResourceMac instance
157 RefPtr
<NativeFontResourceMac
> fontResource
=
158 new NativeFontResourceMac(ctFontDesc
, fontRef
, aDataLength
);
160 return fontResource
.forget();
163 already_AddRefed
<UnscaledFont
> NativeFontResourceMac::CreateUnscaledFont(
164 uint32_t aIndex
, const uint8_t* aInstanceData
,
165 uint32_t aInstanceDataLength
) {
166 RefPtr
<UnscaledFont
> unscaledFont
=
167 new UnscaledFontMac(mFontDescRef
, mFontRef
, true);
169 return unscaledFont
.forget();
173 } // namespace mozilla