Bug 1341724 - Part 2: stylo: Add bindings for fetching font metrics from Gecko; r?heycam draft
authorManish Goregaokar <manishearth@gmail.com>
Fri, 07 Apr 2017 15:49:44 -0700
changeset 559280 9872818523b2b9d3ca0fd42845526b7ef000588e
parent 559273 0133e42f7f7dbacb4f9446f23d465287b19e9013
child 559281 29428d3e8b16759dd59c6e1cc01c39b11a40c4fd
child 559440 564cee469fad010113c1e913f61343913cf814dc
push id53040
push userbmo:manishearth@gmail.com
push dateSun, 09 Apr 2017 11:25:17 +0000
reviewersheycam
bugs1341724
milestone55.0a1
Bug 1341724 - Part 2: stylo: Add bindings for fetching font metrics from Gecko; r?heycam MozReview-Commit-ID: BkPNq22ruwU
layout/build/nsLayoutStatics.cpp
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/nsRuleNode.cpp
servo/components/style/build_gecko.rs
servo/components/style/gecko_bindings/bindings.rs
servo/components/style/gecko_bindings/structs_debug.rs
servo/components/style/gecko_bindings/structs_release.rs
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -307,17 +307,17 @@ nsLayoutStatics::Initialize()
 
   MediaDecoder::InitStatics();
 
   PromiseDebugging::Init();
 
   mozilla::dom::WebCryptoThreadPool::Initialize();
 
 #ifdef MOZ_STYLO
-  Servo_Initialize();
+  InitializeServo();
 #endif
 
 #ifndef MOZ_WIDGET_ANDROID
   // On Android, we instantiate it when constructing AndroidBridge.
   MediaPrefs::GetSingleton();
 #endif
 
   return NS_OK;
@@ -325,17 +325,17 @@ nsLayoutStatics::Initialize()
 
 void
 nsLayoutStatics::Shutdown()
 {
   // Don't need to shutdown nsWindowMemoryReporter, that will be done by the
   // memory reporter manager.
 
 #ifdef MOZ_STYLO
-  Servo_Shutdown();
+  ShutdownServo();
 #endif
 
   nsMessageManagerScriptExecutor::Shutdown();
   nsFocusManager::Shutdown();
 #ifdef MOZ_XUL
   nsXULPopupManager::Shutdown();
 #endif
   StorageObserver::Shutdown();
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -21,30 +21,32 @@
 #include "nsIContentInlines.h"
 #include "nsIDOMNode.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
 #include "nsIPresShellInlines.h"
 #include "nsIPrincipal.h"
+#include "nsFontMetrics.h"
 #include "nsMappedAttributes.h"
 #include "nsMediaFeatures.h"
 #include "nsNameSpaceManager.h"
 #include "nsNetUtil.h"
 #include "nsRuleNode.h"
 #include "nsString.h"
 #include "nsStyleStruct.h"
 #include "nsStyleUtil.h"
 #include "nsTArray.h"
 
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/EffectSet.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/Keyframe.h"
+#include "mozilla/Mutex.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/SystemGroup.h"
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/dom/HTMLTableCellElement.h"
@@ -1542,16 +1544,57 @@ Gecko_GetBaseSize(nsIAtom* aLanguage)
   sizes.mDefaultSerifSize = prefs.mDefaultSerifFont.size;
   sizes.mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size;
   sizes.mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size;
   sizes.mDefaultCursiveSize = prefs.mDefaultCursiveFont.size;
   sizes.mDefaultFantasySize = prefs.mDefaultFantasyFont.size;
   return sizes;
 }
 
+static Mutex* sServoFontMetricsLock = nullptr;
+
+void
+InitializeServo()
+{
+  Servo_Initialize();
+
+  sServoFontMetricsLock = new Mutex("Gecko_GetFontMetrics");
+}
+
+void
+ShutdownServo()
+{
+  delete sServoFontMetricsLock;
+  Servo_Shutdown();
+}
+
+GeckoFontMetrics
+Gecko_GetFontMetrics(RawGeckoPresContextBorrowed aPresContext,
+                     bool aIsVertical,
+                     const nsStyleFont* aFont,
+                     nscoord aFontSize,
+                     bool aUseUserFontSet)
+{
+  MutexAutoLock lock(*sServoFontMetricsLock);
+  aPresContext->SetUsesExChUnits(true);
+  GeckoFontMetrics ret;
+  // Safe because we are locked, and this function is only
+  // ever called from Servo parallel traversal
+  MOZ_ASSERT(ServoStyleSet::IsInServoTraversal());
+  nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
+  RefPtr<nsFontMetrics> fm = nsRuleNode::GetMetricsFor(presContext, aIsVertical,
+                                                       aFont, aFontSize,
+                                                       aUseUserFontSet);
+  ret.mXSize = fm->XHeight();
+  gfxFloat zeroWidth = fm->GetThebesFontGroup()->GetFirstValidFont()->
+                           GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
+  ret.mChSize = ceil(aPresContext->AppUnitsPerDevPixel() * zeroWidth);
+  return ret;
+}
+
 void
 Gecko_LoadStyleSheet(css::Loader* aLoader,
                      ServoStyleSheet* aParent,
                      RawServoStyleSheetBorrowed aChildSheet,
                      RawGeckoURLExtraData* aBaseURLData,
                      const uint8_t* aURLString,
                      uint32_t aURLStringLength,
                      const uint8_t* aMediaString,
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -377,16 +377,30 @@ void Gecko_CSSValue_SetInt(nsCSSValueBor
 void Gecko_CSSValue_Drop(nsCSSValueBorrowedMut css_value);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
 bool Gecko_PropertyId_IsPrefEnabled(nsCSSPropertyID id);
 
 void Gecko_nsStyleFont_SetLang(nsStyleFont* font, nsIAtom* atom);
 void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont, const nsStyleFont* aSource);
 FontSizePrefs Gecko_GetBaseSize(nsIAtom* lang);
 
+struct GeckoFontMetrics
+{
+  nscoord mChSize;
+  nscoord mXSize;
+};
+
+GeckoFontMetrics Gecko_GetFontMetrics(RawGeckoPresContextBorrowed pres_context,
+                                      bool is_vertical,
+                                      const nsStyleFont* font,
+                                      nscoord font_size,
+                                      bool use_user_font_set);
+void InitializeServo();
+void ShutdownServo();
+
 const nsMediaFeature* Gecko_GetMediaFeatures();
 
 // Font face rule
 // Creates and returns a new (already-addrefed) nsCSSFontFaceRule object.
 nsCSSFontFaceRule* Gecko_CSSFontFaceRule_Create();
 void Gecko_CSSFontFaceRule_GetCssText(const nsCSSFontFaceRule* rule, nsAString* result);
 NS_DECL_FFI_REFCOUNTING(nsCSSFontFaceRule, CSSFontFaceRule);
 
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -609,26 +609,26 @@ static nscoord CalcLengthWith(const nsCS
       // CSS2.1 specifies that this unit scales to the computed font
       // size, not the em-width in the font metrics, despite the name.
       aConditions.SetFontSizeDependency(aFontSize);
       return ScaleCoordRound(aValue, float(aFontSize));
     }
     case eCSSUnit_XHeight: {
       aPresContext->SetUsesExChUnits(true);
       RefPtr<nsFontMetrics> fm =
-        GetMetricsFor(aPresContext, aStyleContext, styleFont,
-                      aFontSize, aUseUserFontSet);
+        nsRuleNode::GetMetricsFor(aPresContext, aStyleContext, styleFont,
+                                  aFontSize, aUseUserFontSet);
       aConditions.SetUncacheable();
       return ScaleCoordRound(aValue, float(fm->XHeight()));
     }
     case eCSSUnit_Char: {
       aPresContext->SetUsesExChUnits(true);
       RefPtr<nsFontMetrics> fm =
-        GetMetricsFor(aPresContext, aStyleContext, styleFont,
-                      aFontSize, aUseUserFontSet);
+        nsRuleNode::GetMetricsFor(aPresContext, aStyleContext, styleFont,
+                                  aFontSize, aUseUserFontSet);
       gfxFloat zeroWidth =
         fm->GetThebesFontGroup()->GetFirstValidFont()->
           GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
 
       aConditions.SetUncacheable();
       return ScaleCoordRound(aValue, ceil(aPresContext->AppUnitsPerDevPixel() *
                                           zeroWidth));
     }
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -330,16 +330,17 @@ mod bindings {
             "FontFamilyList",
             "FontFamilyListRefCnt",
             "FontFamilyName",
             "FontFamilyType",
             "FontSizePrefs",
             "FragmentOrURL",
             "FrameRequestCallback",
             "GeckoParserExtraData",
+            "GeckoFontMetrics",
             "gfxAlternateValue",
             "gfxFontFeature",
             "gfxFontVariation",
             "GridNamedArea",
             "HalfCorner",
             "Image",
             "ImageURL",
             "Keyframe",
@@ -607,16 +608,17 @@ mod bindings {
             "RawGeckoStyleAnimationList",
             "RawGeckoURLExtraData",
             "RefPtr",
             "CSSPseudoClassType",
             "TraversalRootBehavior",
             "FontFamilyList",
             "FontFamilyType",
             "FontSizePrefs",
+            "GeckoFontMetrics",
             "Keyframe",
             "ServoBundledURI",
             "ServoElementSnapshot",
             "SheetParsingMode",
             "StyleBasicShape",
             "StyleBasicShapeType",
             "StyleShapeSource",
             "nsCSSFontFaceRule",
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -19,16 +19,17 @@ use gecko_bindings::structs::RawGeckoPre
 use gecko_bindings::structs::RawGeckoStyleAnimationList;
 use gecko_bindings::structs::RawGeckoURLExtraData;
 use gecko_bindings::structs::RefPtr;
 use gecko_bindings::structs::CSSPseudoClassType;
 use gecko_bindings::structs::TraversalRootBehavior;
 use gecko_bindings::structs::FontFamilyList;
 use gecko_bindings::structs::FontFamilyType;
 use gecko_bindings::structs::FontSizePrefs;
+use gecko_bindings::structs::GeckoFontMetrics;
 use gecko_bindings::structs::Keyframe;
 use gecko_bindings::structs::ServoBundledURI;
 use gecko_bindings::structs::ServoElementSnapshot;
 use gecko_bindings::structs::SheetParsingMode;
 use gecko_bindings::structs::StyleBasicShape;
 use gecko_bindings::structs::StyleBasicShapeType;
 use gecko_bindings::structs::StyleShapeSource;
 use gecko_bindings::structs::nsCSSFontFaceRule;
@@ -1020,16 +1021,22 @@ extern "C" {
 extern "C" {
     pub fn Gecko_nsStyleFont_CopyLangFrom(aFont: *mut nsStyleFont,
                                           aSource: *const nsStyleFont);
 }
 extern "C" {
     pub fn Gecko_GetBaseSize(lang: *mut nsIAtom) -> FontSizePrefs;
 }
 extern "C" {
+    pub fn Gecko_GetFontMetrics(pres_context: RawGeckoPresContextBorrowed,
+                                is_vertical: bool, font: *const nsStyleFont,
+                                font_size: nscoord, use_user_font_set: bool)
+     -> GeckoFontMetrics;
+}
+extern "C" {
     pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
 }
 extern "C" {
     pub fn Gecko_CSSFontFaceRule_Create() -> *mut nsCSSFontFaceRule;
 }
 extern "C" {
     pub fn Gecko_CSSFontFaceRule_GetCssText(rule: *const nsCSSFontFaceRule,
                                             result: *mut nsAString);
--- a/servo/components/style/gecko_bindings/structs_debug.rs
+++ b/servo/components/style/gecko_bindings/structs_debug.rs
@@ -26817,16 +26817,43 @@ pub mod root {
                     concat ! (
                     "Alignment of field: " , stringify ! ( FontSizePrefs ) ,
                     "::" , stringify ! ( mDefaultFantasySize ) ));
     }
     impl Clone for FontSizePrefs {
         fn clone(&self) -> Self { *self }
     }
     #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct GeckoFontMetrics {
+        pub mChSize: root::nscoord,
+        pub mXSize: root::nscoord,
+    }
+    #[test]
+    fn bindgen_test_layout_GeckoFontMetrics() {
+        assert_eq!(::std::mem::size_of::<GeckoFontMetrics>() , 8usize , concat
+                   ! ( "Size of: " , stringify ! ( GeckoFontMetrics ) ));
+        assert_eq! (::std::mem::align_of::<GeckoFontMetrics>() , 4usize ,
+                    concat ! (
+                    "Alignment of " , stringify ! ( GeckoFontMetrics ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const GeckoFontMetrics ) ) . mChSize as *
+                    const _ as usize } , 0usize , concat ! (
+                    "Alignment of field: " , stringify ! ( GeckoFontMetrics )
+                    , "::" , stringify ! ( mChSize ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const GeckoFontMetrics ) ) . mXSize as *
+                    const _ as usize } , 4usize , concat ! (
+                    "Alignment of field: " , stringify ! ( GeckoFontMetrics )
+                    , "::" , stringify ! ( mXSize ) ));
+    }
+    impl Clone for GeckoFontMetrics {
+        fn clone(&self) -> Self { *self }
+    }
+    #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsROCSSPrimitiveValue([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy)]
     pub struct nsIDOMCSSFontFaceRule {
         pub _base: root::nsISupports,
     }
     #[repr(C)]
--- a/servo/components/style/gecko_bindings/structs_release.rs
+++ b/servo/components/style/gecko_bindings/structs_release.rs
@@ -26204,16 +26204,43 @@ pub mod root {
                     concat ! (
                     "Alignment of field: " , stringify ! ( FontSizePrefs ) ,
                     "::" , stringify ! ( mDefaultFantasySize ) ));
     }
     impl Clone for FontSizePrefs {
         fn clone(&self) -> Self { *self }
     }
     #[repr(C)]
+    #[derive(Debug, Copy)]
+    pub struct GeckoFontMetrics {
+        pub mChSize: root::nscoord,
+        pub mXSize: root::nscoord,
+    }
+    #[test]
+    fn bindgen_test_layout_GeckoFontMetrics() {
+        assert_eq!(::std::mem::size_of::<GeckoFontMetrics>() , 8usize , concat
+                   ! ( "Size of: " , stringify ! ( GeckoFontMetrics ) ));
+        assert_eq! (::std::mem::align_of::<GeckoFontMetrics>() , 4usize ,
+                    concat ! (
+                    "Alignment of " , stringify ! ( GeckoFontMetrics ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const GeckoFontMetrics ) ) . mChSize as *
+                    const _ as usize } , 0usize , concat ! (
+                    "Alignment of field: " , stringify ! ( GeckoFontMetrics )
+                    , "::" , stringify ! ( mChSize ) ));
+        assert_eq! (unsafe {
+                    & ( * ( 0 as * const GeckoFontMetrics ) ) . mXSize as *
+                    const _ as usize } , 4usize , concat ! (
+                    "Alignment of field: " , stringify ! ( GeckoFontMetrics )
+                    , "::" , stringify ! ( mXSize ) ));
+    }
+    impl Clone for GeckoFontMetrics {
+        fn clone(&self) -> Self { *self }
+    }
+    #[repr(C)]
     #[derive(Debug, Copy, Clone)]
     pub struct nsROCSSPrimitiveValue([u8; 0]);
     #[repr(C)]
     #[derive(Debug, Copy)]
     pub struct nsIDOMCSSFontFaceRule {
         pub _base: root::nsISupports,
     }
     #[repr(C)]