mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			173 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include <unordered_map>
 | 
						|
#include <unordered_set>
 | 
						|
#include "NativeFontResourceMac.h"
 | 
						|
#include "UnscaledFontMac.h"
 | 
						|
#include "Types.h"
 | 
						|
 | 
						|
#include "mozilla/RefPtr.h"
 | 
						|
#include "mozilla/DataMutex.h"
 | 
						|
 | 
						|
#ifdef MOZ_WIDGET_UIKIT
 | 
						|
#  include <CoreFoundation/CoreFoundation.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "nsIMemoryReporter.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace gfx {
 | 
						|
 | 
						|
#define FONT_NAME_MAX 32
 | 
						|
static StaticDataMutex<std::unordered_map<void*, nsAutoCStringN<FONT_NAME_MAX>>>
 | 
						|
    sWeakFontDataMap("WeakFonts");
 | 
						|
 | 
						|
void FontDataDeallocate(void*, void* info) {
 | 
						|
  auto fontMap = sWeakFontDataMap.Lock();
 | 
						|
  fontMap->erase(info);
 | 
						|
  free(info);
 | 
						|
}
 | 
						|
 | 
						|
class NativeFontResourceMacReporter final : public nsIMemoryReporter {
 | 
						|
  ~NativeFontResourceMacReporter() = default;
 | 
						|
 | 
						|
  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
 | 
						|
 public:
 | 
						|
  NS_DECL_ISUPPORTS
 | 
						|
 | 
						|
  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
 | 
						|
                            nsISupports* aData, bool aAnonymize) override {
 | 
						|
    auto fontMap = sWeakFontDataMap.Lock();
 | 
						|
 | 
						|
    nsAutoCString path("explicit/gfx/native-font-resource-mac/font(");
 | 
						|
 | 
						|
    unsigned int unknownFontIndex = 0;
 | 
						|
    for (auto& i : *fontMap) {
 | 
						|
      nsAutoCString subPath(path);
 | 
						|
 | 
						|
      if (aAnonymize) {
 | 
						|
        subPath.AppendPrintf("<anonymized-%p>", this);
 | 
						|
      } else {
 | 
						|
        if (i.second.Length()) {
 | 
						|
          subPath.AppendLiteral("psname=");
 | 
						|
          subPath.Append(i.second);
 | 
						|
        } else {
 | 
						|
          subPath.AppendPrintf("Unknown(%d)", unknownFontIndex);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      size_t bytes = MallocSizeOf(i.first) + FONT_NAME_MAX;
 | 
						|
 | 
						|
      subPath.Append(")");
 | 
						|
 | 
						|
      aHandleReport->Callback(""_ns, subPath, KIND_HEAP, UNITS_BYTES, bytes,
 | 
						|
                              "Memory used by this native font."_ns, aData);
 | 
						|
 | 
						|
      unknownFontIndex++;
 | 
						|
    }
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS(NativeFontResourceMacReporter, nsIMemoryReporter)
 | 
						|
 | 
						|
void NativeFontResourceMac::RegisterMemoryReporter() {
 | 
						|
  RegisterStrongMemoryReporter(new NativeFontResourceMacReporter);
 | 
						|
}
 | 
						|
 | 
						|
/* static */
 | 
						|
already_AddRefed<NativeFontResourceMac> NativeFontResourceMac::Create(
 | 
						|
    uint8_t* aFontData, uint32_t aDataLength) {
 | 
						|
  uint8_t* fontData = (uint8_t*)malloc(aDataLength);
 | 
						|
  if (!fontData) {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
  memcpy(fontData, aFontData, aDataLength);
 | 
						|
  CFAllocatorContext context = {0,       fontData, nullptr, nullptr,
 | 
						|
                                nullptr, nullptr,  nullptr, FontDataDeallocate,
 | 
						|
                                nullptr};
 | 
						|
  CFAllocatorRef allocator = CFAllocatorCreate(kCFAllocatorDefault, &context);
 | 
						|
 | 
						|
  // We create a CFDataRef here that we'l hold until we've determined that we
 | 
						|
  // have a valid font. If and only if we can create a font from the data,
 | 
						|
  // we'll store the font data in our map. Whether or not the font is valid,
 | 
						|
  // we'll later release this CFDataRef.
 | 
						|
  CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, fontData,
 | 
						|
                                               aDataLength, allocator);
 | 
						|
  if (!data) {
 | 
						|
    free(fontData);
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  CTFontDescriptorRef ctFontDesc =
 | 
						|
      CTFontManagerCreateFontDescriptorFromData(data);
 | 
						|
  if (!ctFontDesc) {
 | 
						|
    CFRelease(data);
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  // creating the CGFontRef via the CTFont avoids the data being held alive
 | 
						|
  // in a cache.
 | 
						|
  CTFontRef ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
 | 
						|
 | 
						|
  // Creating the CGFont from the CTFont prevents the font data from being
 | 
						|
  // held in the TDescriptorSource cache. This appears to be true even
 | 
						|
  // if we later create a CTFont from the CGFont.
 | 
						|
  CGFontRef fontRef = CTFontCopyGraphicsFont(ctFont, NULL);
 | 
						|
  CFRelease(ctFont);
 | 
						|
 | 
						|
  if (!fontRef) {
 | 
						|
    // Not a valid font; release the structures we've been holding.
 | 
						|
    CFRelease(data);
 | 
						|
    CFRelease(ctFontDesc);
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  // Determine the font name and store it with the font data in the map.
 | 
						|
  nsAutoCStringN<FONT_NAME_MAX> fontName;
 | 
						|
 | 
						|
  CFStringRef psname = CGFontCopyPostScriptName(fontRef);
 | 
						|
  if (psname) {
 | 
						|
    const char* cstr = CFStringGetCStringPtr(psname, kCFStringEncodingUTF8);
 | 
						|
    if (cstr) {
 | 
						|
      fontName.Assign(cstr);
 | 
						|
    } else {
 | 
						|
      char buf[FONT_NAME_MAX];
 | 
						|
      if (CFStringGetCString(psname, buf, FONT_NAME_MAX,
 | 
						|
                             kCFStringEncodingUTF8)) {
 | 
						|
        fontName.Assign(buf);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    CFRelease(psname);
 | 
						|
  }
 | 
						|
 | 
						|
  {
 | 
						|
    auto fontMap = sWeakFontDataMap.Lock();
 | 
						|
    void* key = (void*)fontData;
 | 
						|
    fontMap->insert({key, fontName});
 | 
						|
  }
 | 
						|
  // It's now safe to release our CFDataRef.
 | 
						|
  CFRelease(data);
 | 
						|
 | 
						|
  // passes ownership of fontRef to the NativeFontResourceMac instance
 | 
						|
  RefPtr<NativeFontResourceMac> fontResource =
 | 
						|
      new NativeFontResourceMac(ctFontDesc, fontRef, aDataLength);
 | 
						|
 | 
						|
  return fontResource.forget();
 | 
						|
}
 | 
						|
 | 
						|
already_AddRefed<UnscaledFont> NativeFontResourceMac::CreateUnscaledFont(
 | 
						|
    uint32_t aIndex, const uint8_t* aInstanceData,
 | 
						|
    uint32_t aInstanceDataLength) {
 | 
						|
  RefPtr<UnscaledFont> unscaledFont =
 | 
						|
      new UnscaledFontMac(mFontDescRef, mFontRef, true);
 | 
						|
 | 
						|
  return unscaledFont.forget();
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace gfx
 | 
						|
}  // namespace mozilla
 |