Bug 1371157 - Cache results of Windows system font lookups. r=jimm
authorL. David Baron <dbaron@dbaron.org>
Fri, 09 Jun 2017 08:59:12 -0700
changeset 411381 70c026121670bd42e43bb87334fec1fd848b77d9
parent 411380 aa3557e8515c8a8a1cbab8f5a5614476cc68ffe6
child 411382 f0c05f5e4dda7ac9d0cf597c5c3f3634a73f21e3
child 411432 7d0171fd883a38c5c8e310b7e66b30002b035653
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1371157
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1371157 - Cache results of Windows system font lookups. r=jimm I haven't really tested that this fixes the performance problem observed in a profile without the patch because the steps to use the Gecko Profiler on local builds on Windows are rather complicated. MozReview-Commit-ID: FmGFs2Cvquv
widget/LookAndFeel.h
widget/windows/nsLookAndFeel.cpp
widget/windows/nsLookAndFeel.h
--- a/widget/LookAndFeel.h
+++ b/widget/LookAndFeel.h
@@ -463,16 +463,17 @@ public:
     // should be added to the calculated caret width.
     eFloatID_CaretAspectRatio
   };
 
   // These constants must be kept in 1:1 correspondence with the
   // NS_STYLE_FONT_* system font constants.
   enum FontID {
     eFont_Caption = 1,     // css2
+    FontID_MINIMUM = eFont_Caption,
     eFont_Icon,
     eFont_Menu,
     eFont_MessageBox,
     eFont_SmallCaption,
     eFont_StatusBar,
 
     eFont_Window,          // css3
     eFont_Document,
@@ -481,17 +482,18 @@ public:
     eFont_Info,
     eFont_Dialog,
     eFont_Button,
     eFont_PullDownMenu,
     eFont_List,
     eFont_Field,
 
     eFont_Tooltips,        // moz
-    eFont_Widget
+    eFont_Widget,
+    FontID_MAXIMUM = eFont_Widget
   };
 
   /**
    * GetColor() return a native color value (might be overwritten by prefs) for
    * aID.  Some platforms don't return an error even if the index doesn't
    * match any system colors.  And also some platforms may initialize the
    * return value even when it returns an error.  Therefore, if you want to
    * use a color for the default value, you should use the other GetColor()
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsLookAndFeel.h"
 #include <windows.h>
 #include <shellapi.h>
 #include "nsStyleConsts.h"
 #include "nsUXThemeData.h"
 #include "nsUXThemeConstants.h"
-#include "gfxFont.h"
 #include "WinUtils.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/WindowsVersion.h"
 #include "gfxFontConstants.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
@@ -658,24 +657,53 @@ GetSysFontInfo(HDC aHDC, LookAndFeel::Fo
   return true;
 }
 
 bool
 nsLookAndFeel::GetFontImpl(FontID anID, nsString &aFontName,
                            gfxFontStyle &aFontStyle,
                            float aDevPixPerCSSPixel)
 {
-  HDC tdc = GetDC(nullptr);
-  bool status = GetSysFontInfo(tdc, anID, aFontName, aFontStyle);
-  ReleaseDC(nullptr, tdc);
+  CachedSystemFont &cacheSlot = mSystemFontCache[anID];
+
+  bool status;
+  if (cacheSlot.mCacheValid) {
+    status = cacheSlot.mHaveFont;
+    if (status) {
+      aFontName = cacheSlot.mFontName;
+      aFontStyle = cacheSlot.mFontStyle;
+    }
+  } else {
+    HDC tdc = GetDC(nullptr);
+    status = GetSysFontInfo(tdc, anID, aFontName, aFontStyle);
+    ReleaseDC(nullptr, tdc);
+
+    cacheSlot.mCacheValid = true;
+    cacheSlot.mHaveFont = status;
+    if (status) {
+      cacheSlot.mFontName = aFontName;
+      cacheSlot.mFontStyle = aFontStyle;
+    }
+  }
   // now convert the logical font size from GetSysFontInfo into device pixels for layout
   aFontStyle.size *= aDevPixPerCSSPixel;
   return status;
 }
 
+/* virtual */ void
+nsLookAndFeel::RefreshImpl()
+{
+  nsXPLookAndFeel::RefreshImpl();
+
+  for (auto e = mSystemFontCache.begin(), end = mSystemFontCache.end();
+       e != end; ++e) {
+    e->mCacheValid = false;
+  }
+}
+
 /* virtual */
 char16_t
 nsLookAndFeel::GetPasswordCharacterImpl()
 {
 #define UNICODE_BLACK_CIRCLE_CHAR 0x25cf
   return UNICODE_BLACK_CIRCLE_CHAR;
 }
 
--- a/widget/windows/nsLookAndFeel.h
+++ b/widget/windows/nsLookAndFeel.h
@@ -2,16 +2,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __nsLookAndFeel
 #define __nsLookAndFeel
 
 #include "nsXPLookAndFeel.h"
+#include "gfxFont.h"
+#include "mozilla/RangedArray.h"
 
 /*
  * Gesture System Metrics
  */
 #ifndef SM_DIGITIZER
 #define SM_DIGITIZER         94
 #define TABLET_CONFIG_NONE   0x00000000
 #define NID_INTEGRATED_TOUCH 0x00000001
@@ -37,22 +39,38 @@ public:
   virtual ~nsLookAndFeel();
 
   nsresult NativeGetColor(ColorID aID, nscolor &aResult) override;
   nsresult GetIntImpl(IntID aID, int32_t &aResult) override;
   nsresult GetFloatImpl(FloatID aID, float &aResult) override;
   bool GetFontImpl(FontID aID, nsString& aFontName,
                    gfxFontStyle& aFontStyle,
                    float aDevPixPerCSSPixel) override;
+  void RefreshImpl() override;
   char16_t GetPasswordCharacterImpl() override;
 
   nsTArray<LookAndFeelInt> GetIntCacheImpl() override;
   void SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) override;
 
 private:
   // Content process cached values that get shipped over from the browser
   // process.
   int32_t mUseAccessibilityTheme;
   int32_t mUseDefaultTheme; // is the current theme a known default?
   int32_t mNativeThemeId; // see LookAndFeel enum 'WindowsTheme'
+
+  struct CachedSystemFont {
+    CachedSystemFont()
+      : mCacheValid(false)
+    {}
+
+    bool mCacheValid;
+    bool mHaveFont;
+    nsString mFontName;
+    gfxFontStyle mFontStyle;
+  };
+
+  mozilla::RangedArray<CachedSystemFont,
+                       FontID_MINIMUM,
+                       FontID_MAXIMUM + 1 - FontID_MINIMUM> mSystemFontCache;
 };
 
 #endif