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"
13 #include "mozilla/RefPtr.h"
14 #include "mozilla/DataMutex.h"
16 #ifdef MOZ_WIDGET_UIKIT
17 # include <CoreFoundation/CoreFoundation.h>
20 #include "nsIMemoryReporter.h"
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();
36 class NativeFontResourceMacReporter final
: public nsIMemoryReporter
{
37 ~NativeFontResourceMacReporter() = default;
39 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf
)
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
);
54 subPath
.AppendPrintf("<anonymized-%p>", this);
56 if (i
.second
.Length()) {
57 subPath
.AppendLiteral("psname=");
58 subPath
.Append(i
.second
);
60 subPath
.AppendPrintf("Unknown(%d)", unknownFontIndex
);
64 size_t bytes
= MallocSizeOf(i
.first
) + FONT_NAME_MAX
;
68 aHandleReport
->Callback(""_ns
, subPath
, KIND_HEAP
, UNITS_BYTES
, bytes
,
69 "Memory used by this native font."_ns
, aData
);
77 NS_IMPL_ISUPPORTS(NativeFontResourceMacReporter
, nsIMemoryReporter
)
79 void NativeFontResourceMac::RegisterMemoryReporter() {
80 RegisterStrongMemoryReporter(new NativeFontResourceMacReporter
);
84 already_AddRefed
<NativeFontResourceMac
> NativeFontResourceMac::Create(
85 uint8_t* aFontData
, uint32_t aDataLength
) {
86 uint8_t* fontData
= (uint8_t*)malloc(aDataLength
);
90 memcpy(fontData
, aFontData
, aDataLength
);
91 CFAllocatorContext context
= {0, fontData
, nullptr, nullptr,
92 nullptr, nullptr, nullptr, FontDataDeallocate
,
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
);
107 CTFontDescriptorRef ctFontDesc
=
108 CTFontManagerCreateFontDescriptorFromData(data
);
114 // creating the CGFontRef via the CTFont avoids the data being held alive
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
);
125 // Not a valid font; release the structures we've been holding.
127 CFRelease(ctFontDesc
);
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
);
136 const char* cstr
= CFStringGetCStringPtr(psname
, kCFStringEncodingUTF8
);
138 fontName
.Assign(cstr
);
140 char buf
[FONT_NAME_MAX
];
141 if (CFStringGetCString(psname
, buf
, FONT_NAME_MAX
,
142 kCFStringEncodingUTF8
)) {
143 fontName
.Assign(buf
);
150 auto fontMap
= sWeakFontDataMap
.Lock();
151 void* key
= (void*)fontData
;
152 fontMap
->insert({key
, fontName
});
154 // It's now safe to release our CFDataRef.
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();
174 } // namespace mozilla