LCOV - code coverage report
Current view: directory - layout/mathml - nsMathMLOperators.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 292 12 4.1 %
Date: 2012-06-02 Functions: 18 3 16.7 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla MathML Project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * The University Of Queensland.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1999
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Roger B. Sidje <rbs@maths.uq.edu.au>
      24                 :  *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
      25                 :  *   Frederic Wang <fred.wang@free.fr>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsCOMPtr.h"
      42                 : #include "nsString.h"
      43                 : #include "nsHashtable.h"
      44                 : #include "nsTArray.h"
      45                 : 
      46                 : #include "nsIComponentManager.h"
      47                 : #include "nsIPersistentProperties2.h"
      48                 : #include "nsNetUtil.h"
      49                 : #include "nsCRT.h"
      50                 : 
      51                 : #include "nsMathMLOperators.h"
      52                 : 
      53                 : // operator dictionary entry
      54               0 : struct OperatorData {
      55               0 :   OperatorData(void)
      56                 :     : mFlags(0),
      57                 :       mLeadingSpace(0.0f),
      58               0 :       mTrailingSpace(0.0f)
      59                 :   {
      60               0 :   }
      61                 : 
      62                 :   // member data
      63                 :   nsString        mStr;
      64                 :   nsOperatorFlags mFlags;
      65                 :   float           mLeadingSpace;   // unit is em
      66                 :   float           mTrailingSpace;  // unit is em
      67                 : };
      68                 : 
      69                 : static PRInt32         gTableRefCount = 0;
      70                 : static PRUint32        gOperatorCount = 0;
      71                 : static OperatorData*   gOperatorArray = nsnull;
      72                 : static nsHashtable*    gOperatorTable = nsnull;
      73                 : static bool            gInitialized   = false;
      74                 : static nsTArray<nsString>*      gInvariantCharArray    = nsnull;
      75                 : 
      76                 : static const PRUnichar kNullCh  = PRUnichar('\0');
      77                 : static const PRUnichar kDashCh  = PRUnichar('#');
      78                 : static const PRUnichar kColonCh = PRUnichar(':');
      79                 : 
      80                 : static const char* const kMathVariant_name[] = {
      81                 :   "normal",
      82                 :   "bold",
      83                 :   "italic",
      84                 :   "bold-italic",
      85                 :   "sans-serif",
      86                 :   "bold-sans-serif",
      87                 :   "sans-serif-italic",
      88                 :   "sans-serif-bold-italic",
      89                 :   "monospace",
      90                 :   "script",
      91                 :   "bold-script",
      92                 :   "fraktur",
      93                 :   "bold-fraktur",
      94                 :   "double-struck"
      95                 : };
      96                 : 
      97                 : static void
      98               0 : SetBooleanProperty(OperatorData* aOperatorData,
      99                 :                    nsString      aName)
     100                 : {
     101               0 :   if (aName.IsEmpty())
     102               0 :     return;
     103                 : 
     104               0 :   if (aName.EqualsLiteral("stretchy") && (1 == aOperatorData->mStr.Length()))
     105               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_STRETCHY;
     106               0 :   else if (aName.EqualsLiteral("fence"))
     107               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_FENCE;
     108               0 :   else if (aName.EqualsLiteral("accent"))
     109               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_ACCENT;
     110               0 :   else if (aName.EqualsLiteral("largeop"))
     111               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_LARGEOP;
     112               0 :   else if (aName.EqualsLiteral("separator"))
     113               0 :     aOperatorData->mFlags |=  NS_MATHML_OPERATOR_SEPARATOR;
     114               0 :   else if (aName.EqualsLiteral("movablelimits"))
     115               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_MOVABLELIMITS;
     116               0 :   else if (aName.EqualsLiteral("symmetric"))
     117               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
     118               0 :   else if (aName.EqualsLiteral("integral"))
     119               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_INTEGRAL;
     120               0 :   else if (aName.EqualsLiteral("mirrorable"))
     121               0 :     aOperatorData->mFlags |= NS_MATHML_OPERATOR_MIRRORABLE;
     122                 : }
     123                 : 
     124                 : static void
     125               0 : SetProperty(OperatorData* aOperatorData,
     126                 :             nsString      aName,
     127                 :             nsString      aValue)
     128                 : {
     129               0 :   if (aName.IsEmpty() || aValue.IsEmpty())
     130               0 :     return;
     131                 : 
     132                 :   // XXX These ones are not kept in the dictionary
     133                 :   // Support for these requires nsString member variables 
     134                 :   // maxsize (default: infinity)
     135                 :   // minsize (default: 1)
     136                 : 
     137               0 :   if (aName.EqualsLiteral("direction")) {
     138               0 :     if (aValue.EqualsLiteral("vertical"))
     139               0 :       aOperatorData->mFlags |= NS_MATHML_OPERATOR_DIRECTION_VERTICAL;
     140               0 :     else if (aValue.EqualsLiteral("horizontal"))
     141               0 :       aOperatorData->mFlags |= NS_MATHML_OPERATOR_DIRECTION_HORIZONTAL;
     142               0 :     else return; // invalid value
     143                 :   } else {
     144                 :     bool isLeadingSpace;
     145               0 :     if (aName.EqualsLiteral("lspace"))
     146               0 :       isLeadingSpace = true;
     147               0 :     else if (aName.EqualsLiteral("rspace"))
     148               0 :       isLeadingSpace = false;
     149               0 :     else return;  // input is not applicable
     150                 : 
     151                 :     // aValue is assumed to be a digit from 0 to 7
     152               0 :     PRInt32 error = 0;
     153               0 :     float space = aValue.ToFloat(&error) / 18.0;
     154               0 :     if (error) return;
     155                 : 
     156               0 :     if (isLeadingSpace)
     157               0 :       aOperatorData->mLeadingSpace = space;
     158                 :     else
     159               0 :       aOperatorData->mTrailingSpace = space;
     160                 :   }
     161                 : }
     162                 : 
     163                 : static bool
     164               0 : SetOperator(OperatorData*   aOperatorData,
     165                 :             nsOperatorFlags aForm,
     166                 :             const nsCString& aOperator,
     167                 :             nsString&        aAttributes)
     168                 : 
     169                 : {
     170                 :   // aOperator is in the expanded format \uNNNN\uNNNN ...
     171                 :   // First compress these Unicode points to the internal nsString format
     172               0 :   PRInt32 i = 0;
     173               0 :   nsAutoString name, value;
     174               0 :   PRInt32 len = aOperator.Length();
     175               0 :   PRUnichar c = aOperator[i++];
     176               0 :   PRUint32 state  = 0;
     177               0 :   PRUnichar uchar = 0;
     178               0 :   while (i <= len) {
     179               0 :     if (0 == state) {
     180               0 :       if (c != '\\')
     181               0 :         return false;
     182               0 :       if (i < len)
     183               0 :         c = aOperator[i];
     184               0 :       i++;
     185               0 :       if (('u' != c) && ('U' != c))
     186               0 :         return false;
     187               0 :       if (i < len)
     188               0 :         c = aOperator[i];
     189               0 :       i++;
     190               0 :       state++;
     191                 :     }
     192                 :     else {
     193               0 :       if (('0' <= c) && (c <= '9'))
     194               0 :          uchar = (uchar << 4) | (c - '0');
     195               0 :       else if (('a' <= c) && (c <= 'f'))
     196               0 :          uchar = (uchar << 4) | (c - 'a' + 0x0a);
     197               0 :       else if (('A' <= c) && (c <= 'F'))
     198               0 :          uchar = (uchar << 4) | (c - 'A' + 0x0a);
     199               0 :       else return false;
     200               0 :       if (i < len)
     201               0 :         c = aOperator[i];
     202               0 :       i++;
     203               0 :       state++;
     204               0 :       if (5 == state) {
     205               0 :         value.Append(uchar);
     206               0 :         uchar = 0;
     207               0 :         state = 0;
     208                 :       }
     209                 :     }
     210                 :   }
     211               0 :   if (0 != state) return false;
     212                 : 
     213                 :   // Quick return when the caller doesn't care about the attributes and just wants
     214                 :   // to know if this is a valid operator (this is the case at the first pass of the
     215                 :   // parsing of the dictionary in InitOperators())
     216               0 :   if (!aForm) return true;
     217                 : 
     218                 :   // Add operator to hash table
     219               0 :   aOperatorData->mFlags |= aForm;
     220               0 :   aOperatorData->mStr.Assign(value);
     221               0 :   value.AppendInt(aForm, 10);
     222               0 :   nsStringKey key(value);
     223               0 :   gOperatorTable->Put(&key, aOperatorData);
     224                 : 
     225                 : #ifdef NS_DEBUG
     226               0 :   NS_LossyConvertUTF16toASCII str(aAttributes);
     227                 : #endif
     228                 :   // Loop over the space-delimited list of attributes to get the name:value pairs
     229               0 :   aAttributes.Append(kNullCh);  // put an extra null at the end
     230               0 :   PRUnichar* start = aAttributes.BeginWriting();
     231               0 :   PRUnichar* end   = start;
     232               0 :   while ((kNullCh != *start) && (kDashCh != *start)) {
     233               0 :     name.SetLength(0);
     234               0 :     value.SetLength(0);
     235                 :     // skip leading space, the dash amounts to the end of the line
     236               0 :     while ((kNullCh!=*start) && (kDashCh!=*start) && nsCRT::IsAsciiSpace(*start)) {
     237               0 :       ++start;
     238                 :     }
     239               0 :     end = start;
     240                 :     // look for ':'
     241               0 :     while ((kNullCh!=*end) && (kDashCh!=*end) && !nsCRT::IsAsciiSpace(*end) &&
     242                 :            (kColonCh!=*end)) {
     243               0 :       ++end;
     244                 :     }
     245                 :     // If ':' is not found, then it's a boolean property
     246               0 :     bool IsBooleanProperty = (kColonCh != *end);
     247               0 :     *end = kNullCh; // end segment here
     248                 :     // this segment is the name
     249               0 :     if (start < end) {
     250               0 :       name.Assign(start);
     251                 :     }
     252               0 :     if (IsBooleanProperty) {
     253               0 :       SetBooleanProperty(aOperatorData, name);
     254                 :     } else {
     255               0 :       start = ++end;
     256                 :       // look for space or end of line
     257               0 :       while ((kNullCh!=*end) && (kDashCh!=*end) &&
     258               0 :              !nsCRT::IsAsciiSpace(*end)) {
     259               0 :         ++end;
     260                 :       }
     261               0 :       *end = kNullCh; // end segment here
     262               0 :       if (start < end) {
     263                 :         // this segment is the value
     264               0 :         value.Assign(start);
     265                 :       }
     266               0 :       SetProperty(aOperatorData, name, value);
     267                 :     }
     268               0 :     start = ++end;
     269                 :   }
     270               0 :   return true;
     271                 : }
     272                 : 
     273                 : static nsresult
     274               0 : InitOperators(void)
     275                 : {
     276                 :   // Load the property file containing the Operator Dictionary
     277                 :   nsresult rv;
     278               0 :   nsCOMPtr<nsIPersistentProperties> mathfontProp;
     279               0 :   rv = NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(mathfontProp),
     280               0 :        NS_LITERAL_CSTRING("resource://gre/res/fonts/mathfont.properties"));
     281               0 :   if (NS_FAILED(rv)) return rv;
     282                 : 
     283                 :   // Get the list of invariant chars
     284               0 :   for (PRInt32 i = 0; i < eMATHVARIANT_COUNT; ++i) {
     285               0 :     nsCAutoString key(NS_LITERAL_CSTRING("mathvariant."));
     286               0 :     key.Append(kMathVariant_name[i]);
     287               0 :     nsAutoString value;
     288               0 :     mathfontProp->GetStringProperty(key, value);
     289               0 :     gInvariantCharArray->AppendElement(value); // i.e., gInvariantCharArray[i] holds this list
     290                 :   }
     291                 : 
     292                 :   // Parse the Operator Dictionary in two passes.
     293                 :   // The first pass is to count the number of operators; the second pass is to
     294                 :   // allocate the necessary space for them and to add them in the hash table.
     295               0 :   for (PRInt32 pass = 1; pass <= 2; pass++) {
     296               0 :     OperatorData dummyData;
     297               0 :     OperatorData* operatorData = &dummyData;
     298               0 :     nsCOMPtr<nsISimpleEnumerator> iterator;
     299               0 :     if (NS_SUCCEEDED(mathfontProp->Enumerate(getter_AddRefs(iterator)))) {
     300                 :       bool more;
     301               0 :       PRUint32 index = 0;
     302               0 :       nsCAutoString name;
     303               0 :       nsAutoString attributes;
     304               0 :       while ((NS_SUCCEEDED(iterator->HasMoreElements(&more))) && more) {
     305               0 :         nsCOMPtr<nsIPropertyElement> element;
     306               0 :         if (NS_SUCCEEDED(iterator->GetNext(getter_AddRefs(element)))) {
     307               0 :           if (NS_SUCCEEDED(element->GetKey(name)) &&
     308               0 :               NS_SUCCEEDED(element->GetValue(attributes))) {
     309                 :             // expected key: operator.\uNNNN.{infix,postfix,prefix}
     310               0 :             if ((21 <= name.Length()) && (0 == name.Find("operator.\\u"))) {
     311               0 :               name.Cut(0, 9); // 9 is the length of "operator.";
     312               0 :               PRInt32 len = name.Length();
     313               0 :               nsOperatorFlags form = 0;
     314               0 :               if (kNotFound != name.RFind(".infix")) {
     315               0 :                 form = NS_MATHML_OPERATOR_FORM_INFIX;
     316               0 :                 len -= 6;  // 6 is the length of ".infix";
     317                 :               }
     318               0 :               else if (kNotFound != name.RFind(".postfix")) {
     319               0 :                 form = NS_MATHML_OPERATOR_FORM_POSTFIX;
     320               0 :                 len -= 8; // 8 is the length of ".postfix";
     321                 :               }
     322               0 :               else if (kNotFound != name.RFind(".prefix")) {
     323               0 :                 form = NS_MATHML_OPERATOR_FORM_PREFIX;
     324               0 :                 len -= 7; // 7 is the length of ".prefix";
     325                 :               }
     326               0 :               else continue; // input is not applicable
     327               0 :               name.SetLength(len);
     328               0 :               if (2 == pass) { // allocate space and start the storage
     329               0 :                 if (!gOperatorArray) {
     330               0 :                   if (0 == gOperatorCount) return NS_ERROR_UNEXPECTED;
     331               0 :                   gOperatorArray = new OperatorData[gOperatorCount];
     332               0 :                   if (!gOperatorArray) return NS_ERROR_OUT_OF_MEMORY;
     333                 :                 }
     334               0 :                 operatorData = &gOperatorArray[index];
     335                 :               }
     336                 :               else {
     337               0 :                 form = 0; // to quickly return from SetOperator() at pass 1
     338                 :               }
     339                 :               // See if the operator should be retained
     340               0 :               if (SetOperator(operatorData, form, name, attributes)) {
     341               0 :                 index++;
     342               0 :                 if (1 == pass) gOperatorCount = index;
     343                 :               }
     344                 :             }
     345                 :           }
     346                 :         }
     347                 :       }
     348                 :     }
     349                 :   }
     350               0 :   return NS_OK;
     351                 : }
     352                 : 
     353                 : static nsresult
     354               0 : InitGlobals()
     355                 : {
     356               0 :   gInitialized = true;
     357               0 :   nsresult rv = NS_ERROR_OUT_OF_MEMORY;
     358               0 :   gInvariantCharArray = new nsTArray<nsString>();
     359               0 :   if (gInvariantCharArray) {
     360               0 :     gOperatorTable = new nsHashtable();
     361               0 :     if (gOperatorTable) {
     362               0 :       rv = InitOperators();
     363                 :     }
     364                 :   }
     365               0 :   if (NS_FAILED(rv))
     366               0 :     nsMathMLOperators::CleanUp();
     367               0 :   return rv;
     368                 : }
     369                 : 
     370                 : void
     371            1403 : nsMathMLOperators::CleanUp()
     372                 : {
     373            1403 :   if (gInvariantCharArray) {
     374               0 :     delete gInvariantCharArray;
     375               0 :     gInvariantCharArray = nsnull;
     376                 :   }
     377            1403 :   if (gOperatorArray) {
     378               0 :     delete[] gOperatorArray;
     379               0 :     gOperatorArray = nsnull;
     380                 :   }
     381            1403 :   if (gOperatorTable) {
     382               0 :     delete gOperatorTable;
     383               0 :     gOperatorTable = nsnull;
     384                 :   }
     385            1403 : }
     386                 : 
     387                 : void
     388            1404 : nsMathMLOperators::AddRefTable(void)
     389                 : {
     390            1404 :   gTableRefCount++;
     391            1404 : }
     392                 : 
     393                 : void
     394            1403 : nsMathMLOperators::ReleaseTable(void)
     395                 : {
     396            1403 :   if (0 == --gTableRefCount) {
     397            1403 :     CleanUp();
     398                 :   }
     399            1403 : }
     400                 : 
     401                 : static OperatorData*
     402               0 : GetOperatorData(const nsString& aOperator, nsOperatorFlags aForm)
     403                 : {
     404               0 :   nsAutoString key(aOperator);
     405               0 :   key.AppendInt(aForm);
     406               0 :   nsStringKey hkey(key);
     407               0 :   return (OperatorData*)gOperatorTable->Get(&hkey);
     408                 : }
     409                 : 
     410                 : bool
     411               0 : nsMathMLOperators::LookupOperator(const nsString&       aOperator,
     412                 :                                   const nsOperatorFlags aForm,
     413                 :                                   nsOperatorFlags*      aFlags,
     414                 :                                   float*                aLeadingSpace,
     415                 :                                   float*                aTrailingSpace)
     416                 : {
     417               0 :   if (!gInitialized) {
     418               0 :     InitGlobals();
     419                 :   }
     420               0 :   if (gOperatorTable) {
     421               0 :     NS_ASSERTION(aFlags && aLeadingSpace && aTrailingSpace, "bad usage");
     422               0 :     NS_ASSERTION(aForm > 0 && aForm < 4, "*** invalid call ***");
     423                 : 
     424                 :     // The MathML REC says:
     425                 :     // If the operator does not occur in the dictionary with the specified form,
     426                 :     // the renderer should use one of the forms which is available there, in the
     427                 :     // order of preference: infix, postfix, prefix.
     428                 : 
     429                 :     OperatorData* found;
     430               0 :     PRInt32 form = NS_MATHML_OPERATOR_GET_FORM(aForm);
     431               0 :     if (!(found = GetOperatorData(aOperator, form))) {
     432               0 :       if (form == NS_MATHML_OPERATOR_FORM_INFIX ||
     433                 :           !(found =
     434                 :             GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_INFIX))) {
     435               0 :         if (form == NS_MATHML_OPERATOR_FORM_POSTFIX ||
     436                 :             !(found =
     437                 :               GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_POSTFIX))) {
     438               0 :           if (form != NS_MATHML_OPERATOR_FORM_PREFIX) {
     439               0 :             found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_PREFIX);
     440                 :           }
     441                 :         }
     442                 :       }
     443                 :     }
     444               0 :     if (found) {
     445               0 :       NS_ASSERTION(found->mStr.Equals(aOperator), "bad setup");
     446               0 :       *aLeadingSpace = found->mLeadingSpace;
     447               0 :       *aTrailingSpace = found->mTrailingSpace;
     448               0 :       *aFlags &= ~NS_MATHML_OPERATOR_FORM; // clear the form bits
     449               0 :       *aFlags |= found->mFlags; // just add bits without overwriting
     450               0 :       return true;
     451                 :     }
     452                 :   }
     453               0 :   return false;
     454                 : }
     455                 : 
     456                 : void
     457               0 : nsMathMLOperators::LookupOperators(const nsString&       aOperator,
     458                 :                                    nsOperatorFlags*      aFlags,
     459                 :                                    float*                aLeadingSpace,
     460                 :                                    float*                aTrailingSpace)
     461                 : {
     462               0 :   if (!gInitialized) {
     463               0 :     InitGlobals();
     464                 :   }
     465                 : 
     466               0 :   aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = 0;
     467               0 :   aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
     468               0 :   aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
     469                 : 
     470               0 :   aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0;
     471               0 :   aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
     472               0 :   aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
     473                 : 
     474               0 :   aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = 0;
     475               0 :   aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
     476               0 :   aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
     477                 : 
     478               0 :   if (gOperatorTable) {
     479                 :     OperatorData* found;
     480               0 :     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_INFIX);
     481               0 :     if (found) {
     482               0 :       aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = found->mFlags;
     483               0 :       aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mLeadingSpace;
     484               0 :       aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mTrailingSpace;
     485                 :     }
     486               0 :     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_POSTFIX);
     487               0 :     if (found) {
     488               0 :       aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mFlags;
     489               0 :       aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mLeadingSpace;
     490               0 :       aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mTrailingSpace;
     491                 :     }
     492               0 :     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_PREFIX);
     493               0 :     if (found) {
     494               0 :       aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mFlags;
     495               0 :       aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mLeadingSpace;
     496               0 :       aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mTrailingSpace;
     497                 :     }
     498                 :   }
     499               0 : }
     500                 : 
     501                 : bool
     502               0 : nsMathMLOperators::IsMutableOperator(const nsString& aOperator)
     503                 : {
     504               0 :   if (!gInitialized) {
     505               0 :     InitGlobals();
     506                 :   }
     507                 :   // lookup all the variants of the operator and return true if there
     508                 :   // is a variant that is stretchy or largeop
     509                 :   nsOperatorFlags flags[4];
     510                 :   float lspace[4], rspace[4];
     511               0 :   nsMathMLOperators::LookupOperators(aOperator, flags, lspace, rspace);
     512                 :   nsOperatorFlags allFlags =
     513               0 :     flags[NS_MATHML_OPERATOR_FORM_INFIX] |
     514               0 :     flags[NS_MATHML_OPERATOR_FORM_POSTFIX] |
     515               0 :     flags[NS_MATHML_OPERATOR_FORM_PREFIX];
     516                 :   return NS_MATHML_OPERATOR_IS_STRETCHY(allFlags) ||
     517               0 :          NS_MATHML_OPERATOR_IS_LARGEOP(allFlags);
     518                 : }
     519                 : 
     520                 : /* static */ bool
     521               0 : nsMathMLOperators::IsMirrorableOperator(const nsString& aOperator)
     522                 : {
     523                 :   // LookupOperator will search infix, postfix and prefix forms of aOperator and
     524                 :   // return the first form found. It is assumed that all these forms have same
     525                 :   // mirrorability.
     526               0 :   nsOperatorFlags flags = 0;
     527                 :   float dummy;
     528                 :   nsMathMLOperators::LookupOperator(aOperator,
     529                 :                                     NS_MATHML_OPERATOR_FORM_INFIX,
     530               0 :                                     &flags, &dummy, &dummy);
     531               0 :   return NS_MATHML_OPERATOR_IS_MIRRORABLE(flags);
     532                 : }
     533                 : 
     534                 : /* static */ nsStretchDirection
     535               0 : nsMathMLOperators::GetStretchyDirection(const nsString& aOperator)
     536                 : {
     537                 :   // LookupOperator will search infix, postfix and prefix forms of aOperator and
     538                 :   // return the first form found. It is assumed that all these forms have same
     539                 :   // direction.
     540               0 :   nsOperatorFlags flags = 0;
     541                 :   float dummy;
     542                 :   nsMathMLOperators::LookupOperator(aOperator,
     543                 :                                     NS_MATHML_OPERATOR_FORM_INFIX,
     544               0 :                                     &flags, &dummy, &dummy);
     545                 : 
     546               0 :   if (NS_MATHML_OPERATOR_IS_DIRECTION_VERTICAL(flags)) {
     547               0 :       return NS_STRETCH_DIRECTION_VERTICAL;
     548               0 :   } else if (NS_MATHML_OPERATOR_IS_DIRECTION_HORIZONTAL(flags)) {
     549               0 :     return NS_STRETCH_DIRECTION_HORIZONTAL;
     550                 :   } else {
     551               0 :     return NS_STRETCH_DIRECTION_UNSUPPORTED;
     552                 :   }
     553                 : }
     554                 : 
     555                 : /* static */ eMATHVARIANT
     556               0 : nsMathMLOperators::LookupInvariantChar(const nsAString& aChar)
     557                 : {
     558               0 :   if (!gInitialized) {
     559               0 :     InitGlobals();
     560                 :   }
     561               0 :   if (gInvariantCharArray) {
     562               0 :     for (PRInt32 i = gInvariantCharArray->Length()-1; i >= 0; --i) {
     563               0 :       const nsString& list = gInvariantCharArray->ElementAt(i);
     564               0 :       nsString::const_iterator start, end;
     565               0 :       list.BeginReading(start);
     566               0 :       list.EndReading(end);
     567                 :       // Style-invariant characters are at offset 3*j + 1.
     568               0 :       if (FindInReadable(aChar, start, end) &&
     569               0 :           start.size_backward() % 3 == 1) {
     570               0 :         return eMATHVARIANT(i);
     571                 :       }
     572                 :     }
     573                 :   }
     574               0 :   return eMATHVARIANT_NONE;
     575                 : }
     576                 : 
     577                 : /* static */ const nsDependentSubstring
     578               0 : nsMathMLOperators::TransformVariantChar(const PRUnichar& aChar,
     579                 :                                         eMATHVARIANT aVariant)
     580                 : {
     581               0 :   if (!gInitialized) {
     582               0 :     InitGlobals();
     583                 :   }
     584               0 :   if (gInvariantCharArray) {
     585               0 :     nsString list = gInvariantCharArray->ElementAt(aVariant);
     586               0 :     PRInt32 index = list.FindChar(aChar);
     587                 :     // BMP characters are at offset 3*j
     588               0 :     if (index != kNotFound && index % 3 == 0 && list.Length() - index >= 2 ) {
     589                 :       // The style-invariant character is the next character
     590                 :       // (and list should contain padding if the next character is in the BMP).
     591               0 :       ++index;
     592               0 :       PRUint32 len = NS_IS_HIGH_SURROGATE(list.CharAt(index)) ? 2 : 1;
     593               0 :       return nsDependentSubstring(list, index, len);
     594                 :     }
     595                 :   }
     596               0 :   return nsDependentSubstring(&aChar, &aChar + 1);  
     597                 : }

Generated by: LCOV version 1.7