Bug 1328868 - Part 1 - Allow setting a global zoom factor via nsLayoutUtils. r?tnikkel,billm draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Wed, 15 Feb 2017 19:23:15 +0100
changeset 485469 c7d931ce1eb7903f034693e6c90dc24a47662977
parent 485468 60eae402dba1da7fdfececa5e94d7c3e6017cb45
child 485470 64effdcc809ac69cceec754275ad7a512b16357b
push id45741
push usermozilla@buttercookie.de
push dateThu, 16 Feb 2017 19:05:17 +0000
reviewerstnikkel, billm
bugs1328868, 1303096
milestone54.0a1
Bug 1328868 - Part 1 - Allow setting a global zoom factor via nsLayoutUtils. r?tnikkel,billm For Android we want to be able to set a global zoom factor that will scale any page where font inflation is not turned on. Android makes the system font scale available as a float factor. For our purposes, converting this to a percentage based value and rounding to an integer is accurate enough and enables us to pass this value as a standard Gecko int preference. This means we can make use of the standard infrastructure for setting and retrieving Gecko-side preferences both from Java and JS (the latter during testing), as opposed to having to write custom JNI and C++/IDL helper functions. To that effect, we implement a method for retrieving that setting via nsLayoutUtils, analogous to the current font inflation settings. Unlike those, we use a custom preferences listener though, since we want to clamp the font scale factor between the limits of zoom.minPercent and maxPercent as a sanity limit. Because we're mimicking the existing font inflation prefs, we also need to add this new pref to the bug 1303096 whitelist. MozReview-Commit-ID: Ler2YmwzImE
dom/ipc/ContentPrefs.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
modules/libpref/init/all.js
--- a/dom/ipc/ContentPrefs.cpp
+++ b/dom/ipc/ContentPrefs.cpp
@@ -55,16 +55,17 @@ const char* mozilla::dom::ContentPrefs::
   "focusmanager.testmode",
   "font.size.inflation.disabledInMasterProcess",
   "font.size.inflation.emPerLine",
   "font.size.inflation.forceEnabled",
   "font.size.inflation.lineThreshold",
   "font.size.inflation.mappingIntercept",
   "font.size.inflation.maxRatio",
   "font.size.inflation.minTwips",
+  "font.size.systemFontScale",
   "full-screen-api.allow-trusted-requests-only",
   "full-screen-api.enabled",
   "full-screen-api.unprefix.enabled",
   "gfx.font_rendering.opentype_svg.enabled",
   "hangmonitor.timeout",
   "html5.flushtimer.initialdelay",
   "html5.flushtimer.subsequentdelay",
   "html5.offmainthread",
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -150,16 +150,17 @@ using namespace mozilla::gfx;
 
 #define GRID_ENABLED_PREF_NAME "layout.css.grid.enabled"
 #define GRID_TEMPLATE_SUBGRID_ENABLED_PREF_NAME "layout.css.grid-template-subgrid-value.enabled"
 #define WEBKIT_PREFIXES_ENABLED_PREF_NAME "layout.css.prefixes.webkit"
 #define DISPLAY_FLOW_ROOT_ENABLED_PREF_NAME "layout.css.display-flow-root.enabled"
 #define TEXT_ALIGN_UNSAFE_ENABLED_PREF_NAME "layout.css.text-align-unsafe-value.enabled"
 #define FLOAT_LOGICAL_VALUES_ENABLED_PREF_NAME "layout.css.float-logical-values.enabled"
 #define BG_CLIP_TEXT_ENABLED_PREF_NAME "layout.css.background-clip-text.enabled"
+#define SYSTEM_FONT_SCALE_PREF_NAME "font.size.systemFontScale"
 
 // The time in number of frames that we estimate for a refresh driver
 // to be quiescent
 #define DEFAULT_QUIESCENT_FRAMES 2
 // The time (milliseconds) we estimate is needed between the end of an
 // idle time and the next Tick.
 #define DEFAULT_IDLE_PERIOD_TIME_LIMIT 1.0f
 
@@ -173,16 +174,17 @@ typedef nsStyleTransformMatrix::Transfor
 
 /* static */ uint32_t nsLayoutUtils::sFontSizeInflationEmPerLine;
 /* static */ uint32_t nsLayoutUtils::sFontSizeInflationMinTwips;
 /* static */ uint32_t nsLayoutUtils::sFontSizeInflationLineThreshold;
 /* static */ int32_t  nsLayoutUtils::sFontSizeInflationMappingIntercept;
 /* static */ uint32_t nsLayoutUtils::sFontSizeInflationMaxRatio;
 /* static */ bool nsLayoutUtils::sFontSizeInflationForceEnabled;
 /* static */ bool nsLayoutUtils::sFontSizeInflationDisabledInMasterProcess;
+/* static */ float nsLayoutUtils::sSystemFontScale;
 /* static */ bool nsLayoutUtils::sInvalidationDebuggingIsEnabled;
 /* static */ bool nsLayoutUtils::sCSSVariablesEnabled;
 /* static */ bool nsLayoutUtils::sInterruptibleReflowEnabled;
 /* static */ bool nsLayoutUtils::sSVGTransformBoxEnabled;
 /* static */ bool nsLayoutUtils::sTextCombineUprightDigitsEnabled;
 #ifdef MOZ_STYLO
 /* static */ bool nsLayoutUtils::sStyloEnabled;
 #endif
@@ -466,16 +468,40 @@ BackgroundClipTextEnabledPrefChangeCallb
   // OK -- now, stomp on or restore the "text" entry in kBackgroundClipKTable,
   // depending on whether the pref is enabled vs. disabled.
   if (sIndexOfTextInBGClipTable >= 0) {
     nsCSSProps::kBackgroundClipKTable[sIndexOfTextInBGClipTable].mKeyword =
       isBGClipTextEnabled ? eCSSKeyword_text : eCSSKeyword_UNKNOWN;
   }
 }
 
+// Update the system font scale held for global zooming while clamping it
+// according to our min and max zoom preferences.
+/* static */ void
+nsLayoutUtils::SystemFontScalePrefChangeCallback(const char* aPrefName, void* aClosure)
+{
+  MOZ_ASSERT(strncmp(aPrefName, SYSTEM_FONT_SCALE_PREF_NAME,
+                     ArrayLength(SYSTEM_FONT_SCALE_PREF_NAME)) == 0,
+             "We only registered this callback for a single pref, so it "
+             "should only be called for that pref");
+
+  int32_t fontScale =
+    Preferences::GetInt(SYSTEM_FONT_SCALE_PREF_NAME, 100);
+  int32_t minZoom = Preferences::GetInt("zoom.minPercent", 30);
+  int32_t maxZoom = Preferences::GetInt("zoom.maxPercent", 300);
+
+  if (fontScale < minZoom) {
+    fontScale = minZoom;
+  } else if (fontScale > maxZoom) {
+    fontScale = maxZoom;
+  }
+
+  sSystemFontScale = fontScale / 100.0f;
+}
+
 template<typename TestType>
 static bool
 HasMatchingAnimations(const nsIFrame* aFrame, TestType&& aTest)
 {
   EffectSet* effects = EffectSet::GetEffectSet(aFrame);
   if (!effects) {
     return false;
   }
@@ -7583,29 +7609,31 @@ nsLayoutUtils::SizeOfTextRunsForFrames(n
   return total;
 }
 
 struct PrefCallbacks
 {
   const char* name;
   PrefChangedFunc func;
 };
-static const PrefCallbacks kPrefCallbacks[] = {
+/* static */ const PrefCallbacks nsLayoutUtils::kPrefCallbacks[] = {
   { GRID_ENABLED_PREF_NAME,
     GridEnabledPrefChangeCallback },
   { WEBKIT_PREFIXES_ENABLED_PREF_NAME,
     WebkitPrefixEnabledPrefChangeCallback },
   { TEXT_ALIGN_UNSAFE_ENABLED_PREF_NAME,
     TextAlignUnsafeEnabledPrefChangeCallback },
   { DISPLAY_FLOW_ROOT_ENABLED_PREF_NAME,
     DisplayFlowRootEnabledPrefChangeCallback },
   { FLOAT_LOGICAL_VALUES_ENABLED_PREF_NAME,
     FloatLogicalValuesEnabledPrefChangeCallback },
   { BG_CLIP_TEXT_ENABLED_PREF_NAME,
     BackgroundClipTextEnabledPrefChangeCallback },
+  { SYSTEM_FONT_SCALE_PREF_NAME,
+    nsLayoutUtils::SystemFontScalePrefChangeCallback },
 };
 
 /* static */
 void
 nsLayoutUtils::Initialize()
 {
   Preferences::AddUintVarCache(&sFontSizeInflationMaxRatio,
                                "font.size.inflation.maxRatio");
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -119,16 +119,18 @@ enum class RelativeTo {
 
 // Flags to customize the behavior of nsLayoutUtils::DrawString.
 enum class DrawStringFlags {
   eDefault         = 0x0,
   eForceHorizontal = 0x1 // Forces the text to be drawn horizontally.
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DrawStringFlags)
 
+struct PrefCallbacks;
+
 /**
  * nsLayoutUtils is a namespace class used for various helper
  * functions that are useful in multiple places in layout.  The goal
  * is not to define multiple copies of the same static helper.
  */
 class nsLayoutUtils
 {
   typedef mozilla::dom::DOMRectList DOMRectList;
@@ -2423,16 +2425,24 @@ public:
   static bool FontSizeInflationForceEnabled() {
     return sFontSizeInflationForceEnabled;
   }
 
   static bool FontSizeInflationDisabledInMasterProcess() {
     return sFontSizeInflationDisabledInMasterProcess;
   }
 
+  /**
+   * See comment above "font.size.systemFontScale" in
+   * modules/libpref/init/all.js.
+   */
+  static float SystemFontScale() {
+    return sSystemFontScale;
+  }
+
   static bool SVGTransformBoxEnabled() {
     return sSVGTransformBoxEnabled;
   }
 
   static bool TextCombineUprightDigitsEnabled() {
     return sTextCombineUprightDigitsEnabled;
   }
 
@@ -2906,36 +2916,41 @@ public:
 private:
   static uint32_t sFontSizeInflationEmPerLine;
   static uint32_t sFontSizeInflationMinTwips;
   static uint32_t sFontSizeInflationLineThreshold;
   static int32_t  sFontSizeInflationMappingIntercept;
   static uint32_t sFontSizeInflationMaxRatio;
   static bool sFontSizeInflationForceEnabled;
   static bool sFontSizeInflationDisabledInMasterProcess;
+  static float sSystemFontScale;
   static bool sInvalidationDebuggingIsEnabled;
   static bool sCSSVariablesEnabled;
   static bool sInterruptibleReflowEnabled;
   static bool sSVGTransformBoxEnabled;
   static bool sTextCombineUprightDigitsEnabled;
 #ifdef MOZ_STYLO
   static bool sStyloEnabled;
 #endif
   static uint32_t sIdlePeriodDeadlineLimit;
   static uint32_t sQuiescentFramesBeforeIdlePeriod;
 
+  static const PrefCallbacks kPrefCallbacks[];
+
   /**
    * Helper function for LogTestDataForPaint().
    */
   static void DoLogTestDataForPaint(mozilla::layers::LayerManager* aManager,
                                     ViewID aScrollId,
                                     const std::string& aKey,
                                     const std::string& aValue);
 
   static bool IsAPZTestLoggingEnabled();
+
+  static void SystemFontScalePrefChangeCallback(const char* aPrefName, void* aClosure);
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsLayoutUtils::PaintFrameFlags)
 
 template<typename PointType, typename RectType, typename CoordType>
 /* static */ bool
 nsLayoutUtils::PointIsCloserToRect(PointType aPoint, const RectType& aRect,
                                    CoordType& aClosestXDistance,
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3193,16 +3193,28 @@ pref("font.size.inflation.mappingInterce
  * i/s * 100 should never exceed the value of this preference.
  *
  * In order for this preference to have any effect, its value must be
  * greater than 100, since font inflation can never decrease the ratio
  * i/s.
  */
 pref("font.size.inflation.maxRatio", 0);
 
+/**
+ * This setting corresponds to a global text zoom setting affecting
+ * all content and is interpreted as a percentage value. With the
+ * default setting of 100 (corresponding to a text zoom of 1.0x),
+ * the responsible code will turn itself off and remain deactivated.
+ *
+ * At all other settings, the corresponding text zoom factor will be
+ * applied to all pages that are not already affected by font size
+ * inflation, subject to the limits of zoom.minPercent and maxPercent.
+ */
+pref("font.size.systemFontScale", 100);
+
 /*
  * When enabled, the touch.radius and mouse.radius prefs allow events to be dispatched
  * to nearby elements that are sensitive to the event. See PositionedEventTargeting.cpp.
  * The 'mm' prefs define a rectangle around the nominal event target point within which
  * we will search for suitable elements. 'visitedWeight' is a percentage weight;
  * a value > 100 makes a visited link be treated as further away from the event target
  * than it really is, while a value < 100 makes a visited link be treated as closer
  * to the event target than it really is.