Fix GetFontWeightFromNSFont()

GetFontWeightFromNSFont() uses a table of CoreText float values to
look up corresponding Font::Weight values. The testing of the
float values was broken; fix it.

Bug: 1112998
Change-Id: Ia3346c2964e3c74cb855b701227a662aa281de8d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2337734
Reviewed-by: Elly Fong-Jones <[email protected]>
Commit-Queue: Avi Drissman <[email protected]>
Cr-Commit-Position: refs/heads/master@{#795061}
diff --git a/ui/gfx/platform_font_mac.mm b/ui/gfx/platform_font_mac.mm
index be3ac0b0..7ade2d4 100644
--- a/ui/gfx/platform_font_mac.mm
+++ b/ui/gfx/platform_font_mac.mm
@@ -91,31 +91,53 @@
   DCHECK(font);
 
   // Map CoreText weights in a manner similar to ct_weight_to_fontstyle() from
-  // SkFontHost_mac.cpp, but adjust for MEDIUM so that the San Francisco's
-  // custom MEDIUM weight can be picked out. San Francisco has weights:
-  // [0.23, 0.23, 0.3, 0.4, 0.56, 0.62, 0.62, ...] (no thin weights).
-  // See PlatformFontMacTest.FontWeightAPIConsistency for details.
-  // Note that the table Skia uses is also determined by experiment.
+  // SkFontHost_mac.cpp, but adjusted for the weights actually used by the
+  // system fonts. See PlatformFontMacTest.FontWeightAPIConsistency for details.
+  // Use ranges for paranoia.
   constexpr struct {
-    CGFloat ct_weight;
+    // A range of CoreText weights.
+    CGFloat weight_lower;
+    CGFloat weight_upper;
     Font::Weight gfx_weight;
   } weight_map[] = {
-      // Missing: Apple "ultralight".
-      {-0.70, Font::Weight::THIN},
-      {-0.50, Font::Weight::EXTRA_LIGHT},
-      {-0.23, Font::Weight::LIGHT},
-      {0.00, Font::Weight::NORMAL},
-      {0.23, Font::Weight::MEDIUM},  // Note: adjusted from 0.20 vs Skia.
-      // Missing: Apple "demibold".
-      {0.30, Font::Weight::SEMIBOLD},
-      {0.40, Font::Weight::BOLD},
-      {0.60, Font::Weight::EXTRA_BOLD},
-      // Missing: Apple "heavyface".
-      // Values will be capped to BLACK (this entry is here for consistency).
-      {0.80, Font::Weight::BLACK},
-      // Missing: Apple "ultrablack".
-      // Missing: Apple "extrablack".
+      // NSFontWeight constants introduced in 10.11:
+      //   NSFontWeightUltraLight: -0.80
+      //   NSFontWeightThin: -0.60
+      //   NSFontWeightLight: -0.40
+      //   NSFontWeightRegular: 0.0
+      //   NSFontWeightMedium: 0.23
+      //   NSFontWeightSemibold: 0.30
+      //   NSFontWeightBold: 0.40
+      //   NSFontWeightHeavy: 0.56
+      //   NSFontWeightBlack: 0.62
+      //
+      // Actual system font weights:
+      //   10.10:
+      //     .HelveticaNeueDeskInterface-Regular: 0.0
+      //     .HelveticaNeueDeskInterface-MediumP4: 0.23
+      //     .HelveticaNeueDeskInterface-Bold: 0.4
+      //     .HelveticaNeueDeskInterface-Heavy: 0.62
+      //   10.11-:
+      //     .AppleSystemUIFontUltraLight: -0.80 (10.12-)
+      //     .AppleSystemUIFontLight: -0.40 (10.12-)
+      //     .AppleSystemUIFont: 0 (10.11-)
+      //     .AppleSystemUIFontMedium: 0.23 (10.12-)
+      //     .AppleSystemUIFontDemi: 0.30 (10.12-)
+      //     .AppleSystemUIFontBold: 0.40 (10.11)
+      //     .AppleSystemUIFontEmphasized: 0.40 (10.12-)
+      //     .AppleSystemUIFontHeavy: 0.56 (10.11-)
+      //     .AppleSystemUIFontBlack: 0.62 (10.11-)
+      {-1000, -0.70, Font::Weight::THIN},         // NSFontWeightUltraLight
+      {-0.70, -0.45, Font::Weight::EXTRA_LIGHT},  // NSFontWeightThin
+      {-0.45, -0.10, Font::Weight::LIGHT},        // NSFontWeightLight
+      {-0.10, 0.10, Font::Weight::NORMAL},        // NSFontWeightRegular
+      {0.10, 0.27, Font::Weight::MEDIUM},         // NSFontWeightMedium
+      {0.27, 0.35, Font::Weight::SEMIBOLD},       // NSFontWeightSemibold
+      {0.35, 0.50, Font::Weight::BOLD},           // NSFontWeightBold
+      {0.50, 0.60, Font::Weight::EXTRA_BOLD},     // NSFontWeightHeavy
+      {0.60, 1000, Font::Weight::BLACK},          // NSFontWeightBlack
   };
+
   base::ScopedCFTypeRef<CFDictionaryRef> traits(
       CTFontCopyTraits(base::mac::NSToCFCast(font)));
   DCHECK(traits);
@@ -125,20 +147,18 @@
   if (!cf_weight)
     return Font::Weight::NORMAL;
 
-  // Documentation is vague about what sized floating point type should be used.
-  // However, numeric_limits::epsilon() for 64-bit types is too small to match
-  // the above table, so use 32-bit float. Do not check for the success of
-  // CFNumberGetValue(). CFNumberGetValue() returns false for *any* loss of
-  // value, and a float is used here deliberately to coarsen the accuracy.
-  // There's no guarantee that any particular value for the kCTFontWeightTrait
-  // will be able to be accurately represented with a float.
-  float weight_value;
-  CFNumberGetValue(cf_weight, kCFNumberFloatType, &weight_value);
+  // The value of kCTFontWeightTrait empirically is a kCFNumberFloat64Type
+  // (double) on all tested versions of macOS. However, that doesn't really
+  // matter as only the first two decimal digits need to be tested. Do not check
+  // for the success of CFNumberGetValue() as it returns false for any loss of
+  // value and all that is needed here is two digits of accuracy.
+  CGFloat weight;
+  CFNumberGetValue(cf_weight, kCFNumberCGFloatType, &weight);
   for (const auto& item : weight_map) {
-    if (weight_value - item.ct_weight <= std::numeric_limits<float>::epsilon())
+    if (item.weight_lower <= weight && weight <= item.weight_upper)
       return item.gfx_weight;
   }
-  return Font::Weight::BLACK;
+  return Font::Weight::INVALID;
 }
 
 // Returns an autoreleased NSFont created with the passed-in specifications.