Bug 524275 - Make nsStretchDirection available for any operators. r=karlt a=dbaron
authorFrédéric Wang <fred.wang@free.fr>
Sat, 21 Nov 2009 22:11:05 +0100
changeset 51006 16fd52fea1aa17fc8db2d0adcc1a7018c5374898
parent 51005 4428b9c468cd5bc231fda3816b664811146ee1bf
child 51007 77e3880307eadb048cb80799ad5650049a277fa6
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, dbaron
bugs524275
milestone2.0b5pre
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 524275 - Make nsStretchDirection available for any operators. r=karlt a=dbaron
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLChar.h
layout/mathml/nsMathMLOperators.cpp
layout/mathml/nsMathMLOperators.h
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -18,16 +18,17 @@
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   Shyjan Mahamud <mahamud@cs.cmu.edu>
  *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -750,21 +751,16 @@ MathFontEnumCallback(const nsString& aFa
   return PR_TRUE; // don't stop
 }
 
 static nsresult
 InitGlobals(nsPresContext* aPresContext)
 {
   NS_ASSERTION(!gInitialized, "Error -- already initialized");
   gInitialized = PR_TRUE;
-  PRUint32 count = nsMathMLOperators::CountStretchyOperator();
-  if (!count) {
-    // nothing to stretch, so why bother...
-    return NS_OK;
-  }
 
   // Allocate the placeholders for the preferred parts and variants
   nsresult rv = NS_ERROR_OUT_OF_MEMORY;
   gGlyphTableList = new nsGlyphTableList();
   if (gGlyphTableList) {
     rv = gGlyphTableList->Initialize();
   }
   if (NS_FAILED(rv)) {
@@ -862,35 +858,29 @@ nsMathMLChar::SetData(nsPresContext* aPr
 {
   NS_ASSERTION(!mParent, "invalid call - not allowed for child chars");
   if (!gInitialized) {
     InitGlobals(aPresContext);
   }
   mData = aData;
   // some assumptions until proven otherwise
   // note that mGlyph is not initialized
-  mOperator = -1;
   mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
   mBoundingMetrics.Clear();
   mGlyphTable = nsnull;
   // check if stretching is applicable ...
   if (gGlyphTableList && (1 == mData.Length())) {
-    mOperator = nsMathMLOperators::FindStretchyOperator(mData[0]);
-    if (mOperator >= 0) {
-      mDirection = nsMathMLOperators::GetStretchyDirectionAt(mOperator);
-      // default tentative table (not the one that is necessarily going to be used)
-      mGlyphTable = gGlyphTableList->GetGlyphTableFor(aPresContext, this);
-      // commom case: we won't bother with the stretching if there is
-      // no glyph table for us...
-      if (!mGlyphTable) { // TODO: consider scaling the base char
-        // never try to stretch this operator again
-        nsMathMLOperators::DisableStretchyOperatorAt(mOperator);
-        mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
-        mOperator = -1;
-      }
+    mDirection = nsMathMLOperators::GetStretchyDirection(mData);
+    // default tentative table (not the one that is necessarily going
+    // to be used)
+    mGlyphTable = gGlyphTableList->GetGlyphTableFor(aPresContext, this);
+    // commom case: we won't bother with the stretching if there is
+    // no glyph table for us...
+    if (!mGlyphTable) { // TODO: consider scaling the base char
+      mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
     }
   }
 }
 
 // -----------------------------------------------------------------------------------
 /*
  The Stretch:
  @param aContainerSize - suggested size for the stretched char
@@ -1542,21 +1532,17 @@ nsMathMLChar::StretchInternal(nsPresCont
                               // These are currently only used when
                               // aStretchHint & NS_STRETCH_MAXWIDTH:
                               float                    aMaxSize,
                               PRBool                   aMaxSizeIsAbsolute)
 {
   // if we have been called before, and we didn't actually stretch, our
   // direction may have been set to NS_STRETCH_DIRECTION_UNSUPPORTED.
   // So first set our direction back to its instrinsic value
-  nsStretchDirection direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-  if (mOperator >= 0) {
-    // mOperator is initialized in SetData() and remains unchanged
-    direction = nsMathMLOperators::GetStretchyDirectionAt(mOperator);
-  }
+  nsStretchDirection direction = nsMathMLOperators::GetStretchyDirection(mData);
 
   // Set default font and get the default bounding metrics
   // mStyleContext is a leaf context used only when stretching happens.
   // For the base size, the default font should come from the parent context
   nsFont font = mStyleContext->GetParent()->GetStyleFont()->mFont;
 
   // Override with specific fonts if applicable for this character
   nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
@@ -1824,17 +1810,16 @@ nsMathMLChar::ComposeChildren(nsPresCont
   else {
     splitSize.ascent = aTargetSize / (count * 2);
     splitSize.descent = splitSize.ascent;
   }
   nscoord dx = 0, dy = 0;
   for (i = 0, child = mSibling; child; child = child->mSibling, i++) {
     // child chars should just inherit our values - which may change between calls...
     child->mData = mData;
-    child->mOperator = mOperator;
     child->mDirection = mDirection;
     child->mStyleContext = mStyleContext;
     child->mGlyphTable = aGlyphTable; // the child is associated to this table
     // there goes the Stretch() ...
     nsBoundingMetrics childSize;
     nsresult rv = child->Stretch(aPresContext, aRenderingContext, mDirection,
                                  splitSize, childSize, aStretchHint);
     // check if something went wrong or the child couldn't fit in the alloted space
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.h
@@ -18,16 +18,17 @@
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   Shyjan Mahamud <mahamud@cs.cmu.edu>
  *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -231,17 +232,16 @@ protected:
   nsString           mData;
 
   // support for handling composite stretchy chars like TeX over/under braces
   nsMathMLChar*      mSibling;
   nsMathMLChar*      mParent;
 
 private:
   nsRect             mRect;
-  PRInt32            mOperator;
   nsStretchDirection mDirection;
   nsBoundingMetrics  mBoundingMetrics;
   nsStyleContext*    mStyleContext;
   nsGlyphTable*      mGlyphTable;
   nsGlyphCode        mGlyph;
   // mFamily is non-empty when the family for the current size is different
   // from the family in the nsStyleContext.
   nsString           mFamily;
--- a/layout/mathml/nsMathMLOperators.cpp
+++ b/layout/mathml/nsMathMLOperators.cpp
@@ -62,21 +62,20 @@ struct OperatorData {
   // member data
   nsString        mStr;
   nsOperatorFlags mFlags;
   float           mLeftSpace;   // unit is em
   float           mRightSpace;  // unit is em
 };
 
 static PRInt32         gTableRefCount = 0;
-static PRInt32         gOperatorCount = 0;
+static PRUint32        gOperatorCount = 0;
 static OperatorData*   gOperatorArray = nsnull;
 static nsHashtable*    gOperatorTable = nsnull;
 static PRBool          gInitialized   = PR_FALSE;
-static nsTArray<OperatorData*>* gStretchyOperatorArray = nsnull;
 static nsTArray<nsString>*      gInvariantCharArray    = nsnull;
 
 static const PRUnichar kNullCh  = PRUnichar('\0');
 static const PRUnichar kDashCh  = PRUnichar('#');
 static const PRUnichar kColonCh = PRUnichar(':');
 
 static const char* const kMathVariant_name[] = {
   "normal",
@@ -97,23 +96,19 @@ static const char* const kMathVariant_na
 
 static void
 SetBooleanProperty(OperatorData* aOperatorData,
                    nsString      aName)
 {
   if (aName.IsEmpty())
     return;
 
-  if (aName.EqualsLiteral("stretchy") && (1 == aOperatorData->mStr.Length())) {
+  if (aName.EqualsLiteral("stretchy") && (1 == aOperatorData->mStr.Length()))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_STRETCHY;
-    if (kNotFound ==
-        nsMathMLOperators::FindStretchyOperator(aOperatorData->mStr[0])) {
-      gStretchyOperatorArray->AppendElement(aOperatorData);
-    }
-  } else if (aName.EqualsLiteral("fence"))
+  else if (aName.EqualsLiteral("fence"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_FENCE;
   else if (aName.EqualsLiteral("accent"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_ACCENT;
   else if (aName.EqualsLiteral("largeop"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_LARGEOP;
   else if (aName.EqualsLiteral("separator"))
     aOperatorData->mFlags |=  NS_MATHML_OPERATOR_SEPARATOR;
   else if (aName.EqualsLiteral("movablelimits"))
@@ -294,17 +289,17 @@ InitOperators(void)
   // The first pass is to count the number of operators; the second pass is to
   // allocate the necessary space for them and to add them in the hash table.
   for (PRInt32 pass = 1; pass <= 2; pass++) {
     OperatorData dummyData;
     OperatorData* operatorData = &dummyData;
     nsCOMPtr<nsISimpleEnumerator> iterator;
     if (NS_SUCCEEDED(mathfontProp->Enumerate(getter_AddRefs(iterator)))) {
       PRBool more;
-      PRInt32 index = 0;
+      PRUint32 index = 0;
       nsCAutoString name;
       nsAutoString attributes;
       while ((NS_SUCCEEDED(iterator->HasMoreElements(&more))) && more) {
         nsCOMPtr<nsIPropertyElement> element;
         if (NS_SUCCEEDED(iterator->GetNext(getter_AddRefs(element)))) {
           if (NS_SUCCEEDED(element->GetKey(name)) &&
               NS_SUCCEEDED(element->GetValue(attributes))) {
             // expected key: operator.\uNNNN.{infix,postfix,prefix}
@@ -352,18 +347,17 @@ InitOperators(void)
 }
 
 static nsresult
 InitGlobals()
 {
   gInitialized = PR_TRUE;
   nsresult rv = NS_ERROR_OUT_OF_MEMORY;
   gInvariantCharArray = new nsTArray<nsString>();
-  gStretchyOperatorArray = new nsTArray<OperatorData*>();
-  if (gInvariantCharArray && gStretchyOperatorArray) {
+  if (gInvariantCharArray) {
     gOperatorTable = new nsHashtable();
     if (gOperatorTable) {
       rv = InitOperators();
     }
   }
   if (NS_FAILED(rv))
     nsMathMLOperators::CleanUp();
   return rv;
@@ -375,20 +369,16 @@ nsMathMLOperators::CleanUp()
   if (gInvariantCharArray) {
     delete gInvariantCharArray;
     gInvariantCharArray = nsnull;
   }
   if (gOperatorArray) {
     delete[] gOperatorArray;
     gOperatorArray = nsnull;
   }
-  if (gStretchyOperatorArray) {
-    delete gStretchyOperatorArray;
-    gStretchyOperatorArray = nsnull;
-  }
   if (gOperatorTable) {
     delete gOperatorTable;
     gOperatorTable = nsnull;
   }
 }
 
 void
 nsMathMLOperators::AddRefTable(void)
@@ -518,69 +508,34 @@ nsMathMLOperators::IsMutableOperator(con
   nsOperatorFlags allFlags =
     flags[NS_MATHML_OPERATOR_FORM_INFIX] |
     flags[NS_MATHML_OPERATOR_FORM_POSTFIX] |
     flags[NS_MATHML_OPERATOR_FORM_PREFIX];
   return NS_MATHML_OPERATOR_IS_STRETCHY(allFlags) ||
          NS_MATHML_OPERATOR_IS_LARGEOP(allFlags);
 }
 
-PRInt32
-nsMathMLOperators::CountStretchyOperator()
-{
-  if (!gInitialized) {
-    InitGlobals();
-  }
-  return (gStretchyOperatorArray) ? gStretchyOperatorArray->Length() : 0;
-}
-
-PRInt32
-nsMathMLOperators::FindStretchyOperator(PRUnichar aOperator)
+/* static */ nsStretchDirection
+nsMathMLOperators::GetStretchyDirection(const nsString& aOperator)
 {
-  if (!gInitialized) {
-    InitGlobals();
-  }
-  if (gStretchyOperatorArray) {
-    for (PRUint32 k = 0; k < gStretchyOperatorArray->Length(); k++) {
-      OperatorData* data = gStretchyOperatorArray->ElementAt(k);
-      if (data && (aOperator == data->mStr[0])) {
-        return k;
-      }
-    }
-  }
-  return kNotFound;
-}
+  // LookupOperator will search infix, postfix and prefix forms of aOperator and
+  // return the first form found. It is assumed that all these forms have same
+  // direction.
+  nsOperatorFlags flags = 0;
+  float dummy;
+  nsMathMLOperators::LookupOperator(aOperator,
+                                    NS_MATHML_OPERATOR_FORM_INFIX,
+                                    &flags, &dummy, &dummy);
 
-nsStretchDirection
-nsMathMLOperators::GetStretchyDirectionAt(PRInt32 aIndex)
-{
-  NS_ASSERTION(gStretchyOperatorArray, "invalid call");
-  if (gStretchyOperatorArray) {
-    NS_ASSERTION(aIndex < PRInt32(gStretchyOperatorArray->Length()),
-                 "invalid call");
-    OperatorData* data = gStretchyOperatorArray->ElementAt(aIndex);
-    if (data) {
-      if (NS_MATHML_OPERATOR_IS_DIRECTION_VERTICAL(data->mFlags))
-        return NS_STRETCH_DIRECTION_VERTICAL;
-      else if (NS_MATHML_OPERATOR_IS_DIRECTION_HORIZONTAL(data->mFlags))
-        return NS_STRETCH_DIRECTION_HORIZONTAL;
-      NS_ASSERTION(PR_FALSE, "*** bad setup ***");
-    }
-  }
-  return NS_STRETCH_DIRECTION_UNSUPPORTED;
-}
-
-void
-nsMathMLOperators::DisableStretchyOperatorAt(PRInt32 aIndex)
-{
-  NS_ASSERTION(gStretchyOperatorArray, "invalid call");
-  if (gStretchyOperatorArray) {
-    NS_ASSERTION(aIndex < PRInt32(gStretchyOperatorArray->Length()),
-                 "invalid call");
-    (*gStretchyOperatorArray)[aIndex] = nsnull;
+  if (NS_MATHML_OPERATOR_IS_DIRECTION_VERTICAL(flags)) {
+      return NS_STRETCH_DIRECTION_VERTICAL;
+  } else if (NS_MATHML_OPERATOR_IS_DIRECTION_HORIZONTAL(flags)) {
+    return NS_STRETCH_DIRECTION_HORIZONTAL;
+  } else {
+    return NS_STRETCH_DIRECTION_UNSUPPORTED;
   }
 }
 
 /* static */ eMATHVARIANT
 nsMathMLOperators::LookupInvariantChar(const nsAString& aChar)
 {
   if (!gInitialized) {
     InitGlobals();
--- a/layout/mathml/nsMathMLOperators.h
+++ b/layout/mathml/nsMathMLOperators.h
@@ -143,38 +143,33 @@ public:
                    float*                aLeftSpace,
                    float*                aRightSpace);
 
   // IsMutableOperator:
   // Return true if the operator exists and is stretchy or largeop
   static PRBool
   IsMutableOperator(const nsString& aOperator);
 
-  // Helper functions for stretchy operators. These are used by the
-  // nsMathMLChar class.
-  static PRInt32 CountStretchyOperator();
-  static PRInt32 FindStretchyOperator(PRUnichar aOperator);
-  static nsStretchDirection GetStretchyDirectionAt(PRInt32 aIndex);
-  static void DisableStretchyOperatorAt(PRInt32 aIndex);
+  // Helper function used by the nsMathMLChar class.
+  static nsStretchDirection GetStretchyDirection(const nsString& aOperator);
 
   // Return the variant type of one Unicode Mathematical Alphanumeric Symbol
   // character (which may be represented by a surrogate pair), or return
   // eMATHVARIANT_NONE if aChar is not such a character.
   static eMATHVARIANT LookupInvariantChar(const nsAString& aChar);
 
   // Return the styled Mathematical Alphanumeric Symbol character
   // corresponding to a BMP character and a mathvariant value, or return aChar
   // if there is no such corresponding character.
   // Note the result may be dependent on aChar, and should be considered a
   // temporary.
   static const nsDependentSubstring
   TransformVariantChar(const PRUnichar& aChar, eMATHVARIANT aVariant);
 };
 
-
 ////////////////////////////////////////////////////////////////////////////
 // Macros that retrieve the bits used to handle operators
 
 #define NS_MATHML_OPERATOR_IS_MUTABLE(_flags) \
   (NS_MATHML_OPERATOR_MUTABLE == ((_flags) & NS_MATHML_OPERATOR_MUTABLE))
 
 #define NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(_flags) \
   (NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR == ((_flags) & NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR))