Index: ui/gfx/platform_font_mac_unittest.mm |
diff --git a/ui/gfx/platform_font_mac_unittest.mm b/ui/gfx/platform_font_mac_unittest.mm |
index e65b8b1fd95e1249e00bbcc89c99b7dfa5230e43..ffc469e34c420fa1a6db296d92a8cd498d731b4d 100644 |
--- a/ui/gfx/platform_font_mac_unittest.mm |
+++ b/ui/gfx/platform_font_mac_unittest.mm |
@@ -2,13 +2,19 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "ui/gfx/platform_font_mac.h" |
+ |
#include <Cocoa/Cocoa.h> |
#include <stddef.h> |
+#include "base/mac/mac_util.h" |
#include "base/macros.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "ui/gfx/font.h" |
+// TODO(tapted): Remove gfx:: prefixes. |
+namespace gfx { |
+ |
TEST(PlatformFontMacTest, DeriveFont) { |
// Use a base font that support all traits. |
gfx::Font base_font("Helvetica", 13); |
@@ -60,28 +66,225 @@ |
EXPECT_EQ(derived_font.GetWeight(), actual_weight); |
} |
+// Tests internal methods for extracting gfx::Font properties from the |
+// underlying CTFont representation. |
TEST(PlatformFontMacTest, ConstructFromNativeFont) { |
- gfx::Font normal_font([NSFont fontWithName:@"Helvetica" size:12]); |
+ Font normal_font([NSFont fontWithName:@"Helvetica" size:12]); |
EXPECT_EQ(12, normal_font.GetFontSize()); |
EXPECT_EQ("Helvetica", normal_font.GetFontName()); |
- EXPECT_EQ(gfx::Font::NORMAL, normal_font.GetStyle()); |
+ EXPECT_EQ(Font::NORMAL, normal_font.GetStyle()); |
+ EXPECT_EQ(Font::Weight::NORMAL, normal_font.GetWeight()); |
- gfx::Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:14]); |
+ Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:14]); |
EXPECT_EQ(14, bold_font.GetFontSize()); |
EXPECT_EQ("Helvetica", bold_font.GetFontName()); |
- EXPECT_EQ(gfx::Font::Weight::BOLD, bold_font.GetWeight()); |
+ EXPECT_EQ(Font::NORMAL, bold_font.GetStyle()); |
+ EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight()); |
- gfx::Font italic_font([NSFont fontWithName:@"Helvetica-Oblique" size:14]); |
+ Font italic_font([NSFont fontWithName:@"Helvetica-Oblique" size:14]); |
EXPECT_EQ(14, italic_font.GetFontSize()); |
EXPECT_EQ("Helvetica", italic_font.GetFontName()); |
- EXPECT_EQ(gfx::Font::ITALIC, italic_font.GetStyle()); |
+ EXPECT_EQ(Font::ITALIC, italic_font.GetStyle()); |
+ EXPECT_EQ(Font::Weight::NORMAL, italic_font.GetWeight()); |
- gfx::Font bold_italic_font( |
- [NSFont fontWithName:@"Helvetica-BoldOblique" size:14]); |
+ Font bold_italic_font([NSFont fontWithName:@"Helvetica-BoldOblique" size:14]); |
EXPECT_EQ(14, bold_italic_font.GetFontSize()); |
EXPECT_EQ("Helvetica", bold_italic_font.GetFontName()); |
- EXPECT_EQ(gfx::Font::ITALIC, bold_italic_font.GetStyle()); |
- EXPECT_EQ(gfx::Font::Weight::BOLD, bold_italic_font.GetWeight()); |
+ EXPECT_EQ(Font::ITALIC, bold_italic_font.GetStyle()); |
+ EXPECT_EQ(Font::Weight::BOLD, bold_italic_font.GetWeight()); |
+} |
+ |
+// Specific test for the mapping from the NSFont weight API to gfx::Font::Weight |
+// values. |
+TEST(PlatformFontMacTest, FontWeightAPIConsistency) { |
+ // Vanilla Helvetica only has bold and normal, so use a system font. |
+ NSFont* ns_font = [NSFont systemFontOfSize:13]; |
+ NSFontManager* manager = [NSFontManager sharedFontManager]; |
+ |
+ // -[NSFontManager convertWeight:ofFont] supposedly steps the font up and down |
+ // in weight values according to a table at |
+ // https://developer.apple.com/reference/appkit/nsfontmanager/1462321-convertweight |
+ // Apple Terminology | ISO Equivalent |
+ // 1. ultralight | none |
+ // 2. thin | W1. ultralight |
+ // 3. light, extralight | W2. extralight |
+ // 4. book | W3. light |
+ // 5. regular, plain, display, roman | W4. semilight |
+ // 6. medium | W5. medium |
+ // 7. demi, demibold | none |
+ // 8. semi, semibold | W6. semibold |
+ // 9. bold | W7. bold |
+ // 10. extra, extrabold | W8. extrabold |
+ // 11. heavy, heavyface | none |
+ // 12. black, super | W9. ultrabold |
+ // 13. ultra, ultrablack, fat | none |
+ // 14. extrablack, obese, nord | none |
+ EXPECT_EQ(Font::Weight::NORMAL, Font(ns_font).GetWeight()); // Row 5. |
+ |
+ // Ensure the Bold "symbolic" trait from the NSFont traits API maps correctly |
+ // to the weight (non-symbolic) trait from the CTFont API. |
+ NSFont* bold_ns_font = |
+ [manager convertFont:ns_font toHaveTrait:NSFontBoldTrait]; |
+ Font bold_font(bold_ns_font); |
+ EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight()); |
+ |
+ // No thin fonts on the lower rows of the table for San Francisco or earlier |
+ // system fonts. |
+ BOOL down = NO; |
+ ns_font = [NSFont systemFontOfSize:13]; |
+ for (int row = 4; row > 0; --row) { |
+ SCOPED_TRACE(testing::Message() << "Row: " << row); |
+ ns_font = [manager convertWeight:down ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::NORMAL, Font(ns_font).GetWeight()); |
+ } |
+ |
+ BOOL up = YES; |
+ // That is... unless we first go up by one and then down. A LIGHT and a THIN |
+ // font reveal themselves somehow. Only tested on 10.12. |
+ if (base::mac::IsAtLeastOS10_12()) { |
+ ns_font = [NSFont systemFontOfSize:13]; |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; |
+ ns_font = [manager convertWeight:down ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::LIGHT, Font(ns_font).GetWeight()); |
+ ns_font = [manager convertWeight:down ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::THIN, Font(ns_font).GetWeight()); |
+ } |
+ |
+ ns_font = [NSFont systemFontOfSize:13]; |
+ if (base::mac::IsOS10_9()) { |
+ // On 10.9 the system font doesn't provide finer-grained weights. It's |
+ // either bold or it isn't. |
+ for (int row = 6; row <= 14; ++row) { |
+ SCOPED_TRACE(testing::Message() << "Row: " << row); |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); |
+ } |
+ return; |
+ } |
+ |
+ if (base::mac::IsOS10_11()) { |
+ // On 10.11 the API jumps to BOLD, but has heavier weights as well. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::EXTRA_BOLD, Font(ns_font).GetWeight()); |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); |
+ return; |
+ } |
+ |
+ // Each typeface maps weight notches differently, and the weight is actually a |
+ // floating point value that may not map directly to a gfx::Font::Weight. For |
+ // example San Francisco on macOS 10.12 goes up from 0 in the sequence: |
+ // [0.23, 0.23, 0.3, 0.4, 0.56, 0.62, 0.62, ...] and has no "thin" weights. |
+ // But also iterating over weights does weird stuff sometimes - occasionally |
+ // the font goes italic, but going up another step goes back to non-italic, |
+ // at a heavier weight. |
+ |
+ // NSCTFontUIUsageAttribute = CTFontMediumUsage. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.23. |
+ EXPECT_EQ(Font::Weight::MEDIUM, Font(ns_font).GetWeight()); // Row 6. |
+ |
+ // Goes italic: NSCTFontUIUsageAttribute = CTFontMediumItalicUsage. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.23. |
+ EXPECT_EQ(Font::Weight::MEDIUM, Font(ns_font).GetWeight()); // Row 7. |
+ |
+ // NSCTFontUIUsageAttribute = CTFontDemiUsage. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.3. |
+ if (base::mac::IsOS10_10()) { |
+ // 10.10 is Helvetica Neue. It only has NORMAL, MEDIUM, BOLD and BLACK. |
+ EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); // Row 8. |
+ } else { |
+ EXPECT_EQ(Font::Weight::SEMIBOLD, Font(ns_font).GetWeight()); // Row 8. |
+ } |
+ |
+ // NSCTFontUIUsageAttribute = CTFontEmphasizedUsage. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.4 on 10.11+. |
+ |
+ if (base::mac::IsOS10_10()) { |
+ // Remaining rows are all BLACK on 10.10. |
+ for (int row = 9; row <= 14; ++row) { |
+ SCOPED_TRACE(testing::Message() << "Row: " << row); |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; |
+ EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); |
+ } |
+ return; |
+ } |
+ EXPECT_EQ(Font::Weight::BOLD, Font(ns_font).GetWeight()); // Row 9. |
+ |
+ // NSCTFontUIUsageAttribute = CTFontHeavyUsage. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.56. |
+ EXPECT_EQ(Font::Weight::EXTRA_BOLD, Font(ns_font).GetWeight()); // Row 10. |
+ |
+ // NSCTFontUIUsageAttribute = CTFontBlackUsage. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. |
+ EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 11. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. |
+ EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 12. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. |
+ EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 13. |
+ ns_font = [manager convertWeight:up ofFont:ns_font]; // 0.62. |
+ EXPECT_EQ(Font::Weight::BLACK, Font(ns_font).GetWeight()); // Row 14. |
+} |
+ |
+// Test font derivation for fine-grained font weights. |
+TEST(PlatformFontMacTest, DerivedFineGrainedFonts) { |
+ // Only test where San Francisco is available. |
+ if (base::mac::IsAtMostOS10_10()) |
+ return; |
+ |
+ using Weight = Font::Weight; |
+ Font base([NSFont systemFontOfSize:13]); |
+ |
+ // The resulting, actual font weight after deriving |weight| from |base|. |
+ auto DerivedWeight = [&](Weight weight) { |
+ Font derived(base.Derive(0, 0, weight)); |
+ // PlatformFont should always pass the requested weight, not what the OS |
+ // could provide. This just checks a constructor argument, so not very |
+ // interesting. |
+ EXPECT_EQ(weight, derived.GetWeight()); |
+ |
+ // Return the weight enum value that PlatformFontMac internally derives from |
+ // the floating point weight given by the kCTFontWeightTrait of |font|. Do |
+ // this by creating a new font based only off the NSFont in |derived|. |
+ return Font(derived.GetNativeFont()).GetWeight(); |
+ }; |
+ |
+ // Only use NORMAL or BOLD as a base font. Mac font APIs go whacky otherwise. |
+ // See comments in PlatformFontMac::DeriveFont(). |
+ for (Weight base_weight : {Weight::NORMAL, Weight::BOLD}) { |
+ SCOPED_TRACE(testing::Message() |
+ << "BaseWeight: " << static_cast<int>(base_weight)); |
+ if (base_weight != Weight::NORMAL) { |
+ base = base.Derive(0, 0, base_weight); |
+ EXPECT_EQ(base_weight, base.GetWeight()); |
+ } |
+ |
+ // Normal and heavy weights map correctly on 10.11 and 10.12. |
+ EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::NORMAL)); |
+ EXPECT_EQ(Weight::BOLD, DerivedWeight(Weight::BOLD)); |
+ EXPECT_EQ(Weight::EXTRA_BOLD, DerivedWeight(Weight::EXTRA_BOLD)); |
+ EXPECT_EQ(Weight::BLACK, DerivedWeight(Weight::BLACK)); |
+ |
+ if (base::mac::IsAtMostOS10_11()) { |
+ // The fine-grained font weights on 10.11 are incomplete. |
+ EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::EXTRA_LIGHT)); |
+ EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::THIN)); |
+ EXPECT_EQ(Weight::NORMAL, DerivedWeight(Weight::LIGHT)); |
+ EXPECT_EQ(Weight::BOLD, DerivedWeight(Weight::MEDIUM)); |
+ EXPECT_EQ(Weight::BOLD, DerivedWeight(Weight::SEMIBOLD)); |
+ continue; |
+ } |
+ |
+ // San Francisco doesn't offer anything between THIN and LIGHT. |
+ EXPECT_EQ(Weight::THIN, DerivedWeight(Weight::EXTRA_LIGHT)); |
+ |
+ // All the rest should map correctly. |
+ EXPECT_EQ(Weight::THIN, DerivedWeight(Weight::THIN)); |
+ EXPECT_EQ(Weight::LIGHT, DerivedWeight(Weight::LIGHT)); |
+ EXPECT_EQ(Weight::MEDIUM, DerivedWeight(Weight::MEDIUM)); |
+ EXPECT_EQ(Weight::SEMIBOLD, DerivedWeight(Weight::SEMIBOLD)); |
+ } |
} |
// Ensures that the Font's reported height is consistent with the native font's |
@@ -126,3 +329,5 @@ |
} |
} |
} |
+ |
+} // namespace gfx |