diff options
Diffstat (limited to 'chromium/ui/gfx/platform_font_mac_unittest.mm')
-rw-r--r-- | chromium/ui/gfx/platform_font_mac_unittest.mm | 347 |
1 files changed, 127 insertions, 220 deletions
diff --git a/chromium/ui/gfx/platform_font_mac_unittest.mm b/chromium/ui/gfx/platform_font_mac_unittest.mm index 8df42d81578..0f812e9e70b 100644 --- a/chromium/ui/gfx/platform_font_mac_unittest.mm +++ b/chromium/ui/gfx/platform_font_mac_unittest.mm @@ -7,277 +7,187 @@ #include <Cocoa/Cocoa.h> #include <stddef.h> +#import "base/mac/foundation_util.h" #include "base/mac/mac_util.h" +#include "base/mac/scoped_cftyperef.h" #include "base/stl_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/font.h" -// TODO(tapted): Remove gfx:: prefixes. namespace gfx { +using Weight = Font::Weight; + TEST(PlatformFontMacTest, DeriveFont) { - // Use a base font that support all traits. - gfx::Font base_font("Helvetica", 13); + // |weight_tri| is either -1, 0, or 1 meaning "light", "normal", or "bold". + auto CheckExpected = [](const Font& font, int weight_tri, bool isItalic) { + base::ScopedCFTypeRef<CFDictionaryRef> traits( + CTFontCopyTraits(base::mac::NSToCFCast(font.GetNativeFont()))); + DCHECK(traits); + + CFNumberRef cf_slant = base::mac::GetValueFromDictionary<CFNumberRef>( + traits, kCTFontSlantTrait); + CGFloat slant; + CFNumberGetValue(cf_slant, kCFNumberCGFloatType, &slant); + if (isItalic) + EXPECT_GT(slant, 0); + else + EXPECT_EQ(slant, 0); + + CFNumberRef cf_weight = base::mac::GetValueFromDictionary<CFNumberRef>( + traits, kCTFontWeightTrait); + CGFloat weight; + CFNumberGetValue(cf_weight, kCFNumberCGFloatType, &weight); + if (weight_tri < 0) + EXPECT_LT(weight, 0); + else if (weight_tri == 0) + EXPECT_EQ(weight, 0); + else + EXPECT_GT(weight, 0); + }; - // Bold - gfx::Font bold_font( - base_font.Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::BOLD)); - NSFontTraitMask traits = [[NSFontManager sharedFontManager] - traitsOfFont:bold_font.GetNativeFont()]; - EXPECT_EQ(NSBoldFontMask, traits); + // Use a base font that support all traits. + Font base_font("Helvetica", 13); + { + SCOPED_TRACE("plain font"); + CheckExpected(base_font, 0, false); + } // Italic - gfx::Font italic_font( - base_font.Derive(0, gfx::Font::ITALIC, gfx::Font::Weight::NORMAL)); - traits = [[NSFontManager sharedFontManager] - traitsOfFont:italic_font.GetNativeFont()]; - EXPECT_EQ(NSItalicFontMask, traits); + Font italic_font(base_font.Derive(0, Font::ITALIC, Weight::NORMAL)); + { + SCOPED_TRACE("italic font"); + CheckExpected(italic_font, 0, true); + } + + // Bold + Font bold_font(base_font.Derive(0, Font::NORMAL, Weight::BOLD)); + { + SCOPED_TRACE("bold font"); + CheckExpected(bold_font, 1, false); + } // Bold italic - gfx::Font bold_italic_font( - base_font.Derive(0, gfx::Font::ITALIC, gfx::Font::Weight::BOLD)); - traits = [[NSFontManager sharedFontManager] - traitsOfFont:bold_italic_font.GetNativeFont()]; - EXPECT_EQ(static_cast<NSFontTraitMask>(NSBoldFontMask | NSItalicFontMask), - traits); + Font bold_italic_font(base_font.Derive(0, Font::ITALIC, Weight::BOLD)); + { + SCOPED_TRACE("bold italic font"); + CheckExpected(bold_italic_font, 1, true); + } + + // Non-existent thin will return the closest weight, light + Font thin_font(base_font.Derive(0, Font::NORMAL, Weight::THIN)); + { + SCOPED_TRACE("thin font"); + CheckExpected(thin_font, -1, false); + } + + // Non-existent black will return the closest weight, bold + Font black_font(base_font.Derive(0, Font::NORMAL, Weight::BLACK)); + { + SCOPED_TRACE("black font"); + CheckExpected(black_font, 1, false); + } } TEST(PlatformFontMacTest, DeriveFontUnderline) { // Create a default font. - gfx::Font base_font; + Font base_font; // Make the font underlined. - gfx::Font derived_font(base_font.Derive( - 0, base_font.GetStyle() | gfx::Font::UNDERLINE, base_font.GetWeight())); + Font derived_font(base_font.Derive(0, base_font.GetStyle() | Font::UNDERLINE, + base_font.GetWeight())); // Validate the derived font properties against its native font instance. NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:derived_font.GetNativeFont()]; - gfx::Font::Weight actual_weight = (traits & NSFontBoldTrait) - ? gfx::Font::Weight::BOLD - : gfx::Font::Weight::NORMAL; + Weight actual_weight = + (traits & NSFontBoldTrait) ? Weight::BOLD : Weight::NORMAL; - int actual_style = gfx::Font::UNDERLINE; + int actual_style = Font::UNDERLINE; if (traits & NSFontItalicTrait) - actual_style |= gfx::Font::ITALIC; + actual_style |= Font::ITALIC; - EXPECT_TRUE(derived_font.GetStyle() & gfx::Font::UNDERLINE); + EXPECT_TRUE(derived_font.GetStyle() & Font::UNDERLINE); EXPECT_EQ(derived_font.GetStyle(), actual_style); EXPECT_EQ(derived_font.GetWeight(), actual_weight); } -// Tests internal methods for extracting gfx::Font properties from the +// Tests internal methods for extracting Font properties from the // underlying CTFont representation. TEST(PlatformFontMacTest, ConstructFromNativeFont) { + Font light_font([NSFont fontWithName:@"Helvetica-Light" size:12]); + EXPECT_EQ(12, light_font.GetFontSize()); + EXPECT_EQ("Helvetica", light_font.GetFontName()); + EXPECT_EQ(Font::NORMAL, light_font.GetStyle()); + EXPECT_EQ(Weight::LIGHT, light_font.GetWeight()); + + Font light_italic_font([NSFont fontWithName:@"Helvetica-LightOblique" + size:14]); + EXPECT_EQ(14, light_italic_font.GetFontSize()); + EXPECT_EQ("Helvetica", light_italic_font.GetFontName()); + EXPECT_EQ(Font::ITALIC, light_italic_font.GetStyle()); + EXPECT_EQ(Weight::LIGHT, light_italic_font.GetWeight()); + Font normal_font([NSFont fontWithName:@"Helvetica" size:12]); EXPECT_EQ(12, normal_font.GetFontSize()); EXPECT_EQ("Helvetica", normal_font.GetFontName()); EXPECT_EQ(Font::NORMAL, normal_font.GetStyle()); - EXPECT_EQ(Font::Weight::NORMAL, normal_font.GetWeight()); - - Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:14]); - EXPECT_EQ(14, bold_font.GetFontSize()); - EXPECT_EQ("Helvetica", bold_font.GetFontName()); - EXPECT_EQ(Font::NORMAL, bold_font.GetStyle()); - EXPECT_EQ(Font::Weight::BOLD, bold_font.GetWeight()); + EXPECT_EQ(Weight::NORMAL, normal_font.GetWeight()); Font italic_font([NSFont fontWithName:@"Helvetica-Oblique" size:14]); EXPECT_EQ(14, italic_font.GetFontSize()); EXPECT_EQ("Helvetica", italic_font.GetFontName()); EXPECT_EQ(Font::ITALIC, italic_font.GetStyle()); - EXPECT_EQ(Font::Weight::NORMAL, italic_font.GetWeight()); + EXPECT_EQ(Weight::NORMAL, italic_font.GetWeight()); + + Font bold_font([NSFont fontWithName:@"Helvetica-Bold" size:12]); + EXPECT_EQ(12, bold_font.GetFontSize()); + EXPECT_EQ("Helvetica", bold_font.GetFontName()); + EXPECT_EQ(Font::NORMAL, bold_font.GetStyle()); + EXPECT_EQ(Weight::BOLD, bold_font.GetWeight()); 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(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_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 - before macOS 10.15, - // 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. - - // 10.15 fixed the bug where the step up from medium created a medium italic. - if (base::mac::IsAtMostOS10_14()) { - // 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. + EXPECT_EQ(Weight::BOLD, bold_italic_font.GetWeight()); } // 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) { + auto DerivedIntWeight = [](Weight weight) { + Font base; // The default system font. 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()); + EXPECT_EQ(static_cast<int>(weight), static_cast<int>(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(); + return static_cast<int>(PlatformFontMac::GetFontWeightFromNSFontForTesting( + derived.GetNativeFont())); }; - // 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)); + EXPECT_EQ(static_cast<int>(Weight::THIN), DerivedIntWeight(Weight::THIN)); + EXPECT_EQ(static_cast<int>(Weight::EXTRA_LIGHT), + DerivedIntWeight(Weight::EXTRA_LIGHT)); + EXPECT_EQ(static_cast<int>(Weight::LIGHT), DerivedIntWeight(Weight::LIGHT)); + EXPECT_EQ(static_cast<int>(Weight::NORMAL), DerivedIntWeight(Weight::NORMAL)); + EXPECT_EQ(static_cast<int>(Weight::MEDIUM), DerivedIntWeight(Weight::MEDIUM)); + if (base::mac::IsAtMostOS10_10()) { + // If a SEMIBOLD system font is requested, 10.10 will return the bold system + // font, but somehow bearing a weight number of 0.24, which is really a + // medium weight (0.23). + EXPECT_EQ(static_cast<int>(Weight::MEDIUM), + DerivedIntWeight(Weight::SEMIBOLD)); + } else { + EXPECT_EQ(static_cast<int>(Weight::SEMIBOLD), + DerivedIntWeight(Weight::SEMIBOLD)); } + EXPECT_EQ(static_cast<int>(Weight::BOLD), DerivedIntWeight(Weight::BOLD)); + EXPECT_EQ(static_cast<int>(Weight::EXTRA_BOLD), + DerivedIntWeight(Weight::EXTRA_BOLD)); + EXPECT_EQ(static_cast<int>(Weight::BLACK), DerivedIntWeight(Weight::BLACK)); } // Ensures that the Font's reported height is consistent with the native font's @@ -285,16 +195,14 @@ TEST(PlatformFontMacTest, DerivedFineGrainedFonts) { TEST(PlatformFontMacTest, ValidateFontHeight) { // Use the default ResourceBundle system font. E.g. Helvetica Neue in 10.10, // Lucida Grande before that, and San Francisco after. - gfx::Font default_font; - gfx::Font::FontStyle styles[] = {gfx::Font::NORMAL, gfx::Font::ITALIC, - gfx::Font::UNDERLINE}; + Font default_font; + Font::FontStyle styles[] = {Font::NORMAL, Font::ITALIC, Font::UNDERLINE}; for (size_t i = 0; i < base::size(styles); ++i) { SCOPED_TRACE(testing::Message() << "Font::FontStyle: " << styles[i]); // Include the range of sizes used by ResourceBundle::FontStyle (-1 to +8). for (int delta = -1; delta <= 8; ++delta) { - gfx::Font font = - default_font.Derive(delta, styles[i], gfx::Font::Weight::NORMAL); + Font font = default_font.Derive(delta, styles[i], Weight::NORMAL); SCOPED_TRACE(testing::Message() << "FontSize(): " << font.GetFontSize()); NSFont* native_font = font.GetNativeFont(); @@ -328,15 +236,14 @@ TEST(PlatformFontMacTest, ValidateFontHeight) { // Appkit's bug was detected on macOS 10.10 which uses Helvetica Neue as the // system font. TEST(PlatformFontMacTest, DerivedSemiboldFontIsNotItalic) { - gfx::Font base_font; + Font base_font; { NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:base_font.GetNativeFont()]; ASSERT_FALSE(traits & NSItalicFontMask); } - gfx::Font semibold_font( - base_font.Derive(0, gfx::Font::NORMAL, gfx::Font::Weight::SEMIBOLD)); + Font semibold_font(base_font.Derive(0, Font::NORMAL, Weight::SEMIBOLD)); NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:semibold_font.GetNativeFont()]; EXPECT_FALSE(traits & NSItalicFontMask); |