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

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

Issue 2869803005: Support finer grained font weights on Mac. (Closed)
Patch Set: fix 10.11 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 | « ui/gfx/platform_font_mac.mm ('k') | ui/views/examples/example_combobox_model.h » ('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"
6
5 #include <Cocoa/Cocoa.h> 7 #include <Cocoa/Cocoa.h>
6 #include <stddef.h> 8 #include <stddef.h>
7 9
10 #include "base/mac/mac_util.h"
8 #include "base/macros.h" 11 #include "base/macros.h"
9 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/gfx/font.h" 13 #include "ui/gfx/font.h"
11 14
15 // TODO(tapted): Remove gfx:: prefixes.
16 namespace gfx {
17
12 TEST(PlatformFontMacTest, DeriveFont) { 18 TEST(PlatformFontMacTest, DeriveFont) {
13 // Use a base font that support all traits. 19 // Use a base font that support all traits.
14 gfx::Font base_font("Helvetica", 13); 20 gfx::Font base_font("Helvetica", 13);
15 21
16 // Bold 22 // Bold
17 gfx::Font bold_font( 23 gfx::Font bold_font(
18 base_font.Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); 24 base_font.Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::BOLD));
19 NSFontTraitMask traits = [[NSFontManager sharedFontManager] 25 NSFontTraitMask traits = [[NSFontManager sharedFontManager]
20 traitsOfFont:bold_font.GetNativeFont()]; 26 traitsOfFont:bold_font.GetNativeFont()];
21 EXPECT_EQ(NSBoldFontMask, traits); 27 EXPECT_EQ(NSBoldFontMask, traits);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 59
54 int actual_style = gfx::Font::UNDERLINE; 60 int actual_style = gfx::Font::UNDERLINE;
55 if (traits & NSFontItalicTrait) 61 if (traits & NSFontItalicTrait)
56 actual_style |= gfx::Font::ITALIC; 62 actual_style |= gfx::Font::ITALIC;
57 63
58 EXPECT_TRUE(derived_font.GetStyle() & gfx::Font::UNDERLINE); 64 EXPECT_TRUE(derived_font.GetStyle() & gfx::Font::UNDERLINE);
59 EXPECT_EQ(derived_font.GetStyle(), actual_style); 65 EXPECT_EQ(derived_font.GetStyle(), actual_style);
60 EXPECT_EQ(derived_font.GetWeight(), actual_weight); 66 EXPECT_EQ(derived_font.GetWeight(), actual_weight);
61 } 67 }
62 68
69 // Tests internal methods for extracting gfx::Font properties from the
70 // underlying CTFont representation.
63 TEST(PlatformFontMacTest, ConstructFromNativeFont) { 71 TEST(PlatformFontMacTest, ConstructFromNativeFont) {
64 gfx::Font normal_font([NSFont fontWithName:@"Helvetica" size:12]); 72 Font normal_font([NSFont fontWithName:@"Helvetica" size:12]);
65 EXPECT_EQ(12, normal_font.GetFontSize()); 73 EXPECT_EQ(12, normal_font.GetFontSize());
66 EXPECT_EQ("Helvetica", normal_font.GetFontName()); 74 EXPECT_EQ("Helvetica", normal_font.GetFontName());
67 EXPECT_EQ(gfx::Font::NORMAL, normal_font.GetStyle()); 75 EXPECT_EQ(Font::NORMAL, normal_font.GetStyle());
68 76 EXPECT_EQ(Font::Weight::NORMAL, normal_font.GetWeight());
69 gfx::Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:14]); 77
78 Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:14]);
70 EXPECT_EQ(14, bold_font.GetFontSize()); 79 EXPECT_EQ(14, bold_font.GetFontSize());
71 EXPECT_EQ("Helvetica", bold_font.GetFontName()); 80 EXPECT_EQ("Helvetica", bold_font.GetFontName());
72 EXPECT_EQ(gfx::Font::Weight::BOLD, bold_font.GetWeight()); 81 EXPECT_EQ(Font::NORMAL, bold_font.GetStyle());
73 82 EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight());
74 gfx::Font italic_font([NSFont fontWithName:@"Helvetica-Oblique" size:14]); 83
84 Font italic_font([NSFont fontWithName:@"Helvetica-Oblique" size:14]);
75 EXPECT_EQ(14, italic_font.GetFontSize()); 85 EXPECT_EQ(14, italic_font.GetFontSize());
76 EXPECT_EQ("Helvetica", italic_font.GetFontName()); 86 EXPECT_EQ("Helvetica", italic_font.GetFontName());
77 EXPECT_EQ(gfx::Font::ITALIC, italic_font.GetStyle()); 87 EXPECT_EQ(Font::ITALIC, italic_font.GetStyle());
78 88 EXPECT_EQ(Font::Weight::NORMAL, italic_font.GetWeight());
79 gfx::Font bold_italic_font( 89
80 [NSFont fontWithName:@"Helvetica-BoldOblique" size:14]); 90 Font bold_italic_font([NSFont fontWithName:@"Helvetica-BoldOblique" size:14]);
81 EXPECT_EQ(14, bold_italic_font.GetFontSize()); 91 EXPECT_EQ(14, bold_italic_font.GetFontSize());
82 EXPECT_EQ("Helvetica", bold_italic_font.GetFontName()); 92 EXPECT_EQ("Helvetica", bold_italic_font.GetFontName());
83 EXPECT_EQ(gfx::Font::ITALIC, bold_italic_font.GetStyle()); 93 EXPECT_EQ(Font::ITALIC, bold_italic_font.GetStyle());
84 EXPECT_EQ(gfx::Font::Weight::BOLD, bold_italic_font.GetWeight()); 94 EXPECT_EQ(Font::Weight::BOLD, bold_italic_font.GetWeight());
95 }
96
97 // Specific test for the mapping from the NSFont weight API to gfx::Font::Weight
98 // values.
99 TEST(PlatformFontMacTest, FontWeightAPIConsistency) {
100 // Vanilla Helvetica only has bold and normal, so use a system font.
101 NSFont* ns_font = [NSFont systemFontOfSize:13];
102 NSFontManager* manager = [NSFontManager sharedFontManager];
103
104 // -[NSFontManager convertWeight:ofFont] supposedly steps the font up and down
105 // in weight values according to a table at
106 // https://developer.apple.com/reference/appkit/nsfontmanager/1462321-convertw eight
107 // Apple Terminology | ISO Equivalent
108 // 1. ultralight | none
109 // 2. thin | W1. ultralight
110 // 3. light, extralight | W2. extralight
111 // 4. book | W3. light
112 // 5. regular, plain, display, roman | W4. semilight
113 // 6. medium | W5. medium
114 // 7. demi, demibold | none
115 // 8. semi, semibold | W6. semibold
116 // 9. bold | W7. bold
117 // 10. extra, extrabold | W8. extrabold
118 // 11. heavy, heavyface | none
119 // 12. black, super | W9. ultrabold
120 // 13. ultra, ultrablack, fat | none
121 // 14. extrablack, obese, nord | none
122 EXPECT_EQ(Font::Weight::NORMAL, Font(ns_font).GetWeight()); // Row 5.
123
124 // Ensure the Bold "symbolic" trait from the NSFont traits API maps correctly
125 // to the weight (non-symbolic) trait from the CTFont API.
126 NSFont* bold_ns_font =
127 [manager convertFont:ns_font toHaveTrait:NSFontBoldTrait];
128 Font bold_font(bold_ns_font);
129 EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight());
130
131 // No thin fonts on the lower rows of the table for San Francisco or earlier
132 // system fonts.
133 BOOL down = NO;
134 ns_font = [NSFont systemFontOfSize:13];
135 for (int row = 4; row > 0; --row) {
136 SCOPED_TRACE(testing::Message() << "Row: " << row);
137 ns_font = [manager convertWeight:down ofFont:ns_font];
138 EXPECT_EQ(Font::Weight::NORMAL, Font(ns_font).GetWeight());
139 }
140
141 BOOL up = YES;
142 // That is... unless we first go up by one and then down. A LIGHT and a THIN
143 // font reveal themselves somehow. Only tested on 10.12.
144 if (base::mac::IsAtLeastOS10_12()) {
145 ns_font = [NSFont systemFontOfSize:13];
146 ns_font = [manager convertWeight:up ofFont:ns_font];
147 ns_font = [manager convertWeight:down ofFont:ns_font];
148 EXPECT_EQ(Font::Weight::LIGHT, Font(ns_font).GetWeight());
149 ns_font = [manager convertWeight:down ofFont:ns_font];
150 EXPECT_EQ(Font::Weight::THIN, Font(ns_font).GetWeight());
151 }
152
153 ns_font = [NSFont systemFontOfSize:13];
154 if (base::mac::IsOS10_9()) {
155 // On 10.9 the system font doesn't provide finer-grained weights. It's
156 // either bold or it isn't.
157 for (int row = 6; row <= 14; ++row) {
158 SCOPED_TRACE(testing::Message() << "Row: " << row);
159 ns_font = [manager convertWeight:up ofFont:ns_font];
160 EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight());
161 }
162 return;
163 }
164
165 if (base::mac::IsOS10_11()) {
166 // On 10.11 the API jumps to BOLD, but has heavier weights as well.
167 ns_font = [manager convertWeight:up ofFont:ns_font];
168 EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight());
169 ns_font = [manager convertWeight:up ofFont:ns_font];
170 EXPECT_EQ(Font::Weight::EXTRA_BOLD, Font(ns_font).GetWeight());
171 ns_font = [manager convertWeight:up ofFont:ns_font];
172 EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight());
173 return;
174 }
175
176 // Each typeface maps weight notches differently, and the weight is actually a
177 // floating point value that may not map directly to a gfx::Font::Weight. For
178 // example San Francisco on macOS 10.12 goes up from 0 in the sequence:
179 // [0.23, 0.23, 0.3, 0.4, 0.56, 0.62, 0.62, ...] and has no "thin" weights.
180 // But also iterating over weights does weird stuff sometimes - occasionally
181 // the font goes italic, but going up another step goes back to non-italic,
182 // at a heavier weight.
183
184 // NSCTFontUIUsageAttribute = CTFontMediumUsage.
185 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.23.
186 EXPECT_EQ(Font::Weight::MEDIUM, Font(ns_font).GetWeight()); // Row 6.
187
188 // Goes italic: NSCTFontUIUsageAttribute = CTFontMediumItalicUsage.
189 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.23.
190 EXPECT_EQ(Font::Weight::MEDIUM, Font(ns_font).GetWeight()); // Row 7.
191
192 // NSCTFontUIUsageAttribute = CTFontDemiUsage.
193 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.3.
194 if (base::mac::IsOS10_10()) {
195 // 10.10 is Helvetica Neue. It only has NORMAL, MEDIUM, BOLD and BLACK.
196 EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); // Row 8.
197 } else {
198 EXPECT_EQ(Font::Weight::SEMIBOLD, Font(ns_font).GetWeight()); // Row 8.
199 }
200
201 // NSCTFontUIUsageAttribute = CTFontEmphasizedUsage.
202 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.4 on 10.11+.
203
204 if (base::mac::IsOS10_10()) {
205 // Remaining rows are all BLACK on 10.10.
206 for (int row = 9; row <= 14; ++row) {
207 SCOPED_TRACE(testing::Message() << "Row: " << row);
208 ns_font = [manager convertWeight:up ofFont:ns_font];
209 EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight());
210 }
211 return;
212 }
213 EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); // Row 9.
214
215 // NSCTFontUIUsageAttribute = CTFontHeavyUsage.
216 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.56.
217 EXPECT_EQ(Font::Weight::EXTRA_BOLD, Font(ns_font).GetWeight()); // Row 10.
218
219 // NSCTFontUIUsageAttribute = CTFontBlackUsage.
220 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62.
221 EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 11.
222 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62.
223 EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 12.
224 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62.
225 EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 13.
226 ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62.
227 EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 14.
228 }
229
230 // Test font derivation for fine-grained font weights.
231 TEST(PlatformFontMacTest, DerivedFineGrainedFonts) {
232 // Only test where San Francisco is available.
233 if (base::mac::IsAtMostOS10_10())
234 return;
235
236 using Weight = Font::Weight;
237 Font base([NSFont systemFontOfSize:13]);
238
239 // The resulting, actual font weight after deriving |weight| from |base|.
240 auto DerivedWeight = [&](Weight weight) {
241 Font derived(base.Derive(0, 0, weight));
242 // PlatformFont should always pass the requested weight, not what the OS
243 // could provide. This just checks a constructor argument, so not very
244 // interesting.
245 EXPECT_EQ(weight, derived.GetWeight());
246
247 // Return the weight enum value that PlatformFontMac internally derives from
248 // the floating point weight given by the kCTFontWeightTrait of |font|. Do
249 // this by creating a new font based only off the NSFont in |derived|.
250 return Font(derived.GetNativeFont()).GetWeight();
251 };
252
253 // Only use NORMAL or BOLD as a base font. Mac font APIs go whacky otherwise.
254 // See comments in PlatformFontMac::DeriveFont().
255 for (Weight base_weight : {Weight::NORMAL, Weight::BOLD}) {
256 SCOPED_TRACE(testing::Message()
257 << "BaseWeight: " << static_cast<int>(base_weight));
258 if (base_weight != Weight::NORMAL) {
259 base = base.Derive(0, 0, base_weight);
260 EXPECT_EQ(base_weight, base.GetWeight());
261 }
262
263 // Normal and heavy weights map correctly on 10.11 and 10.12.
264 EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::NORMAL));
265 EXPECT_EQ(Weight::BOLD, DerivedWeight(Weight::BOLD));
266 EXPECT_EQ(Weight::EXTRA_BOLD, DerivedWeight(Weight::EXTRA_BOLD));
267 EXPECT_EQ(Weight::BLACK, DerivedWeight(Weight::BLACK));
268
269 if (base::mac::IsAtMostOS10_11()) {
270 // The fine-grained font weights on 10.11 are incomplete.
tapted 2017/05/22 01:16:37 Naive of me to think that there was even one OS ve
271 EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::EXTRA_LIGHT));
272 EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::THIN));
273 EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::LIGHT));
274 EXPECT_EQ(Weight::BOLD, DerivedWeight(Weight::MEDIUM));
275 EXPECT_EQ(Weight::BOLD, DerivedWeight(Weight::SEMIBOLD));
276 continue;
277 }
278
279 // San Francisco doesn't offer anything between THIN and LIGHT.
280 EXPECT_EQ(Weight::THIN, DerivedWeight(Weight::EXTRA_LIGHT));
281
282 // All the rest should map correctly.
283 EXPECT_EQ(Weight::THIN, DerivedWeight(Weight::THIN));
284 EXPECT_EQ(Weight::LIGHT, DerivedWeight(Weight::LIGHT));
285 EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::NORMAL));
286 EXPECT_EQ(Weight::MEDIUM, DerivedWeight(Weight::MEDIUM));
287 EXPECT_EQ(Weight::SEMIBOLD, DerivedWeight(Weight::SEMIBOLD));
288 }
85 } 289 }
86 290
87 // Ensures that the Font's reported height is consistent with the native font's 291 // Ensures that the Font's reported height is consistent with the native font's
88 // ascender and descender metrics. 292 // ascender and descender metrics.
89 TEST(PlatformFontMacTest, ValidateFontHeight) { 293 TEST(PlatformFontMacTest, ValidateFontHeight) {
90 // Use the default ResourceBundle system font. E.g. Helvetica Neue in 10.10, 294 // Use the default ResourceBundle system font. E.g. Helvetica Neue in 10.10,
91 // Lucida Grande before that, and San Francisco after. 295 // Lucida Grande before that, and San Francisco after.
92 gfx::Font default_font; 296 gfx::Font default_font;
93 gfx::Font::FontStyle styles[] = {gfx::Font::NORMAL, gfx::Font::ITALIC, 297 gfx::Font::FontStyle styles[] = {gfx::Font::NORMAL, gfx::Font::ITALIC,
94 gfx::Font::UNDERLINE}; 298 gfx::Font::UNDERLINE};
(...skipping 24 matching lines...) Expand all
119 // (plus baseline). So the height depends on the rounding of the ascender, 323 // (plus baseline). So the height depends on the rounding of the ascender,
120 // and can be as much as 1 greater than the simple sum of floats. 324 // and can be as much as 1 greater than the simple sum of floats.
121 EXPECT_LE(sum, font.GetHeight()); 325 EXPECT_LE(sum, font.GetHeight());
122 EXPECT_GE(sum + 1, font.GetHeight()); 326 EXPECT_GE(sum + 1, font.GetHeight());
123 327
124 // Recreate the rounding performed for GetBaseLine(). 328 // Recreate the rounding performed for GetBaseLine().
125 EXPECT_EQ(ceil(ceil(ascender) - descender + leading), font.GetHeight()); 329 EXPECT_EQ(ceil(ceil(ascender) - descender + leading), font.GetHeight());
126 } 330 }
127 } 331 }
128 } 332 }
333
334 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/platform_font_mac.mm ('k') | ui/views/examples/example_combobox_model.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698