Bug 1088599 - Move nsRenderingContext::GetBoundingMetrics to nsLayoutUtils. r=mstange
authorJonathan Watt <jwatt@jwatt.org>
Fri, 24 Oct 2014 16:28:14 +0100
changeset 236567 e0a681c4c4fe334e024d1891c3a910ad7a571db1
parent 236566 cd13fcbf38538c9166849279fc4a7e83743e915f
child 236568 6d6117a79a0ef2de724404d23f27389203e2e2e2
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1088599
milestone36.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 1088599 - Move nsRenderingContext::GetBoundingMetrics to nsLayoutUtils. r=mstange
gfx/src/nsRenderingContext.cpp
gfx/src/nsRenderingContext.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLFrame.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfencedFrame.cpp
layout/mathml/nsMathMLmrootFrame.cpp
--- a/gfx/src/nsRenderingContext.cpp
+++ b/gfx/src/nsRenderingContext.cpp
@@ -1,113 +1,31 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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/. */
 
 #include "nsRenderingContext.h"
-#include <string.h>                     // for strlen
-#include <algorithm>                    // for min
-#include "gfxColor.h"                   // for gfxRGBA
-#include "gfxMatrix.h"                  // for gfxMatrix
-#include "gfxPoint.h"                   // for gfxPoint, gfxSize
-#include "gfxRect.h"                    // for gfxRect
-#include "gfxTypes.h"                   // for gfxFloat
-#include "mozilla/gfx/BasePoint.h"      // for BasePoint
-#include "mozilla/mozalloc.h"           // for operator delete[], etc
-#include "nsBoundingMetrics.h"          // for nsBoundingMetrics
-#include "nsCharTraits.h"               // for NS_IS_LOW_SURROGATE
-#include "nsDebug.h"                    // for NS_ERROR
-#include "nsPoint.h"                    // for nsPoint
-#include "nsRect.h"                     // for nsRect, nsIntRect
-#include "nsRegion.h"                   // for nsIntRegionRectIterator, etc
-
-// Hard limit substring lengths to 8000 characters ... this lets us statically
-// size the cluster buffer array in FindSafeLength
-#define MAX_GFX_TEXT_BUF_SIZE 8000
-
-/*static*/ int32_t
-nsRenderingContext::FindSafeLength(const char16_t *aString, uint32_t aLength,
-                              uint32_t aMaxChunkLength)
-{
-    if (aLength <= aMaxChunkLength)
-        return aLength;
-
-    int32_t len = aMaxChunkLength;
-
-    // Ensure that we don't break inside a surrogate pair
-    while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
-        len--;
-    }
-    if (len == 0) {
-        // We don't want our caller to go into an infinite loop, so don't
-        // return zero. It's hard to imagine how we could actually get here
-        // unless there are languages that allow clusters of arbitrary size.
-        // If there are and someone feeds us a 500+ character cluster, too
-        // bad.
-        return aMaxChunkLength;
-    }
-    return len;
-}
-
-//////////////////////////////////////////////////////////////////////
-//// nsRenderingContext
 
 void
 nsRenderingContext::Init(gfxContext *aThebesContext)
 {
     mThebes = aThebesContext;
     mThebes->SetLineWidth(1.0);
 }
 
 void
 nsRenderingContext::Init(DrawTarget *aDrawTarget)
 {
     Init(new gfxContext(aDrawTarget));
 }
 
-
-//
-// text
-//
-
 void
 nsRenderingContext::SetTextRunRTL(bool aIsRTL)
 {
     mFontMetrics->SetTextRunRTL(aIsRTL);
 }
 
 void
 nsRenderingContext::SetFont(nsFontMetrics *aFontMetrics)
 {
     mFontMetrics = aFontMetrics;
 }
-
-int32_t
-nsRenderingContext::GetMaxChunkLength()
-{
-    return std::min(mFontMetrics->GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
-}
-
-nsBoundingMetrics
-nsRenderingContext::GetBoundingMetrics(const char16_t* aString,
-                                       uint32_t aLength)
-{
-    uint32_t maxChunkLength = GetMaxChunkLength();
-    int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
-    // Assign directly in the first iteration. This ensures that
-    // negative ascent/descent can be returned and the left bearing
-    // is properly initialized.
-    nsBoundingMetrics totalMetrics
-        = mFontMetrics->GetBoundingMetrics(aString, len, this);
-    aLength -= len;
-    aString += len;
-
-    while (aLength > 0) {
-        len = FindSafeLength(aString, aLength, maxChunkLength);
-        nsBoundingMetrics metrics
-            = mFontMetrics->GetBoundingMetrics(aString, len, this);
-        totalMetrics += metrics;
-        aLength -= len;
-        aString += len;
-    }
-    return totalMetrics;
-}
--- a/gfx/src/nsRenderingContext.h
+++ b/gfx/src/nsRenderingContext.h
@@ -42,22 +42,16 @@ public:
 
     // Text
 
     void SetFont(nsFontMetrics *aFontMetrics);
     nsFontMetrics *FontMetrics() { return mFontMetrics; } // may be null
 
     void SetTextRunRTL(bool aIsRTL);
 
-    nsBoundingMetrics GetBoundingMetrics(const char16_t *aString,
-                                         uint32_t aLength);
-
-    int32_t GetMaxChunkLength();
-    static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
-                                  uint32_t aMaxChunkLength);
 private:
     // Private destructor, to discourage deletion outside of Release():
     ~nsRenderingContext()
     {
     }
 
     nsRefPtr<gfxContext> mThebes;
     nsRefPtr<nsFontMetrics> mFontMetrics;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6,16 +6,17 @@
 
 #include "nsLayoutUtils.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
+#include "nsCharTraits.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsFrameList.h"
 #include "nsGkAtoms.h"
 #include "nsIAtom.h"
 #include "nsCSSPseudoElements.h"
@@ -4625,39 +4626,97 @@ nsLayoutUtils::GetSnappedBaselineY(nsIFr
   gfxFloat appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
   gfxFloat baseline = gfxFloat(aY) + aAscent;
   gfxRect putativeRect(0, baseline/appUnitsPerDevUnit, 1, 1);
   if (!aContext->UserToDevicePixelSnapped(putativeRect, true))
     return baseline;
   return aContext->DeviceToUser(putativeRect.TopLeft()).y * appUnitsPerDevUnit;
 }
 
+// Hard limit substring lengths to 8000 characters ... this lets us statically
+// size the cluster buffer array in FindSafeLength
+#define MAX_GFX_TEXT_BUF_SIZE 8000
+
+static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
+                              uint32_t aMaxChunkLength)
+{
+  if (aLength <= aMaxChunkLength)
+    return aLength;
+
+  int32_t len = aMaxChunkLength;
+
+  // Ensure that we don't break inside a surrogate pair
+  while (len > 0 && NS_IS_LOW_SURROGATE(aString[len])) {
+    len--;
+  }
+  if (len == 0) {
+    // We don't want our caller to go into an infinite loop, so don't
+    // return zero. It's hard to imagine how we could actually get here
+    // unless there are languages that allow clusters of arbitrary size.
+    // If there are and someone feeds us a 500+ character cluster, too
+    // bad.
+    return aMaxChunkLength;
+  }
+  return len;
+}
+
+static int32_t GetMaxChunkLength(nsFontMetrics& aFontMetrics)
+{
+  return std::min(aFontMetrics.GetMaxStringLength(), MAX_GFX_TEXT_BUF_SIZE);
+}
+
 nscoord
 nsLayoutUtils::AppUnitWidthOfString(const nsString& aString,
                                     nsRenderingContext& aContext)
 {
   return AppUnitWidthOfString(aString.get(), aString.Length(), aContext);
 }
 
 nscoord
 nsLayoutUtils::AppUnitWidthOfString(const char16_t *aString,
                                     uint32_t aLength,
                                     nsRenderingContext& aContext)
 {
-  uint32_t maxChunkLength = aContext.GetMaxChunkLength();
+  uint32_t maxChunkLength = GetMaxChunkLength(*aContext.FontMetrics());
   nscoord width = 0;
   while (aLength > 0) {
-    int32_t len = aContext.FindSafeLength(aString, aLength, maxChunkLength);
+    int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
     width += aContext.FontMetrics()->GetWidth(aString, len, &aContext);
     aLength -= len;
     aString += len;
   }
   return width;
 }
 
+nsBoundingMetrics
+nsLayoutUtils::AppUnitBoundsOfString(const char16_t* aString,
+                                     uint32_t aLength,
+                                     nsRenderingContext& aContext)
+{
+  uint32_t maxChunkLength = GetMaxChunkLength(*aContext.FontMetrics());
+  int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
+  // Assign directly in the first iteration. This ensures that
+  // negative ascent/descent can be returned and the left bearing
+  // is properly initialized.
+  nsBoundingMetrics totalMetrics =
+    aContext.FontMetrics()->GetBoundingMetrics(aString, len, &aContext);
+  aLength -= len;
+  aString += len;
+
+  while (aLength > 0) {
+    len = FindSafeLength(aString, aLength, maxChunkLength);
+    nsBoundingMetrics metrics =
+      aContext.FontMetrics()->GetBoundingMetrics(aString, len, &aContext);
+    totalMetrics += metrics;
+    aLength -= len;
+    aString += len;
+  }
+  return totalMetrics;
+}
+
 void
 nsLayoutUtils::DrawString(const nsIFrame*       aFrame,
                           nsRenderingContext*   aContext,
                           const char16_t*      aString,
                           int32_t               aLength,
                           nsPoint               aPoint,
                           nsStyleContext*       aStyleContext)
 {
@@ -4684,31 +4743,31 @@ nsLayoutUtils::DrawUniDirString(const ch
                                 nsPoint aPoint,
                                 nsRenderingContext& aContext)
 {
   nscoord x = aPoint.x;
   nscoord y = aPoint.y;
 
   nsFontMetrics* fm = aContext.FontMetrics();
 
-  uint32_t maxChunkLength = aContext.GetMaxChunkLength();
+  uint32_t maxChunkLength = GetMaxChunkLength(*aContext.FontMetrics());
   if (aLength <= maxChunkLength) {
     fm->DrawString(aString, aLength, x, y, &aContext, &aContext);
     return;
   }
 
   bool isRTL = fm->GetTextRunRTL();
 
   // If we're drawing right to left, we must start at the end.
   if (isRTL) {
     x += nsLayoutUtils::AppUnitWidthOfString(aString, aLength, aContext);
   }
 
   while (aLength > 0) {
-    int32_t len = nsRenderingContext::FindSafeLength(aString, aLength, maxChunkLength);
+    int32_t len = FindSafeLength(aString, aLength, maxChunkLength);
     nscoord width = fm->GetWidth(aString, len, &aContext);
     if (isRTL) {
       x -= width;
     }
     fm->DrawString(aString, len, x, y, &aContext, &aContext);
     if (!isRTL) {
       x += width;
     }
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -3,16 +3,17 @@
  * 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 nsLayoutUtils_h__
 #define nsLayoutUtils_h__
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ArrayUtils.h"
+#include "nsBoundingMetrics.h"
 #include "nsChangeHint.h"
 #include "nsAutoPtr.h"
 #include "nsFrameList.h"
 #include "mozilla/layout/FrameChildList.h"
 #include "nsThreadUtils.h"
 #include "nsIPrincipal.h"
 #include "GraphicsFilter.h"
 #include "nsCSSPseudoElements.h"
@@ -1321,16 +1322,19 @@ public:
                                       nsRenderingContext& aContext) {
     return AppUnitWidthOfString(&aC, 1, aContext);
   }
   static nscoord AppUnitWidthOfString(const nsString& aString,
                                       nsRenderingContext& aContext);
   static nscoord AppUnitWidthOfString(const char16_t *aString,
                                       uint32_t aLength,
                                       nsRenderingContext& aContext);
+  static nsBoundingMetrics AppUnitBoundsOfString(const char16_t* aString,
+                                                 uint32_t aLength,
+                                                 nsRenderingContext& aContext);
 
   static void DrawString(const nsIFrame*       aFrame,
                          nsRenderingContext*   aContext,
                          const char16_t*      aString,
                          int32_t               aLength,
                          nsPoint               aPoint,
                          nsStyleContext*       aStyleContext = nullptr);
 
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -53,17 +53,18 @@ nsMathMLContainerFrame::ReflowError(nsRe
   // Set font
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   aRenderingContext.SetFont(fm);
 
   // bounding metrics
   nsAutoString errorMsg; errorMsg.AssignLiteral("invalid-markup");
   mBoundingMetrics =
-    aRenderingContext.GetBoundingMetrics(errorMsg.get(), errorMsg.Length());
+    nsLayoutUtils::AppUnitBoundsOfString(errorMsg.get(), errorMsg.Length(),
+                                         aRenderingContext);
 
   // reflow metrics
   WritingMode wm = aDesiredSize.GetWritingMode();
   aDesiredSize.SetBlockStartAscent(fm->MaxAscent());
   nscoord descent = fm->MaxDescent();
   aDesiredSize.BSize(wm) = aDesiredSize.BlockStartAscent() + descent;
   aDesiredSize.ISize(wm) = mBoundingMetrics.width;
 
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -175,17 +175,18 @@ nsMathMLFrame::GetRuleThickness(nsRender
   // get the bounding metrics of the overbar char, the rendering context
   // is assumed to have been set with the font of the current style context
   NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
                Equals(aFontMetrics->Font()),
                "unexpected state");
 
   nscoord xHeight = aFontMetrics->XHeight();
   char16_t overBar = 0x00AF;
-  nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&overBar, 1);
+  nsBoundingMetrics bm =
+    nsLayoutUtils::AppUnitBoundsOfString(&overBar, 1, aRenderingContext);
   aRuleThickness = bm.ascent + bm.descent;
   if (aRuleThickness <= 0 || aRuleThickness >= xHeight) {
     // fall-back to the other version
     GetRuleThickness(aFontMetrics, aRuleThickness);
   }
 }
 
 /* static */ void
@@ -204,17 +205,18 @@ nsMathMLFrame::GetAxisHeight(nsRendering
   // get the bounding metrics of the minus sign, the rendering context
   // is assumed to have been set with the font of the current style context
   NS_ASSERTION(aRenderingContext.FontMetrics()->Font().
                Equals(aFontMetrics->Font()),
                "unexpected state");
 
   nscoord xHeight = aFontMetrics->XHeight();
   char16_t minus = 0x2212; // not '-', but official Unicode minus sign
-  nsBoundingMetrics bm = aRenderingContext.GetBoundingMetrics(&minus, 1);
+  nsBoundingMetrics bm =
+    nsLayoutUtils::AppUnitBoundsOfString(&minus, 1, aRenderingContext);
   aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
   if (aAxisHeight <= 0 || aAxisHeight >= xHeight) {
     // fall-back to the other version
     GetAxisHeight(aFontMetrics, aAxisHeight);
   }
 }
 
 /* static */ nscoord
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -347,17 +347,18 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   aRenderingContext.SetFont(fm);
   GetRuleThickness(aRenderingContext, fm, mRuleThickness);
   if (mRuleThickness < onePixel) {
     mRuleThickness = onePixel;
   }
 
   char16_t one = '1';
-  nsBoundingMetrics bmOne = aRenderingContext.GetBoundingMetrics(&one, 1);
+  nsBoundingMetrics bmOne =
+    nsLayoutUtils::AppUnitBoundsOfString(&one, 1, aRenderingContext);
 
   ///////////////
   // General rules: the menclose element takes the size of the enclosed content.
   // We add a padding when needed.
 
   // determine padding & psi
   nscoord padding = 3 * mRuleThickness;
   nscoord delta = padding % onePixel;
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -496,23 +496,24 @@ nsMathMLmfencedFrame::ReflowChar(nsPresC
     if (NS_STRETCH_DIRECTION_UNSUPPORTED != aMathMLChar->GetStretchDirection()) {
       // has changed... so center the char around the axis
       nscoord height = charSize.ascent + charSize.descent;
       charSize.ascent = height/2 + axisHeight;
       charSize.descent = height - charSize.ascent;
     }
     else {
       // either it hasn't changed or stretching the char failed (i.e.,
-      // GetBoundingMetrics failed)
+      // nsLayoutUtils::AppUnitBoundsOfString failed)
       leading = 0;
       if (NS_FAILED(res)) {
         nsAutoString data;
         aMathMLChar->GetData(data);
         nsBoundingMetrics metrics =
-          aRenderingContext.GetBoundingMetrics(data.get(), data.Length());
+          nsLayoutUtils::AppUnitBoundsOfString(data.get(), data.Length(),
+                                               aRenderingContext);
         charSize.ascent = metrics.ascent;
         charSize.descent = metrics.descent;
         charSize.width = metrics.width;
         // Set this as the bounding metrics of the MathMLChar to leave
         // the necessary room to paint the char.
         aMathMLChar->SetBoundingMetrics(charSize);
       }
     }
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -229,17 +229,18 @@ nsMathMLmrootFrame::Reflow(nsPresContext
 
   nscoord ruleThickness, leading, psi;
   GetRadicalParameters(fm, StyleFont()->mMathDisplay ==
                        NS_MATHML_DISPLAYSTYLE_BLOCK,
                        ruleThickness, leading, psi);
 
   // built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131)
   char16_t one = '1';
-  nsBoundingMetrics bmOne = renderingContext.GetBoundingMetrics(&one, 1);
+  nsBoundingMetrics bmOne =
+    nsLayoutUtils::AppUnitBoundsOfString(&one, 1, renderingContext);
   if (bmOne.ascent > bmBase.ascent)
     psi += bmOne.ascent - bmBase.ascent;
 
   // make sure that the rule appears on on screen
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
   if (ruleThickness < onePixel) {
     ruleThickness = onePixel;
   }