blob: d5f80e0519e5f47f74c928ad4f9e7617a5b6e831 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/font_access/font_enumeration_data_source_mac.h"
#import <CoreFoundation/CoreFoundation.h>
#import <CoreText/CoreText.h>
#include "third_party/blink/public/common/font_access/font_enumeration_table.pb.h"
#include <string>
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/notreached.h"
#include "base/strings/sys_string_conversions.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
namespace {
base::ScopedCFTypeRef<CFStringRef> GetLocalizedString(CTFontDescriptorRef fd,
CFStringRef attribute) {
return base::ScopedCFTypeRef<CFStringRef>(base::mac::CFCast<CFStringRef>(
CTFontDescriptorCopyLocalizedAttribute(fd, attribute, nullptr)));
}
base::ScopedCFTypeRef<CFStringRef> GetString(CTFontDescriptorRef fd,
CFStringRef attribute) {
return base::ScopedCFTypeRef<CFStringRef>(base::mac::CFCast<CFStringRef>(
CTFontDescriptorCopyAttribute(fd, attribute)));
}
} // namespace
FontEnumerationDataSourceMac::FontEnumerationDataSourceMac() {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
FontEnumerationDataSourceMac::~FontEnumerationDataSourceMac() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
blink::FontEnumerationTable FontEnumerationDataSourceMac::GetFonts(
const std::string& locale) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
blink::FontEnumerationTable font_enumeration_table;
@autoreleasepool {
CFTypeRef values[1] = {kCFBooleanTrue};
base::ScopedCFTypeRef<CFDictionaryRef> options(CFDictionaryCreate(
kCFAllocatorDefault,
(const void**)kCTFontCollectionRemoveDuplicatesOption,
(const void**)&values,
/*numValues=*/1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
base::ScopedCFTypeRef<CTFontCollectionRef> collection(
CTFontCollectionCreateFromAvailableFonts(options));
base::ScopedCFTypeRef<CFArrayRef> font_descs(
CTFontCollectionCreateMatchingFontDescriptors(collection));
// Used to filter duplicates.
std::set<std::string> fonts_seen;
for (CFIndex i = 0; i < CFArrayGetCount(font_descs); ++i) {
CTFontDescriptorRef fd = base::mac::CFCast<CTFontDescriptorRef>(
CFArrayGetValueAtIndex(font_descs, i));
base::ScopedCFTypeRef<CFStringRef> cf_postscript_name =
GetString(fd, kCTFontNameAttribute);
base::ScopedCFTypeRef<CFStringRef> cf_full_name =
GetLocalizedString(fd, kCTFontDisplayNameAttribute);
base::ScopedCFTypeRef<CFStringRef> cf_family =
GetString(fd, kCTFontFamilyNameAttribute);
base::ScopedCFTypeRef<CFStringRef> cf_style =
GetString(fd, kCTFontStyleNameAttribute);
std::string postscript_name =
base::SysCFStringRefToUTF8(cf_postscript_name.get());
auto it_and_success = fonts_seen.emplace(postscript_name);
if (!it_and_success.second) {
// Skip duplicate.
continue;
}
blink::FontEnumerationTable_FontData* data =
font_enumeration_table.add_fonts();
data->set_postscript_name(std::move(postscript_name));
data->set_full_name(base::SysCFStringRefToUTF8(cf_full_name.get()));
data->set_family(base::SysCFStringRefToUTF8(cf_family.get()));
data->set_style(base::SysCFStringRefToUTF8(cf_style.get()));
}
return font_enumeration_table;
}
}
} // namespace content