Bug 878931: Add a FontSizeInflation() method to Element in order to retrieve font size inflation to use during reflow-on-zoom. [r=kats,mounir][a=akeybl]
authorScott Johnson <sjohnson@mozilla.com>
Wed, 03 Jul 2013 17:15:30 -0500
changeset 147833 afb602f09bc90279f6ff95431150582a4ef664dd
parent 147832 38ed376e845be5c7add4034289c6036b1ec4ee8b
child 147834 77ba223a21e2a1d869bb63abf565cc0b65e60adb
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, mounir, akeybl
bugs878931
milestone24.0a2
Bug 878931: Add a FontSizeInflation() method to Element in order to retrieve font size inflation to use during reflow-on-zoom. [r=kats,mounir][a=akeybl] The reflow-on-zoom behavior needs a more robust determination of the font size inflation, so that it can adjust its behavior depending on whether font size inflation has been enabled for a given element's text. This patch also modifies the behavior of reflow- on-zoom such that it will zoom in to piece of text, with reflow, if the minimum specified font size in the font size inflation preferences is greater than the current font size, with font size inflation, of the element.
content/base/public/Element.h
content/base/src/Element.cpp
dom/webidl/Element.webidl
mobile/android/chrome/content/browser.js
modules/libpref/src/init/all.js
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -916,16 +916,32 @@ public:
    * Sets value of boolean attribute by removing attribute or setting it to
    * the empty string. Only works for attributes in null namespace.
    *
    * @param aAttr    name of attribute.
    * @param aValue   Boolean value of attribute.
    */
   NS_HIDDEN_(nsresult) SetBoolAttr(nsIAtom* aAttr, bool aValue);
 
+  /**
+   * Retrieve the ratio of font-size-inflated text font size to computed font
+   * size for this element. This will query the element for its primary frame,
+   * and then use this to get font size inflation information about the frame.
+   *
+   * @returns The font size inflation ratio (inflated font size to uninflated
+   *          font size) for the primary frame of this element. Returns 1.0
+   *          by default if font size inflation is not enabled. Returns -1
+   *          if the element does not have a primary frame.
+   *
+   * @note The font size inflation ratio that is returned is actually the
+   *       font size inflation data for the element's _primary frame_, not the
+   *       element itself, but for most purposes, this should be sufficient.
+   */
+  float FontSizeInflation();
+
 protected:
   /*
    * Named-bools for use with SetAttrAndNotify to make call sites easier to
    * read.
    */
   static const bool kFireMutationEvent           = true;
   static const bool kDontFireMutationEvent       = false;
   static const bool kNotifyDocumentObservers     = true;
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -3508,8 +3508,23 @@ nsresult
 Element::SetBoolAttr(nsIAtom* aAttr, bool aValue)
 {
   if (aValue) {
     return SetAttr(kNameSpaceID_None, aAttr, EmptyString(), true);
   }
 
   return UnsetAttr(kNameSpaceID_None, aAttr, true);
 }
+
+float
+Element::FontSizeInflation()
+{
+  nsIFrame* frame = mPrimaryFrame;
+  if (!frame) {
+    return -1.0;
+  }
+
+  if (nsLayoutUtils::FontSizeInflationEnabled(frame->PresContext())) {
+    return nsLayoutUtils::FontSizeInflationFor(frame);
+  }
+
+  return 1.0;
+}
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -63,16 +63,30 @@ interface Element : Node {
   readonly attribute Element? lastElementChild;
   [Pure]
   readonly attribute Element? previousElementSibling;
   [Pure]
   readonly attribute Element? nextElementSibling;
   [Pure]
   readonly attribute unsigned long childElementCount;
 
+  /**
+   * The ratio of font-size-inflated text font size to computed font
+   * size for this element. This will query the element for its primary frame,
+   * and then use this to get font size inflation information about the frame.
+   * This will be 1.0 if font size inflation is not enabled, and -1.0 if an
+   * error occurred during the retrieval of the font size inflation.
+   *
+   * @note The font size inflation ratio that is returned is actually the
+   *       font size inflation data for the element's _primary frame_, not the
+   *       element itself, but for most purposes, this should be sufficient.
+   */
+  [ChromeOnly]
+  readonly attribute float fontSizeInflation;
+
   // Mozilla specific stuff
 
   [SetterThrows,LenientThis]
            attribute EventHandler onmouseenter;
   [SetterThrows,LenientThis]
            attribute EventHandler onmouseleave;
   [SetterThrows]
            attribute EventHandler onwheel;
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -176,21 +176,21 @@ function doChangeMaxLineBoxWidth(aWidth)
   }
 }
 
 function fuzzyEquals(a, b) {
   return (Math.abs(a - b) < 1e-6);
 }
 
 /**
- * Convert a font size from CSS pixels (px) to twenteiths-of-a-point
+ * Convert a font size to CSS pixels (px) from twentieiths-of-a-point
  * (twips).
  */
-function convertFromPxToTwips(aSize) {
-  return (20.0 * 12.0 * (aSize/16.0));
+function convertFromTwipsToPx(aSize) {
+  return aSize/240 * 16.0;
 }
 
 #ifdef MOZ_CRASHREPORTER
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
   "@mozilla.org/xre/app-info;1", "nsICrashReporter");
 #endif
 
@@ -2630,38 +2630,35 @@ Tab.prototype = {
         dump("Handled load error: " + e);
       }
     }
   },
 
   /**
    * Retrieves the font size in twips for a given element.
    */
-  getFontSizeInTwipsFor: function(aElement) {
+  getInflatedFontSizeFor: function(aElement) {
     // GetComputedStyle should always give us CSS pixels for a font size.
     let fontSizeStr = this.window.getComputedStyle(aElement)['fontSize'];
     let fontSize = fontSizeStr.slice(0, -2);
-    // This is in px, so we want to convert it to points then to twips.
-    return convertFromPxToTwips(fontSize);
+    return aElement.fontSizeInflation * fontSize;
   },
 
   /**
    * This returns the zoom necessary to match the font size of an element to
    * the minimum font size specified by the browser.zoom.reflowOnZoom.minFontSizeTwips
    * preference.
    */
   getZoomToMinFontSize: function(aElement) {
-    let currentZoom = this._zoom;
-    let minFontSize = Services.prefs.getIntPref("browser.zoom.reflowZoom.minFontSizeTwips");
-    let curFontSize = this.getFontSizeInTwipsFor(aElement);
-    if (!fuzzyEquals(curFontSize*(currentZoom), minFontSize)) {
-      return 1.0 + minFontSize / curFontSize;
-    }
-
-    return 1.0;
+    // We only use the font.size.inflation.minTwips preference because this is
+    // the only one that is controlled by the user-interface in the 'Settings'
+    // menu. Thus, if font.size.inflation.emPerLine is changed, this does not
+    // effect reflow-on-zoom.
+    let minFontSize = convertFromTwipsToPx(Services.prefs.getIntPref("font.size.inflation.minTwips"));
+    return minFontSize / this.getInflatedFontSizeFor(aElement);
   },
 
   performReflowOnZoom: function(aViewport) {
       let zoom = this._drawZoom ? this._drawZoom : aViewport.zoom;
 
       let viewportWidth = gScreenWidth / zoom;
       let reflozTimeout = Services.prefs.getIntPref("browser.zoom.reflowZoom.reflowTimeout");
 
@@ -4228,18 +4225,18 @@ var BrowserEventHandler = {
     // constrict the rect to the screen's right edge
     bRect.width = Math.min(bRect.width, viewport.cssPageRight - bRect.x);
 
     // if the rect is already taking up most of the visible area and is stretching the
     // width of the page, then we want to zoom out instead.
     if (BrowserEventHandler.mReflozPref) {
       let zoomFactor = BrowserApp.selectedTab.getZoomToMinFontSize(aElement);
 
-      bRect.width = zoomFactor == 1.0 ? bRect.width : gScreenWidth / zoomFactor;
-      bRect.height = zoomFactor == 1.0 ? bRect.height : bRect.height / zoomFactor;
+      bRect.width = zoomFactor <= 1.0 ? bRect.width : gScreenWidth / zoomFactor;
+      bRect.height = zoomFactor <= 1.0 ? bRect.height : bRect.height / zoomFactor;
       if (zoomFactor == 1.0 || this._isRectZoomedIn(bRect, viewport)) {
         if (aCanZoomOut) {
           this._zoomOut();
         }
         return;
       }
     } else if (this._isRectZoomedIn(bRect, viewport)) {
       if (aCanZoomOut) {
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3890,24 +3890,16 @@ pref("browser.zoom.reflowZoom.reflowTime
  * but has no effect if browser.zoom.reflowOnZoom is disabled.
  *
  * Note that this should be turned off only in cases where debugging of the
  * reflow-on-zoom feature is necessary, and enabling the feature during
  * a page load inhbits this debugging.
  */
 pref("browser.zoom.reflowZoom.reflowTextOnPageLoad", true);
 
-
-/**
- * The minimum font size to maintain when double-tap zooming into an element, in
- * twips. The browser will attempt to make the frame large enough to enlarge the
- * font size to this value.
- */
-pref("browser.zoom.reflowZoom.minFontSizeTwips", 120);
-
 // Image-related prefs
 // The maximum size, in bytes, of the decoded images we cache
 pref("image.cache.size", 5242880);
 // A weight, from 0-1000, to place on time when comparing to size.
 // Size is given a weight of 1000 - timeweight.
 pref("image.cache.timeweight", 500);
 
 // The default Accept header sent for images loaded over HTTP(S)