File: font_fallback_mac.mm

package info (click to toggle)
chromium-browser 70.0.3538.110-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,619,476 kB
  • sloc: cpp: 13,024,755; ansic: 1,349,823; python: 916,672; xml: 314,489; java: 280,047; asm: 276,936; perl: 75,771; objc: 66,634; sh: 45,860; cs: 28,354; php: 11,064; makefile: 10,911; yacc: 9,109; tcl: 8,403; ruby: 4,065; lex: 1,779; pascal: 1,411; lisp: 1,055; awk: 41; jsp: 39; sed: 17; sql: 3
file content (92 lines) | stat: -rw-r--r-- 3,378 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gfx/font_fallback.h"

#include <CoreText/CoreText.h>
#import <Foundation/Foundation.h>

#include "base/mac/foundation_util.h"
#import "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#import "base/strings/sys_string_conversions.h"
#include "ui/gfx/font.h"

namespace gfx {
namespace {

// CTFontCreateForString() sometimes re-wraps its result in a new CTFontRef with
// identical attributes. This wastes time shaping the text run and confounds
// Skia's internal typeface cache.
bool FontsEqual(CTFontRef lhs, CTFontRef rhs) {
  if (lhs == rhs)
    return true;

  // Compare ATSFontRef typeface IDs. These are typedef uint32_t. Typically if
  // RenderText decided to hunt for a fallback in the first place, this check
  // fails and FontsEqual returns here.
  if (CTFontGetPlatformFont(lhs, nil) != CTFontGetPlatformFont(rhs, nil))
    return false;

  // Comparing addresses of descriptors seems to be sufficient for other cases.
  base::ScopedCFTypeRef<CTFontDescriptorRef> lhs_descriptor(
      CTFontCopyFontDescriptor(lhs));
  base::ScopedCFTypeRef<CTFontDescriptorRef> rhs_descriptor(
      CTFontCopyFontDescriptor(rhs));
  return lhs_descriptor.get() == rhs_descriptor.get();
}

}  // namespace

std::vector<Font> GetFallbackFonts(const Font& font) {
  DCHECK(font.GetNativeFont());
  // On Mac "There is a system default cascade list (which is polymorphic, based
  // on the user's language setting and current font)" - CoreText Programming
  // Guide.
  NSArray* languages = [[NSUserDefaults standardUserDefaults]
      stringArrayForKey:@"AppleLanguages"];
  CFArrayRef languages_cf = base::mac::NSToCFCast(languages);
  base::ScopedCFTypeRef<CFArrayRef> cascade_list(
      CTFontCopyDefaultCascadeListForLanguages(
          static_cast<CTFontRef>(font.GetNativeFont()), languages_cf));

  std::vector<Font> fallback_fonts;
  if (!cascade_list)
    return fallback_fonts;  // This should only happen for an invalid |font|.

  const CFIndex fallback_count = CFArrayGetCount(cascade_list);
  for (CFIndex i = 0; i < fallback_count; ++i) {
    CTFontDescriptorRef descriptor =
        base::mac::CFCastStrict<CTFontDescriptorRef>(
            CFArrayGetValueAtIndex(cascade_list, i));
    base::ScopedCFTypeRef<CTFontRef> font(
        CTFontCreateWithFontDescriptor(descriptor, 0.0, nullptr));
    if (font.get())
      fallback_fonts.push_back(Font(static_cast<NSFont*>(font.get())));
  }

  if (fallback_fonts.empty())
    return std::vector<Font>(1, font);

  return fallback_fonts;
}

bool GetFallbackFont(const Font& font,
                     const base::char16* text,
                     int text_length,
                     Font* result) {
  base::ScopedCFTypeRef<CFStringRef> cf_string(
      CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, text, text_length,
                                         kCFAllocatorNull));
  CTFontRef ct_font = base::mac::NSToCFCast(font.GetNativeFont());
  base::ScopedCFTypeRef<CTFontRef> ct_result(
      CTFontCreateForString(ct_font, cf_string, {0, text_length}));
  if (FontsEqual(ct_font, ct_result))
    return false;

  *result = Font(base::mac::CFToNSCast(ct_result.get()));
  return true;
}

}  // namespace gfx