Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1147)

Side by Side Diff: ui/gfx/platform_font_mac.mm

Issue 2898613002: Revert of Support finer grained font weights on Mac. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ui/gfx/platform_font_mac_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/platform_font_mac.h" 5 #include "ui/gfx/platform_font_mac.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include <Cocoa/Cocoa.h> 9 #include <Cocoa/Cocoa.h>
10 10
11 #import "base/mac/foundation_util.h" 11 #include "base/mac/scoped_nsobject.h"
12 #include "base/mac/scoped_cftyperef.h"
13 #import "base/mac/scoped_nsobject.h"
14 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
16 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/font.h" 15 #include "ui/gfx/font.h"
18 #include "ui/gfx/font_render_params.h" 16 #include "ui/gfx/font_render_params.h"
19 17
20 namespace gfx { 18 namespace gfx {
21 19
22 namespace { 20 namespace {
23 21
24 // How to get from NORMAL weight to a fine-grained font weight using calls to
25 // -[NSFontManager convertWeight:(BOOL)upFlag ofFont:(NSFont)].
26 struct WeightSolver {
27 int steps_up; // Times to call with upFlag:YES.
28 int steps_down; // Times to call with upFlag:NO.
29 // Either NORMAL or BOLD: whether to set the NSBoldFontMask symbolic trait.
30 Font::Weight nearest;
31 };
32
33 // Solve changes to the font weight according to the following table, from
34 // https://developer.apple.com/reference/appkit/nsfontmanager/1462321-convertwei ght
35 // 1. ultralight | none
36 // 2. thin | W1. ultralight
37 // 3. light, extralight | W2. extralight
38 // 4. book | W3. light
39 // 5. regular, plain, display, roman | W4. semilight
40 // 6. medium | W5. medium
41 // 7. demi, demibold | none
42 // 8. semi, semibold | W6. semibold
43 // 9. bold | W7. bold
44 // 10. extra, extrabold | W8. extrabold
45 // 11. heavy, heavyface | none
46 // 12. black, super | W9. ultrabold
47 // 13. ultra, ultrablack, fat | none
48 // 14. extrablack, obese, nord | none
49 WeightSolver WeightChangeFromNormal(Font::Weight desired) {
50 using Weight = Font::Weight;
51 switch (desired) {
52 case Weight::THIN:
53 // It's weird, but to get LIGHT and THIN fonts, first go up a step.
54 // Without this, the font stays stuck at NORMAL. See
55 // PlatformFontMacTest, FontWeightAPIConsistency.
56 return {1, 3, Weight::NORMAL};
57 case Weight::EXTRA_LIGHT:
58 return {1, 2, Weight::NORMAL};
59 case Weight::LIGHT:
60 return {1, 1, Weight::NORMAL};
61 case Weight::NORMAL:
62 return {0, 0, Weight::NORMAL};
63 case Weight::MEDIUM:
64 return {1, 0, Weight::NORMAL};
65 case Weight::SEMIBOLD:
66 return {0, 1, Weight::BOLD};
67 case Weight::BOLD:
68 return {0, 0, Weight::BOLD};
69 case Weight::EXTRA_BOLD:
70 return {1, 0, Weight::BOLD};
71 case Weight::BLACK:
72 return {3, 0, Weight::BOLD}; // Skip row 12.
73 case Weight::INVALID:
74 return {0, 0, Weight::NORMAL};
75 }
76 }
77
78 // Returns the font style for |font|. Disregards Font::UNDERLINE, since NSFont 22 // Returns the font style for |font|. Disregards Font::UNDERLINE, since NSFont
79 // does not support it as a trait. 23 // does not support it as a trait.
80 int GetFontStyleFromNSFont(NSFont* font) { 24 int GetFontStyleFromNSFont(NSFont* font) {
81 int font_style = Font::NORMAL; 25 int font_style = Font::NORMAL;
82 NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits]; 26 NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits];
83 if (traits & NSFontItalicTrait) 27 if (traits & NSFontItalicTrait)
84 font_style |= Font::ITALIC; 28 font_style |= Font::ITALIC;
85 return font_style; 29 return font_style;
86 } 30 }
87 31
88 // Returns the Font weight for |font|. 32 // Returns the Font weight for |font|.
89 Font::Weight GetFontWeightFromNSFont(NSFont* font) { 33 Font::Weight GetFontWeightFromNSFont(NSFont* font) {
90 if (!font) 34 NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits];
91 return Font::Weight::INVALID; 35 return (traits & NSFontBoldTrait) ? Font::Weight::BOLD : Font::Weight::NORMAL;
92
93 // Map CoreText weights in a manner similar to ct_weight_to_fontstyle() from
94 // SkFontHost_mac.cpp, but adjust for MEDIUM so that the San Francisco's
95 // custom MEDIUM weight can be picked out. San Francisco has weights:
96 // [0.23, 0.23, 0.3, 0.4, 0.56, 0.62, 0.62, ...] (no thin weights).
97 // See PlatformFontMacTest.FontWeightAPIConsistency for details.
98 // Note that the table Skia uses is also determined by experiment.
99 constexpr struct {
100 CGFloat ct_weight;
101 Font::Weight gfx_weight;
102 } weight_map[] = {
103 // Missing: Apple "ultralight".
104 {-0.70, Font::Weight::THIN},
105 {-0.50, Font::Weight::EXTRA_LIGHT},
106 {-0.23, Font::Weight::LIGHT},
107 {0.00, Font::Weight::NORMAL},
108 {0.23, Font::Weight::MEDIUM}, // Note: adjusted from 0.20 vs Skia.
109 // Missing: Apple "demibold".
110 {0.30, Font::Weight::SEMIBOLD},
111 {0.40, Font::Weight::BOLD},
112 {0.60, Font::Weight::EXTRA_BOLD},
113 // Missing: Apple "heavyface".
114 // Values will be capped to BLACK (this entry is here for consistency).
115 {0.80, Font::Weight::BLACK},
116 // Missing: Apple "ultrablack".
117 // Missing: Apple "extrablack".
118 };
119 base::ScopedCFTypeRef<CFDictionaryRef> traits(
120 CTFontCopyTraits(base::mac::NSToCFCast(font)));
121 DCHECK(traits);
122 CFNumberRef cf_weight = base::mac::GetValueFromDictionary<CFNumberRef>(
123 traits, kCTFontWeightTrait);
124 // A missing weight attribute just means 0 -> NORMAL.
125 if (!cf_weight)
126 return Font::Weight::NORMAL;
127
128 // Documentation is vague about what sized floating point type should be used.
129 // However, numeric_limits::epsilon() for 64-bit types is too small to match
130 // the above table, so use 32-bit float.
131 float weight_value;
132 Boolean success =
133 CFNumberGetValue(cf_weight, kCFNumberFloatType, &weight_value);
134 DCHECK(success);
135 for (const auto& item : weight_map) {
136 if (weight_value - item.ct_weight <= std::numeric_limits<float>::epsilon())
137 return item.gfx_weight;
138 }
139 return Font::Weight::BLACK;
140 } 36 }
141 37
142 // Returns an autoreleased NSFont created with the passed-in specifications. 38 // Returns an autoreleased NSFont created with the passed-in specifications.
143 NSFont* NSFontWithSpec(const std::string& font_name, 39 NSFont* NSFontWithSpec(const std::string& font_name,
144 int font_size, 40 int font_size,
145 int font_style, 41 int font_style,
146 Font::Weight font_weight) { 42 Font::Weight font_weight) {
147 NSFontSymbolicTraits trait_bits = 0; 43 NSFontSymbolicTraits trait_bits = 0;
148 // TODO(mboc): Add support for other weights as well. 44 // TODO(mboc): Add support for other weights as well.
149 if (font_weight >= Font::Weight::BOLD) 45 if (font_weight >= Font::Weight::BOLD)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 Font::Weight::NORMAL) {} 93 Font::Weight::NORMAL) {}
198 94
199 //////////////////////////////////////////////////////////////////////////////// 95 ////////////////////////////////////////////////////////////////////////////////
200 // PlatformFontMac, PlatformFont implementation: 96 // PlatformFontMac, PlatformFont implementation:
201 97
202 Font PlatformFontMac::DeriveFont(int size_delta, 98 Font PlatformFontMac::DeriveFont(int size_delta,
203 int style, 99 int style,
204 Font::Weight weight) const { 100 Font::Weight weight) const {
205 // For some reason, creating fonts using the NSFontDescriptor API's seem to be 101 // For some reason, creating fonts using the NSFontDescriptor API's seem to be
206 // unreliable. Hence use the NSFontManager. 102 // unreliable. Hence use the NSFontManager.
207 NSFont* derived = native_font_; 103 NSFont* derived_font = native_font_;
208 NSFontManager* font_manager = [NSFontManager sharedFontManager]; 104 NSFontManager* font_manager = [NSFontManager sharedFontManager];
209 105
210 if (weight != font_weight_) { 106 NSFontTraitMask bold_trait_mask =
211 // Find a font without any bold traits. Ideally, all bold traits are 107 weight >= Font::Weight::BOLD ? NSBoldFontMask : NSUnboldFontMask;
212 // removed here, but non-symbolic traits are read-only properties of a 108 derived_font =
213 // particular set of glyphs. And attempting to "reset" the attribute with a 109 [font_manager convertFont:derived_font toHaveTrait:bold_trait_mask];
214 // new font descriptor will lose internal properties that Mac decorates its
215 // UI fonts with. E.g., solving the plans below from NORMAL result in a
216 // CTFontDescriptor attribute entry of NSCTFontUIUsageAttribute in
217 // CTFont{Regular,Medium,Demi,Emphasized,Heavy,Black}Usage. Attempting to
218 // "solve" weights starting at other than NORMAL has unpredictable results.
219 if (font_weight_ != Font::Weight::NORMAL)
220 derived = [font_manager convertFont:derived toHaveTrait:NSUnboldFontMask];
221 DLOG_IF(WARNING, GetFontWeightFromNSFont(derived) != Font::Weight::NORMAL)
222 << "Deriving from a font with an internal unmodifiable weight.";
223 110
224 WeightSolver plan = WeightChangeFromNormal(weight); 111 NSFontTraitMask italic_trait_mask =
225 if (plan.nearest == Font::Weight::BOLD) 112 (style & Font::ITALIC) ? NSItalicFontMask : NSUnitalicFontMask;
226 derived = [font_manager convertFont:derived toHaveTrait:NSBoldFontMask]; 113 derived_font =
227 for (int i = 0; i < plan.steps_up; ++i) 114 [font_manager convertFont:derived_font toHaveTrait:italic_trait_mask];
228 derived = [font_manager convertWeight:YES ofFont:derived];
229 for (int i = 0; i < plan.steps_down; ++i)
230 derived = [font_manager convertWeight:NO ofFont:derived];
231 }
232 115
233 if (style != font_style_) { 116 derived_font =
234 NSFontTraitMask italic_trait_mask = 117 [font_manager convertFont:derived_font toSize:font_size_ + size_delta];
235 (style & Font::ITALIC) ? NSItalicFontMask : NSUnitalicFontMask;
236 derived = [font_manager convertFont:derived toHaveTrait:italic_trait_mask];
237 }
238 118
239 if (size_delta != 0) 119 return Font(new PlatformFontMac(derived_font, font_name_,
240 derived = [font_manager convertFont:derived toSize:font_size_ + size_delta]; 120 font_size_ + size_delta, style, weight));
241
242 return Font(new PlatformFontMac(derived, font_name_, font_size_ + size_delta,
243 style, weight));
244 } 121 }
245 122
246 int PlatformFontMac::GetHeight() { 123 int PlatformFontMac::GetHeight() {
247 return height_; 124 return height_;
248 } 125 }
249 126
250 int PlatformFontMac::GetBaseline() { 127 int PlatformFontMac::GetBaseline() {
251 return ascent_; 128 return ascent_;
252 } 129 }
253 130
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 return new PlatformFontMac(native_font); 251 return new PlatformFontMac(native_font);
375 } 252 }
376 253
377 // static 254 // static
378 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, 255 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name,
379 int font_size) { 256 int font_size) {
380 return new PlatformFontMac(font_name, font_size); 257 return new PlatformFontMac(font_name, font_size);
381 } 258 }
382 259
383 } // namespace gfx 260 } // namespace gfx
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/platform_font_mac_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698