Bug 1732629 - [gfx/wr] Fix new_ct_font_with_variations to use non-localized variation axis names from Core Graphics. r=jrmuizel a=RyanVM
authorJonathan Kew <jkew@mozilla.com>
Wed, 27 Oct 2021 14:37:40 +0000 (2021-10-27)
changeset 597047 b5086513fe50f9598db2391f8cb021425033fadd
parent 597046 0ad5486182ffdf455a0c0285b87780e7c39e5244
child 597086 39022aacb0e43d8c1777eec6ba6cfbad690038b1
push id38919
push userarchaeopteryx@coole-files.de
push dateWed, 27 Oct 2021 15:06:08 +0000 (2021-10-27)
treeherdermozilla-central@b5086513fe50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, RyanVM
bugs1732629
milestone95.0a1
first release with
nightly mac
b5086513fe50 / 95.0a1 / 20211027150608 / files
nightly linux32
nightly linux64
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly mac
Bug 1732629 - [gfx/wr] Fix new_ct_font_with_variations to use non-localized variation axis names from Core Graphics. r=jrmuizel a=RyanVM Differential Revision: https://phabricator.services.mozilla.com/D129636 Depends on D129576
Cargo.lock
gfx/wr/Cargo.lock
gfx/wr/webrender/Cargo.toml
gfx/wr/webrender/src/lib.rs
gfx/wr/webrender/src/platform/macos/font.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5568,16 +5568,17 @@ dependencies = [
  "byteorder",
  "core-foundation",
  "core-graphics",
  "core-text",
  "derive_more",
  "dwrote",
  "etagere",
  "euclid",
+ "foreign-types",
  "freetype",
  "fxhash",
  "gleam",
  "glslopt",
  "lazy_static",
  "libc",
  "log",
  "malloc_size_of_derive",
--- a/gfx/wr/Cargo.lock
+++ b/gfx/wr/Cargo.lock
@@ -1676,16 +1676,17 @@ dependencies = [
  "byteorder",
  "core-foundation 0.9.0",
  "core-graphics 0.22.0",
  "core-text",
  "derive_more",
  "dwrote",
  "etagere",
  "euclid",
+ "foreign-types",
  "freetype",
  "fxhash",
  "gleam 0.13.1",
  "glslopt",
  "lazy_static",
  "libc",
  "log",
  "malloc_size_of_derive",
--- a/gfx/wr/webrender/Cargo.toml
+++ b/gfx/wr/webrender/Cargo.toml
@@ -64,8 +64,9 @@ libc = "0.2"
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.11"
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-foundation = "0.9"
 core-graphics = "0.22"
 core-text = { version = "19", default-features = false }
 objc = "0.2"
+foreign-types = "0.3.0"
--- a/gfx/wr/webrender/src/lib.rs
+++ b/gfx/wr/webrender/src/lib.rs
@@ -66,16 +66,18 @@ extern crate malloc_size_of_derive;
 #[macro_use]
 extern crate serde;
 #[macro_use]
 extern crate tracy_rs;
 #[macro_use]
 extern crate derive_more;
 extern crate malloc_size_of;
 extern crate svg_fmt;
+#[cfg(target_os = "macos")]
+extern crate foreign_types;
 
 #[macro_use]
 mod profiler;
 
 mod batch;
 mod border;
 mod box_shadow;
 #[cfg(any(feature = "capture", feature = "replay"))]
--- a/gfx/wr/webrender/src/platform/macos/font.rs
+++ b/gfx/wr/webrender/src/platform/macos/font.rs
@@ -14,28 +14,32 @@ use core_graphics::base::{kCGBitmapByteO
 use core_graphics::color_space::CGColorSpace;
 use core_graphics::context::CGContext;
 use core_graphics::context::{CGBlendMode, CGTextDrawingMode};
 use core_graphics::font::{CGFont, CGGlyph};
 use core_graphics::geometry::{CGAffineTransform, CGPoint, CGSize};
 use core_graphics::geometry::{CG_AFFINE_TRANSFORM_IDENTITY, CGRect};
 use core_text::{self, font_descriptor::CTFontDescriptorCreateCopyWithAttributes};
 use core_text::font::{CTFont, CTFontRef};
-use core_text::font_descriptor::{CTFontDescriptor, CTFontSymbolicTraits};
+use core_text::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, CTFontSymbolicTraits};
 use core_text::font_descriptor::{kCTFontDefaultOrientation, kCTFontColorGlyphsTrait};
 use euclid::default::Size2D;
 use crate::gamma_lut::{ColorLut, GammaLut};
 use crate::glyph_rasterizer::{FontInstance, FontTransform, GlyphKey};
 use crate::glyph_rasterizer::{GlyphFormat, GlyphRasterError, GlyphRasterResult, RasterizedGlyph};
 use crate::internal_types::{FastHashMap, ResourceCacheError};
 use std::collections::hash_map::Entry;
 use std::sync::Arc;
+use foreign_types::ForeignType;
 
 const INITIAL_CG_CONTEXT_SIDE_LENGTH: u32 = 32;
 
+// Needed for calling CGFontCopyVariationAxes manually.
+type CGFontRef = *mut <CGFont as ForeignType>::CType;
+
 // We prefer to create CTFonts from a CTFontDescriptor, but that doesn't work in the case
 // of hidden system fonts on recent macOS versions, so for those we will instead use a
 // native CGFont as the basis.
 enum DescOrFont {
     Desc(CTFontDescriptor),
     Font(CGFont),
 }
 
@@ -214,50 +218,71 @@ fn get_glyph_metrics(
         rasterized_descent: -bottom,
         advance: advance.width as f32,
     }
 }
 
 #[link(name = "ApplicationServices", kind = "framework")]
 extern {
     static kCTFontVariationAxisIdentifierKey: CFStringRef;
-    static kCTFontVariationAxisNameKey: CFStringRef;
     static kCTFontVariationAxisMinimumValueKey: CFStringRef;
     static kCTFontVariationAxisMaximumValueKey: CFStringRef;
     static kCTFontVariationAxisDefaultValueKey: CFStringRef;
     static kCTFontVariationAttribute: CFStringRef;
+    static kCGFontVariationAxisName: CFStringRef;
 
     fn CTFontCopyVariationAxes(font: CTFontRef) -> CFArrayRef;
+    fn CGFontCopyVariationAxes(font: CGFontRef) -> CFArrayRef;
 }
 
 fn new_ct_font_with_variations(desc_or_font: &DescOrFont, size: f64, variations: &[FontVariation]) -> CTFont {
     unsafe {
         let ct_font = match desc_or_font {
             DescOrFont::Desc(ct_font_desc) => core_text::font::new_from_descriptor(ct_font_desc, size),
             DescOrFont::Font(cg_font) => core_text::font::new_from_CGFont(cg_font, size)
         };
         if variations.is_empty() {
             return ct_font;
         }
-        let axes_ref = CTFontCopyVariationAxes(ct_font.as_concrete_TypeRef());
-        if axes_ref.is_null() {
+
+        // We get the axes from Core Text in order to get the tags.
+        let ct_axes_ref = CTFontCopyVariationAxes(ct_font.as_concrete_TypeRef());
+        if ct_axes_ref.is_null() {
             return ct_font;
         }
-        let axes: CFArray<CFDictionary> = TCFType::wrap_under_create_rule(axes_ref);
+        let ct_axes: CFArray<CFDictionary> = TCFType::wrap_under_create_rule(ct_axes_ref);
+
+        // And get them from Core Graphics to get non-localized names.
+        let cg_font = match desc_or_font {
+            DescOrFont::Desc(_) => ct_font.copy_to_CGFont(),
+            DescOrFont::Font(cg_font) => cg_font.clone(),
+        };
+        let cg_axes_ref = CGFontCopyVariationAxes(cg_font.as_ptr());
+        if cg_axes_ref.is_null() {
+            return ct_font;
+        }
+        let cg_axes: CFArray<CFDictionary> = TCFType::wrap_under_create_rule(cg_axes_ref);
+
+        // Bail out if the array lengths don't match.
+        if ct_axes.len() != cg_axes.len() {
+            return ct_font;
+        }
+
         // We collect the values with either number or string keys, depending whether
         // we're going to instantiate the CTFont from a descriptor or a CGFont.
         // It'd probably be better to switch the CGFont-related APIs to expect numbers,
         // but that's left for a future cleanup.
         let mut vals: Vec<(CFNumber, CFNumber)> = Vec::with_capacity(variations.len() as usize);
         let mut vals_str: Vec<(CFString, CFNumber)> = Vec::with_capacity(variations.len() as usize);
-        for axis in axes.iter() {
-            if !axis.instance_of::<CFDictionary>() {
+
+        for (ct_axis, cg_axis) in ct_axes.iter().zip(cg_axes.iter()) {
+            if !ct_axis.instance_of::<CFDictionary>() {
                 return ct_font;
             }
-            let tag_val = match axis.find(kCTFontVariationAxisIdentifierKey as *const _) {
+            let tag_val = match ct_axis.find(kCTFontVariationAxisIdentifierKey as *const _) {
                 Some(tag_ptr) => {
                     let tag: CFNumber = TCFType::wrap_under_get_rule(*tag_ptr as CFNumberRef);
                     if !tag.instance_of::<CFNumber>() {
                         return ct_font;
                     }
                     match tag.to_i64() {
                         Some(val) => val,
                         None => return ct_font,
@@ -265,51 +290,51 @@ fn new_ct_font_with_variations(desc_or_f
                 }
                 None => return ct_font,
             };
             let mut val = match variations.iter().find(|variation| (variation.tag as i64) == tag_val) {
                 Some(variation) => variation.value as f64,
                 None => continue,
             };
 
-            let name: CFString = match axis.find(kCTFontVariationAxisNameKey as *const _) {
+            let name: CFString = match cg_axis.find(kCGFontVariationAxisName as *const _) {
                 Some(name_ptr) => TCFType::wrap_under_get_rule(*name_ptr as CFStringRef),
                 None => return ct_font,
             };
             if !name.instance_of::<CFString>() {
                 return ct_font;
             }
 
-            let min_val = match axis.find(kCTFontVariationAxisMinimumValueKey as *const _) {
+            let min_val = match ct_axis.find(kCTFontVariationAxisMinimumValueKey as *const _) {
                 Some(min_ptr) => {
                     let min: CFNumber = TCFType::wrap_under_get_rule(*min_ptr as CFNumberRef);
                     if !min.instance_of::<CFNumber>() {
                         return ct_font;
                     }
                     match min.to_f64() {
                         Some(val) => val,
                         None => return ct_font,
                     }
                 }
                 None => return ct_font,
             };
-            let max_val = match axis.find(kCTFontVariationAxisMaximumValueKey as *const _) {
+            let max_val = match ct_axis.find(kCTFontVariationAxisMaximumValueKey as *const _) {
                 Some(max_ptr) => {
                     let max: CFNumber = TCFType::wrap_under_get_rule(*max_ptr as CFNumberRef);
                     if !max.instance_of::<CFNumber>() {
                         return ct_font;
                     }
                     match max.to_f64() {
                         Some(val) => val,
                         None => return ct_font,
                     }
                 }
                 None => return ct_font,
             };
-            let def_val = match axis.find(kCTFontVariationAxisDefaultValueKey as *const _) {
+            let def_val = match ct_axis.find(kCTFontVariationAxisDefaultValueKey as *const _) {
                 Some(def_ptr) => {
                     let def: CFNumber = TCFType::wrap_under_get_rule(*def_ptr as CFNumberRef);
                     if !def.instance_of::<CFNumber>() {
                         return ct_font;
                     }
                     match def.to_f64() {
                         Some(val) => val,
                         None => return ct_font,
@@ -1010,17 +1035,16 @@ fn CFData_wrapping_arc_vec(buffer: Arc<V
         });
         let data_ref =
             CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, ptr, len, allocator.as_CFTypeRef());
         TCFType::wrap_under_create_rule(data_ref)
     }
 }
 
 fn create_font_descriptor(cf_data: CFData) -> Result<CTFontDescriptor, ()> {
-    use core_text::font_descriptor::CTFontDescriptorRef;
     use core_foundation::data::CFDataRef;
     extern {
         pub fn CTFontManagerCreateFontDescriptorFromData(data: CFDataRef) -> CTFontDescriptorRef;
     }
     unsafe {
         let ct_font_descriptor_ref = CTFontManagerCreateFontDescriptorFromData(cf_data.as_concrete_TypeRef());
         if ct_font_descriptor_ref.is_null() {
             return Err(());