Bug 355548. Clean up MathML's font handling by moving most of it to the style system. Creates nsMathMLElement to put functionality there. Tightens MathML attribute parsing and introduces full support for 'scriptsizemultiplier', 'scriptminsize' and their interactions with CSS font-size. r+sr=dbaron
authorroc+@cs.cmu.edu
Tue, 08 Jan 2008 14:36:46 -0800
changeset 10026 76075fc0b51928b26bbb5e520aa23cb7c3ba6716
parent 10025 cd353cf8b2bc8736192d95d9925b30522d09e865
child 10027 99ce1d01fea100b6de471546d7a377a3a6722cb9
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)
bugs355548
milestone1.9b3pre
Bug 355548. Clean up MathML's font handling by moving most of it to the style system. Creates nsMathMLElement to put functionality there. Tightens MathML attribute parsing and introduces full support for 'scriptsizemultiplier', 'scriptminsize' and their interactions with CSS font-size. r+sr=dbaron
content/Makefile.in
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/src/Makefile.in
content/base/src/nsAttrAndChildArray.cpp
content/base/src/nsAttrAndChildArray.h
content/base/src/nsMappedAttributeElement.cpp
content/base/src/nsMappedAttributeElement.h
content/base/src/nsMappedAttributes.h
content/events/public/nsIEventStateManager.h
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/document/src/nsImageDocument.cpp
content/mathml/Makefile.in
content/mathml/content/Makefile.in
content/mathml/content/src/Makefile.in
content/mathml/content/src/nsMathMLElement.cpp
content/mathml/content/src/nsMathMLElement.h
content/mathml/content/src/nsMathMLElementFactory.cpp
content/xml/document/src/nsXMLContentSink.cpp
dom/src/base/nsHistory.cpp
dom/src/base/nsLocation.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsStyleConsts.h
layout/build/Makefile.in
layout/mathml/base/src/Makefile.in
layout/mathml/base/src/nsIMathMLFrame.h
layout/mathml/base/src/nsMathMLContainerFrame.cpp
layout/mathml/base/src/nsMathMLContainerFrame.h
layout/mathml/base/src/nsMathMLForeignFrameWrapper.h
layout/mathml/base/src/nsMathMLFrame.cpp
layout/mathml/base/src/nsMathMLFrame.h
layout/mathml/base/src/nsMathMLmfencedFrame.cpp
layout/mathml/base/src/nsMathMLmfracFrame.cpp
layout/mathml/base/src/nsMathMLmfracFrame.h
layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp
layout/mathml/base/src/nsMathMLmoFrame.cpp
layout/mathml/base/src/nsMathMLmoverFrame.cpp
layout/mathml/base/src/nsMathMLmoverFrame.h
layout/mathml/base/src/nsMathMLmrootFrame.cpp
layout/mathml/base/src/nsMathMLmsqrtFrame.cpp
layout/mathml/base/src/nsMathMLmstyleFrame.cpp
layout/mathml/base/src/nsMathMLmstyleFrame.h
layout/mathml/base/src/nsMathMLmsubFrame.cpp
layout/mathml/base/src/nsMathMLmsubsupFrame.cpp
layout/mathml/base/src/nsMathMLmsupFrame.cpp
layout/mathml/base/src/nsMathMLmtableFrame.cpp
layout/mathml/base/src/nsMathMLmtableFrame.h
layout/mathml/base/src/nsMathMLmunderFrame.cpp
layout/mathml/base/src/nsMathMLmunderFrame.h
layout/mathml/base/src/nsMathMLmunderoverFrame.cpp
layout/mathml/base/src/nsMathMLmunderoverFrame.h
layout/mathml/content/src/mathml.css
layout/reftests/bugs/355548-1-ref.xml
layout/reftests/bugs/355548-1.xml
layout/reftests/bugs/355548-2-ref.xml
layout/reftests/bugs/355548-2.xml
layout/reftests/bugs/355548-3-ref.xml
layout/reftests/bugs/355548-3.xml
layout/reftests/bugs/355548-4-ref.xml
layout/reftests/bugs/355548-4.xml
layout/reftests/bugs/355548-5-ref.xml
layout/reftests/bugs/355548-5.xml
layout/reftests/bugs/reftest.list
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSPseudoClassList.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSStruct.h
layout/style/nsRuleNode.cpp
layout/style/nsRuleNode.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/ListCSSProperties.cpp
--- a/content/Makefile.in
+++ b/content/Makefile.in
@@ -48,16 +48,20 @@ DIRS		= base canvas html xml xul xbl xsl
 ifdef MOZ_SVG
 DIRS		+= svg
 endif
 
 ifdef MOZ_XTF
 DIRS            += xtf
 endif
 
+ifdef MOZ_MATHML
+DIRS            += mathml
+endif
+
 DIRS           += events
 
 ifdef ENABLE_TESTS
 TOOL_DIRS += test
 endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -270,17 +270,17 @@ public:
   /**
    * Return the language of this document.
    */
   void GetContentLanguage(nsAString& aContentLanguage) const
   {
     CopyASCIItoUTF16(mContentLanguage, aContentLanguage);
   }
 
-  // The state BidiEnabled should persist across multiple views
+  // The states BidiEnabled and MathMLEnabled should persist across multiple views
   // (screen, print) of the same document.
 
   /**
    * Check if the document contains bidi data.
    * If so, we have to apply the Unicode Bidi Algorithm.
    */
   PRBool GetBidiEnabled() const
   {
@@ -292,16 +292,29 @@ public:
    * Currently, we cannot disable bidi, because once bidi is enabled,
    * it affects a frame model irreversibly, and plays even though
    * the document no longer contains bidi data.
    */
   void SetBidiEnabled(PRBool aBidiEnabled)
   {
     mBidiEnabled = aBidiEnabled;
   }
+  
+  /**
+   * Check if the document contains (or has contained) any MathML elements.
+   */
+  PRBool GetMathMLEnabled() const
+  {
+    return mMathMLEnabled;
+  }
+  
+  void SetMathMLEnabled()
+  {
+    mMathMLEnabled = PR_TRUE;
+  }
 
   /**
    * Ask this document whether it's the initial document in its window.
    */
   PRBool IsInitialDocument() const
   {
     return mIsInitialDocumentInWindow;
   }
@@ -960,16 +973,18 @@ protected:
   // Table of element properties for this document.
   nsPropertyTable mPropertyTable;
 
   // Compatibility mode
   nsCompatibility mCompatMode;
 
   // True if BIDI is enabled.
   PRPackedBool mBidiEnabled;
+  // True if a MathML element has ever been owned by this document.
+  PRPackedBool mMathMLEnabled;
 
   // True if this document is the initial document for a window.  This should
   // basically be true only for documents that exist in newly-opened windows or
   // documents created to satisfy a GetDocument() on a window when there's no
   // document in it.
   PRPackedBool mIsInitialDocumentInWindow;
 
   PRPackedBool mShellsAreHidden;
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -175,17 +175,19 @@ public:
     /** XUL elements */
     eXUL                 = 1 << 9,
     /** svg elements */
     eSVG                 = 1 << 10,
     /** document fragments */
     eDOCUMENT_FRAGMENT   = 1 << 11,
     /** data nodes (comments, PIs, text). Nodes of this type always
      returns a non-null value for nsIContent::GetText() */
-    eDATA_NODE           = 1 << 12
+    eDATA_NODE           = 1 << 12,
+    /** nsMathMLElement */
+    eMATHML              = 1 << 13,
   };
 
   /**
    * API for doing a quick check if a content is of a given
    * type, such as HTML, XUL, Text, ...  Use this when you can instead of
    * checking the tag.
    *
    * @param aFlags what types you want to test for (see above)
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -131,16 +131,17 @@ CPPSRCS		= \
 		nsGenericDOMDataNode.cpp \
 		nsGenericDOMNodeList.cpp \
 		nsGenericElement.cpp \
 		nsGkAtoms.cpp \
 		nsHTMLContentSerializer.cpp \
 		nsImageLoadingContent.cpp \
 		nsLineBreaker.cpp \
 		nsLoadListenerProxy.cpp \
+		nsMappedAttributeElement.cpp \
 		nsMappedAttributes.cpp \
 		nsNameSpaceManager.cpp \
 		nsNoDataProtocolContentPolicy.cpp \
 		nsNodeInfo.cpp \
 		nsNodeInfoManager.cpp \
 		nsNodeUtils.cpp \
 		nsObjectLoadingContent.cpp \
 		nsParserUtils.cpp \
--- a/content/base/src/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Storage of the children and attributes of a DOM node; storage for
  * the two is unified to minimize footprint.
  */
 
 #include "nsAttrAndChildArray.h"
-#include "nsGenericHTMLElement.h"
+#include "nsMappedAttributeElement.h"
 #include "prmem.h"
 #include "prbit.h"
 #include "nsString.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsRuleWalker.h"
 #include "nsMappedAttributes.h"
 #include "nsUnicharUtils.h"
 #include "nsAutoPtr.h"
@@ -556,17 +556,17 @@ nsAttrAndChildArray::IndexOfAttr(nsIAtom
   }
 
   return -1;
 }
 
 nsresult
 nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName,
                                           nsAttrValue& aValue,
-                                          nsGenericHTMLElement* aContent,
+                                          nsMappedAttributeElement* aContent,
                                           nsHTMLStyleSheet* aSheet)
 {
   nsRefPtr<nsMappedAttributes> mapped;
   nsresult rv = GetModifiableMapped(aContent, aSheet, PR_TRUE,
                                     getter_AddRefs(mapped));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mapped->SetAndTakeAttr(aLocalName, aValue);
@@ -646,17 +646,17 @@ nsAttrAndChildArray::NonMappedAttrCount(
 
 PRUint32
 nsAttrAndChildArray::MappedAttrCount() const
 {
   return mImpl && mImpl->mMappedAttrs ? (PRUint32)mImpl->mMappedAttrs->Count() : 0;
 }
 
 nsresult
-nsAttrAndChildArray::GetModifiableMapped(nsGenericHTMLElement* aContent,
+nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
                                          nsHTMLStyleSheet* aSheet,
                                          PRBool aWillAddAttr,
                                          nsMappedAttributes** aModifiable)
 {
   *aModifiable = nsnull;
 
   if (mImpl && mImpl->mMappedAttrs) {
     *aModifiable = mImpl->mMappedAttrs->Clone(aWillAddAttr);
--- a/content/base/src/nsAttrAndChildArray.h
+++ b/content/base/src/nsAttrAndChildArray.h
@@ -48,17 +48,17 @@
 #include "nsAttrName.h"
 #include "nsAttrValue.h"
 
 class nsINode;
 class nsIContent;
 class nsMappedAttributes;
 class nsHTMLStyleSheet;
 class nsRuleWalker;
-class nsGenericHTMLElement;
+class nsMappedAttributeElement;
 
 #define ATTRCHILD_ARRAY_GROWSIZE 8
 #define ATTRCHILD_ARRAY_LINEAR_THRESHOLD 32
 
 #define ATTRCHILD_ARRAY_ATTR_SLOTS_BITS 10
 
 #define ATTRCHILD_ARRAY_MAX_ATTR_COUNT \
     ((1 << ATTRCHILD_ARRAY_ATTR_SLOTS_BITS) - 1)
@@ -115,31 +115,31 @@ public:
   // Returns attribute name at given position or null if aPos is out-of-bounds
   const nsAttrName* GetSafeAttrNameAt(PRUint32 aPos) const;
 
   // aName is UTF-8 encoded
   const nsAttrName* GetExistingAttrNameFromQName(const nsACString& aName) const;
   PRInt32 IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const;
 
   nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
-                                nsGenericHTMLElement* aContent,
+                                nsMappedAttributeElement* aContent,
                                 nsHTMLStyleSheet* aSheet);
   nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet);
   void WalkMappedAttributeStyleRules(nsRuleWalker* aRuleWalker);
 
 private:
   nsAttrAndChildArray(const nsAttrAndChildArray& aOther); // Not to be implemented
   nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther); // Not to be implemented
 
   void Clear();
 
   PRUint32 NonMappedAttrCount() const;
   PRUint32 MappedAttrCount() const;
 
-  nsresult GetModifiableMapped(nsGenericHTMLElement* aContent,
+  nsresult GetModifiableMapped(nsMappedAttributeElement* aContent,
                                nsHTMLStyleSheet* aSheet,
                                PRBool aWillAddAttr,
                                nsMappedAttributes** aModifiable);
   nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
 
   PRUint32 AttrSlotsSize() const
   {
     return AttrSlotCount() * ATTRSIZE;
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsMappedAttributeElement.cpp
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mats Palmgren <mats.palmgren@bredband.net>
+ *   Daniel Kraft <d@domob.eu>
+ *
+ * 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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMappedAttributeElement.h"
+#include "nsIDocument.h"
+
+nsresult
+nsMappedAttributeElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                                     nsIContent* aBindingParent,
+                                     PRBool aCompileEventHandlers)
+{
+  nsresult rv = nsMappedAttributeElementBase::BindToTree(aDocument, aParent,
+                                                         aBindingParent,
+                                                         aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDocument) {
+    // If we're in a document now, let our mapped attrs know what their new
+    // sheet is.
+    nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
+    if (sheet) {
+      mAttrsAndChildren.SetMappedAttrStyleSheet(sheet);
+    }
+  }
+
+  return rv;
+}
+
+nsresult
+nsMappedAttributeElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
+{
+  mAttrsAndChildren.WalkMappedAttributeStyleRules(aRuleWalker);
+  return NS_OK;
+}
+
+PRBool
+nsMappedAttributeElement::SetMappedAttribute(nsIDocument* aDocument,
+                                             nsIAtom* aName,
+                                             nsAttrValue& aValue,
+                                             nsresult* aRetval)
+{
+  NS_PRECONDITION(aDocument == GetCurrentDoc(), "Unexpected document");
+  nsHTMLStyleSheet* sheet = aDocument ?
+    aDocument->GetAttributeStyleSheet() : nsnull;
+
+  *aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
+                                                    this, sheet);
+  return PR_TRUE;
+}
+
+nsMapRuleToAttributesFunc
+nsMappedAttributeElement::GetAttributeMappingFunction() const
+{
+  return &MapNoAttributesInto;
+}
+
+void
+nsMappedAttributeElement::MapNoAttributesInto(const nsMappedAttributes* aAttributes,
+                                              nsRuleData* aData)
+{
+}
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsMappedAttributeElement.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Daniel Kraft <d@domob.eu>
+ *
+ * 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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * nsMappedAttributeElement is the base for elements supporting style mapped
+ * attributes via nsMappedAttributes (HTML and MathML).
+ */
+
+#ifndef NS_MAPPEDATTRIBUTEELEMENT_H_
+#define NS_MAPPEDATTRIBUTEELEMENT_H_
+
+#include "nsStyledElement.h"
+
+class nsMappedAttributes;
+class nsRuleData;
+
+typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, 
+                                          nsRuleData* aData);
+
+typedef nsStyledElement nsMappedAttributeElementBase;
+
+class nsMappedAttributeElement : public nsMappedAttributeElementBase
+{
+
+protected:
+
+  nsMappedAttributeElement(nsINodeInfo *aNodeInfo)
+    : nsMappedAttributeElementBase(aNodeInfo)
+  {}
+
+public:
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+
+  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+
+  static void MapNoAttributesInto(const nsMappedAttributes* aAttributes, 
+                                  nsRuleData* aRuleData);
+
+  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
+  virtual PRBool SetMappedAttribute(nsIDocument* aDocument,
+                                    nsIAtom* aName,
+                                    nsAttrValue& aValue,
+                                    nsresult* aRetval);
+};
+
+#endif // NS_MAPPEDATTRIBUTEELEMENT_H_
--- a/content/base/src/nsMappedAttributes.h
+++ b/content/base/src/nsMappedAttributes.h
@@ -40,17 +40,17 @@
  * A unique per-element set of attributes that is used as an
  * nsIStyleRule; used to implement presentational attributes.
  */
 
 #ifndef nsMappedAttributes_h___
 #define nsMappedAttributes_h___
 
 #include "nsAttrAndChildArray.h"
-#include "nsGenericHTMLElement.h"
+#include "nsMappedAttributeElement.h"
 #include "nsIStyleRule.h"
 
 class nsIAtom;
 class nsHTMLStyleSheet;
 class nsRuleWalker;
 
 class nsMappedAttributes : public nsIStyleRule
 {
--- a/content/events/public/nsIEventStateManager.h
+++ b/content/events/public/nsIEventStateManager.h
@@ -210,10 +210,13 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventSt
 // Content suppressed by the user (ad blocking, etc)
 #define NS_EVENT_STATE_SUPPRESSED    0x00100000
 // Content is still loading such that there is nothing to show the
 // user (eg an image which hasn't started coming in yet)
 #define NS_EVENT_STATE_LOADING       0x00200000
 // Content is of a type that gecko can't handle
 #define NS_EVENT_STATE_TYPE_UNSUPPORTED \
                                      0x00400000
+#ifdef MOZ_MATHML
+#define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL 0x00800000
+#endif
 
 #endif // nsIEventStateManager_h__
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1141,23 +1141,16 @@ nsGenericHTMLElement::BindToTree(nsIDocu
 
   if (aDocument) {
     if (HasFlag(NODE_IS_EDITABLE) && GetContentEditableValue() == eTrue) {
       nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(aDocument);
       if (htmlDocument) {
         htmlDocument->ChangeContentEditableCount(this, +1);
       }
     }
-
-    // If we're in a document now, let our mapped attrs know what their new
-    // sheet is.
-    nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
-    if (sheet) {
-      mAttrsAndChildren.SetMappedAttrStyleSheet(sheet);
-    }
   }
 
   return rv;
 }
 
 void
 nsGenericHTMLElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
@@ -1430,23 +1423,16 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 
       }
     }
   }
 
   return nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute,
                                              aNotify);
 }
 
-nsresult
-nsGenericHTMLElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
-{
-  mAttrsAndChildren.WalkMappedAttributeStyleRules(aRuleWalker);
-  return NS_OK;
-}
-
 already_AddRefed<nsIURI>
 nsGenericHTMLElement::GetBaseURI() const
 {
   nsIDocument* doc = GetOwnerDoc();
 
   void* prop;
   if (HasFlag(NODE_HAS_PROPERTIES) && (prop = GetProperty(nsGkAtoms::htmlBaseHref))) {
     nsIURI* uri = static_cast<nsIURI*>(prop);
@@ -1535,32 +1521,16 @@ nsGenericHTMLElement::IsAttributeMapped(
 {
   static const MappedAttributeEntry* const map[] = {
     sCommonAttributeMap
   };
   
   return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
 }
 
-PRBool
-nsGenericHTMLElement::SetMappedAttribute(nsIDocument* aDocument,
-                                         nsIAtom* aName,
-                                         nsAttrValue& aValue,
-                                         nsresult* aRetval)
-{
-  NS_PRECONDITION(aDocument == GetCurrentDoc(), "Unexpected document");
-  nsHTMLStyleSheet* sheet = aDocument ?
-    aDocument->GetAttributeStyleSheet() : nsnull;
-  
-  *aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
-                                                    this, sheet);
-  return PR_TRUE;
-}
-
-
 nsMapRuleToAttributesFunc
 nsGenericHTMLElement::GetAttributeMappingFunction() const
 {
   return &MapCommonAttributesInto;
 }
 
 // static
 nsIFormControlFrame*
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -33,48 +33,43 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsGenericHTMLElement_h___
 #define nsGenericHTMLElement_h___
 
-#include "nsStyledElement.h"
+#include "nsMappedAttributeElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsIDOMNSHTMLFrameElement.h"
 #include "nsFrameLoader.h"
 #include "nsGkAtoms.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
-class nsMappedAttributes;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
 class nsIDOMCSSStyleDeclaration;
 class nsIURI;
 class nsIFormControlFrame;
 class nsIForm;
 class nsPresState;
 class nsIScrollableView;
 class nsILayoutHistoryState;
 class nsIEditor;
 struct nsRect;
 struct nsSize;
-struct nsRuleData;
 
-typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, 
-                                          nsRuleData* aData);
-
-typedef nsStyledElement nsGenericHTMLElementBase;
+typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
 public:
   nsGenericHTMLElement(nsINodeInfo *aNodeInfo)
@@ -234,33 +229,28 @@ public:
   // Callers must hold a reference to nsHTMLUtils's global reference count.
   nsresult GetHrefURIForAnchors(nsIURI** aURI) const;
 
   // HTML element methods
   const nsAttrValue* GetParsedAttr(nsIAtom* aAttr) const
   {
     return mAttrsAndChildren.GetAttr(aAttr);
   }
-  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   virtual void UpdateEditableState();
 
-  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
   already_AddRefed<nsIURI> GetBaseURI() const;
 
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
 
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
-  virtual PRBool SetMappedAttribute(nsIDocument* aDocument,
-                                    nsIAtom* aName,
-                                    nsAttrValue& aValue,
-                                    nsresult* aRetval);
+  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   /**
    * Get the base target for any links within this piece
    * of content. Generally, this is the document's base target,
    * but certain content carries a local base for backward
    * compatibility.
    *
    * @param aBaseTarget the base target [OUT]
--- a/content/html/document/src/nsImageDocument.cpp
+++ b/content/html/document/src/nsImageDocument.cpp
@@ -603,17 +603,17 @@ nsImageDocument::CreateSyntheticDocument
 
   return NS_OK;
 }
 
 nsresult
 nsImageDocument::CheckOverflowing(PRBool changeState)
 {
   /* Create a scope so that the style context gets destroyed before we might
-   * call ClearStyleDataAndReflow.  Also, holding onto pointers to the
+   * call RebuildStyleData.  Also, holding onto pointers to the
    * presentatation through style resolution is potentially dangerous.
    */
   {
     nsIPresShell *shell = GetPrimaryShell();
     if (!shell) {
       return NS_OK;
     }
 
new file mode 100644
--- /dev/null
+++ b/content/mathml/Makefile.in
@@ -0,0 +1,47 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# 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
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS		= content
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/content/mathml/content/Makefile.in
@@ -0,0 +1,48 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# 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
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS		= src
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/content/mathml/content/src/Makefile.in
@@ -0,0 +1,87 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla MathML DOM code.
+#
+# The Initial Developer of the Original Code is
+# mozilla.org.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vlad Sukhoy <vladimir.sukhoy@gmail.com> (original developer)
+#
+# 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
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= content
+LIBRARY_NAME	= gkcontentmathml_s
+LIBXUL_LIBRARY	= 1
+REQUIRES	= xpcom       \
+		  string      \
+		  layout      \
+		  content     \
+		  widget      \
+		  gfx         \
+		  dom         \
+		  js          \
+		  locale      \
+		  pref        \
+		  webshell    \
+		  unicharutil \
+		  docshell    \
+		  thebes      \
+		  $(NULL)
+
+CPPSRCS		= \
+		nsMathMLElement.cpp               \
+		nsMathMLElementFactory.cpp        \
+		$(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+# we don't want the shared lib, but we want to force the creation of a static 
+# lib.
+FORCE_STATIC_LIB = 1
+
+EXPORTS = \
+	$(NULL)
+
+
+include $(topsrcdir)/config/rules.mk
+
+INCLUDES += 	\
+		-I$(srcdir)/../../../shared/public \
+		-I$(srcdir)/../../../base/src \
+		$(NULL)
+
+DEFINES += -D_IMPL_NS_LAYOUT
new file mode 100644
--- /dev/null
+++ b/content/mathml/content/src/nsMathMLElement.cpp
@@ -0,0 +1,457 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MathML DOM code.
+ *
+ * The Initial Developer of the Original Code is
+ * mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Vlad Sukhoy <vladimir.sukhoy@gmail.com> (original developer)
+ *    Daniel Kraft <d@domob.eu> (nsMathMLElement patch, attachment 262925)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMathMLElement.h"
+#include "nsDOMClassInfoID.h" // for eDOMClassInfo_MathElement_id.
+#include "nsGkAtoms.h"
+#include "nsCRT.h"
+#include "nsRuleData.h"
+#include "nsCSSValue.h"
+#include "nsMappedAttributes.h"
+#include "nsStyleConsts.h"
+#include "nsIDocument.h"
+#include "nsIEventStateManager.h"
+#include "nsPresShellIterator.h"
+#include "nsIPresShell.h"
+#include "nsPresContext.h"
+#include "nsDOMClassInfoID.h"
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMETHODIMP 
+nsMathMLElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+  NS_PRECONDITION(aInstancePtr, "null out param");
+
+  nsresult rv = nsMathMLElementBase::QueryInterface(aIID, aInstancePtr);
+
+  if (NS_SUCCEEDED(rv))
+    return rv;
+
+  nsISupports *inst = nsnull;
+
+  if (aIID.Equals(NS_GET_IID(nsIDOMNode))) {
+    inst = static_cast<nsIDOMNode *>(this);
+  } else if (aIID.Equals(NS_GET_IID(nsIDOMElement))) {
+    inst = static_cast<nsIDOMElement *>(this);
+  } else if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
+    inst = NS_GetDOMClassInfoInstance(eDOMClassInfo_Element_id);
+    NS_ENSURE_TRUE(inst, NS_ERROR_OUT_OF_MEMORY);
+  } else {
+    return PostQueryInterface(aIID, aInstancePtr);
+  }
+
+  NS_ADDREF(inst);
+
+  *aInstancePtr = inst;
+
+  return NS_OK;
+}
+
+NS_IMPL_ADDREF_INHERITED(nsMathMLElement, nsMathMLElementBase)
+NS_IMPL_RELEASE_INHERITED(nsMathMLElement, nsMathMLElementBase)
+
+nsresult
+nsMathMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                            nsIContent* aBindingParent,
+                            PRBool aCompileEventHandlers)
+{
+  static const char kMathMLStyleSheetURI[] = "resource://gre/res/mathml.css";
+
+  nsresult rv = nsMathMLElementBase::BindToTree(aDocument, aParent,
+                                                aBindingParent,
+                                                aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDocument && !aDocument->GetMathMLEnabled()) {
+    // Enable MathML and setup the style sheet during binding, not element
+    // construction, because we could move a MathML element from the document
+    // that created it to another document.
+    aDocument->SetMathMLEnabled();
+    aDocument->EnsureCatalogStyleSheet(kMathMLStyleSheetURI);
+
+    // Rebuild style data for all the presshells, because style system
+    // optimizations may have taken place assuming MathML was disabled.
+    // (See nsRuleNode::CheckSpecifiedProperties.)
+    // nsPresShellIterator skips hidden presshells, but that's OK because
+    // if we're changing the document for one of those presshells the whole
+    // presshell will be torn down.
+    nsPresShellIterator iter(aDocument);
+    nsCOMPtr<nsIPresShell> shell;
+    while ((shell = iter.GetNextShell()) != nsnull) {
+      shell->GetPresContext()->PostRebuildAllStyleDataEvent();
+    }
+  }
+
+  return rv;
+}
+
+PRBool
+nsMathMLElement::ParseAttribute(PRInt32 aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None) {
+    if (aAttribute == nsGkAtoms::color ||
+        aAttribute == nsGkAtoms::mathcolor_ ||
+        aAttribute == nsGkAtoms::background ||
+        aAttribute == nsGkAtoms::mathbackground_) {
+      return aResult.ParseColor(aValue, GetOwnerDoc());
+    }
+  }
+
+  return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
+                                             aValue, aResult);
+}
+
+static nsGenericElement::MappedAttributeEntry sTokenStyles[] = {
+  { &nsGkAtoms::mathsize_ },
+  { &nsGkAtoms::fontsize_ },
+  { &nsGkAtoms::mathcolor_ },
+  { &nsGkAtoms::color },
+  { &nsGkAtoms::mathbackground_ },
+  { &nsGkAtoms::fontfamily_ },
+  { nsnull }
+};
+
+static nsGenericElement::MappedAttributeEntry sEnvironmentStyles[] = {
+  { &nsGkAtoms::scriptlevel_ },
+  { &nsGkAtoms::scriptminsize_ },
+  { &nsGkAtoms::scriptsizemultiplier_ },
+  { &nsGkAtoms::background },
+  { nsnull }
+};
+
+PRBool
+nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
+{
+  static const MappedAttributeEntry* const tokenMap[] = {
+    sTokenStyles
+  };
+  static const MappedAttributeEntry* const mstyleMap[] = {
+    sTokenStyles,
+    sEnvironmentStyles
+  };
+  
+  // We don't support mglyph (yet).
+  nsIAtom* tag = Tag();
+  if (tag == nsGkAtoms::ms_ || tag == nsGkAtoms::mi_ ||
+      tag == nsGkAtoms::mn_ || tag == nsGkAtoms::mo_ ||
+      tag == nsGkAtoms::mtext_)
+    return FindAttributeDependence(aAttribute, tokenMap,
+                                   NS_ARRAY_LENGTH(tokenMap));
+  if (tag == nsGkAtoms::mstyle_)
+    return FindAttributeDependence(aAttribute, mstyleMap,
+                                   NS_ARRAY_LENGTH(mstyleMap));
+  return PR_FALSE;
+}
+
+nsMapRuleToAttributesFunc
+nsMathMLElement::GetAttributeMappingFunction() const
+{
+  // It doesn't really matter what our tag is here, because only attributes
+  // that satisfy IsAttributeMapped will be stored in the mapped attributes
+  // list and available to the mapping function
+  return &MapMathMLAttributesInto;
+}
+
+// ================
+// Utilities for parsing and retrieving numeric values
+
+/*
+The REC says:
+  An explicit plus sign ('+') is not allowed as part of a numeric value
+  except when it is specifically listed in the syntax (as a quoted '+'
+  or "+"),
+
+  Units allowed
+  ID  Description
+  em  ems (font-relative unit traditionally used for horizontal lengths)
+  ex  exs (font-relative unit traditionally used for vertical lengths)
+  px  pixels, or pixel size of a "typical computer display"
+  in  inches (1 inch = 2.54 centimeters)
+  cm  centimeters
+  mm  millimeters
+  pt  points (1 point = 1/72 inch)
+  pc  picas (1 pica = 12 points)
+  %   percentage of default value
+
+Implementation here:
+  The numeric value is valid only if it is of the form [-] nnn.nnn
+  [h/v-unit]
+*/
+
+/* static */ PRBool
+nsMathMLElement::ParseNumericValue(const nsString& aString,
+                                   nsCSSValue&     aCSSValue,
+                                   PRBool          aRequireLengthUnit)
+{
+  nsAutoString str(aString);
+  str.CompressWhitespace(); // aString is const in this code...
+
+  PRInt32 stringLength = str.Length();
+  if (!stringLength)
+    return PR_FALSE;
+
+  nsAutoString number, unit;
+
+  // see if the negative sign is there
+  PRInt32 i = 0;
+  PRUnichar c = str[0];
+  if (c == '-') {
+    number.Append(c);
+    i++;
+
+    // skip any space after the negative sign
+    if (i < stringLength && nsCRT::IsAsciiSpace(str[i]))
+      i++;
+  }
+
+  // Gather up characters that make up the number
+  PRBool gotDot = PR_FALSE;
+  for ( ; i < stringLength; i++) {
+    c = str[i];
+    if (gotDot && c == '.')
+      return PR_FALSE;  // two dots encountered
+    else if (c == '.')
+      gotDot = PR_TRUE;
+    else if (!nsCRT::IsAsciiDigit(c)) {
+      str.Right(unit, stringLength - i);
+      // some authors leave blanks before the unit, but that shouldn't
+      // be allowed, so don't CompressWhitespace on 'unit'.
+      break;
+    }
+    number.Append(c);
+  }
+
+  // Convert number to floating point
+  PRInt32 errorCode;
+  float floatValue = number.ToFloat(&errorCode);
+  if (NS_FAILED(errorCode))
+    return PR_FALSE;
+
+  nsCSSUnit cssUnit;
+  if (unit.IsEmpty()) {
+    if (aRequireLengthUnit) {
+      // We are supposed to have a length unit, but there isn't one.
+      // If the value is 0 we can just call it "pixels" otherwise
+      // this is illegal.
+      if (floatValue != 0.0)
+        return PR_FALSE;
+      cssUnit = eCSSUnit_Pixel;
+    } else {
+      // no explicit unit, this is a number that will act as a multiplier
+      cssUnit = eCSSUnit_Number;
+    }
+  }
+  else if (unit.EqualsLiteral("%")) {
+    aCSSValue.SetPercentValue(floatValue / 100.0f);
+    return PR_TRUE;
+  }
+  else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM;
+  else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight;
+  else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel;
+  else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch;
+  else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter;
+  else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter;
+  else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point;
+  else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica;
+  else // unexpected unit
+    return PR_FALSE;
+
+  aCSSValue.SetFloatValue(floatValue, cssUnit);
+  return PR_TRUE;
+}
+
+void
+nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
+                                         nsRuleData* aData)
+{
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
+    const nsAttrValue* value =
+      aAttributes->GetAttr(nsGkAtoms::scriptsizemultiplier_);
+    if (value && value->Type() == nsAttrValue::eString &&
+        aData->mFontData->mScriptSizeMultiplier.GetUnit() == eCSSUnit_Null) {
+      nsAutoString str(value->GetStringValue());
+      str.CompressWhitespace();
+      // MathML numbers can't have leading '+'
+      if (str.Length() > 0 && str.CharAt(0) != '+') {
+        PRInt32 errorCode;
+        float floatValue = str.ToFloat(&errorCode);
+        // Negative scriptsizemultipliers are not parsed
+        if (NS_SUCCEEDED(errorCode) && floatValue >= 0.0f) {
+          aData->mFontData->mScriptSizeMultiplier.
+            SetFloatValue(floatValue, eCSSUnit_Number);
+        }
+      }
+    }
+
+    value = aAttributes->GetAttr(nsGkAtoms::scriptminsize_);
+    if (value && value->Type() == nsAttrValue::eString &&
+        aData->mFontData->mScriptMinSize.GetUnit() == eCSSUnit_Null) {
+      ParseNumericValue(value->GetStringValue(),
+                        aData->mFontData->mScriptMinSize, PR_TRUE);
+    }
+
+    value = aAttributes->GetAttr(nsGkAtoms::scriptlevel_);
+    if (value && value->Type() == nsAttrValue::eString &&
+        aData->mFontData->mScriptLevel.GetUnit() == eCSSUnit_Null) {
+      nsAutoString str(value->GetStringValue());
+      str.CompressWhitespace();
+      if (str.Length() > 0) {
+        PRInt32 errorCode;
+        PRInt32 intValue = str.ToInteger(&errorCode);
+        if (NS_SUCCEEDED(errorCode)) {
+          // This is kind of cheesy ... if the scriptlevel has a sign,
+          // then it's a relative value and we store the nsCSSValue as an
+          // Integer to indicate that. Otherwise we store it as a Number
+          // to indicate that the scriptlevel is absolute.
+          PRUnichar ch = str.CharAt(0);
+          if (ch == '+' || ch == '-') {
+            aData->mFontData->mScriptLevel.SetIntValue(intValue, eCSSUnit_Integer);
+          } else {
+            aData->mFontData->mScriptLevel.SetFloatValue(intValue, eCSSUnit_Number);
+          }
+        }
+      }
+    }
+
+    PRBool parseSizeKeywords = PR_TRUE;
+    value = aAttributes->GetAttr(nsGkAtoms::mathsize_);
+    if (!value) {
+      parseSizeKeywords = PR_FALSE;
+      value = aAttributes->GetAttr(nsGkAtoms::fontsize_);
+    }
+    if (value && value->Type() == nsAttrValue::eString &&
+        aData->mFontData->mSize.GetUnit() == eCSSUnit_Null) {
+      nsAutoString str(value->GetStringValue());
+      if (!ParseNumericValue(str, aData->mFontData->mSize, PR_TRUE) &&
+          parseSizeKeywords) {
+        static const char sizes[3][7] = { "small", "normal", "big" };
+        static const PRInt32 values[NS_ARRAY_LENGTH(sizes)] = {
+          NS_STYLE_FONT_SIZE_SMALL, NS_STYLE_FONT_SIZE_MEDIUM,
+          NS_STYLE_FONT_SIZE_LARGE
+        };
+        str.CompressWhitespace();
+        for (PRInt32 i = 0; i < NS_ARRAY_LENGTH(sizes); ++i) {
+          if (str.EqualsASCII(sizes[i])) {
+            aData->mFontData->mSize.SetIntValue(values[i], eCSSUnit_Enumerated);
+            break;
+          }
+        }
+      }
+    }
+
+    value = aAttributes->GetAttr(nsGkAtoms::fontfamily_);
+    if (value && value->Type() == nsAttrValue::eString &&
+        aData->mFontData->mFamily.GetUnit() == eCSSUnit_Null) {
+      aData->mFontData->mFamily.SetStringValue(value->GetStringValue(),
+                                               eCSSUnit_String);
+      aData->mFontData->mFamilyFromHTML = PR_FALSE;
+    }
+  }
+
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)) {
+    const nsAttrValue* value =
+      aAttributes->GetAttr(nsGkAtoms::mathbackground_);
+    if (!value) {
+      value = aAttributes->GetAttr(nsGkAtoms::background);
+    }
+    if (value && aData->mColorData->mBackColor.GetUnit() == eCSSUnit_Null) {
+      nscolor color;
+      if (value->GetColorValue(color)) {
+        aData->mColorData->mBackColor.SetColorValue(color);
+      } else {
+        nsAutoString str(value->GetStringValue());
+        str.CompressWhitespace();
+        if (str.EqualsLiteral("transparent")) {
+          aData->mColorData->mBackColor.SetColorValue(NS_RGBA(0,0,0,0));
+        }
+      }
+    }
+  }
+
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Color)) {
+    const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::mathcolor_);
+    if (!value) {
+      value = aAttributes->GetAttr(nsGkAtoms::color);
+    }
+    nscolor color;
+    if (value && value->GetColorValue(color) &&
+        aData->mColorData->mColor.GetUnit() == eCSSUnit_Null) {
+      aData->mColorData->mColor.SetColorValue(color);
+    }
+  }
+}
+
+NS_IMPL_ELEMENT_CLONE(nsMathMLElement)
+
+PRInt32
+nsMathMLElement::IntrinsicState() const
+{
+  return nsMathMLElementBase::IntrinsicState() |
+    (mIncrementScriptLevel ? NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL : 0);
+}
+
+PRBool
+nsMathMLElement::IsNodeOfType(PRUint32 aFlags) const
+{
+  return !(aFlags & ~(eCONTENT | eELEMENT | eMATHML));
+}
+
+void
+nsMathMLElement::SetIncrementScriptLevel(PRBool aIncrementScriptLevel,
+                                         PRBool aNotify)
+{
+  if (aIncrementScriptLevel == mIncrementScriptLevel)
+    return;
+  mIncrementScriptLevel = aIncrementScriptLevel;
+
+  NS_ASSERTION(aNotify, "We always notify!");
+
+  nsIDocument* doc = GetCurrentDoc();
+  if (!doc)
+    return;
+
+  mozAutoDocUpdate upd(doc, UPDATE_CONTENT_STATE, PR_TRUE);
+  doc->ContentStatesChanged(this, nsnull,
+                            NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL);
+}
new file mode 100644
--- /dev/null
+++ b/content/mathml/content/src/nsMathMLElement.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MathML DOM code.
+ *
+ * The Initial Developer of the Original Code is
+ * mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Vlad Sukhoy <vladimir.sukhoy@gmail.com> (original developer)
+ *    Daniel Kraft <d@domob.eu> (nsMathMLElement patch, attachment 262925) 
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsMathMLElement_h
+#define nsMathMLElement_h
+
+#include "nsMappedAttributeElement.h"
+#include "nsIDOMElement.h"
+
+class nsCSSValue;
+
+typedef nsMappedAttributeElement nsMathMLElementBase;
+
+/*
+ * The base class for MathML elements.
+ */
+class nsMathMLElement : public nsMathMLElementBase
+                      , public nsIDOMElement
+{
+public:
+  nsMathMLElement(nsINodeInfo* aNodeInfo)
+    : nsMathMLElementBase(aNodeInfo), mIncrementScriptLevel(PR_FALSE)
+  {}
+
+  // Implementation of nsISupports is inherited from nsMathMLElementBase
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // Forward implementations of parent interfaces of nsMathMLElement to 
+  // our base class
+  NS_FORWARD_NSIDOMNODE(nsMathMLElementBase::)
+  NS_FORWARD_NSIDOMELEMENT(nsMathMLElementBase::)
+
+  nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                      nsIContent* aBindingParent,
+                      PRBool aCompileEventHandlers);
+
+  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult);
+
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+
+  static PRBool ParseNumericValue(const nsString& aString,
+                                  nsCSSValue&     aCSSValue,
+                                  PRBool          aRequireLengthUnit);
+
+  static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes, 
+                                      nsRuleData* aRuleData);
+  
+  nsresult Clone(nsINodeInfo*, nsINode**) const;
+  virtual PRInt32 IntrinsicState() const;
+  virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
+
+  // Set during reflow as necessary. Does a style change notification,
+  // aNotify must be true.
+  void SetIncrementScriptLevel(PRBool aIncrementScriptLevel, PRBool aNotify);
+  PRBool GetIncrementScriptLevel() const {
+    return mIncrementScriptLevel;
+  }
+
+private:
+  PRPackedBool mIncrementScriptLevel;
+};
+
+#endif // nsMathMLElement_h
new file mode 100644
--- /dev/null
+++ b/content/mathml/content/src/nsMathMLElementFactory.cpp
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is MathML DOM code.
+ *
+ * The Initial Developer of the Original Code is
+ * mozilla.org.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Vlad Sukhoy <vladimir.sukhoy@gmail.com> (original developer)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsContentCreatorFunctions.h"
+#include "nsGkAtoms.h"
+#include "nsIDocument.h"
+#include "nsMathMLElement.h"
+
+// MathML Element Factory (declared in nsContentCreatorFunctions.h)
+nsresult
+NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo)
+{
+  aNodeInfo->SetIDAttributeAtom(nsGkAtoms::id);
+
+  nsMathMLElement* it = new (aNodeInfo) nsMathMLElement(aNodeInfo);
+  NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY);
+
+  NS_ADDREF(*aResult = it);
+  return NS_OK;
+}
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -904,38 +904,16 @@ nsXMLContentSink::MaybeStartLayout(PRBoo
   // XXXbz if aIgnorePendingSheets is true, what should we do when
   // mXSLTProcessor or CanStillPrettyPrint()?
   if (mLayoutStarted || mXSLTProcessor || CanStillPrettyPrint()) {
     return;
   }
   StartLayout(aIgnorePendingSheets);
 }
 
-#ifdef MOZ_MATHML
-////////////////////////////////////////////////////////////////////////
-// MathML Element Factory - temporary location for bug 132844
-// Will be factored out post 1.0
-
-nsresult
-NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo)
-{
-  static const char kMathMLStyleSheetURI[] = "resource://gre/res/mathml.css";
-
-  aNodeInfo->SetIDAttributeAtom(nsGkAtoms::id);
-  
-  // this bit of code is to load mathml.css on demand
-  nsIDocument *doc = aNodeInfo->GetDocument();
-  if (doc)
-    doc->EnsureCatalogStyleSheet(kMathMLStyleSheetURI);
-
-  return NS_NewXMLElement(aResult, aNodeInfo);
-}
-#endif // MOZ_MATHML
-
-
 ////////////////////////////////////////////////////////////////////////
 
 PRBool
 nsXMLContentSink::SetDocElement(PRInt32 aNameSpaceID,
                                 nsIAtom* aTagName,
                                 nsIContent *aContent)
 {
   if (mDocElement)
--- a/dom/src/base/nsHistory.cpp
+++ b/dom/src/base/nsHistory.cpp
@@ -290,17 +290,17 @@ nsHistory::Go()
 
       nsCOMPtr<nsIDocument> doc =
         do_QueryInterface(window->GetExtantDocument());
 
       nsIPresShell *shell;
       nsPresContext *pcx;
       if (doc && (shell = doc->GetPrimaryShell()) &&
           (pcx = shell->GetPresContext())) {
-        pcx->ClearStyleDataAndReflow();
+        pcx->RebuildAllStyleData();
       }
 
       return NS_OK;
     }
   }
 
   return Go(delta);
 }
--- a/dom/src/base/nsLocation.cpp
+++ b/dom/src/base/nsLocation.cpp
@@ -887,17 +887,17 @@ nsLocation::Reload()
     // reflow bugs, and this should have the same effect.
 
     nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
 
     nsIPresShell *shell;
     nsPresContext *pcx;
     if (doc && (shell = doc->GetPrimaryShell()) &&
         (pcx = shell->GetPresContext())) {
-      pcx->ClearStyleDataAndReflow();
+      pcx->RebuildAllStyleData();
     }
 
     return NS_OK;
   }
 
   PRBool force_get = PR_FALSE;
 
   PRUint32 argc;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1830,16 +1830,17 @@ nsCSSFrameConstructor::nsCSSFrameConstru
   , mDocElementContainingBlock(nsnull)
   , mGfxScrollFrame(nsnull)
   , mPageSequenceFrame(nsnull)
   , mUpdateCount(0)
   , mQuotesDirty(PR_FALSE)
   , mCountersDirty(PR_FALSE)
   , mInitialContainingBlockIsAbsPosContainer(PR_FALSE)
   , mIsDestroyingFrameTree(PR_FALSE)
+  , mRebuildAllStyleData(PR_FALSE)
 {
   if (!gGotXBLFormPrefs) {
     gGotXBLFormPrefs = PR_TRUE;
 
     gUseXBLForms =
       nsContentUtils::GetBoolPref("nglayout.debug.enable_xbl_forms");
   }
 
@@ -13259,16 +13260,49 @@ nsCSSFrameConstructor::ProcessOneRestyle
   if (aRestyleHint & eReStyle_LaterSiblings) {
     RestyleLaterSiblings(aContent);
   }
 }
 
 #define RESTYLE_ARRAY_STACKSIZE 128
 
 void
+nsCSSFrameConstructor::RebuildAllStyleData()
+{
+  mRebuildAllStyleData = PR_FALSE;
+
+  if (!mPresShell || !mPresShell->GetRootFrame())
+    return;
+
+  // Tell the style set to get the old rule tree out of the way
+  // so we can recalculate while maintaining rule tree immutability
+  nsresult rv = mPresShell->StyleSet()->BeginReconstruct();
+  if (NS_FAILED(rv))
+    return;
+
+  // Recalculate all of the style contexts for the document
+  // Note that we can ignore the return value of ComputeStyleChangeFor
+  // because we never need to reframe the root frame
+  // XXX This could be made faster by not rerunning rule matching
+  // (but note that nsPresShell::SetPreferenceStyleRules currently depends
+  // on us re-running rule matching here
+  nsStyleChangeList changeList;
+  mPresShell->FrameManager()->ComputeStyleChangeFor(mPresShell->GetRootFrame(),
+                                                    &changeList, nsChangeHint(0));
+  // Process the required changes
+  ProcessRestyledFrames(changeList);
+  // Tell the style set it's safe to destroy the old rule tree.  We
+  // must do this after the ProcessRestyledFrames call in case the
+  // change list has frame reconstructs in it (since frames to be
+  // reconstructed will still have their old style context pointers
+  // until they are destroyed).
+  mPresShell->StyleSet()->EndReconstruct();
+}
+
+void
 nsCSSFrameConstructor::ProcessPendingRestyles()
 {
   PRUint32 count = mPendingRestyles.Count();
   if (!count) {
     // Nothing to do
     return;
   }
   
@@ -13304,16 +13338,22 @@ nsCSSFrameConstructor::ProcessPendingRes
                       currentRestyle->mChangeHint);
   }
 
   EndUpdate();
 
 #ifdef DEBUG
   mPresShell->VerifyStyleTree();
 #endif
+
+  if (mRebuildAllStyleData) {
+    // We probably wasted a lot of work up above, but this seems safest
+    // and it should be rarely used.
+    RebuildAllStyleData();
+  }
 }
 
 void
 nsCSSFrameConstructor::PostRestyleEvent(nsIContent* aContent,
                                         nsReStyleHint aRestyleHint,
                                         nsChangeHint aMinChangeHint)
 {
   if (aRestyleHint == 0 && !aMinChangeHint) {
@@ -13341,16 +13381,24 @@ nsCSSFrameConstructor::PostRestyleEvent(
       NS_WARNING("failed to dispatch restyle event");
       // XXXbz and what?
     } else {
       mRestyleEvent = ev;
     }
   }
 }
 
+void
+nsCSSFrameConstructor::PostRebuildAllStyleDataEvent()
+{
+  mRebuildAllStyleData = PR_TRUE;
+  // Get a restyle event posted if necessary
+  mPresShell->ReconstructStyleDataInternal();
+}
+
 NS_IMETHODIMP nsCSSFrameConstructor::RestyleEvent::Run()
 {
   if (!mConstructor)
     return NS_OK;  // event was revoked
 
   // Make sure that any restyles that happen from now on will go into
   // a new event.
   mConstructor->mRestyleEvent.Forget();  
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -172,20 +172,34 @@ private:
 
 public:
   // Note: It's the caller's responsibility to make sure to wrap a
   // ProcessPendingRestyles call in a view update batch.
   // This function does not call ProcessAttachedQueue() on the binding manager.
   // If the caller wants that to happen synchronously, it needs to handle that
   // itself.
   void ProcessPendingRestyles();
+  
+  void RebuildAllStyleData();
 
   void PostRestyleEvent(nsIContent* aContent, nsReStyleHint aRestyleHint,
                         nsChangeHint aMinChangeHint);
 
+  /**
+   * Asynchronously clear style data from the root frame downwards and ensure
+   * it will all be rebuilt. This is safe to call anytime; it will schedule
+   * a restyle and take effect next time style changes are flushed.
+   * This method is used to recompute the style data when some change happens
+   * outside of any style rules, like a color preference change or a change
+   * in a system font size, or to fix things up when an optimization in the
+   * style data has become invalid. We assume that the root frame will not
+   * need to be reframed.
+   */
+  void PostRebuildAllStyleDataEvent();
+
   // Request to create a continuing frame
   nsresult CreateContinuingFrame(nsPresContext* aPresContext,
                                  nsIFrame*       aFrame,
                                  nsIFrame*       aParentFrame,
                                  nsIFrame**      aContinuingFrame,
                                  PRBool          aIsFluid = PR_TRUE);
 
   // Copy over fixed frames from aParentFrame's prev-in-flow
@@ -1129,16 +1143,17 @@ private:
   nsIFrame*           mPageSequenceFrame;
   nsQuoteList         mQuoteList;
   nsCounterManager    mCounterManager;
   PRUint16            mUpdateCount;
   PRPackedBool        mQuotesDirty : 1;
   PRPackedBool        mCountersDirty : 1;
   PRPackedBool        mInitialContainingBlockIsAbsPosContainer : 1;
   PRPackedBool        mIsDestroyingFrameTree : 1;
+  PRPackedBool        mRebuildAllStyleData : 1;
 
   nsRevocableEventPtr<RestyleEvent> mRestyleEvent;
 
   nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
 
   nsDataHashtable<nsISupportsHashKey, RestyleData> mPendingRestyles;
 
   static nsIXBLService * gXBLService;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -696,48 +696,16 @@ nsPresContext::GetUserPreferences()
   SET_BIDI_OPTION_CHARACTERSET(bidiOptions, prefInt);
 
   // We don't need to force reflow: either we are initializing a new
   // prescontext or we are being called from UpdateAfterPreferencesChanged()
   // which triggers a reflow anyway.
   SetBidi(bidiOptions, PR_FALSE);
 }
 
-void
-nsPresContext::ClearStyleDataAndReflow()
-{
-  // This method is used to recompute the style data when some change happens
-  // outside of any style rules, like a color preference change or a change
-  // in a system font size
-  if (mShell && mShell->GetRootFrame()) {
-    // Tell the style set to get the old rule tree out of the way
-    // so we can recalculate while maintaining rule tree immutability
-    nsresult rv = mShell->StyleSet()->BeginReconstruct();
-    if (NS_FAILED(rv))
-      return;
-    // Recalculate all of the style contexts for the document
-    // Note that we can ignore the return value of ComputeStyleChangeFor
-    // because we never need to reframe the root frame
-    // XXX This could be made faster by not rerunning rule matching
-    // (but note that nsPresShell::SetPreferenceStyleRules currently depends
-    // on us re-running rule matching here
-    nsStyleChangeList changeList;
-    mShell->FrameManager()->ComputeStyleChangeFor(mShell->GetRootFrame(),
-                                                  &changeList, nsChangeHint(0));
-    // Tell the frame constructor to process the required changes
-    mShell->FrameConstructor()->ProcessRestyledFrames(changeList);
-    // Tell the style set it's safe to destroy the old rule tree.  We
-    // must do this after the ProcessRestyledFrames call in case the
-    // change list has frame reconstructs in it (since frames to be
-    // reconstructed will still have their old style context pointers
-    // until they are destroyed).
-    mShell->StyleSet()->EndReconstruct();
-  }
-}
-
 static const char sMinFontSizePref[] = "browser.display.auto_quality_min_font_size";
 
 void
 nsPresContext::PreferenceChanged(const char* aPrefName)
 {
   if (!nsCRT::strcmp(aPrefName, "layout.css.dpi")) {
     PRInt32 oldAppUnitsPerDevPixel = AppUnitsPerDevPixel();
     if (mDeviceContext->CheckDPIChange() && mShell) {
@@ -750,23 +718,23 @@ nsPresContext::PreferenceChanged(const c
       vm->GetWindowDimensions(&oldWidthAppUnits, &oldHeightAppUnits);
       float oldWidthDevPixels = oldWidthAppUnits/oldAppUnitsPerDevPixel;
       float oldHeightDevPixels = oldHeightAppUnits/oldAppUnitsPerDevPixel;
 
       nscoord width = NSToCoordRound(oldWidthDevPixels*AppUnitsPerDevPixel());
       nscoord height = NSToCoordRound(oldHeightDevPixels*AppUnitsPerDevPixel());
       vm->SetWindowDimensions(width, height);
 
-      ClearStyleDataAndReflow();
+      RebuildAllStyleData();
     }
     return;
   }
   if (!nsCRT::strcmp(aPrefName, sMinFontSizePref)) {
     mAutoQualityMinFontSizePixelsPref = nsContentUtils::GetIntPref(sMinFontSizePref);
-    ClearStyleDataAndReflow();
+    RebuildAllStyleData();
     return;
   }
   // we use a zero-delay timer to coalesce multiple pref updates
   if (!mPrefChangedTimer)
   {
     mPrefChangedTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (!mPrefChangedTimer)
       return;
@@ -791,17 +759,17 @@ nsPresContext::UpdateAfterPreferencesCha
   GetUserPreferences();
 
   // update the presShell: tell it to set the preference style rules up
   if (mShell) {
     mShell->SetPreferenceStyleRules(PR_TRUE);
   }
 
   mDeviceContext->FlushFontCache();
-  ClearStyleDataAndReflow();
+  RebuildAllStyleData();
 }
 
 nsresult
 nsPresContext::Init(nsIDeviceContext* aDeviceContext)
 {
   NS_ASSERTION(!(mInitialized == PR_TRUE), "attempt to reinit pres context");
   NS_ENSURE_ARG(aDeviceContext);
 
@@ -977,18 +945,17 @@ nsPresContext::UpdateCharSet(const nsAFl
 NS_IMETHODIMP
 nsPresContext::Observe(nsISupports* aSubject, 
                         const char* aTopic,
                         const PRUnichar* aData)
 {
   if (!nsCRT::strcmp(aTopic, "charset")) {
     UpdateCharSet(NS_LossyConvertUTF16toASCII(aData));
     mDeviceContext->FlushFontCache();
-    ClearStyleDataAndReflow();
-
+    RebuildAllStyleData();
     return NS_OK;
   }
 
   NS_WARNING("unrecognized topic in nsPresContext::Observe");
   return NS_ERROR_FAILURE;
 }
 
 // We may want to replace this with something faster, maybe caching the root prescontext
@@ -1169,17 +1136,17 @@ nsPresContext::SetFullZoom(float aZoom)
   float oldWidthDevPixels = oldWidthAppUnits / float(mCurAppUnitsPerDevPixel);
   float oldHeightDevPixels = oldHeightAppUnits / float(mCurAppUnitsPerDevPixel);
   if (mDeviceContext->SetPixelScale(aZoom)) {
     mDeviceContext->FlushFontCache();
   }
   mFullZoom = aZoom;
   GetViewManager()->SetWindowDimensions(NSToCoordRound(oldWidthDevPixels*AppUnitsPerDevPixel()),
                                         NSToCoordRound(oldHeightDevPixels*AppUnitsPerDevPixel()));
-  ClearStyleDataAndReflow();
+  RebuildAllStyleData();
   mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
 }
 
 imgIRequest*
 nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
 {
   // look and see if we have a loader for the target frame.
   nsCOMPtr<nsImageLoader> loader;
@@ -1279,24 +1246,24 @@ nsPresContext::GetBidiUtils()
 {
   if (!mBidiUtils)
     mBidiUtils = new nsBidiPresUtils;
 
   return mBidiUtils;
 }
 
 void
-nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow)
+nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceRestyle)
 {
   // Don't do all this stuff unless the options have changed.
   if (aSource == GetBidi()) {
     return;
   }
 
-  NS_ASSERTION(!(aForceReflow && (GetBidi() == 0)), 
+  NS_ASSERTION(!(aForceRestyle && (GetBidi() == 0)), 
                "ForceReflow on new prescontext");
 
   Document()->SetBidiOptions(aSource);
   if (IBMBIDI_TEXTDIRECTION_RTL == GET_BIDI_OPTION_DIRECTION(aSource)
       || IBMBIDI_NUMERAL_HINDI == GET_BIDI_OPTION_NUMERAL(aSource)) {
     SetBidiEnabled(PR_TRUE);
   }
   if (IBMBIDI_TEXTTYPE_VISUAL == GET_BIDI_OPTION_TEXTTYPE(aSource)) {
@@ -1306,18 +1273,18 @@ nsPresContext::SetBidi(PRUint32 aSource,
     SetVisualMode(PR_FALSE);
   }
   else {
     nsIDocument* doc = mShell->GetDocument();
     if (doc) {
       SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
     }
   }
-  if (aForceReflow) {
-    ClearStyleDataAndReflow();
+  if (aForceRestyle) {
+    RebuildAllStyleData();
   }
 }
 
 PRUint32
 nsPresContext::GetBidi() const
 {
   return Document()->GetBidiOptions();
 }
@@ -1368,17 +1335,17 @@ nsPresContext::ThemeChangedInternal()
     mLookAndFeel->LookAndFeelChanged();
     sLookAndFeelChanged = PR_FALSE;
   }
 
   // We have to clear style data because the assumption of style rule
   // immutability has been violated since any style rule that uses
   // system colors or fonts (and probably -moz-appearance as well) has
   // changed.
-  nsPresContext::ClearStyleDataAndReflow();
+  RebuildAllStyleData();
 }
 
 void
 nsPresContext::SysColorChanged()
 {
   if (!mPendingSysColorChanged) {
     sLookAndFeelChanged = PR_TRUE;
     nsCOMPtr<nsIRunnable> ev =
@@ -1404,17 +1371,31 @@ nsPresContext::SysColorChangedInternal()
   // Reset default background and foreground colors for the document since
   // they may be using system colors
   GetDocumentColorPreferences();
 
   // We need to do a full reflow (and view update) here. Clearing the style
   // data without reflowing/updating views will lead to incorrect change hints
   // later, because when generating change hints, any style structs which have
   // been cleared and not reread are assumed to not be used at all.
-  ClearStyleDataAndReflow();
+  // XXXroc not sure what to make of the above comment, because we don't reflow
+  // synchronously here
+  RebuildAllStyleData();
+}
+
+void
+nsPresContext::RebuildAllStyleData()
+{
+  mShell->FrameConstructor()->RebuildAllStyleData();
+}
+
+void
+nsPresContext::PostRebuildAllStyleDataEvent()
+{
+  mShell->FrameConstructor()->PostRebuildAllStyleDataEvent();
 }
 
 void
 nsPresContext::SetPaginatedScrolling(PRBool aPaginated)
 {
   if (mType == eContext_PrintPreview || mType == eContext_PageLayout)
     mCanPaginatedScroll = aPaginated;
 }
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -196,16 +196,19 @@ public:
   nsIViewManager* GetViewManager() { return GetPresShell()->GetViewManager(); } 
 #ifdef _IMPL_NS_LAYOUT
   nsStyleSet* StyleSet() { return GetPresShell()->StyleSet(); }
 
   nsFrameManager* FrameManager()
     { return GetPresShell()->FrameManager(); } 
 #endif
 
+  void RebuildAllStyleData();
+  void PostRebuildAllStyleDataEvent();
+
   /**
    * Access compatibility mode for this context.  This is the same as
    * our document's compatibility mode.
    */
   nsCompatibility CompatibilityMode() const {
     return Document()->GetCompatibilityMode();
   }
   /**
@@ -233,21 +236,16 @@ public:
    */
   nsILookAndFeel* LookAndFeel() { return mLookAndFeel; }
 
   /** 
    * Get medium of presentation
    */
   nsIAtom* Medium() { return mMedium; }
 
-  /**
-   * Clear style data from the root frame downwards, and reflow.
-   */
-  NS_HIDDEN_(void) ClearStyleDataAndReflow();
-
   void* AllocateFromShell(size_t aSize)
   {
     if (mShell)
       return mShell->AllocateFrame(aSize);
     return nsnull;
   }
 
   void FreeToShell(size_t aSize, void* aFreeChunk)
@@ -463,17 +461,17 @@ public:
 
   nsIDeviceContext* DeviceContext() { return mDeviceContext; }
   nsIEventStateManager* EventStateManager() { return mEventManager; }
   nsIAtom* GetLangGroup() { return mLangGroup; }
 
   float TextZoom() { return mTextZoom; }
   void SetTextZoom(float aZoom) {
     mTextZoom = aZoom;
-    ClearStyleDataAndReflow();
+    RebuildAllStyleData();
   }
 
   float GetFullZoom() { return mFullZoom; }
   void SetFullZoom(float aZoom);
 
   nscoord GetAutoQualityMinFontSize() {
     return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
   }
@@ -632,17 +630,17 @@ public:
    * Get a Bidi presentation utilities object
    */
   NS_HIDDEN_(nsBidiPresUtils*) GetBidiUtils();
 
   /**
    * Set the Bidi options for the presentation context
    */  
   NS_HIDDEN_(void) SetBidi(PRUint32 aBidiOptions,
-                           PRBool aForceReflow = PR_FALSE);
+                           PRBool aForceRestyle = PR_FALSE);
 
   /**
    * Get the Bidi options for the presentation context
    * Not inline so consumers of nsPresContext are not forced to
    * include nsIDocument.
    */  
   NS_HIDDEN_(PRUint32) GetBidi() const;
 
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -423,16 +423,20 @@
 #define NS_STYLE_FONT_DESKTOP										10
 #define NS_STYLE_FONT_INFO											11
 #define NS_STYLE_FONT_DIALOG										12
 #define NS_STYLE_FONT_BUTTON										13
 #define NS_STYLE_FONT_PULL_DOWN_MENU						14
 #define NS_STYLE_FONT_LIST											15
 #define NS_STYLE_FONT_FIELD											16
 
+// defaults per MathML spec
+#define NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER 0.71f
+#define NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT 8
+
 // See nsStylePosition::mWidth, mMinWidth, mMaxWidth
 #define NS_STYLE_WIDTH_MAX_CONTENT              0
 #define NS_STYLE_WIDTH_MIN_CONTENT              1
 #define NS_STYLE_WIDTH_FIT_CONTENT              2
 #define NS_STYLE_WIDTH_AVAILABLE                3
 
 // See nsStylePosition.mPosition
 #define NS_STYLE_POSITION_STATIC                0
--- a/layout/build/Makefile.in
+++ b/layout/build/Makefile.in
@@ -173,33 +173,34 @@ REQUIRES += \
       $(NULL)
 SHARED_LIBRARY_LIBS += ../inspector/src/$(LIB_PREFIX)inspector_s.$(LIB_SUFFIX)
 else
 DEFINES += -DMOZ_NO_INSPECTOR_APIS
 endif
 
 ifdef MOZ_MATHML
 SHARED_LIBRARY_LIBS += \
-                ../mathml/content/src/$(LIB_PREFIX)gkmathmlcon_s.$(LIB_SUFFIX) \
-                ../mathml/base/src/$(LIB_PREFIX)gkmathmlbase_s.$(LIB_SUFFIX) \
-                $(NULL)
+		../mathml/content/src/$(LIB_PREFIX)gkmathmlcon_s.$(LIB_SUFFIX) \
+		../mathml/base/src/$(LIB_PREFIX)gkmathmlbase_s.$(LIB_SUFFIX) \
+		$(DEPTH)/content/mathml/content/src/$(LIB_PREFIX)gkcontentmathml_s.$(LIB_SUFFIX) \
+		$(NULL)
 endif
 
 ifdef MOZ_XTF
 SHARED_LIBRARY_LIBS += \
 		$(DEPTH)/content/xtf/src/$(LIB_PREFIX)gkcontentxtf_s.$(LIB_SUFFIX) \
 		$(NULL)
 endif
 
 ifdef MOZ_SVG
 SHARED_LIBRARY_LIBS += \
-                ../svg/base/src/$(LIB_PREFIX)gksvgbase_s.$(LIB_SUFFIX) \
+		../svg/base/src/$(LIB_PREFIX)gksvgbase_s.$(LIB_SUFFIX) \
 		$(DEPTH)/content/svg/document/src/$(LIB_PREFIX)gkconsvgdoc_s.$(LIB_SUFFIX) \
 		$(DEPTH)/content/svg/content/src/$(LIB_PREFIX)gkcontentsvg_s.$(LIB_SUFFIX) \
-                $(NULL)
+		$(NULL)
 endif
 
 ifdef MOZ_PLAINTEXT_EDITOR_ONLY
 DEFINES += -DMOZILLA_PLAINTEXT_EDITOR_ONLY
 else
 SHARED_LIBRARY_LIBS += \
 	$(DEPTH)/editor/libeditor/html/$(LIB_PREFIX)htmleditor_s.$(LIB_SUFFIX) \
 	$(DEPTH)/editor/txtsvc/src/$(LIB_PREFIX)txtsvc_s.$(LIB_SUFFIX) \
--- a/layout/mathml/base/src/Makefile.in
+++ b/layout/mathml/base/src/Makefile.in
@@ -71,16 +71,18 @@ REQUIRES	= xpcom \
 		  $(NULL)
 
 LOCAL_INCLUDES = \
 	-I$(srcdir)/../../../style \
 	-I$(srcdir)/../../../base \
 	-I$(srcdir)/../../../generic \
 	-I$(srcdir)/../../../tables \
 	-I$(srcdir)/../../content/src \
+	-I$(topsrcdir)/content/base/src \
+	-I$(topsrcdir)/content/mathml/content/src \
 	-I$(srcdir)/../../../xul/base/src \
 	$(NULL)
 
 CPPSRCS =         nsMathMLChar.cpp		        \
                   nsMathMLFrame.cpp		\
                   nsMathMLContainerFrame.cpp		\
                   nsMathMLForeignFrameWrapper.cpp		\
                   nsMathMLTokenFrame.cpp		\
--- a/layout/mathml/base/src/nsIMathMLFrame.h
+++ b/layout/mathml/base/src/nsIMathMLFrame.h
@@ -221,116 +221,74 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent) = 0;
 
   NS_IMETHOD
   TransmitAutomaticData() = 0;
 
  /* UpdatePresentationData :
-  * Increments the scriptlevel of the frame, and updates its displaystyle and
-  * compression flags. The displaystyle flag of an environment gets updated
-  * according to the MathML specification. A frame becomes "compressed" (or
-  * "cramped") according to TeX rendering rules (TeXBook, Ch.17, p.140-141).
+  * Updates the frame's displaystyle and compression flags. The displaystyle
+  * flag of an environment gets updated according to the MathML specification.
+  * A frame becomes "compressed" (or "cramped") according to TeX rendering
+  * rules (TeXBook, Ch.17, p.140-141).
   *
   * Note that <mstyle> is the only tag which allows to set
-  * <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
-  * to reset or increment the scriptlevel in a manual way. 
+  * <mstyle displaystyle="true|false">
   * Therefore <mstyle> has its own peculiar version of this method.
   *
-  * @param aScriptLevelIncrement [in]
-  *        The value with which to increment mScriptLevel in the frame.
-  *
   * @param aFlagsValues [in]
   *        The new values (e.g., display, compress) that are going to be
   *        updated.
   *
   * @param aWhichFlags [in]
   *        The flags that are relevant to this call. Since not all calls
   *        are meant to update all flags at once, aWhichFlags is used
   *        to distinguish flags that need to retain their existing values
   *        from flags that need to be turned on (or turned off). If a bit
   *        is set in aWhichFlags, then the corresponding value (which
   *        can be 0 or 1) is taken from aFlagsValues and applied to the
   *        frame. Therefore, by setting their bits in aWhichFlags, and
   *        setting their desired values in aFlagsValues, it is possible to
   *        update some flags in the frame, leaving the other flags unchanged.
   */
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
+  UpdatePresentationData(PRUint32        aFlagsValues,
                          PRUint32        aWhichFlags) = 0;
 
  /* UpdatePresentationDataFromChildAt :
-  * Increments the scriplevel and sets the displaystyle and compression flags
-  * on the whole tree. For child frames at aFirstIndex up to aLastIndex, this
-  * method sets their displaystyle and compression flags, and increment their
-  * mScriptLevel with aScriptLevelIncrement. The update is propagated down 
-  * the subtrees of each of these child frames. 
+  * Sets displaystyle and compression flags on the whole tree. For child frames
+  * at aFirstIndex up to aLastIndex, this method sets their displaystyle and
+  * compression flags. The update is propagated down the subtrees of each of
+  * these child frames. 
   *
   * Note that <mstyle> is the only tag which allows
-  * <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
-  * to reset or increment the scriptlevel in a manual way.
+  * <mstyle displaystyle="true|false">
   * Therefore <mstyle> has its own peculiar version of this method.
   *
   * @param aFirstIndex [in]
   *        Index of the first child from where the update is propagated.
   *
   * @param aLastIndex [in]
   *        Index of the last child where to stop the update.
   *        A value of -1 means up to last existing child.
   *
-  * @param aScriptLevelIncrement [in]
-  *        The value with which to increment mScriptLevel in the whole sub-trees.
-  *
   * @param aFlagsValues [in]
   *        The new values (e.g., display, compress) that are going to be
   *        assigned in the whole sub-trees.
   *
   * @param aWhichFlags [in]
   *        The flags that are relevant to this call. See UpdatePresentationData()
   *        for more details about this parameter.
   */
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aWhichFlags) = 0;
-
- /* ReResolveScriptStyle :
-  * During frame construction, the Style System gives us style contexts in
-  * which the sizes of the fonts are not suitable for scripting elements.
-  * Our expected behavior is that, when given the markup <mtag>base arguments</mtag>,
-  * we want to render the 'base' in a normal size, and the 'arguments' in a smaller
-  * size. This is a common functionality to tags like msub, msup, msubsup, mover,
-  * munder, munderover, mmultiscripts. Moreover, we want the reduction of the font
-  * size to happen in a top-down manner within the hierarchies of sub-expressions;
-  * and more importantly, we don't want the sizes to keep decreasing up to a point
-  * where the scripts become unreadably small.
-  *
-  * In general, this scaling effet arises when the scriptlevel changes between a
-  * parent and a child. Whenever the scriptlevel changes, either automatically or
-  * by being explicitly incremented, decremented, or set, the current font size has
-  * to be multiplied by the predefined value of 'scriptsizemultiplier' to the power
-  * of the change in the scriptlevel, and this scaling effect (downwards or upwards)
-  * has to be propagated down the subtrees, with the caveat that the font size is
-  * never allowed to go below the predefined value of 'scriptminsize' within a 
-  * sub-expression.
-  *
-  * ReResolveScriptStyle() will walk a subtree to cause this mathml-specific behavior
-  * to happen. The method is recursive and only a top-level parent wishing to reflect
-  * the changes in its children needs to call to the method.
-  *
-  * This function is *very* expensive. Unfortunately, there isn't much
-  * to do about it at the moment. For background on the problem @see 
-  * http://groups.google.com/groups?selm=3A9192B5.D22B6C38%40maths.uq.edu.au
-  */
-  NS_IMETHOD
-  ReResolveScriptStyle(PRInt32 aParentScriptLevel) = 0;
 };
 
 // struct used by a container frame to keep track of its embellishments.
 // By convention, the data that we keep here is bubbled from the embellished
 // hierarchy, and it remains unchanged unless we have to recover from a change
 // that occurs in the embellished hierarchy. The struct remains in its nil
 // state in those frames that are not part of the embellished hierarchy.
 struct nsEmbellishData {
@@ -374,25 +332,20 @@ struct nsPresentationData {
   // handy pointer on our base child (the 'nucleus' in TeX), but it may be
   // null here (e.g., tags like <mrow>, <mfrac>, <mtable>, etc, won't
   // pick a particular child in their child list to be the base)
   nsIFrame* baseFrame;
 
   // up-pointer on the mstyle frame, if any, that defines the scope
   nsIFrame* mstyle;
 
-  // level of nested frames within: msub, msup, msubsup, munder,
-  // mover, munderover, mmultiscripts, mfrac, mroot, mtable.
-  PRInt32 scriptLevel;
-
   nsPresentationData() {
     flags = 0;
     baseFrame = nsnull;
     mstyle = nsnull;
-    scriptLevel = 0;
   }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIMathMLFrame, NS_IMATHMLFRAME_IID)
 
 
 // ==========================================================================
 // Bits used for the presentation flags -- these bits are set
@@ -418,22 +371,16 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMathMLF
 
 // This bit is set if the frame will fire a horizontal stretch
 // command on all its (non-empty) children.
 // Tags like munder, mover, munderover, will fire a 
 // horizontal stretch command on all their non-empty children
 #define NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY   0x00000008
 
 // This bit is set if the frame has the explicit attribute
-// scriptlevel="value". It is only relevant to <mstyle> because that's
-// the only tag where the attribute is allowed by the spec.
-// Note: the flag is not set if the <mstyle> instead has an incremental +/-value.
-#define NS_MATHML_EXPLICIT_SCRIPTLEVEL                0x00000010
-
-// This bit is set if the frame has the explicit attribute
 // displaystyle="true" or "false". It is only relevant to <mstyle> and <mtable>
 // because they are the only tags where the attribute is allowed by the spec.
 #define NS_MATHML_EXPLICIT_DISPLAYSTYLE               0x00000020
 
 // This bit is set when the frame cannot be formatted due to an
 // error (e.g., invalid markup such as a <msup> without an overscript).
 // When set, a visual feedback will be provided to the user.
 #define NS_MATHML_ERROR                               0x80000000
@@ -459,19 +406,16 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIMathMLF
   (NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY))
 
 #define NS_MATHML_WILL_STRETCH_ALL_CHILDREN_HORIZONTALLY(_flags) \
   (NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY))
 
 #define NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(_flags) \
   (NS_MATHML_EXPLICIT_DISPLAYSTYLE == ((_flags) & NS_MATHML_EXPLICIT_DISPLAYSTYLE))
 
-#define NS_MATHML_HAS_EXPLICIT_SCRIPTLEVEL(_flags) \
-  (NS_MATHML_EXPLICIT_SCRIPTLEVEL == ((_flags) & NS_MATHML_EXPLICIT_SCRIPTLEVEL))
-
 #define NS_MATHML_HAS_ERROR(_flags) \
   (NS_MATHML_ERROR == ((_flags) & NS_MATHML_ERROR))
 
 #define NS_MATHML_STRETCH_WAS_DONE(_flags) \
   (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE))
 
 #define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \
   (NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS))
--- a/layout/mathml/base/src/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLContainerFrame.cpp
@@ -59,16 +59,17 @@
 #include "nsGkAtoms.h"
 #include "nsMathMLParts.h"
 #include "nsMathMLChar.h"
 #include "nsMathMLContainerFrame.h"
 #include "nsAutoPtr.h"
 #include "nsStyleSet.h"
 #include "nsDisplayList.h"
 #include "nsCSSFrameConstructor.h"
+#include "nsIReflowCallback.h"
 
 NS_DEFINE_CID(kInlineFrameCID, NS_INLINE_FRAME_CID);
 
 //
 // nsMathMLContainerFrame implementation
 //
 
 // nsISupports
@@ -564,186 +565,66 @@ nsMathMLContainerFrame::FinalizeReflow(n
  * mfrac, mroot, mtable).
  * =============================================================================
  */
 
 // helper to let the update of presentation data pass through
 // a subtree that may contain non-mathml container frames
 /* static */ void
 nsMathMLContainerFrame::PropagatePresentationDataFor(nsIFrame*       aFrame,
-                                                     PRInt32         aScriptLevelIncrement,
                                                      PRUint32        aFlagsValues,
                                                      PRUint32        aFlagsToUpdate)
 {
-  if (!aFrame || (!aFlagsToUpdate && !aScriptLevelIncrement))
+  if (!aFrame || !aFlagsToUpdate)
     return;
   nsIMathMLFrame* mathMLFrame;
   aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
   if (mathMLFrame) {
     // update
-    mathMLFrame->UpdatePresentationData(aScriptLevelIncrement, aFlagsValues,
+    mathMLFrame->UpdatePresentationData(aFlagsValues,
                                         aFlagsToUpdate);
     // propagate using the base method to make sure that the control
     // is passed on to MathML frames that may be overloading the method
     mathMLFrame->UpdatePresentationDataFromChildAt(0, -1,
-      aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+      aFlagsValues, aFlagsToUpdate);
   }
   else {
     // propagate down the subtrees
     nsIFrame* childFrame = aFrame->GetFirstChild(nsnull);
     while (childFrame) {
       PropagatePresentationDataFor(childFrame,
-        aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+        aFlagsValues, aFlagsToUpdate);
       childFrame = childFrame->GetNextSibling();
     }
   }
 }
 
 /* static */ void
 nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(nsIFrame*       aParentFrame,
                                                              PRInt32         aFirstChildIndex,
                                                              PRInt32         aLastChildIndex,
-                                                             PRInt32         aScriptLevelIncrement,
                                                              PRUint32        aFlagsValues,
                                                              PRUint32        aFlagsToUpdate)
 {
-  if (!aParentFrame || (!aFlagsToUpdate && !aScriptLevelIncrement))
+  if (!aParentFrame || !aFlagsToUpdate)
     return;
   PRInt32 index = 0;
   nsIFrame* childFrame = aParentFrame->GetFirstChild(nsnull);
   while (childFrame) {
     if ((index >= aFirstChildIndex) &&
         ((aLastChildIndex <= 0) || ((aLastChildIndex > 0) &&
          (index <= aLastChildIndex)))) {
       PropagatePresentationDataFor(childFrame,
-        aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+        aFlagsValues, aFlagsToUpdate);
     }
     index++;
     childFrame = childFrame->GetNextSibling();
   }
 }
 
-// helper to let the scriptstyle re-resolution pass through
-// a subtree that may contain non-mathml container frames.
-// This function is *very* expensive. Unfortunately, there isn't much
-// to do about it at the moment. For background on the problem @see 
-// http://groups.google.com/groups?selm=3A9192B5.D22B6C38%40maths.uq.edu.au
-/* static */ void
-nsMathMLContainerFrame::PropagateScriptStyleFor(nsIFrame*       aFrame,
-                                                PRInt32         aParentScriptLevel)
-{
-  if (!aFrame)
-    return;
-  nsIMathMLFrame* mathMLFrame;
-  aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
-  if (mathMLFrame) {
-    // we will re-resolve our style data based on our current scriptlevel
-    nsPresentationData presentationData;
-    mathMLFrame->GetPresentationData(presentationData);
-    PRInt32 gap = presentationData.scriptLevel - aParentScriptLevel;
-
-    // since we are a MathML frame, our current scriptlevel becomes
-    // the one to use when we will propagate the recursion
-    aParentScriptLevel = presentationData.scriptLevel;
-
-    nsStyleContext* oldStyleContext = aFrame->GetStyleContext();
-    nsStyleContext* parentContext = oldStyleContext->GetParent();
-
-    nsIContent* content = aFrame->GetContent();
-    if (!gap) {
-      // unset any -moz-math-font-size attribute without notifying that we want a reflow
-      // (but leave it to the primary frame to do that, a child pseudo can't overrule)
-      if (!aFrame->GetParent() || aFrame->GetParent()->GetContent() != content)
-        content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::MOZfontsize, PR_FALSE);
-    }
-    else {
-      // By default scriptminsize=8pt and scriptsizemultiplier=0.71
-      nscoord scriptminsize = aFrame->PresContext()->PointsToAppUnits(NS_MATHML_SCRIPTMINSIZE);
-      float scriptsizemultiplier = NS_MATHML_SCRIPTSIZEMULTIPLIER;
-#if 0
-       // XXX Bug 44201
-       // user-supplied scriptminsize and scriptsizemultiplier that are
-       // restricted to particular elements are not supported because our
-       // css rules are fixed in mathml.css and are applicable to all elements.
-
-       // see if there is a scriptminsize attribute on a <mstyle> that wraps us
-       GetAttribute(nsnull, presentationData.mstyle,
-                        nsGkAtoms::scriptminsize_, fontsize);
-       if (!fontsize.IsEmpty()) {
-         nsCSSValue cssValue;
-         if (ParseNumericValue(fontsize, cssValue)) {
-           nsCSSUnit unit = cssValue.GetUnit();
-           if (eCSSUnit_Number == unit)
-             scriptminsize = nscoord(float(scriptminsize) * cssValue.GetFloatValue());
-           else if (eCSSUnit_Percent == unit)
-             scriptminsize = nscoord(float(scriptminsize) * cssValue.GetPercentValue());
-           else if (eCSSUnit_Null != unit)
-             scriptminsize = CalcLength(mStyleContext, cssValue);
-         }
-       }
-#endif
-
-      // figure out the incremental factor
-      nsAutoString fontsize;
-      if (0 > gap) { // the size is going to be increased
-        if (gap < NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT)
-          gap = NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT;
-        gap = -gap;
-        scriptsizemultiplier = 1.0f / scriptsizemultiplier;
-        fontsize.AssignLiteral("-");
-      }
-      else { // the size is going to be decreased
-        if (gap > NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT)
-          gap = NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT;
-        fontsize.AssignLiteral("+");
-      }
-      fontsize.AppendInt(gap, 10);
-      // we want to make sure that the size will stay readable
-      const nsStyleFont* font = parentContext->GetStyleFont();
-      nscoord newFontSize = font->mFont.size;
-      while (0 < gap--) {
-        newFontSize = (nscoord)((float)(newFontSize) * scriptsizemultiplier);
-      }
-      if (newFontSize <= scriptminsize) {
-        fontsize.AssignLiteral("scriptminsize");
-      }
-
-      // set the -moz-math-font-size attribute without notifying that we want a reflow
-      content->SetAttr(kNameSpaceID_None, nsGkAtoms::MOZfontsize,
-                       fontsize, PR_FALSE);
-    }
-
-    // now, re-resolve the style contexts in our subtree
-    nsFrameManager *fm = aFrame->PresContext()->FrameManager();
-    nsStyleChangeList changeList;
-    fm->ComputeStyleChangeFor(aFrame, &changeList, NS_STYLE_HINT_NONE);
-#ifdef DEBUG
-    // Use the parent frame to make sure we catch in-flows and such
-    nsIFrame* parentFrame = aFrame->GetParent();
-    fm->DebugVerifyStyleTree(parentFrame ? parentFrame : aFrame);
-#endif
-  }
-
-  // recurse down the subtrees for changes that may arise deep down
-  nsIFrame* childFrame = aFrame->GetFirstChild(nsnull);
-  while (childFrame) {
-    childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
-    if (mathMLFrame) {
-      // propagate using the base method to make sure that the control
-      // is passed on to MathML frames that may be overloading the method
-      mathMLFrame->ReResolveScriptStyle(aParentScriptLevel);
-    }
-    else {
-      PropagateScriptStyleFor(childFrame, aParentScriptLevel);
-    }
-    childFrame = childFrame->GetNextSibling();
-  }
-}
-
-
 /* //////////////////
  * Frame construction
  * =============================================================================
  */
 
 
 NS_IMETHODIMP
 nsMathMLContainerFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
@@ -771,32 +652,16 @@ nsMathMLContainerFrame::BuildDisplayList
   // your mBoundingMetrics and mReference point, and set
   // mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS
   // in the Init() of your sub-class
   rv = DisplayBoundingMetrics(aBuilder, this, mReference, mBoundingMetrics, aLists);
 #endif
   return rv;
 }
 
-// This method is called in a top-down manner, as we descend the frame tree
-// during its construction
-NS_IMETHODIMP
-nsMathMLContainerFrame::Init(nsIContent*      aContent,
-                             nsIFrame*        aParent,
-                             nsIFrame*        aPrevInFlow)
-{
-  MapCommonAttributesIntoCSS(PresContext(), aContent);
-
-  // let the base class do its Init()
-  return nsHTMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
-
-  // ...We will build our automatic MathML data once the entire <math>...</math>
-  // tree is constructed.
-}
-
 // Note that this method re-builds the automatic data in the children -- not
 // in aParentFrame itself (except for those particular operations that the
 // parent frame may do in its TransmitAutomaticData()).
 /* static */ void
 nsMathMLContainerFrame::RebuildAutomaticDataForChildren(nsIFrame* aParentFrame)
 {
   // 1. As we descend the tree, make each child frame inherit data from
   // the parent
@@ -822,32 +687,27 @@ nsMathMLContainerFrame::RebuildAutomatic
 /* static */ nsresult
 nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame,
                                          nsFrameState aBits)
 {
   if (!aParentFrame)
     return NS_OK;
 
   // walk-up to the first frame that is a MathML frame, stop if we reach <math>
-  PRInt32 parentScriptLevel = 0;
   nsIFrame* frame = aParentFrame;
   while (1) {
      nsIFrame* parent = frame->GetParent();
      if (!parent || !parent->GetContent())
        break;
 
     // stop if it is a MathML frame
     nsIMathMLFrame* mathMLFrame;
     frame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
-    if (mathMLFrame) {
-      nsPresentationData parentData;
-      mathMLFrame->GetPresentationData(parentData);
-      parentScriptLevel = parentData.scriptLevel;
+    if (mathMLFrame)
       break;
-    }
 
     // stop if we reach the root <math> tag
     nsIContent* content = frame->GetContent();
     NS_ASSERTION(content, "dangling frame without a content node");
     if (!content)
       break;
     // XXXldb This should check namespaces too.
     if (content->Tag() == nsGkAtoms::math)
@@ -858,32 +718,16 @@ nsMathMLContainerFrame::ReLayoutChildren
     frame->AddStateBits(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
 
     frame = parent;
   }
 
   // re-sync the presentation data and embellishment data of our children
   RebuildAutomaticDataForChildren(frame);
 
-  // re-resolve the style data to sync any change of script sizes
-  nsIFrame* childFrame = aParentFrame->GetFirstChild(nsnull);
-  while (childFrame) {
-    nsIMathMLFrame* mathMLFrame;
-    childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
-    if (mathMLFrame) {
-      // propagate using the base method to make sure that the control
-      // is passed on to MathML frames that may be overloading the method
-      mathMLFrame->ReResolveScriptStyle(parentScriptLevel);
-    }
-    else {
-      PropagateScriptStyleFor(childFrame, parentScriptLevel);
-    }
-    childFrame = childFrame->GetNextSibling();
-  }
-
   // Ask our parent frame to reflow us
   nsIFrame* parent = frame->GetParent();
   NS_ASSERTION(parent, "No parent to pass the reflow request up to");
   if (!parent)
     return NS_OK;
 
   return frame->PresContext()->PresShell()->
     FrameNeedsReflow(frame, nsIPresShell::eStyleChange, aBits);
@@ -958,20 +802,16 @@ nsMathMLContainerFrame::RemoveFrame(nsIA
   return ChildListChanged(nsIDOMMutationEvent::REMOVAL);
 }
 
 NS_IMETHODIMP
 nsMathMLContainerFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                          nsIAtom*        aAttribute,
                                          PRInt32         aModType)
 {
-  // Attributes common to MathML tags
-  if (CommonAttributeChangedFor(PresContext(), mContent, aAttribute))
-    return NS_OK;
-
   // XXX Since they are numerous MathML attributes that affect layout, and
   // we can't check all of them here, play safe by requesting a reflow.
   // XXXldb This should only do work for attributes that cause changes!
   return PresContext()->PresShell()->
            FrameNeedsReflow(this, nsIPresShell::eStyleChange,
                             NS_FRAME_IS_DIRTY);
 }
 
@@ -1298,21 +1138,22 @@ public:
     mChildFrame = mChildFrame->GetNextSibling();
     if (!mChildFrame)
       return *this;
 
     eMathMLFrameType prevFrameType = mChildFrameType;
     InitMetricsForChild();
 
     // add inter frame spacing
+    const nsStyleFont* font = mParentFrame->GetStyleFont();
     nscoord space =
-      GetInterFrameSpacing(mParentFrame->mPresentationData.scriptLevel,
+      GetInterFrameSpacing(font->mScriptLevel,
                            prevFrameType, mChildFrameType,
                            &mFromFrameType, &mCarrySpace);
-    mX += space * GetThinSpace(mParentFrame->GetStyleFont());
+    mX += space * GetThinSpace(font);
     return *this;
   }
 
   nsIFrame* Frame() const { return mChildFrame; }
   nscoord X() const { return mX; }
   const nsHTMLReflowMetrics& ReflowMetrics() const { return mSize; }
   nscoord Ascent() const { return mSize.ascent; }
   nscoord Descent() const { return mSize.height - mSize.ascent; }
@@ -1397,16 +1238,48 @@ nsMathMLContainerFrame::PositionRowChild
     nscoord dx = aOffsetX + child.X();
     nscoord dy = aBaseline - child.Ascent();
     FinishReflowChild(child.Frame(), PresContext(), nsnull,
                       child.ReflowMetrics(), dx, dy, 0);
     ++child;
   }
 }
 
+class ForceReflow : public nsIReflowCallback {
+public:
+  virtual PRBool ReflowFinished() {
+    return PR_TRUE;
+  }
+  virtual void ReflowCallbackCanceled() {}
+};
+
+// We only need one of these so we just make it a static global, no need
+// to dynamically allocate/destroy it.
+static ForceReflow gForceReflow;
+
+void
+nsMathMLContainerFrame::SetIncrementScriptLevel(PRInt32 aChildIndex, PRBool aIncrement)
+{
+  nsIFrame* child = nsFrameList(GetFirstChild(nsnull)).FrameAt(aChildIndex);
+  if (!child)
+    return;
+  nsIContent* content = child->GetContent();
+  if (!content->IsNodeOfType(nsINode::eMATHML))
+    return;
+  nsMathMLElement* element = static_cast<nsMathMLElement*>(content);
+
+  if (element->GetIncrementScriptLevel() == aIncrement)
+    return;
+
+  // XXXroc this does a ContentStatesChanged, is it safe to call here? If
+  // not we should do it in a post-reflow callback.
+  element->SetIncrementScriptLevel(aIncrement, PR_TRUE);
+  PresContext()->PresShell()->PostReflowCallback(&gForceReflow);
+}
+
 // helpers to fix the inter-spacing when <math> is the only parent
 // e.g., it fixes <math> <mi>f</mi> <mo>q</mo> <mi>f</mi> <mo>I</mo> </math>
 
 static nscoord
 GetInterFrameSpacingFor(PRInt32         aScriptLevel,
                         nsIFrame*       aParentFrame,
                         nsIFrame*       aChildFrame)
 {
@@ -1445,17 +1318,17 @@ nsMathMLContainerFrame::FixInterFrameSpa
   nsIContent* parentContent = mParent->GetContent();
   if (NS_UNLIKELY(!parentContent)) {
     return 0;
   }
   // XXXldb This should check namespaces too.
   nsIAtom *parentTag = parentContent->Tag();
   if (parentTag == nsGkAtoms::math ||
       parentTag == nsGkAtoms::mtd_) {
-    gap = GetInterFrameSpacingFor(mPresentationData.scriptLevel, mParent, this);
+    gap = GetInterFrameSpacingFor(GetStyleFont()->mScriptLevel, mParent, this);
     // add our own italic correction
     nscoord leftCorrection = 0, italicCorrection = 0;
     GetItalicCorrection(mBoundingMetrics, leftCorrection, italicCorrection);
     gap += leftCorrection;
     // see if we should shift our children to account for the correction
     if (gap) {
       nsIFrame* childFrame = mFrames.FirstChild();
       while (childFrame) {
--- a/layout/mathml/base/src/nsMathMLContainerFrame.h
+++ b/layout/mathml/base/src/nsMathMLContainerFrame.h
@@ -56,26 +56,16 @@
  * Base class for MathML container frames. It acts like an inferred 
  * mrow. By default, this frame uses its Reflow() method to lay its 
  * children horizontally and ensure that their baselines are aligned.
  * The Reflow() method relies upon Place() to position children.
  * By overloading Place() in derived classes, it is therefore possible
  * to position children in various customized ways.
  */
 
-// Parameters to handle the change of font-size induced by changing the
-// scriptlevel. These are hard-coded values that match with the rules in
-// mathml.css. Note that mScriptLevel can exceed these bounds, but the
-// scaling effect on the font-size will be bounded. The following bounds can
-// be expanded provided the new corresponding rules are added in mathml.css.
-#define NS_MATHML_CSS_POSITIVE_SCRIPTLEVEL_LIMIT  +5
-#define NS_MATHML_CSS_NEGATIVE_SCRIPTLEVEL_LIMIT  -5
-#define NS_MATHML_SCRIPTSIZEMULTIPLIER             0.71f
-#define NS_MATHML_SCRIPTMINSIZE                    8
-
 // Options for the preferred size at which to stretch our stretchy children 
 #define STRETCH_CONSIDER_ACTUAL_SIZE    0x00000001 // just use our current size
 #define STRETCH_CONSIDER_EMBELLISHMENTS 0x00000002 // size calculations include embellishments
 
 class nsMathMLContainerFrame : public nsHTMLContainerFrame,
                                public nsMathMLFrame {
   friend class nsMathMLmfencedFrame;
 public:
@@ -95,47 +85,46 @@ public:
   NS_IMETHOD
   Place(nsIRenderingContext& aRenderingContext,
         PRBool               aPlaceOrigin,
         nsHTMLReflowMetrics& aDesiredSize);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate)
   {
     PropagatePresentationDataFromChildAt(this, aFirstIndex, aLastIndex,
-      aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+      aFlagsValues, aFlagsToUpdate);
     return NS_OK;
   }
-
-  NS_IMETHOD
-  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
-  {
-    PropagateScriptStyleFor(this, aParentScriptLevel);
-    return NS_OK;
-  }
+  
+  // helper to set the "increment script level" flag on the element belonging
+  // to a child frame given by aChildIndex.
+  // When this flag is set, the style system will increment the scriptlevel
+  // for the child element. This is needed for situations where the style system
+  // cannot itself determine the scriptlevel (mfrac, munder, mover, munderover).
+  // This should be called during reflow. We set the flag and if it changed,
+  // we request appropriate restyling and also queue a post-reflow callback
+  // to ensure that restyle and reflow happens immediately after the current
+  // reflow.
+  void
+  SetIncrementScriptLevel(PRInt32 aChildIndex, PRBool aIncrement);
 
   // --------------------------------------------------------------------------
   // Overloaded nsHTMLContainerFrame methods -- see documentation in nsIFrame.h
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     return !(aFlags & nsIFrame::eLineParticipant) &&
       nsHTMLContainerFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
   }
 
   NS_IMETHOD
-  Init(nsIContent*      aContent,
-       nsIFrame*        aParent,
-       nsIFrame*        aPrevInFlow);
-
-  NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
                nsIFrame*       aFrameList);
 
   NS_IMETHOD
   InsertFrames(nsIAtom*        aListName,
                nsIFrame*       aPrevFrame,
                nsIFrame*       aFrameList);
 
@@ -247,35 +236,27 @@ public:
   // where it is assumed that the frame's rect is still acting as place holder
   // for the frame's ascent and descent information
   static void
   GetReflowAndBoundingMetricsFor(nsIFrame*            aFrame,
                                  nsHTMLReflowMetrics& aReflowMetrics,
                                  nsBoundingMetrics&   aBoundingMetrics,
                                  eMathMLFrameType*    aMathMLFrameType = nsnull);
 
-  // helper to let the scriptstyle re-resolution pass through
-  // a subtree that may contain non-MathML container frames
-  static void
-  PropagateScriptStyleFor(nsIFrame*       aFrame,
-                          PRInt32         aParentScriptLevel);
-
   // helper to let the update of presentation data pass through
   // a subtree that may contain non-MathML container frames
   static void
   PropagatePresentationDataFor(nsIFrame*       aFrame,
-                               PRInt32         aScriptLevelIncrement,
                                PRUint32        aFlagsValues,
                                PRUint32        aFlagsToUpdate);
 
   static void
   PropagatePresentationDataFromChildAt(nsIFrame*       aParentFrame,
                                        PRInt32         aFirstChildIndex,
                                        PRInt32         aLastChildIndex,
-                                       PRInt32         aScriptLevelIncrement,
                                        PRUint32        aFlagsValues,
                                        PRUint32        aFlagsToUpdate);
 
   // helper to let the rebuild of automatic data (presentation data
   // and embellishement data) walk through a subtree that may contain
   // non-MathML container frames. Note that this method re-builds the
   // automatic data in the children -- not in aParentFrame itself (except
   // for those particular operations that the parent frame may do in its
@@ -347,35 +328,21 @@ public:
   // cannot use mFrames{.FirstChild()|.etc} since the block code doesn't set mFrames
   NS_IMETHOD
   SetInitialChildList(nsIAtom*        aListName,
                       nsIFrame*       aChildList)
   {
     NS_ASSERTION(!aListName, "unexpected frame list");
     nsresult rv = nsBlockFrame::SetInitialChildList(aListName, aChildList);
     // re-resolve our subtree to set any mathml-expected data
-    nsMathMLContainerFrame::MapCommonAttributesIntoCSS(PresContext(), this);
     nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this);
     return rv;
   }
 
   NS_IMETHOD
-  Reflow(nsPresContext*           aPresContext,
-         nsHTMLReflowMetrics&     aDesiredSize,
-         const nsHTMLReflowState& aReflowState,
-         nsReflowStatus&          aStatus)
-  {
-    if (mScriptStyleChanged) {
-      mScriptStyleChanged = PR_FALSE;
-      nsMathMLContainerFrame::PropagateScriptStyleFor(this, 0);
-    }
-    return nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-  }
-
-  NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
                nsIFrame*       aFrameList)
   {
     NS_ASSERTION(!aListName || nsGkAtoms::nextBidi == aListName,
                  "unexpected frame list");
     nsresult rv = nsBlockFrame::AppendFrames(aListName, aFrameList);
     if (NS_LIKELY(!aListName))
       nsMathMLContainerFrame::ReLayoutChildren(this,
@@ -416,59 +383,36 @@ public:
 
 protected:
   nsMathMLmathBlockFrame(nsStyleContext* aContext) : nsBlockFrame(aContext) {
     // We should always have a space manager.  Not that things can really try
     // to float out of us anyway, but we need one for line layout.
     AddStateBits(NS_BLOCK_SPACE_MGR);
   }
   virtual ~nsMathMLmathBlockFrame() {}
-
-  NS_IMETHOD
-  DidSetStyleContext()
-  {
-    mScriptStyleChanged = PR_TRUE;
-    return nsBlockFrame::DidSetStyleContext();
-  }
-
-  PRBool mScriptStyleChanged;
 };
 
 // --------------
 
 class nsMathMLmathInlineFrame : public nsInlineFrame {
 public:
   friend nsIFrame* NS_NewMathMLmathInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_IMETHOD
   SetInitialChildList(nsIAtom*        aListName,
                       nsIFrame*       aChildList)
   {
     NS_ASSERTION(!aListName, "unexpected frame list");
     nsresult rv = nsInlineFrame::SetInitialChildList(aListName, aChildList);
     // re-resolve our subtree to set any mathml-expected data
-    nsMathMLContainerFrame::MapCommonAttributesIntoCSS(PresContext(), this);
     nsMathMLContainerFrame::RebuildAutomaticDataForChildren(this);
     return rv;
   }
 
   NS_IMETHOD
-  Reflow(nsPresContext*           aPresContext,
-         nsHTMLReflowMetrics&     aDesiredSize,
-         const nsHTMLReflowState& aReflowState,
-         nsReflowStatus&          aStatus)
-  {
-    if (mScriptStyleChanged) {
-      mScriptStyleChanged = PR_FALSE;
-      nsMathMLContainerFrame::PropagateScriptStyleFor(this, 0);
-    }
-    return nsInlineFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
-  }
-
-  NS_IMETHOD
   AppendFrames(nsIAtom*        aListName,
                nsIFrame*       aFrameList)
   {
     NS_ASSERTION(!aListName || nsGkAtoms::nextBidi == aListName,
                  "unexpected frame list");
     nsresult rv = nsInlineFrame::AppendFrames(aListName, aFrameList);
     if (NS_LIKELY(!aListName))
       nsMathMLContainerFrame::ReLayoutChildren(this,
@@ -505,20 +449,11 @@ public:
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const {
     return nsInlineFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
   }
 
 protected:
   nsMathMLmathInlineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
   virtual ~nsMathMLmathInlineFrame() {}
-
-  NS_IMETHOD
-  DidSetStyleContext()
-  {
-    mScriptStyleChanged = PR_TRUE;
-    return nsInlineFrame::DidSetStyleContext();
-  }
-
-  PRBool mScriptStyleChanged;
 };
 
 #endif /* nsMathMLContainerFrame_h___ */
--- a/layout/mathml/base/src/nsMathMLForeignFrameWrapper.h
+++ b/layout/mathml/base/src/nsMathMLForeignFrameWrapper.h
@@ -54,29 +54,21 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // Overloaded nsIMathMLFrame methods
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate)
   {
     nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(this,
-      aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
-    return NS_OK;
-  }
-
-  NS_IMETHOD
-  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
-  {
-    nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel);
+      aFirstIndex, aLastIndex, aFlagsValues, aFlagsToUpdate);
     return NS_OK;
   }
 
   // overloaded nsBlockFrame methods
 
 #ifdef NS_DEBUG
   NS_IMETHOD
   SetInitialChildList(nsIAtom*        aListName,
--- a/layout/mathml/base/src/nsMathMLFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLFrame.cpp
@@ -112,40 +112,36 @@ nsMathMLFrame::InheritAutomaticData(nsIF
   mEmbellishData.coreFrame = nsnull;
   mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
   mEmbellishData.leftSpace = 0;
   mEmbellishData.rightSpace = 0;
 
   mPresentationData.flags = 0;
   mPresentationData.baseFrame = nsnull;
   mPresentationData.mstyle = nsnull;
-  mPresentationData.scriptLevel = 0;
 
-  // by default, just inherit the display & scriptlevel of our parent
+  // by default, just inherit the display of our parent
   nsPresentationData parentData;
   GetPresentationDataFrom(aParent, parentData);
   mPresentationData.mstyle = parentData.mstyle;
-  mPresentationData.scriptLevel = parentData.scriptLevel;
   if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) {
     mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
   }
 
 #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
   mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
 #endif
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsMathMLFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                                      PRUint32        aFlagsValues,
+nsMathMLFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                       PRUint32        aWhichFlags)
 {
-  mPresentationData.scriptLevel += aScriptLevelIncrement;
   // update flags that are relevant to this call
   if (NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags)) {
     // updating the displaystyle flag is allowed
     if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
       mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
     }
     else {
       mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE;
@@ -210,17 +206,16 @@ nsMathMLFrame::GetEmbellishDataFrom(nsIF
 nsMathMLFrame::GetPresentationDataFrom(nsIFrame*           aFrame,
                                        nsPresentationData& aPresentationData,
                                        PRBool              aClimbTree)
 {
   // initialize OUT params
   aPresentationData.flags = 0;
   aPresentationData.baseFrame = nsnull;
   aPresentationData.mstyle = nsnull;
-  aPresentationData.scriptLevel = 0;
 
   nsIFrame* frame = aFrame;
   while (frame) {
     if (frame->IsFrameOfType(nsIFrame::eMathML)) {
       nsIMathMLFrame* mathMLFrame;
       CallQueryInterface(frame, &mathMLFrame);
       if (mathMLFrame) {
         mathMLFrame->GetPresentationData(aPresentationData);
@@ -346,116 +341,16 @@ nsMathMLFrame::GetAxisHeight(nsIRenderin
     aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
   }
   if (NS_FAILED(rv) || aAxisHeight <= 0 || aAxisHeight >= xHeight) {
     // fall-back to the other version
     GetAxisHeight(aFontMetrics, aAxisHeight);
   }
 }
 
-// ================
-// Utilities for parsing and retrieving numeric values
-// All returned values are in twips.
-
-/*
-The REC says:
-  An explicit plus sign ('+') is not allowed as part of a numeric value
-  except when it is specifically listed in the syntax (as a quoted '+'  or "+"),
-
-  Units allowed
-  ID  Description
-  em  ems (font-relative unit traditionally used for horizontal lengths)
-  ex  exs (font-relative unit traditionally used for vertical lengths)
-  px  pixels, or pixel size of a "typical computer display"
-  in  inches (1 inch = 2.54 centimeters)
-  cm  centimeters
-  mm  millimeters
-  pt  points (1 point = 1/72 inch)
-  pc  picas (1 pica = 12 points)
-  %   percentage of default value
-
-Implementation here:
-  The numeric value is valid only if it is of the form [-] nnn.nnn [h/v-unit]
-*/
-
-/* static */ PRBool
-nsMathMLFrame::ParseNumericValue(nsString&   aString,
-                                 nsCSSValue& aCSSValue)
-{
-  aCSSValue.Reset();
-  aString.CompressWhitespace(); //  aString is not a const in this code...
-
-  PRInt32 stringLength = aString.Length();
-  if (!stringLength)
-    return PR_FALSE;
-
-  nsAutoString number, unit;
-
-  // see if the negative sign is there
-  PRInt32 i = 0;
-  PRUnichar c = aString[0];
-  if (c == '-') {
-    number.Append(c);
-    i++;
-
-    // skip any space after the negative sign
-    if (i < stringLength && nsCRT::IsAsciiSpace(aString[i]))
-      i++;
-  }
-
-  // Gather up characters that make up the number
-  PRBool gotDot = PR_FALSE;
-  for ( ; i < stringLength; i++) {
-    c = aString[i];
-    if (gotDot && c == '.')
-      return PR_FALSE;  // two dots encountered
-    else if (c == '.')
-      gotDot = PR_TRUE;
-    else if (!nsCRT::IsAsciiDigit(c)) {
-      aString.Right(unit, stringLength - i);
-      unit.CompressWhitespace(); // some authors leave blanks before the unit
-      break;
-    }
-    number.Append(c);
-  }
-
-  // on exit, also return a nicer string version of the value in case
-  // the caller wants it (e.g., this removes whitespace before units)
-  aString.Assign(number);
-  aString.Append(unit);
-
-  // Convert number to floating point
-  PRInt32 errorCode;
-  float floatValue = number.ToFloat(&errorCode);
-  if (errorCode)
-    return PR_FALSE;
-
-  nsCSSUnit cssUnit;
-  if (unit.IsEmpty()) {
-    cssUnit = eCSSUnit_Number; // no explicit unit, this is a number that will act as a multiplier
-  }
-  else if (unit.EqualsLiteral("%")) {
-    aCSSValue.SetPercentValue(floatValue / 100.0f);
-    return PR_TRUE;
-  }
-  else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM;
-  else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight;
-  else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel;
-  else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch;
-  else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter;
-  else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter;
-  else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point;
-  else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica;
-  else // unexpected unit
-    return PR_FALSE;
-
-  aCSSValue.SetFloatValue(floatValue, cssUnit);
-  return PR_TRUE;
-}
-
 /* static */ nscoord
 nsMathMLFrame::CalcLength(nsPresContext*   aPresContext,
                           nsStyleContext*   aStyleContext,
                           const nsCSSValue& aCSSValue)
 {
   NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit");
 
   if (aCSSValue.IsFixedLengthUnit()) {
@@ -555,257 +450,16 @@ static const PRInt32 kMathMLversion2 = 2
 
 struct
 nsCSSMapping {
   PRInt32        compatibility;
   const nsIAtom* attrAtom;
   const char*    cssProperty;
 };
 
-static void
-GetMathMLAttributeStyleSheet(nsPresContext* aPresContext,
-                             nsIStyleSheet** aSheet)
-{
-  static const char kTitle[] = "Internal MathML/CSS Attribute Style Sheet";
-  *aSheet = nsnull;
-
-  // first, look if the attribute stylesheet is already there
-  nsStyleSet *styleSet = aPresContext->StyleSet();
-  NS_ASSERTION(styleSet, "no style set");
-
-  nsAutoString title;
-  for (PRInt32 i = styleSet->SheetCount(nsStyleSet::eAgentSheet) - 1;
-       i >= 0; --i) {
-    nsIStyleSheet *sheet = styleSet->StyleSheetAt(nsStyleSet::eAgentSheet, i);
-    nsCOMPtr<nsICSSStyleSheet> cssSheet(do_QueryInterface(sheet));
-    if (cssSheet) {
-      cssSheet->GetTitle(title);
-      if (title.Equals(NS_ConvertASCIItoUTF16(kTitle))) {
-        *aSheet = sheet;
-        NS_IF_ADDREF(*aSheet);
-        return;
-      }
-    }
-  }
-
-  // then, create a new one if it isn't yet there
-  nsCOMPtr<nsIURI> uri;
-  NS_NewURI(getter_AddRefs(uri), "about:internal-mathml-attribute-stylesheet");
-  if (!uri)
-    return;
-  nsCOMPtr<nsICSSStyleSheet> cssSheet(do_CreateInstance(kCSSStyleSheetCID));
-  if (!cssSheet)
-    return;
-  cssSheet->SetURIs(uri, nsnull, uri);
-  cssSheet->SetTitle(NS_ConvertASCIItoUTF16(kTitle));
-  // all done, no further activity from the net involved, so we better do this
-  cssSheet->SetComplete();
-
-  nsCOMPtr<nsIDOMCSSStyleSheet> domSheet(do_QueryInterface(cssSheet));
-  if (domSheet) {
-    PRUint32 index;
-    domSheet->InsertRule(NS_LITERAL_STRING("@namespace url(http://www.w3.org/1998/Math/MathML);"),
-                                           0, &index);
-  }
-
-  // insert the stylesheet into the styleset without notifying observers
-  // XXX Should this be at a different level?
-  styleSet->PrependStyleSheet(nsStyleSet::eAgentSheet, cssSheet);
-  *aSheet = cssSheet;
-  NS_ADDREF(*aSheet);
-}
-
-/* static */ PRInt32
-nsMathMLFrame::MapCommonAttributesIntoCSS(nsPresContext* aPresContext,
-                                          nsIContent*    aContent)
-{
-  // normal case, quick return if there are no attributes
-  NS_ASSERTION(aContent, "null arg");
-  PRUint32 attrCount = 0;
-  if (aContent)
-    attrCount = aContent->GetAttrCount();
-  if (!attrCount)
-    return 0;
-
-  // need to initialize here -- i.e., after registering nsGkAtoms
-  static const nsCSSMapping
-  kCSSMappingTable[] = {
-    {kMathMLversion2, nsGkAtoms::mathcolor_,      "color:"},
-    {kMathMLversion1, nsGkAtoms::color,           "color:"},
-    {kMathMLversion2, nsGkAtoms::mathsize_,       "font-size:"},
-    {kMathMLversion1, nsGkAtoms::fontsize_,       "font-size:"},
-    {kMathMLversion1, nsGkAtoms::fontfamily_,     "font-family:"},
-    {kMathMLversion2, nsGkAtoms::mathbackground_, "background-color:"},
-    {kMathMLversion1, nsGkAtoms::background,      "background-color:"},
-    {0, nsnull, nsnull}
-  };
-
-  nsCOMPtr<nsIDocument> doc;
-  nsCOMPtr<nsIStyleSheet> sheet;
-  nsCOMPtr<nsICSSStyleSheet> cssSheet;
-  nsCOMPtr<nsIDOMCSSStyleSheet> domSheet;
-
-  PRInt32 ruleCount = 0;
-  for (PRUint32 i = 0; i < attrCount; ++i) {
-    const nsAttrName* name = aContent->GetAttrNameAt(i);
-    if (name->NamespaceID() != kNameSpaceID_None)
-      continue;
-
-    nsIAtom* attrAtom = name->LocalName();
-
-    // lookup the equivalent CSS property
-    const nsCSSMapping* map = kCSSMappingTable;
-    while (map->attrAtom && map->attrAtom != attrAtom)
-      ++map;
-    if (!map->attrAtom)
-      continue;
-    nsAutoString cssProperty(NS_ConvertASCIItoUTF16(map->cssProperty));
-
-    nsAutoString attrValue;
-    aContent->GetAttr(kNameSpaceID_None, attrAtom, attrValue);
-    if (attrValue.IsEmpty())
-      continue;
-    nsAutoString escapedAttrValue;
-    nsStyleUtil::EscapeCSSString(attrValue, escapedAttrValue);
-
-    // don't add rules that are already in mathml.css
-    // (this will also clean up whitespace before units - see bug 125303)
-    if (attrAtom == nsGkAtoms::fontsize_ || attrAtom == nsGkAtoms::mathsize_) {
-      nsCSSValue cssValue;
-      nsAutoString numericValue(attrValue);
-      if (!ParseNumericValue(numericValue, cssValue))
-        continue;
-      // on exit, ParseNumericValue also returns a nicer string
-      // in which the whitespace before the unit is cleaned up 
-      cssProperty.Append(numericValue);
-    }
-    else
-      cssProperty.Append(attrValue);
-
-    nsAutoString attrName;
-    attrAtom->ToString(attrName);
-
-    // make a style rule that maps to the equivalent CSS property
-    nsAutoString selector, cssRule;
-    selector.Assign(NS_LITERAL_STRING("[") + attrName +
-                    NS_LITERAL_STRING("=\"") + escapedAttrValue +
-                    NS_LITERAL_STRING("\"]"));
-    cssRule.Assign(selector +
-                   NS_LITERAL_STRING("{") + cssProperty + NS_LITERAL_STRING("}"));
-
-    if (!sheet) {
-      // first time... we do this to defer the lookup up to the
-      // point where we encounter attributes that actually matter
-      doc = aContent->GetDocument();
-      if (!doc) 
-        return 0;
-      GetMathMLAttributeStyleSheet(aPresContext, getter_AddRefs(sheet));
-      if (!sheet)
-        return 0;
-      // by construction, these cannot be null at this point
-      cssSheet = do_QueryInterface(sheet);
-      domSheet = do_QueryInterface(sheet);
-      NS_ASSERTION(cssSheet && domSheet, "unexpected null pointers");
-      // we will keep the sheet orphan as we populate it. This way,
-      // observers of the document won't be notified and we avoid any troubles
-      // that may come from reconstructing the frame tree. Our rules only need
-      // a re-resolve of style data and a reflow, not a reconstruct-all...
-      sheet->SetOwningDocument(nsnull);
-    }
-
-    // check for duplicate, if a similar rule is already there,
-    // don't bother to add another one
-    PRInt32 k, count;
-    cssSheet->StyleRuleCount(count);
-    for (k = 0; k < count; ++k) {
-      nsAutoString tmpSelector;
-      nsCOMPtr<nsICSSRule> tmpRule;
-      cssSheet->GetStyleRuleAt(k, *getter_AddRefs(tmpRule));
-      nsCOMPtr<nsICSSStyleRule> tmpStyleRule = do_QueryInterface(tmpRule);
-      if (tmpStyleRule) {
-        tmpStyleRule->GetSelectorText(tmpSelector);
-        NS_ASSERTION(tmpSelector.CharAt(0) != '*', "unexpected universal symbol");
-#ifdef DEBUG_rbs
-        nsCAutoString str;
-        LossyAppendUTF16toASCII(selector, str);
-        str.AppendLiteral(" vs ");
-        LossyAppendUTF16toASCII(tmpSelector, str);
-        printf("Attr selector %s %s\n", str.get(),
-        tmpSelector.Equals(selector)? " ... match" : " ... nomatch");
-#endif
-        if (tmpSelector.Equals(selector)) {
-          k = -1;
-          break;
-        }
-      }
-    }
-    if (k >= 0) {
-      // insert the rule (note: when the sheet already has @namespace and
-      // friends, insert after them, e.g., at the end, otherwise it won't work)
-      // For MathML 2, insert at the end to give it precedence
-      PRInt32 pos = (map->compatibility == kMathMLversion2) ? count : 1;
-      PRUint32 index;
-      domSheet->InsertRule(cssRule, pos, &index);
-      ++ruleCount;
-    }
-  }
-  // restore the sheet to its owner
-  if (sheet) {
-    sheet->SetOwningDocument(doc);
-  }
-
-  return ruleCount;
-}
-
-/* static */ PRInt32
-nsMathMLFrame::MapCommonAttributesIntoCSS(nsPresContext* aPresContext,
-                                          nsIFrame*      aFrame)
-{
-  PRInt32 ruleCount = MapCommonAttributesIntoCSS(aPresContext, aFrame->GetContent());
-  if (!ruleCount)
-    return 0;
-
-  // now, re-resolve the style contexts in our subtree
-  nsFrameManager *fm = aPresContext->FrameManager();
-  nsStyleChangeList changeList;
-  fm->ComputeStyleChangeFor(aFrame, &changeList, NS_STYLE_HINT_NONE);
-#ifdef DEBUG
-  // Use the parent frame to make sure we catch in-flows and such
-  nsIFrame* parentFrame = aFrame->GetParent();
-  fm->DebugVerifyStyleTree(parentFrame ? parentFrame : aFrame);
-#endif
-
-  return ruleCount;
-}
-
-/* static */ PRBool
-nsMathMLFrame::CommonAttributeChangedFor(nsPresContext* aPresContext,
-                                         nsIContent*    aContent,
-                                         nsIAtom*       aAttribute)
-{
-  if (aAttribute == nsGkAtoms::mathcolor_      ||
-      aAttribute == nsGkAtoms::color           ||
-      aAttribute == nsGkAtoms::mathsize_       ||
-      aAttribute == nsGkAtoms::fontsize_       ||
-      aAttribute == nsGkAtoms::fontfamily_     ||
-      aAttribute == nsGkAtoms::mathbackground_ ||
-      aAttribute == nsGkAtoms::background) {
-
-    MapCommonAttributesIntoCSS(aPresContext, aContent);
-
-    // That's all folks. Common attributes go in the internal MathML attribute
-    // stylesheet. So when nsCSSFrameConstructor checks if the content
-    // HasAttributeDependentStyle(), it will detect them and issue a
-    // PostRestyleEvent() to re-resolve the style data and reflow if needed.
-    return PR_TRUE;
-  }
-
-  return PR_FALSE;
-}
-
 #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
 class nsDisplayMathMLBoundingMetrics : public nsDisplayItem {
 public:
   nsDisplayMathMLBoundingMetrics(nsIFrame* aFrame, const nsRect& aRect)
     : nsDisplayItem(aFrame), mRect(aRect) {
     MOZ_COUNT_CTOR(nsDisplayMathMLBoundingMetrics);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
--- a/layout/mathml/base/src/nsMathMLFrame.h
+++ b/layout/mathml/base/src/nsMathMLFrame.h
@@ -44,16 +44,17 @@
 #include "nsIRenderingContext.h"
 #include "nsIFontMetrics.h"
 #include "nsStyleContext.h"
 #include "nsMathMLAtoms.h"
 #include "nsMathMLOperators.h"
 #include "nsIMathMLFrame.h"
 #include "nsFrame.h"
 #include "nsCSSValue.h"
+#include "nsMathMLElement.h"
 
 class nsMathMLChar;
 
 // Concrete base class with default methods that derived MathML frames can override
 class nsMathMLFrame : public nsIMathMLFrame {
 public:
 
   // nsISupports ------
@@ -144,36 +145,28 @@ public:
 
   NS_IMETHOD
   TransmitAutomaticData()
   {
     return NS_OK;
   }
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
+  UpdatePresentationData(PRUint32        aFlagsValues,
                          PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate)
   {
     return NS_OK;
   }
 
-  NS_IMETHOD
-  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
-  {
-    return NS_OK;
-  }
-
   // helper to give a style context suitable for doing the stretching to the
   // MathMLChar. Frame classes that use this should make the extra style contexts
   // accessible to the Style System via Get/Set AdditionalStyleContext.
   static void
   ResolveMathMLCharStyle(nsPresContext*  aPresContext,
                          nsIContent*      aContent,
                          nsStyleContext*  aParenStyleContext,
                          nsMathMLChar*    aMathMLChar,
@@ -218,18 +211,20 @@ public:
   GetAttribute(nsIContent* aContent,
                nsIFrame*   aMathMLmstyleFrame,          
                nsIAtom*    aAttributeAtom,
                nsString&   aValue);
 
   // utilities to parse and retrieve numeric values in CSS units
   // All values are stored in twips.
   static PRBool
-  ParseNumericValue(nsString&   aString,
-                    nsCSSValue& aCSSValue);
+  ParseNumericValue(const nsString& aString,
+                    nsCSSValue&     aCSSValue) {
+    return nsMathMLElement::ParseNumericValue(aString, aCSSValue, PR_FALSE);
+  }
 
   static nscoord 
   CalcLength(nsPresContext*   aPresContext,
              nsStyleContext*   aStyleContext,
              const nsCSSValue& aCSSValue);
 
   static PRBool
   ParseNamedSpaceValue(nsIFrame*   aMathMLmstyleFrame,
@@ -428,34 +423,16 @@ public:
                    nsIFontMetrics*      aFontMetrics,
                    nscoord&             aRuleThickness);
 
   static void
   GetAxisHeight(nsIRenderingContext& aRenderingContext, 
                 nsIFontMetrics*      aFontMetrics,
                 nscoord&             aAxisHeight);
 
-  // ================
-  // helpers to map attributes into CSS rules (work-around to bug 69409 which
-  // is not scheduled to be fixed anytime soon)
-  static PRInt32
-  MapCommonAttributesIntoCSS(nsPresContext* aPresContext,
-                             nsIContent*    aContent);
-  static PRInt32
-  MapCommonAttributesIntoCSS(nsPresContext* aPresContext,
-                             nsIFrame*      aFrame);
- 
-  // helper used by all AttributeChanged() methods. It handles
-  // those attributes that are common to all tags.
-  // @return true if the attribue is handled.
-  static PRBool
-  CommonAttributeChangedFor(nsPresContext* aPresContext,
-                            nsIContent*    aContent,
-                            nsIAtom*       aAttribute);
-
 protected:
 #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
   nsresult DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
                                   nsIFrame* aFrame, const nsPoint& aPt,
                                   const nsBoundingMetrics& aMetrics,
                                   const nsDisplayListSet& aLists);
 #endif
 
--- a/layout/mathml/base/src/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmfencedFrame.cpp
@@ -262,17 +262,18 @@ nsMathMLmfencedFrame::doReflow(nsPresCon
   aDesiredSize.ascent = 0;
   aDesiredSize.mBoundingMetrics.Clear();
 
   nsMathMLContainerFrame* mathMLFrame =
     static_cast<nsMathMLContainerFrame*>(aForFrame);
 
   PRInt32 i;
   nsCOMPtr<nsIFontMetrics> fm;
-  aReflowState.rendContext->SetFont(aForFrame->GetStyleFont()->mFont, nsnull);
+  const nsStyleFont* font = aForFrame->GetStyleFont();
+  aReflowState.rendContext->SetFont(font->mFont, nsnull);
   aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
   nscoord axisHeight, em;
   GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
   GetEmHeight(fm, em);
   // leading to be left at the top and the bottom of stretched chars
   nscoord leading = NSToCoordRound(0.2f * em); 
 
   /////////////
@@ -385,29 +386,29 @@ nsMathMLmfencedFrame::doReflow(nsPresCon
                            containerSize.descent + axisHeight);
     containerSize.ascent = delta + axisHeight;
     containerSize.descent = delta - axisHeight;
   }
 
   /////////////////
   // opening fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, aOpenChar,
-             NS_MATHML_OPERATOR_FORM_PREFIX, presentationData.scriptLevel, 
+             NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, 
              axisHeight, leading, em, containerSize, ascent, descent);
   /////////////////
   // separators ...
   for (i = 0; i < aSeparatorsCount; i++) {
     ReflowChar(aPresContext, *aReflowState.rendContext, &aSeparatorsChar[i],
-               NS_MATHML_OPERATOR_FORM_INFIX, presentationData.scriptLevel,
+               NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
                axisHeight, leading, em, containerSize, ascent, descent);
   }
   /////////////////
   // closing fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, aCloseChar,
-             NS_MATHML_OPERATOR_FORM_POSTFIX, presentationData.scriptLevel,
+             NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
              axisHeight, leading, em, containerSize, ascent, descent);
 
   //////////////////
   // Adjust the origins of each child.
   // and update our bounding metrics
 
   i = 0;
   nscoord dx = 0;
--- a/layout/mathml/base/src/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmfracFrame.cpp
@@ -125,23 +125,24 @@ nsMathMLmfracFrame::GetMathMLFrameType()
 NS_IMETHODIMP
 nsMathMLmfracFrame::TransmitAutomaticData()
 {
   // 1. The REC says:
   //    The <mfrac> element sets displaystyle to "false", or if it was already
   //    false increments scriptlevel by 1, within numerator and denominator.
   // 2. The TeXbook (Ch 17. p.141) says the numerator inherits the compression
   //    while the denominator is compressed
-  PRInt32 increment =
-     NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) ? 0 : 1;
-  mInnerScriptLevel = mPresentationData.scriptLevel + increment;
-  UpdatePresentationDataFromChildAt(0, -1, increment,
+  SetIncrementScriptLevel(0, !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags));
+  // XXXroc how come point 1 above says we should increment scriptlevel for
+  // the denominator, but the old code didn't?
+
+  UpdatePresentationDataFromChildAt(0, -1,
     ~NS_MATHML_DISPLAYSTYLE,
      NS_MATHML_DISPLAYSTYLE);
-  UpdatePresentationDataFromChildAt(1,  1, 0,
+  UpdatePresentationDataFromChildAt(1,  1,
      NS_MATHML_COMPRESSED,
      NS_MATHML_COMPRESSED);
 
   // if our numerator is an embellished operator, let its state bubble to us
   GetEmbellishDataFrom(mFrames.FirstChild(), mEmbellishData);
   if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) {
     // even when embellished, we need to record that <mfrac> won't fire
     // Stretch() on its embellished child
@@ -473,64 +474,18 @@ nsMathMLmfracFrame::AttributeChanged(PRI
       }
     }
   }
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmfracFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                                           PRUint32        aFlagsValues,
-                                           PRUint32        aFlagsToUpdate)
-{
-  // mfrac is special... The REC says:
-  // The <mfrac> element sets displaystyle to "false", or if it was already
-  // false increments scriptlevel by 1, within numerator and denominator.
-  // @see similar peculiarities for <mover>, <munder>, <munderover>
-
-  // This means that
-  // 1. If our displaystyle is being changed from true to false, we have
-  //    to propagate an inner scriptlevel increment to our children
-  // 2. If the displaystyle is changed from false to true, we have to undo
-  //    any incrementation that was done on the inner scriptlevel
-
-  if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsToUpdate)) {
-    if (mInnerScriptLevel > mPresentationData.scriptLevel) {
-      // we get here if our displaystyle is currently false
-      NS_ASSERTION(!NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags), "out of sync");
-      if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
-        // ...and is being set to true, so undo the inner increment now
-        mInnerScriptLevel = mPresentationData.scriptLevel;
-        UpdatePresentationDataFromChildAt(0, -1, -1, 0, 0);
-      }
-    }
-    else {
-      // case of mInnerScriptLevel == mPresentationData.scriptLevel, our
-      // current displaystyle is true; we increment the inner scriptlevel if
-      // our displaystyle is about to be set to false; since mInnerScriptLevel
-      // is changed, we can only get here once
-      NS_ASSERTION(NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags), "out of sync");
-      if (!NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
-        mInnerScriptLevel = mPresentationData.scriptLevel + 1;
-        UpdatePresentationDataFromChildAt(0, -1, 1, 0, 0);
-      }
-    }
-  }
-
-  mInnerScriptLevel += aScriptLevelIncrement;
-  return nsMathMLContainerFrame::
-    UpdatePresentationData(aScriptLevelIncrement, aFlagsValues,
-                           aFlagsToUpdate);
-}
-
-NS_IMETHODIMP
 nsMathMLmfracFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                                       PRInt32         aLastIndex,
-                                                      PRInt32         aScriptLevelIncrement,
                                                       PRUint32        aFlagsValues,
                                                       PRUint32        aFlagsToUpdate)
 {
   // The REC says "The <mfrac> element sets displaystyle to "false" within
   // numerator and denominator"
 #if 0
   // At one point I thought that it meant that the displaystyle state of
   // the numerator and denominator cannot be modified by an ancestor, i.e.,
@@ -540,17 +495,17 @@ nsMathMLmfracFrame::UpdatePresentationDa
   // Commenting out for now until it is clear what the intention really is.
   // See also the variants for <mover>, <munder>, <munderover>
 
   aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
   aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
 #endif
   return nsMathMLContainerFrame::
     UpdatePresentationDataFromChildAt(aFirstIndex, aLastIndex,
-      aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+      aFlagsValues, aFlagsToUpdate);
 }
 
 // ----------------------
 // the Style System will use these to pass the proper style context to our MathMLChar
 nsStyleContext*
 nsMathMLmfracFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
 {
   if (!mSlashChar) {
--- a/layout/mathml/base/src/nsMathMLmfracFrame.h
+++ b/layout/mathml/base/src/nsMathMLmfracFrame.h
@@ -120,24 +120,18 @@ public:
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
-                         PRUint32        aFlagsToUpdate);
-
-  NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate);
 
   // override the base method so that we can deal with the fraction line
   virtual nscoord
   FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize);
 
   // helper to translate the thickness attribute into a usable form
@@ -152,14 +146,13 @@ protected:
   nsMathMLmfracFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
   virtual ~nsMathMLmfracFrame();
   
   virtual PRIntn GetSkipSides() const { return 0; }
 
   PRBool
   IsBevelled();
 
-  PRInt32 mInnerScriptLevel;
   nsRect  mLineRect;
   nsMathMLChar* mSlashChar;
 };
 
 #endif /* nsMathMLmfracFrame_h___ */
--- a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp
@@ -68,17 +68,17 @@ nsMathMLmmultiscriptsFrame::TransmitAuto
 {
   // if our base is an embellished operator, let its state bubble to us
   mPresentationData.baseFrame = mFrames.FirstChild();
   GetEmbellishDataFrom(mPresentationData.baseFrame, mEmbellishData);
 
   // The REC says:
   // The <mmultiscripts> element increments scriptlevel by 1, and sets
   // displaystyle to "false", within each of its arguments except base
-  UpdatePresentationDataFromChildAt(1, -1, 1,
+  UpdatePresentationDataFromChildAt(1, -1,
     ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE);
 
   // The TeXbook (Ch 17. p.141) says the superscript inherits the compression
   // while the subscript is compressed. So here we collect subscripts and set
   // the compression flag in them.
   PRInt32 count = 0;
   PRBool isSubScript = PR_FALSE;
   nsAutoVoidArray subScriptFrames;
@@ -101,17 +101,17 @@ nsMathMLmmultiscriptsFrame::TransmitAuto
       }
       isSubScript = !isSubScript;
     }
     count++;
     childFrame = childFrame->GetNextSibling();
   }
   for (PRInt32 i = subScriptFrames.Count() - 1; i >= 0; i--) {
     childFrame = (nsIFrame*)subScriptFrames[i];
-    PropagatePresentationDataFor(childFrame, 0,
+    PropagatePresentationDataFor(childFrame,
       NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED);
   }
 
   return NS_OK;
 }
 
 void
 nsMathMLmmultiscriptsFrame::ProcessAttributes()
@@ -153,17 +153,18 @@ nsMathMLmmultiscriptsFrame::Place(nsIRen
   ////////////////////////////////////////
   // Initialize super/sub shifts that
   // depend only on the current font
   ////////////////////////////////////////
 
   ProcessAttributes();
 
   // get x-height (an ex)
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull);
+  const nsStyleFont* font = GetStyleFont();
+  aRenderingContext.SetFont(font->mFont, nsnull);
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord xHeight;
   fm->GetXHeight (xHeight);
 
   nscoord ruleSize;
   GetRuleThickness (aRenderingContext, fm, ruleSize);
@@ -212,17 +213,17 @@ nsMathMLmmultiscriptsFrame::Place(nsIRen
     supScriptShift1 = PR_MAX(supScriptShift1, mSupScriptShift);
     supScriptShift2 = NSToCoordRound(scaler2 * supScriptShift1);
     supScriptShift3 = NSToCoordRound(scaler3 * supScriptShift1);
   }
 
   // get sup script shift depending on current script level and display style
   // Rule 18c, App. G, TeXbook
   nscoord supScriptShift;
-  if ( mPresentationData.scriptLevel == 0 &&
+  if ( font->mScriptLevel == 0 &&
        NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) &&
       !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) {
     // Style D in TeXbook
     supScriptShift = supScriptShift1;
   }
   else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) {
     // Style C' in TeXbook = D',T',S',SS'
     supScriptShift = supScriptShift3;
--- a/layout/mathml/base/src/nsMathMLmoFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmoFrame.cpp
@@ -392,17 +392,17 @@ nsMathMLmoFrame::ProcessOperatorData()
       GetEmHeight(fm, em);
 
       mEmbellishData.leftSpace = NSToCoordRound(lspace * em);
       mEmbellishData.rightSpace = NSToCoordRound(rspace * em);
 
       // tuning if we don't want too much extra space when we are a script.
       // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0.
       // Our fonts can be anything, so...)
-      if (mPresentationData.scriptLevel > 0) {
+      if (GetStyleFont()->mScriptLevel > 0) {
         if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) {
           // could be an isolated accent or script, e.g., x^{+}, just zero out
           mEmbellishData.leftSpace = 0;
           mEmbellishData.rightSpace  = 0;
         }
         else if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) {
           mEmbellishData.leftSpace /= 2;
           mEmbellishData.rightSpace  /= 2;
--- a/layout/mathml/base/src/nsMathMLmoverFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmoverFrame.cpp
@@ -77,37 +77,34 @@ nsMathMLmoverFrame::AttributeChanged(PRI
     return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
   }
 
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmoverFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                                           PRUint32        aFlagsValues,
+nsMathMLmoverFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                            PRUint32        aFlagsToUpdate)
 {
-  nsMathMLContainerFrame::UpdatePresentationData(
-    aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+  nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
   // disable the stretch-all flag if we are going to act like a superscript
   if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
       !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
     mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
   }
   else {
     mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmoverFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                                       PRInt32         aLastIndex,
-                                                      PRInt32         aScriptLevelIncrement,
                                                       PRUint32        aFlagsValues,
                                                       PRUint32        aFlagsToUpdate)
 {
   // mover is special... The REC says:
   // Within overscript, <mover> always sets displaystyle to "false", 
   // but increments scriptlevel by 1 only when accent is "false".
   // This means that
   // 1. don't allow displaystyle to change in the overscript
@@ -121,18 +118,17 @@ nsMathMLmoverFrame::UpdatePresentationDa
   while (childFrame) {
     if ((index >= aFirstIndex) &&
         ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) {
       if (index > 0) {
         // disable the flag
         aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
         aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
       }
-      PropagatePresentationDataFor(childFrame, aScriptLevelIncrement,
-                                   aFlagsValues, aFlagsToUpdate);
+      PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate);
     }
     index++;
     childFrame = childFrame->GetNextSibling();
   }
   return NS_OK;
 
   // For #2, changing the accent attribute will trigger a re-build of
   // all automatic data in the embellished hierarchy
@@ -214,21 +210,20 @@ XXX The winner is the outermost in confl
      Within overscript, <mover> always sets displaystyle to "false", 
      but increments scriptlevel by 1 only when accent is "false".
 
      The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a
      say it shouldn't be compressed. However, The TeXBook says
      that math accents and \overline change uncramped styles to their
      cramped counterparts.
   */
-  PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
-    ? 0 : 1;
+  SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags));
   PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
     ? NS_MATHML_COMPRESSED : 0;
-  PropagatePresentationDataFor(overscriptFrame, increment,
+  PropagatePresentationDataFor(overscriptFrame,
     ~NS_MATHML_DISPLAYSTYLE | compress,
      NS_MATHML_DISPLAYSTYLE | compress);
 
   return NS_OK;
 }
 
 /*
 The REC says:
--- a/layout/mathml/base/src/nsMathMLmoverFrame.h
+++ b/layout/mathml/base/src/nsMathMLmoverFrame.h
@@ -59,24 +59,22 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
+  UpdatePresentationData(PRUint32        aFlagsValues,
                          PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   AttributeChanged(PRInt32         aNameSpaceID,
                    nsIAtom*        aAttribute,
                    PRInt32         aModType);
 
--- a/layout/mathml/base/src/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmrootFrame.cpp
@@ -106,20 +106,20 @@ nsMathMLmrootFrame::Init(nsIContent*    
 
 NS_IMETHODIMP
 nsMathMLmrootFrame::TransmitAutomaticData()
 {
   // 1. The REC says:
   //    The <mroot> element increments scriptlevel by 2, and sets displaystyle to
   //    "false", within index, but leaves both attributes unchanged within base.
   // 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed
-  UpdatePresentationDataFromChildAt(1, 1, 2,
+  UpdatePresentationDataFromChildAt(1, 1,
     ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
      NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
-  UpdatePresentationDataFromChildAt(0, 0, 0,
+  UpdatePresentationDataFromChildAt(0, 0,
      NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmrootFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                      const nsRect&           aDirtyRect,
--- a/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp
@@ -119,17 +119,17 @@ nsMathMLmsqrtFrame::InheritAutomaticData
 
 NS_IMETHODIMP
 nsMathMLmsqrtFrame::TransmitAutomaticData()
 {
   // 1. The REC says:
   //    The <msqrt> element leaves both attributes [displaystyle and scriptlevel]
   //    unchanged within all its arguments.
   // 2. The TeXBook (Ch 17. p.141) says that \sqrt is cramped 
-  UpdatePresentationDataFromChildAt(0, -1, 0,
+  UpdatePresentationDataFromChildAt(0, -1,
      NS_MATHML_COMPRESSED,
      NS_MATHML_COMPRESSED);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmsqrtFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
--- a/layout/mathml/base/src/nsMathMLmstyleFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmstyleFrame.cpp
@@ -72,33 +72,16 @@ nsMathMLmstyleFrame::InheritAutomaticDat
 
   // sync with our current state
   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
   mPresentationData.mstyle = this;
 
   // see if the displaystyle attribute is there
   nsMathMLFrame::FindAttrDisplaystyle(mContent, mPresentationData);
 
-  // see if the scriptlevel attribute is there
-  nsAutoString value;
-  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::scriptlevel_, value);
-  if (!value.IsEmpty()) {
-    PRInt32 errorCode, userValue;
-    userValue = value.ToInteger(&errorCode); 
-    if (!errorCode) {
-      if (value[0] != '+' && value[0] != '-') { // record that it is an explicit value
-        mPresentationData.flags |= NS_MATHML_EXPLICIT_SCRIPTLEVEL;
-        mPresentationData.scriptLevel = userValue;
-      }
-      else {
-        mPresentationData.scriptLevel += userValue; // incremental value...
-      }
-    }
-  }
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmstyleFrame::TransmitAutomaticData()
 {
   // Nothing particular to do here, the values that we computed in
   // InheritAutomaticData() are the values that we wanted to pass to
@@ -107,66 +90,50 @@ nsMathMLmstyleFrame::TransmitAutomaticDa
 
   return NS_OK;
 }
 
 // displaystyle and scriptlevel are special in <mstyle>...
 // Since UpdatePresentation() and UpdatePresentationDataFromChildAt() can be called
 // by a parent, ensure that the explicit attributes of <mstyle> take precedence
 NS_IMETHODIMP
-nsMathMLmstyleFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                                            PRUint32        aFlagsValues,
+nsMathMLmstyleFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                             PRUint32        aWhichFlags)
 {
   if (NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(mPresentationData.flags)) {
     // our current state takes precedence, disallow updating the displastyle
     aWhichFlags &= ~NS_MATHML_DISPLAYSTYLE;
     aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
   }
-  if (NS_MATHML_HAS_EXPLICIT_SCRIPTLEVEL(mPresentationData.flags)) {
-    // our current state takes precedence, disallow updating the scriptlevel
-    aScriptLevelIncrement = 0;
-  }
 
-  return nsMathMLContainerFrame::UpdatePresentationData(
-    aScriptLevelIncrement, aFlagsValues, aWhichFlags);
+  return nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aWhichFlags);
 }
 
 NS_IMETHODIMP
 nsMathMLmstyleFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                                        PRInt32         aLastIndex,
-                                                       PRInt32         aScriptLevelIncrement,
                                                        PRUint32        aFlagsValues,
                                                        PRUint32        aWhichFlags)
 {
   if (NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(mPresentationData.flags)) {
     // our current state takes precedence, disallow updating the displastyle
     aWhichFlags &= ~NS_MATHML_DISPLAYSTYLE;
     aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
   }
-  if (NS_MATHML_HAS_EXPLICIT_SCRIPTLEVEL(mPresentationData.flags)) {
-    // our current state takes precedence, disallow updating the scriptlevel
-    aScriptLevelIncrement = 0;
-  }
 
   // let the base class worry about the update
   return
     nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(
-      aFirstIndex, aLastIndex, aScriptLevelIncrement,
-      aFlagsValues, aWhichFlags); 
+      aFirstIndex, aLastIndex, aFlagsValues, aWhichFlags); 
 }
 
 NS_IMETHODIMP
 nsMathMLmstyleFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                       nsIAtom*        aAttribute,
                                       PRInt32         aModType)
 {
-  // Attributes common to MathML tags
-  if (CommonAttributeChangedFor(PresContext(), mContent, aAttribute))
-    return NS_OK;
-
   // Other attributes can affect too many things, ask our parent to re-layout
   // its children so that we can pick up changes in our attributes & transmit
   // them in our subtree. However, our siblings will be re-laid too. We used
   // to have a more speedier but more verbose alternative that didn't re-layout
   // our siblings. See bug 114909 - attachment 67668.
   return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
 }
--- a/layout/mathml/base/src/nsMathMLmstyleFrame.h
+++ b/layout/mathml/base/src/nsMathMLmstyleFrame.h
@@ -58,24 +58,22 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
+  UpdatePresentationData(PRUint32        aFlagsValues,
                          PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate);
 
 protected:
   nsMathMLmstyleFrame(nsStyleContext* aContext) : nsMathMLContainerFrame(aContext) {}
   virtual ~nsMathMLmstyleFrame();
 
   virtual PRIntn GetSkipSides() const { return 0; }
--- a/layout/mathml/base/src/nsMathMLmsubFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmsubFrame.cpp
@@ -69,17 +69,17 @@ nsMathMLmsubFrame::TransmitAutomaticData
   // if our base is an embellished operator, let its state bubble to us
   mPresentationData.baseFrame = mFrames.FirstChild();
   GetEmbellishDataFrom(mPresentationData.baseFrame, mEmbellishData);
 
   // 1. The REC says:
   // The <msub> element increments scriptlevel by 1, and sets displaystyle to
   // "false", within subscript, but leaves both attributes unchanged within base.
   // 2. The TeXbook (Ch 17. p.141) says the subscript is compressed
-  UpdatePresentationDataFromChildAt(1, -1, 1,
+  UpdatePresentationDataFromChildAt(1, -1,
     ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
      NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmsubFrame::Place (nsIRenderingContext& aRenderingContext,
--- a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp
@@ -71,20 +71,20 @@ nsMathMLmsubsupFrame::TransmitAutomaticD
   GetEmbellishDataFrom(mPresentationData.baseFrame, mEmbellishData);
 
   // 1. The REC says:
   //    The <msubsup> element increments scriptlevel by 1, and sets displaystyle to
   //    "false", within subscript and superscript, but leaves both attributes
   //    unchanged within base.
   // 2. The TeXbook (Ch 17. p.141) says the superscript inherits the compression
   //    while the subscript is compressed
-  UpdatePresentationDataFromChildAt(1, -1, 1,
+  UpdatePresentationDataFromChildAt(1, -1,
     ~NS_MATHML_DISPLAYSTYLE,
      NS_MATHML_DISPLAYSTYLE);
-  UpdatePresentationDataFromChildAt(1,  1, 0,
+  UpdatePresentationDataFromChildAt(1,  1,
      NS_MATHML_COMPRESSED,
      NS_MATHML_COMPRESSED);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmsubsupFrame::Place(nsIRenderingContext& aRenderingContext,
@@ -249,17 +249,17 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(
     supScriptShift3 = NSToCoordRound(scaler3 * supScriptShift1);
   }
 
   // get sup script shift depending on current script level and display style
   // Rule 18c, App. G, TeXbook
   nscoord supScriptShift;
   nsPresentationData presentationData;
   aFrame->GetPresentationData(presentationData);
-  if ( presentationData.scriptLevel == 0 &&
+  if ( aFrame->GetStyleFont()->mScriptLevel == 0 &&
        NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) &&
       !NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
     // Style D in TeXbook
     supScriptShift = supScriptShift1;
   }
   else if (NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
     // Style C' in TeXbook = D',T',S',SS'
     supScriptShift = supScriptShift3;
--- a/layout/mathml/base/src/nsMathMLmsupFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmsupFrame.cpp
@@ -69,17 +69,17 @@ nsMathMLmsupFrame::TransmitAutomaticData
   mPresentationData.baseFrame = mFrames.FirstChild();
   GetEmbellishDataFrom(mPresentationData.baseFrame, mEmbellishData);
 
   // 1. The REC says:
   // The <msup> element increments scriptlevel by 1, and sets displaystyle to
   // "false", within superscript, but leaves both attributes unchanged within base.
   // 2. The TeXbook (Ch 17. p.141) says the superscript *inherits* the compression,
   // so we don't set the compression flag. Our parent will propagate its own.
-  UpdatePresentationDataFromChildAt(1, -1, 1,
+  UpdatePresentationDataFromChildAt(1, -1,
     ~NS_MATHML_DISPLAYSTYLE,
      NS_MATHML_DISPLAYSTYLE);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmsupFrame::Place(nsIRenderingContext& aRenderingContext,
@@ -185,17 +185,17 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPr
     supScriptShift3 = NSToCoordRound(scaler3 * supScriptShift1);
   }
 
   // get sup script shift depending on current script level and display style
   // Rule 18c, App. G, TeXbook
   nscoord supScriptShift;
   nsPresentationData presentationData;
   aFrame->GetPresentationData (presentationData);
-  if ( presentationData.scriptLevel == 0 && 
+  if ( aFrame->GetStyleFont()->mScriptLevel == 0 && 
        NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) &&
       !NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
     // Style D in TeXbook
     supScriptShift = supScriptShift1;
   }
   else if (NS_MATHML_IS_COMPRESSED(presentationData.flags)) {
     // Style C' in TeXbook = D',T',S',SS'
     supScriptShift = supScriptShift3;
--- a/layout/mathml/base/src/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmtableFrame.cpp
@@ -346,86 +346,69 @@ NS_NewMathMLmtableOuterFrame (nsIPresShe
   return new (aPresShell) nsMathMLmtableOuterFrame(aContext);
 }
 
 nsMathMLmtableOuterFrame::~nsMathMLmtableOuterFrame()
 {
 }
 
 NS_IMETHODIMP
-nsMathMLmtableOuterFrame::Init(nsIContent*      aContent,
-                               nsIFrame*        aParent,
-                               nsIFrame*        aPrevInFlow)
-{
-  nsresult rv = nsTableOuterFrame::Init(aContent, aParent, aPrevInFlow);
-  nsMathMLFrame::MapCommonAttributesIntoCSS(PresContext(), aContent);
-  return rv;
-}
-
-NS_IMETHODIMP
 nsMathMLmtableOuterFrame::InheritAutomaticData(nsIFrame* aParent)
 {
   // XXX the REC says that by default, displaystyle=false in <mtable>
 
-  // let the base class inherit the scriptlevel and displaystyle from our parent
+  // let the base class inherit the displaystyle from our parent
   nsMathMLFrame::InheritAutomaticData(aParent);
 
   // see if the displaystyle attribute is there and let it override what we inherited
   if (mContent->Tag() == nsGkAtoms::mtable_)
     nsMathMLFrame::FindAttrDisplaystyle(mContent, mPresentationData);
 
   return NS_OK;
 }
 
 // displaystyle is special in mtable...
 // Since UpdatePresentation() and UpdatePresentationDataFromChildAt() can be called
 // by a parent, ensure that the displaystyle attribute of mtable takes precedence
 NS_IMETHODIMP
-nsMathMLmtableOuterFrame::UpdatePresentationData(PRInt32  aScriptLevelIncrement,
-                                                 PRUint32 aFlagsValues,
+nsMathMLmtableOuterFrame::UpdatePresentationData(PRUint32 aFlagsValues,
                                                  PRUint32 aWhichFlags)
 {
   if (NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(mPresentationData.flags)) {
     // our current state takes precedence, disallow updating the displastyle
     aWhichFlags &= ~NS_MATHML_DISPLAYSTYLE;
     aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
   }
 
-  return nsMathMLFrame::UpdatePresentationData(
-    aScriptLevelIncrement, aFlagsValues, aWhichFlags);
+  return nsMathMLFrame::UpdatePresentationData(aFlagsValues, aWhichFlags);
 }
 
 NS_IMETHODIMP
 nsMathMLmtableOuterFrame::UpdatePresentationDataFromChildAt(PRInt32  aFirstIndex,
                                                             PRInt32  aLastIndex,
-                                                            PRInt32  aScriptLevelIncrement,
                                                             PRUint32 aFlagsValues,
                                                             PRUint32 aWhichFlags)
 {
   if (NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(mPresentationData.flags)) {
     // our current state takes precedence, disallow updating the displastyle
     aWhichFlags &= ~NS_MATHML_DISPLAYSTYLE;
     aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
   }
 
   nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(this,
-    aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aWhichFlags);
+    aFirstIndex, aLastIndex, aFlagsValues, aWhichFlags);
 
   return NS_OK; 
 }
 
 NS_IMETHODIMP
 nsMathMLmtableOuterFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                            nsIAtom* aAttribute,
                                            PRInt32  aModType)
 {
-  // Attributes common to MathML tags
-  if (nsMathMLFrame::CommonAttributeChangedFor(PresContext(), mContent, aAttribute))
-    return NS_OK;
-
   // Attributes specific to <mtable>:
   // frame         : in mathml.css
   // framespacing  : not yet supported 
   // groupalign    : not yet supported
   // equalrows     : not yet supported 
   // equalcolumns  : not yet supported 
   // displaystyle  : here 
   // align         : in reflow 
@@ -451,17 +434,16 @@ nsMathMLmtableOuterFrame::AttributeChang
     return NS_OK;
   }
 
   // displaystyle - may seem innocuous, but it is actually very harsh --
   // like changing an unit. Blow away and recompute all our automatic
   // presentational data, and issue a style-changed reflow request
   if (aAttribute == nsGkAtoms::displaystyle_) {
     nsMathMLContainerFrame::RebuildAutomaticDataForChildren(mParent);
-    nsMathMLContainerFrame::PropagateScriptStyleFor(tableFrame, mPresentationData.scriptLevel);
     // Need to reflow the parent, not us, because this can actually
     // affect siblings.
     PresContext()->PresShell()->
       FrameNeedsReflow(mParent, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
     return NS_OK;
   }
 
   // ...and the other attributes affect rows or columns in one way or another
@@ -702,34 +684,20 @@ NS_NewMathMLmtrFrame(nsIPresShell* aPres
   return new (aPresShell) nsMathMLmtrFrame(aContext);
 }
 
 nsMathMLmtrFrame::~nsMathMLmtrFrame()
 {
 }
 
 NS_IMETHODIMP
-nsMathMLmtrFrame::Init(nsIContent* aContent,
-                       nsIFrame*   aParent,
-                       nsIFrame*   aPrevInFlow)
-{
-  nsresult rv = nsTableRowFrame::Init(aContent, aParent, aPrevInFlow);
-  nsMathMLFrame::MapCommonAttributesIntoCSS(PresContext(), aContent);
-  return rv;
-}
-
-NS_IMETHODIMP
 nsMathMLmtrFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                    nsIAtom* aAttribute,
                                    PRInt32  aModType)
 {
-  // Attributes common to MathML tags
-  if (nsMathMLFrame::CommonAttributeChangedFor(PresContext(), mContent, aAttribute))
-    return NS_OK;
-
   // Attributes specific to <mtr>:
   // groupalign  : Not yet supported.
   // rowalign    : Fully specified in mathml.css, and so HasAttributeDependentStyle() will
   //               pick it up and nsCSSFrameConstructor will issue a PostRestyleEvent().
   // columnalign : Need an explicit re-style call.
 
   if (aAttribute == nsGkAtoms::rowalign_) {
     // unset any -moz attribute that we may have set earlier, and re-sync
@@ -776,26 +744,16 @@ NS_NewMathMLmtdFrame(nsIPresShell* aPres
 {
   return new (aPresShell) nsMathMLmtdFrame(aContext);
 }
 
 nsMathMLmtdFrame::~nsMathMLmtdFrame()
 {
 }
 
-NS_IMETHODIMP
-nsMathMLmtdFrame::Init(nsIContent* aContent,
-                       nsIFrame*   aParent,
-                       nsIFrame*   aPrevInFlow)
-{
-  nsresult rv = nsTableCellFrame::Init(aContent, aParent, aPrevInFlow);
-  nsMathMLFrame::MapCommonAttributesIntoCSS(PresContext(), aContent);
-  return rv;
-}
-
 PRInt32
 nsMathMLmtdFrame::GetRowSpan()
 {
   PRInt32 rowspan = 1;
 
   // Don't look at the content's rowspan if we're not an mtd.
   if (mContent->Tag() == nsGkAtoms::mtd_) {
     nsAutoString value;
@@ -829,20 +787,16 @@ nsMathMLmtdFrame::GetColSpan()
   return colspan;
 }
 
 NS_IMETHODIMP
 nsMathMLmtdFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                    nsIAtom* aAttribute,
                                    PRInt32  aModType)
 {
-  // Attributes common to MathML tags
-  if (nsMathMLFrame::CommonAttributeChangedFor(PresContext(), mContent, aAttribute))
-    return NS_OK;
-
   // Attributes specific to <mtd>:
   // groupalign  : Not yet supported
   // rowalign    : in mathml.css
   // columnalign : here
   // rowspan     : here
   // columnspan  : here
 
   if (aAttribute == nsGkAtoms::columnalign_) {
--- a/layout/mathml/base/src/nsMathMLmtableFrame.h
+++ b/layout/mathml/base/src/nsMathMLmtableFrame.h
@@ -55,42 +55,28 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // Overloaded nsIMathMLFrame methods
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32  aScriptLevelIncrement,
-                         PRUint32 aFlagsValues,
+  UpdatePresentationData(PRUint32 aFlagsValues,
                          PRUint32 aWhichFlags);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aWhichFlags);
 
-  NS_IMETHOD
-  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
-  {
-    nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel);
-    return NS_OK;
-  }
-
   // overloaded nsTableOuterFrame methods
 
   NS_IMETHOD
-  Init(nsIContent*      aContent,
-       nsIFrame*        aParent,
-       nsIFrame*        aPrevInFlow);
-
-  NS_IMETHOD
   Reflow(nsPresContext*          aPresContext,
          nsHTMLReflowMetrics&     aDesiredSize,
          const nsHTMLReflowState& aReflowState,
          nsReflowStatus&          aStatus);
 
   NS_IMETHOD
   AttributeChanged(PRInt32  aNameSpaceID,
                    nsIAtom* aAttribute,
@@ -178,21 +164,16 @@ class nsMathMLmtrFrame : public nsTableR
 public:
   friend nsIFrame* NS_NewMathMLmtrFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // overloaded nsTableRowFrame methods
 
   NS_IMETHOD
-  Init(nsIContent* aContent,
-       nsIFrame*   aParent,
-       nsIFrame*   aPrevInFlow);
-
-  NS_IMETHOD
   AttributeChanged(PRInt32  aNameSpaceID,
                    nsIAtom* aAttribute,
                    PRInt32  aModType);
 
   NS_IMETHOD
   AppendFrames(nsIAtom*  aListName,
                nsIFrame* aFrameList)
   {
@@ -247,21 +228,16 @@ class nsMathMLmtdFrame : public nsTableC
 public:
   friend nsIFrame* NS_NewMathMLmtdFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // overloaded nsTableCellFrame methods
 
   NS_IMETHOD
-  Init(nsIContent* aContent,
-       nsIFrame*   aParent,
-       nsIFrame*   aPrevInFlow);
-
-  NS_IMETHOD
   AttributeChanged(PRInt32  aNameSpaceID,
                    nsIAtom* aAttribute,
                    PRInt32  aModType);
 
   virtual PRInt32 GetRowSpan();
   virtual PRInt32 GetColSpan();
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
@@ -282,29 +258,21 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // Overloaded nsIMathMLFrame methods
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate)
   {
     nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(this,
-      aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
-    return NS_OK;
-  }
-
-  NS_IMETHOD
-  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
-  {
-    nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel);
+      aFirstIndex, aLastIndex, aFlagsValues, aFlagsToUpdate);
     return NS_OK;
   }
 
   // overloaded nsBlockFrame methods
 
   NS_IMETHOD
   Init(nsIContent*      aContent,
        nsIFrame*        aParent,
--- a/layout/mathml/base/src/nsMathMLmunderFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmunderFrame.cpp
@@ -77,37 +77,34 @@ nsMathMLmunderFrame::AttributeChanged(PR
     return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
   }
 
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmunderFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                                            PRUint32        aFlagsValues,
+nsMathMLmunderFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                             PRUint32        aFlagsToUpdate)
 {
-  nsMathMLContainerFrame::UpdatePresentationData(
-    aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+  nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
   // disable the stretch-all flag if we are going to act like a subscript
   if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
       !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
     mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
   }
   else {
     mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmunderFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                                        PRInt32         aLastIndex,
-                                                       PRInt32         aScriptLevelIncrement,
                                                        PRUint32        aFlagsValues,
                                                        PRUint32        aFlagsToUpdate)
 {
   // munder is special... The REC says:
   // Within underscript, <munder> always sets displaystyle to "false", 
   // but increments scriptlevel by 1 only when accentunder is "false".
   // This means that
   // 1. don't allow displaystyle to change in the underscript
@@ -121,18 +118,17 @@ nsMathMLmunderFrame::UpdatePresentationD
   while (childFrame) {
     if ((index >= aFirstIndex) &&
         ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) {
       if (index > 0) {
         // disable the flag
         aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
         aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
       }
-      PropagatePresentationDataFor(childFrame,
-        aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+      PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate);
     }
     index++;
     childFrame = childFrame->GetNextSibling();
   }
   return NS_OK;
 
   // For #2, changing the accent attribute will trigger a re-build of
   // all automatic data in the embellished hierarchy
@@ -212,19 +208,18 @@ XXX The winner is the outermost setting 
 
   /* The REC says:
      Within underscript, <munder> always sets displaystyle to "false", 
      but increments scriptlevel by 1 only when accentunder is "false".
 
      The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a 
      say it should be compressed
   */
-  PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)
-    ? 0 : 1;
-  PropagatePresentationDataFor(underscriptFrame, increment,
+  SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags));
+  PropagatePresentationDataFor(underscriptFrame,
     ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
      NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
 
   return NS_OK;
 }
 
 /*
 The REC says:
--- a/layout/mathml/base/src/nsMathMLmunderFrame.h
+++ b/layout/mathml/base/src/nsMathMLmunderFrame.h
@@ -59,24 +59,22 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
+  UpdatePresentationData(PRUint32        aFlagsValues,
                          PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   AttributeChanged(PRInt32         aNameSpaceID,
                    nsIAtom*        aAttribute,
                    PRInt32         aModType);
 
--- a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp
+++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp
@@ -78,37 +78,34 @@ nsMathMLmunderoverFrame::AttributeChange
     return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
   }
 
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmunderoverFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                                                PRUint32        aFlagsValues,
+nsMathMLmunderoverFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                                 PRUint32        aFlagsToUpdate)
 {
-  nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement,
-    aFlagsValues, aFlagsToUpdate);
+  nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
   // disable the stretch-all flag if we are going to act like a subscript-superscript pair
   if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
       !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
     mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
   }
   else {
     mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmunderoverFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                                            PRInt32         aLastIndex,
-                                                           PRInt32         aScriptLevelIncrement,
                                                            PRUint32        aFlagsValues,
                                                            PRUint32        aFlagsToUpdate)
 {
   // munderover is special... The REC says:
   // Within underscript, <munder> always sets displaystyle to "false", 
   // but increments scriptlevel by 1 only when accentunder is "false".
   // Within underscript, <munderover> always sets displaystyle to "false",
   // but increments scriptlevel by 1 only when accentunder is "false". 
@@ -127,18 +124,17 @@ nsMathMLmunderoverFrame::UpdatePresentat
   while (childFrame) {
     if ((index >= aFirstIndex) &&
         ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) {
       if (index > 0) {
         // disable the flag
         aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
         aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
       }
-      PropagatePresentationDataFor(childFrame,
-        aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+      PropagatePresentationDataFor(childFrame, aFlagsValues, aFlagsToUpdate);
     }
     index++;
     childFrame = childFrame->GetNextSibling();
   }
   return NS_OK;
 
   // For #2, changing the accent attribute will trigger a re-build of
   // all automatic data in the embellished hierarchy
@@ -237,31 +233,29 @@ nsMathMLmunderoverFrame::TransmitAutomat
      Within overscript, <munderover> always sets displaystyle to "false", 
      but increments scriptlevel by 1 only when accent is "false".
  
      The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a
      say it shouldn't be compressed. However, The TeXBook says
      that math accents and \overline change uncramped styles to their
      cramped counterparts.
   */
-  PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
-    ? 0 : 1;
   PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
     ? NS_MATHML_COMPRESSED : 0;
-  PropagatePresentationDataFor(overscriptFrame, increment,
+  SetIncrementScriptLevel(2, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags));
+  PropagatePresentationDataFor(overscriptFrame,
     ~NS_MATHML_DISPLAYSTYLE | compress,
      NS_MATHML_DISPLAYSTYLE | compress);
 
   /*
      The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a 
      say it should be compressed
   */
-  increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)
-    ? 0 : 1;
-  PropagatePresentationDataFor(underscriptFrame, increment,
+  SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags));
+  PropagatePresentationDataFor(underscriptFrame,
     ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
      NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
 
   return NS_OK;
 }
 
 /*
 The REC says:
--- a/layout/mathml/base/src/nsMathMLmunderoverFrame.h
+++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.h
@@ -59,24 +59,22 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
-                         PRUint32        aFlagsValues,
+  UpdatePresentationData(PRUint32        aFlagsValues,
                          PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
                                     PRInt32         aLastIndex,
-                                    PRInt32         aScriptLevelIncrement,
                                     PRUint32        aFlagsValues,
                                     PRUint32        aFlagsToUpdate);
 
   NS_IMETHOD
   AttributeChanged(PRInt32         aNameSpaceID,
                    nsIAtom*        aAttribute,
                    PRInt32         aModType);
 
--- a/layout/mathml/content/src/mathml.css
+++ b/layout/mathml/content/src/mathml.css
@@ -79,50 +79,16 @@ math[display="inline"] {
   font-style: italic; /* if the textual content consists of a single character */
 }
 [-moz-math-font-style="normal"] {
   font-style: normal; /* if the textual content consists of multiple characters */
 }
 [-moz-math-font-style="invariant"] {
   font-style: normal; /* a non-stylable character preserves its own style */
 }
-/* change of size induced by changing the scriptlevel */
-[-moz-math-font-size="+1"] {
-  font-size: 71%;
-}
-[-moz-math-font-size="+2"] {
-  font-size: 50%;
-}
-[-moz-math-font-size="+3"] {
-  font-size: 36%;
-}
-[-moz-math-font-size="+4"] {
-  font-size: 25%;
-}
-[-moz-math-font-size="+5"] {
-  font-size: 18%;
-}
-[-moz-math-font-size="scriptminsize"] {
-  font-size: 8pt;
-}
-[-moz-math-font-size="-1"] {
-  font-size: 141%;
-}
-[-moz-math-font-size="-2"] {
-  font-size: 200%;
-}
-[-moz-math-font-size="-3"] {
-  font-size: 283%;
-}
-[-moz-math-font-size="-4"] {
-  font-size: 400%;
-}
-[-moz-math-font-size="-5"] {
-  font-size: 566%;
-}
 
 /**************************************************************************/
 /* attributes common to all tags                                          */
 /**************************************************************************/
 
 /* deprecated attributes from MathML 1.0 */
 
 /* fontstyle */
@@ -134,61 +100,25 @@ math[display="inline"] {
 }
 /* fontweight */
 [fontweight="normal"] {
   font-weight: normal;
 }
 [fontweight="bold"] {
   font-weight: bold;
 }
-/* fontsize */
-[fontsize="xx-small"] {
-  font-size: xx-small;
-}
-[fontsize="x-small"] {
-  font-size: x-small;
-}
-[fontsize="small"] {
-  font-size: small;
-}
-[fontsize="smaller"] {
-  font-size: smaller;
-}
-[fontsize="medium"] {
-  font-size: medium;
-}
-[fontsize="large"] {
-  font-size: large;
-}
-[fontsize="larger"] {
-  font-size: larger;
-}
-[fontsize="x-large"] {
-  font-size: x-large;
-}
-[fontsize="xx-large"] {
-  font-size: xx-large;
-}
 
 /* attributes from MathML 2.0 */
 
 /* These ones are handled in the back-end:
    mathcolor (replaces 'color'):
      #rgb | #rrggbb | html-color-name
    mathbackground (replaces 'background'):
      #rgb | #rrggbb | html-color-name
 */
-/* mathsize (replaces 'fontsize'):
-     small, big, number v-unit (a numeric value is handled in the back-end) */
-[mathsize="small"] {
-  font-size: small;
-}
-[mathsize="big"] {
-  font-size: large;
-}
 /* mathvariant (replaces 'fontstyle' & 'fontweight' & 'fontslant'):
      normal | bold | italic | bold-italic | double-struck | bold-fraktur | script |
      bold-script | fraktur | sans-serif | bold-sans-serif | sans-serif-italic |
      sans-serif-bold-italic | monospace
 
    Note1: These are handled with additional back-end code:
           double-struck, script, fraktur, bold-fraktur, bold-script
 
@@ -476,8 +406,26 @@ semantics > :not(:first-child) {
 }
 
 /**********************************************************************/
 /* This is used when wrapping non-MathML inline elements inside math. */
 *|*::-moz-mathml-anonymous-block {
   display: inline-block !important;
   position: static !important;
 }
+
+/*****************************************/
+/* Controlling scriptlevel               */
+/*****************************************/
+
+/* mfrac, munder, mover and munderover change the scriptlevels of their children using
+   -moz-math-increment-script-level because regular CSS rules are insufficient to
+   control when the scriptlevel should be incremented */
+:-moz-math-increment-script-level { -moz-script-level:+1; }
+
+/* all other cases can be described using regular CSS, so we do it this way because it's
+   more efficient and less code */
+mroot > :not(:first-child) { -moz-script-level:+2; }
+
+msub > :not(:first-child),
+msup > :not(:first-child),
+msubsup > :not(:first-child),
+mmultiscripts > :not(:first-child) { -moz-script-level:+1; }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-1-ref.xml
@@ -0,0 +1,36 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:96px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:192px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:96px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:192px;">Id</m:mi></m:mstyle>
+</m:math></p>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:96px;">Id</m:mi></m:mstyle>
+</m:math></p>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+</m:math></p>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+</m:math></p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-1.xml
@@ -0,0 +1,36 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mi>Id</m:mi>
+  <m:mstyle scriptlevel="+1"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle scriptlevel="+2"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle scriptlevel="+3"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle scriptlevel="-2"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+    <m:mstyle scriptlevel="+1"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+1"><m:mstyle scriptlevel="-2"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+1"><m:mstyle scriptlevel="-3"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+    <m:mstyle scriptlevel="+2"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+2"><m:mstyle scriptlevel="-2"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+2"><m:mstyle scriptlevel="-3"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+    <m:mstyle scriptlevel="+3"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+3"><m:mstyle scriptlevel="-2"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+3"><m:mstyle scriptlevel="-3"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+    <m:mstyle scriptlevel="+4"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+4"><m:mstyle scriptlevel="-2"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+    <m:mstyle scriptlevel="+4"><m:mstyle scriptlevel="-3"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-2-ref.xml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:10px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:10px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:20px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:40px;">Id</m:mi></m:mstyle>
+</m:math></p>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:18px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:12px;">Id</m:mi></m:mstyle>
+</m:math></p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-2.xml
@@ -0,0 +1,38 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<!-- Test interactions between CSS font-size and scriptlevel changes -->
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle scriptlevel="+5"><m:mi>Id</m:mi></m:mstyle>
+  <!-- Test that we can explicitly go below scriptminsize -->
+  <m:mi style="font-size:10px;">Id</m:mi>
+  <!-- Test that a relative font-size ignores the scriptlevel change in the same element -->
+  <m:mstyle scriptlevel="+5" style="font-size:100%;"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <!-- Test that scriptlevel changes are incremental (this should be 24px) -->
+  <m:mstyle scriptlevel="+1" style="font-size:48px;"><m:mstyle scriptlevel="+1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <!-- Decreasing the font size due to a scriptlevel change should do nothing when we're below minscriptsize -->
+  <m:mstyle style="font-size:10px;"><m:mstyle scriptlevel="+1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+  <!-- but we can increase -->
+  <m:mstyle style="font-size:10px;"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+  <m:mstyle style="font-size:10px;"><m:mstyle scriptlevel="-2"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <!-- An absolute font-size value resets the unconstrained size to that value, so we
+       can increase above that value with a negative scriptlevel change -->
+  <m:mstyle scriptlevel="+5"><m:mstyle style="font-size:24px;"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle></m:mstyle>
+  <!-- An relative font-size value is applied to the unconstrained size -->
+  <m:mstyle scriptlevel="+2"><m:mstyle style="font-size:200%;"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle></m:mstyle>
+  <!-- The unconstrained size does not cap the font size to below scriptminsize (so this is 18px) -->
+  <m:mstyle scriptlevel="+2"><m:mstyle style="font-size:50%;"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle></m:mstyle>
+  <!-- The unconstrained size cap the font size otherwise (so this is 12px) -->
+  <m:mstyle scriptlevel="+2"><m:mstyle style="font-size:50%;" scriptminsize="0"><m:mstyle scriptlevel="-1"><m:mi>Id</m:mi></m:mstyle></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-3-ref.xml
@@ -0,0 +1,67 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:30px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:30px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:30px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:30px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:small;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:medium;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:large;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-family:Verdana; font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-family:monospace; font-size:48px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px; background:green;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; background:green;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; background:green;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; background:green;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px; background:rgb(0,255,0);">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; background:rgb(0,255,0);">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px; color:green;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; color:green;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; color:green;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px; color:green;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:48px;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+<p><m:math>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:24px;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:0;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:0;">Id</m:mi></m:mstyle>
+  <m:mstyle><m:mi style="font-size:0;">Id</m:mi></m:mstyle>
+</m:math></p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-3.xml
@@ -0,0 +1,78 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<!-- Test attribute parsing -->
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <!-- MathML number attributes cannot start with '+' -->
+  <m:mstyle scriptsizemultiplier="+1"><m:mstyle scriptlevel="+1"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle mathsize="30px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle fontsize="30px"><m:mi>Id</m:mi></m:mstyle>
+  <!-- mathsize takes priority over fontsize -->
+  <m:mstyle mathsize="30px" fontsize="20px"><m:mi>Id</m:mi></m:mstyle>
+  <!-- CSS takes priority over mathsize and fontsize -->
+  <m:mstyle mathsize="24px" fontsize="20px" style="font-size:30px;"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle mathsize="small"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="normal"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="big"><m:mi>Id</m:mi></m:mstyle>
+  <!-- check that fontsize doesn't accept those values -->
+  <m:mstyle fontsize="small"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle fontsize="normal"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle fontsize="big"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle fontfamily="Verdana"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle fontfamily="Verdana" style="font-family:monospace;"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle mathbackground="green"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle background="green"><m:mi>Id</m:mi></m:mstyle>
+  <!-- mathsize takes priority over fontsize -->
+  <m:mstyle mathbackground="green" background="red"><m:mi>Id</m:mi></m:mstyle>
+  <!-- CSS takes priority over mathsize and fontsize -->
+  <m:mstyle mathbackground="red" background="yellow" style="background:green;"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle mathbackground="#0F0"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathbackground="#00FF00"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle mathcolor="green"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle color="green"><m:mi>Id</m:mi></m:mstyle>
+  <!-- mathsize takes priority over fontsize -->
+  <m:mstyle mathcolor="green" color="red"><m:mi>Id</m:mi></m:mstyle>
+  <!-- CSS takes priority over mathsize and fontsize -->
+  <m:mstyle mathcolor="red" color="yellow" style="color:green;"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <!-- test invalid values for MathML length attributes -->
+  <m:mstyle mathsize="20 px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="20PX"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="20"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize=".px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="..px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="+20px"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <!-- test valid values for MathML length attributes -->
+  <m:mstyle mathsize=" 24px "><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="24.0px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="24.px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="50%"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize=".0px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="-0px"><m:mi>Id</m:mi></m:mstyle>
+  <m:mstyle mathsize="0"><m:mi>Id</m:mi></m:mstyle>
+</m:mstyle></m:math></p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-4-ref.xml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<head>
+<style>
+.v { font: 48px "Verdana"; }
+</style>
+</head>
+<body>
+<p><span class="v">Hello</span></p>
+<m:math><m:mstyle><m:mi style="font-size:24px; font-family:Verdana">Id</m:mi></m:mstyle></m:math> 
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-4.xml
@@ -0,0 +1,41 @@
+<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
+<head>
+<style>
+/* test the situation where an nsStyleFont is cached in the rule tree but we have to blow it
+   away because MathML is suddenly introduced */
+.v { font: 48px "Verdana"; }
+</style>
+<script>
+function addMathML() {
+  function createMathMLElement(tag) {
+    return document.createElementNS("http://www.w3.org/1998/Math/MathML", tag);
+  }
+  
+  var body = document.getElementById("body");
+  body.offsetTop;
+
+  // if we don't blow away the rule tree correctly, then we will cache an nsStyleFont with
+  // a scriptsizemultiplier of 0.71 (the default) and use it to style mstyle2, so the
+  // scriptlevel change will not scale the text by 0.5
+  var math = createMathMLElement("math");
+  var mstyle = createMathMLElement("mstyle");
+  mstyle.setAttribute("scriptsizemultiplier", "0.5");
+  var mstyle2 = createMathMLElement("mstyle");
+  mstyle2.setAttribute("class", "v");
+  var mstyle3 = createMathMLElement("mstyle");
+  mstyle3.setAttribute("scriptlevel", "+1");
+  var mi = createMathMLElement("mi");
+  mi.textContent = "Id";
+  mstyle3.appendChild(mi);
+  mstyle2.appendChild(mstyle3);
+  mstyle.appendChild(mstyle2);
+  math.appendChild(mstyle);
+  body.appendChild(math);
+  document.documentElement.className = '';
+}
+</script>
+</head>
+<body id="body" onload="addMathML()">
+<p><span class="v">Hello</span></p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-5-ref.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle scriptlevel="+1"><m:mstyle style="font-family:serif;"><m:mi>Id</m:mi></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/355548-5.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://www.w3.org/1998/Math/MathML">
+<body>
+<p><m:math><m:mstyle scriptlevel="0" scriptsizemultiplier="0.5" scriptminsize="18px" style="font-size:48px;">
+  <m:mstyle style="font-family:sans-serif;"><m:mstyle scriptlevel="+1"><m:mstyle style="font-family:serif;"><m:mi>Id</m:mi></m:mstyle></m:mstyle></m:mstyle>
+</m:mstyle></m:math></p>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -299,16 +299,21 @@ fails == 352980-1h.html 352980-1-ref.htm
 == 352980-2e.html 352980-2-ref.html
 == 352980-2f.html 352980-2-ref.html
 == 352980-3a.html 352980-3-ref.html
 == 352980-3b.html 352980-3-ref.html
 == 352980-3c.html 352980-3-ref.html
 == 352980-3d.html 352980-3-ref.html
 == 352980-3e.html 352980-3-ref.html
 == 352980-3f.html 352980-3-ref.html
+== 355548-1.xml 355548-1-ref.xml
+== 355548-2.xml 355548-2-ref.xml
+== 355548-3.xml 355548-3-ref.xml
+== 355548-4.xml 355548-4-ref.xml
+== 355548-5.xml 355548-5-ref.xml
 == 359903-1.html 359903-1-ref.html
 == 359869-1.html 359869-1-ref.html
 == 359903-2.html 359903-2-ref.html
 == 360065-1.html 360065-1-ref.html
 == 360746-1.html 360746-1-ref.html
 == 360757-1a.html 360757-1-ref.html
 == 360757-1b.html 360757-1-ref.html
 == 361091-1.html 361091-1-ref.html
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -4613,16 +4613,20 @@ PRBool CSSParserImpl::ParseSingleValuePr
   case eCSSProperty_border_left_style_ltr_source:
   case eCSSProperty_border_left_style_rtl_source:
   case eCSSProperty_border_right_style_ltr_source:
   case eCSSProperty_border_right_style_rtl_source:
   case eCSSProperty_border_left_width_ltr_source:
   case eCSSProperty_border_left_width_rtl_source:
   case eCSSProperty_border_right_width_ltr_source:
   case eCSSProperty_border_right_width_rtl_source:
+#ifdef MOZ_MATHML
+  case eCSSProperty_script_size_multiplier:
+  case eCSSProperty_script_min_size:
+#endif
     NS_ERROR("not currently parsed here");
     return PR_FALSE;
 
   case eCSSProperty_appearance:
     return ParseVariant(aErrorCode, aValue, VARIANT_HK,
                         nsCSSProps::kAppearanceKTable);
   case eCSSProperty_azimuth:
     return ParseAzimuth(aErrorCode, aValue);
@@ -4928,16 +4932,26 @@ PRBool CSSParserImpl::ParseSingleValuePr
   case eCSSProperty_pitch:
     return ParseVariant(aErrorCode, aValue, VARIANT_HKF, nsCSSProps::kPitchKTable);
   case eCSSProperty_pitch_range:
     return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);
   case eCSSProperty_position:
     return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kPositionKTable);
   case eCSSProperty_richness:
     return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);
+#ifdef MOZ_MATHML
+  // script-level can take Integer or Number values, but only Integer ("relative")
+  // values can be specified in a style sheet. Also we only allow this property
+  // when unsafe rules are enabled, because otherwise it could interfere
+  // with rulenode optimizations if used in a non-MathML-enabled document.
+  case eCSSProperty_script_level:
+    if (!mUnsafeRulesEnabled)
+      return PR_FALSE;
+    return ParseVariant(aErrorCode, aValue, VARIANT_HI, nsnull);
+#endif
   case eCSSProperty_speak:
     return ParseVariant(aErrorCode, aValue, VARIANT_HMK | VARIANT_NONE,
                         nsCSSProps::kSpeakKTable);
   case eCSSProperty_speak_header:
     return ParseVariant(aErrorCode, aValue, VARIANT_HK,
                         nsCSSProps::kSpeakHeaderKTable);
   case eCSSProperty_speak_numeral:
     return ParseVariant(aErrorCode, aValue, VARIANT_HK,
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -512,16 +512,24 @@ CSS_PROP_POSITION(z-index, z_index, ZInd
 
 CSS_PROP_XUL(-moz-box-align, box_align, MozBoxAlign, XUL, mBoxAlign, eCSSType_Value, kBoxAlignKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-direction, box_direction, MozBoxDirection, XUL, mBoxDirection, eCSSType_Value, kBoxDirectionKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-flex, box_flex, MozBoxFlex, XUL, mBoxFlex, eCSSType_Value, nsnull) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-orient, box_orient, MozBoxOrient, XUL, mBoxOrient, eCSSType_Value, kBoxOrientKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-pack, box_pack, MozBoxPack, XUL, mBoxPack, eCSSType_Value, kBoxPackKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-ordinal-group, box_ordinal_group, MozBoxOrdinalGroup, XUL, mBoxOrdinal, eCSSType_Value, nsnull)
 
+#ifdef MOZ_MATHML
+#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
+CSS_PROP_FONT(-moz-script-level, script_level, ScriptLevel, Font, mScriptLevel, eCSSType_Value, nsnull)
+CSS_PROP_FONT(-moz-script-size-multiplier, script_size_multiplier, ScriptSizeMultiplier, Font, mScriptSizeMultiplier, eCSSType_Value, nsnull)
+CSS_PROP_FONT(-moz-script-min-size, script_min_size, ScriptMinSize, Font, mScriptMinSize, eCSSType_Value, nsnull)
+#endif
+#endif
+
 #ifdef MOZ_SVG
 // XXX treat SVG's CSS Properties as internal for now.
 // Do we want to create an nsIDOMSVGCSS2Properties interface?
 #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
 CSS_PROP_SVGRESET(clip-path, clip_path, ClipPath, SVG, mClipPath, eCSSType_Value, nsnull)
 CSS_PROP_SVG(clip-rule, clip_rule, ClipRule, SVG, mClipRule, eCSSType_Value, kFillRuleKTable)
 CSS_PROP_SVG(color-interpolation, color_interpolation, ColorInterpolation, SVG, mColorInterpolation, eCSSType_Value, kColorInterpolationKTable)
 CSS_PROP_SVG(color-interpolation-filters, color_interpolation_filters, ColorInterpolationFilters, SVG, mColorInterpolationFilters, eCSSType_Value, kColorInterpolationKTable)
--- a/layout/style/nsCSSPseudoClassList.h
+++ b/layout/style/nsCSSPseudoClassList.h
@@ -89,16 +89,20 @@ CSS_PSEUDO_CLASS(mozTypeUnsupported, ":-
 CSS_PSEUDO_CLASS(mozHasHandlerRef, ":-moz-has-handlerref")
 
 // Match nodes that are HTML but not XHTML
 CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html")
 
 // Matches anything when the specified look-and-feel metric is set
 CSS_PSEUDO_CLASS(mozSystemMetric, ":-moz-system-metric")
 
+#ifdef MOZ_MATHML
+CSS_PSEUDO_CLASS(mozMathIncrementScriptLevel, ":-moz-math-increment-script-level")
+#endif
+
 // CSS 3 UI
 // http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
 CSS_PSEUDO_CLASS(required, ":required")
 CSS_PSEUDO_CLASS(optional, ":optional")
 CSS_PSEUDO_CLASS(valid, ":valid")
 CSS_PSEUDO_CLASS(invalid, ":invalid")
 CSS_PSEUDO_CLASS(inRange, ":in-range")
 CSS_PSEUDO_CLASS(outOfRange, ":out-of-range")
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -1330,16 +1330,21 @@ static PRBool SelectorMatches(RuleProces
     }
     else if (nsCSSPseudoClasses::mozReadWrite == pseudoClass->mAtom) {
       stateToCheck = NS_EVENT_STATE_MOZ_READWRITE;
     }
     else if (nsCSSPseudoClasses::mozIsHTML == pseudoClass->mAtom) {
       result = data.mIsHTMLContent &&
         data.mContent->GetNameSpaceID() == kNameSpaceID_None;
     }
+#ifdef MOZ_MATHML
+    else if (nsCSSPseudoClasses::mozMathIncrementScriptLevel == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL;
+    }
+#endif
     else {
       NS_ERROR("CSS parser parsed a pseudo-class that we do not handle");
       result = PR_FALSE;  // unknown pseudo class
     }
     if (stateToCheck) {
       // check if the element is event-sensitive for :hover and :active
       if ((stateToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) &&
           data.mCompatMode == eCompatibility_NavQuirks &&
@@ -1913,16 +1918,19 @@ PRBool IsStateSelector(nsCSSSelector& aS
         (pseudoClass->mAtom == nsCSSPseudoClasses::required) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::optional) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::valid) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::invalid) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::inRange) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::outOfRange) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadOnly) ||
         (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadWrite) ||
+#ifdef MOZ_MATHML
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozMathIncrementScriptLevel) ||
+#endif
         (pseudoClass->mAtom == nsCSSPseudoClasses::defaultPseudo)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 static PRBool
--- a/layout/style/nsCSSStruct.h
+++ b/layout/style/nsCSSStruct.h
@@ -205,16 +205,22 @@ struct nsCSSFont : public nsCSSStruct {
   nsCSSValue mFamily;
   nsCSSValue mStyle;
   nsCSSValue mVariant;
   nsCSSValue mWeight;
   nsCSSValue mSize;
   nsCSSValue mSizeAdjust; // NEW
   nsCSSValue mStretch; // NEW
 
+#ifdef MOZ_MATHML
+  nsCSSValue mScriptLevel; // Integer values mean "relative", Number values mean "absolute" 
+  nsCSSValue mScriptSizeMultiplier;
+  nsCSSValue mScriptMinSize;
+#endif
+
 private:
   nsCSSFont(const nsCSSFont& aOther); // NOT IMPLEMENTED
 };
 
 struct nsRuleDataFont : public nsCSSFont {
   PRBool mFamilyFromHTML; // Is the family from an HTML FONT element
   nsRuleDataFont() {}
 private:
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -180,80 +180,98 @@ static void EnsureBlockDisplay(PRUint8& 
 
   default :
     // make it a block
     display = NS_STYLE_DISPLAY_BLOCK;
   }
 }
 
 // XXX This should really be done in the CSS parser.
-nsString& Unquote(nsString& aString)
+static nsString& Unquote(nsString& aString)
 {
   PRUnichar start = aString.First();
   PRUnichar end = aString.Last();
 
   if ((start == end) && 
       ((start == PRUnichar('\"')) || 
        (start == PRUnichar('\'')))) {
     PRInt32 length = aString.Length();
     aString.Truncate(length - 1);
     aString.Cut(0, 1);
   }
   return aString;
 }
 
-nscoord CalcLength(const nsCSSValue& aValue,
-                   const nsFont* aFont, 
-                   nsStyleContext* aStyleContext,
-                   nsPresContext* aPresContext,
-                   PRBool& aInherited)
+static nscoord CalcLengthWith(const nsCSSValue& aValue,
+                              nscoord aFontSize,
+                              const nsStyleFont* aStyleFont,
+                              nsStyleContext* aStyleContext,
+                              nsPresContext* aPresContext,
+                              PRBool& aInherited)
 {
   NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit");
+  NS_ASSERTION(aStyleFont || aStyleContext, "Must have style data");
+  NS_ASSERTION(aPresContext, "Must have prescontext");
+
   if (aValue.IsFixedLengthUnit()) {
     return aPresContext->TwipsToAppUnits(aValue.GetLengthTwips());
   }
   nsCSSUnit unit = aValue.GetUnit();
   if (unit == eCSSUnit_Pixel) {
     return nsPresContext::CSSPixelsToAppUnits(aValue.GetFloatValue());
   }
   // Common code for all units other than pixels:
   aInherited = PR_TRUE;
-  const nsFont* font;
-  if (aStyleContext) {
-    font = &aStyleContext->GetStyleFont()->mFont;
-  } else {
-    font = aFont;
+  if (!aStyleFont) {
+    aStyleFont = aStyleContext->GetStyleFont();
+  }
+  if (aFontSize == -1) {
+    // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize
+    // prefs into account?
+    aFontSize = aStyleFont->mFont.size;
   }
   switch (unit) {
     case eCSSUnit_EM:
     case eCSSUnit_Char: {
-      return NSToCoordRound(aValue.GetFloatValue() * (float)font->size);
+      return NSToCoordRound(aValue.GetFloatValue() * float(aFontSize));
       // XXX scale against font metrics height instead?
     }
     case eCSSUnit_EN: {
-      return NSToCoordRound((aValue.GetFloatValue() * (float)font->size) / 2.0f);
+      return NSToCoordRound((aValue.GetFloatValue() * float(aFontSize)) / 2.0f);
     }
     case eCSSUnit_XHeight: {
-      nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(*font);
+      nsFont font = aStyleFont->mFont;
+      font.size = aFontSize;
+      nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
       nscoord xHeight;
       fm->GetXHeight(xHeight);
-      return NSToCoordRound(aValue.GetFloatValue() * (float)xHeight);
+      return NSToCoordRound(aValue.GetFloatValue() * float(xHeight));
     }
     case eCSSUnit_CapHeight: {
       NS_NOTYETIMPLEMENTED("cap height unit");
-      nscoord capHeight = ((font->size / 3) * 2); // XXX HACK!
-      return NSToCoordRound(aValue.GetFloatValue() * (float)capHeight);
+      nscoord capHeight = ((aFontSize / 3) * 2); // XXX HACK!
+      return NSToCoordRound(aValue.GetFloatValue() * float(capHeight));
     }
     default:
       NS_NOTREACHED("unexpected unit");
       break;
   }
   return 0;
 }
 
+static nscoord CalcLength(const nsCSSValue& aValue,
+                          nsStyleContext* aStyleContext,
+                          nsPresContext* aPresContext,
+                          PRBool& aInherited)
+{
+  NS_ASSERTION(aStyleContext, "Must have style data");
+
+  return CalcLengthWith(aValue, -1, nsnull, aStyleContext, aPresContext, aInherited);
+}
+
 #define SETCOORD_NORMAL                 0x01   // N
 #define SETCOORD_AUTO                   0x02   // A
 #define SETCOORD_INHERIT                0x04   // H
 #define SETCOORD_PERCENT                0x08   // P
 #define SETCOORD_FACTOR                 0x10   // F
 #define SETCOORD_LENGTH                 0x20   // L
 #define SETCOORD_INTEGER                0x40   // I
 #define SETCOORD_ENUMERATED             0x80   // E
@@ -289,18 +307,18 @@ static PRBool SetCoord(const nsCSSValue&
     result = PR_FALSE;
   }
   else if (((aMask & SETCOORD_LENGTH) != 0) && 
            (aValue.GetUnit() == eCSSUnit_Char)) {
     aCoord.SetIntValue(NSToIntFloor(aValue.GetFloatValue()), eStyleUnit_Chars);
   } 
   else if (((aMask & SETCOORD_LENGTH) != 0) && 
            aValue.IsLengthUnit()) {
-    aCoord.SetCoordValue(CalcLength(aValue, nsnull, aStyleContext, aPresContext, aInherited));
-  } 
+    aCoord.SetCoordValue(CalcLength(aValue, aStyleContext, aPresContext, aInherited));
+  }
   else if (((aMask & SETCOORD_PERCENT) != 0) && 
            (aValue.GetUnit() == eCSSUnit_Percent)) {
     aCoord.SetPercentValue(aValue.GetPercentValue());
   } 
   else if (((aMask & SETCOORD_INTEGER) != 0) && 
            (aValue.GetUnit() == eCSSUnit_Integer)) {
     aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer);
   } 
@@ -671,16 +689,19 @@ CheckFontCallback(const nsRuleDataStruct
   // the parent.
   const nsCSSValue& size = fontData.mSize;
   const nsCSSValue& weight = fontData.mWeight;
   if ((size.IsRelativeLengthUnit() && size.GetUnit() != eCSSUnit_Pixel) ||
       size.GetUnit() == eCSSUnit_Percent ||
       (size.GetUnit() == eCSSUnit_Enumerated &&
        (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER ||
         size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) ||
+#ifdef MOZ_MATHML
+      fontData.mScriptLevel.GetUnit() == eCSSUnit_Integer ||
+#endif
       (weight.GetUnit() == eCSSUnit_Enumerated &&
        (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER ||
         weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) {
     NS_ASSERTION(aResult == nsRuleNode::eRulePartialReset ||
                  aResult == nsRuleNode::eRuleFullReset ||
                  aResult == nsRuleNode::eRulePartialMixed ||
                  aResult == nsRuleNode::eRuleFullMixed,
                  "we know we already have a reset-counted property");
@@ -944,16 +965,26 @@ CounterDataAtOffset(const nsRuleDataStru
 
 inline const nsCSSQuotes*
 QuotesAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
 {
   return * reinterpret_cast<const nsCSSQuotes*const*>
                            (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
 }
 
+#if defined(MOZ_MATHML) && defined(DEBUG)
+static PRBool
+AreAllMathMLPropertiesUndefined(const nsCSSFont& aRuleData)
+{
+  return aRuleData.mScriptLevel.GetUnit() == eCSSUnit_Null &&
+         aRuleData.mScriptSizeMultiplier.GetUnit() == eCSSUnit_Null &&
+         aRuleData.mScriptMinSize.GetUnit() == eCSSUnit_Null;
+}
+#endif
+
 inline nsRuleNode::RuleDetail
 nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
                                      const nsRuleDataStruct& aRuleDataStruct)
 {
   const StructCheckData *structData = gCheckProperties + aSID;
 
   // Build a count of the:
   PRUint32 total = 0,      // total number of props in the struct
@@ -1033,25 +1064,43 @@ nsRuleNode::CheckSpecifiedProperties(con
 
     }
 
 #if 0
   printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
          aSID, total, specified, inherited);
 #endif
 
+#ifdef MOZ_MATHML
+  NS_ASSERTION(aSID != eStyleStruct_Font ||
+               mPresContext->Document()->GetMathMLEnabled() ||
+               AreAllMathMLPropertiesUndefined(static_cast<const nsCSSFont&>(aRuleDataStruct)),
+               "MathML style property was defined even though MathML is disabled");
+#endif
+
   /*
    * Return the most specific information we can: prefer None or Full
    * over Partial, and Reset or Inherited over Mixed, since we can
    * optimize based on the edge cases and not the in-between cases.
    */
   nsRuleNode::RuleDetail result;
   if (inherited == total)
     result = eRuleFullInherited;
-  else if (specified == total) {
+  else if (specified == total
+#ifdef MOZ_MATHML
+           // MathML defines 3 properties in Font that will never be set when
+           // MathML is not in use. Therefore if all but three
+           // properties have been set, and MathML is not enabled, we can treat
+           // this as fully specified. Code in nsMathMLElementFactory will
+           // rebuild the rule tree and style data when MathML is first enabled
+           // (see nsMathMLElement::BindToTree).
+           || (aSID == eStyleStruct_Font && specified + 3 == total &&
+               !mPresContext->Document()->GetMathMLEnabled())
+#endif
+          ) {
     if (inherited == 0)
       result = eRuleFullReset;
     else
       result = eRuleFullMixed;
   } else if (specified == 0)
     result = eRuleNone;
   else if (specified == inherited)
     result = eRulePartialInherited;
@@ -1880,23 +1929,211 @@ nsRuleNode::AdjustLogicalBoxProp(nsStyle
       }                                                                       \
     }                                                                         \
     aHighestNode->mStyleData.mResetData->m##type_##Data = data_;              \
     /* Propagate the bit down. */                                             \
     PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode);         \
   }                                                                           \
                                                                               \
   return data_;
-  
+
+#ifdef MOZ_MATHML
+// This function figures out how much scaling should be suppressed to
+// satisfy scriptminsize. This is our attempt to implement
+// http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
+// This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
+// have been set in aFont.
+//
+// Here are the invariants we enforce:
+// 1) A decrease in size must not reduce the size below minscriptsize.
+// 2) An increase in size must not increase the size above the size we would
+// have if minscriptsize had not been applied anywhere.
+// 3) The scriptlevel-induced size change must between 1.0 and the parent's
+// scriptsizemultiplier^(new script level - old script level), as close to the
+// latter as possible subject to constraints 1 and 2.
+static nscoord
+ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont,
+                       nsPresContext* aPresContext, nscoord* aUnconstrainedSize)
+{
+  PRInt32 scriptLevelChange =
+    aFont->mScriptLevel - aParentFont->mScriptLevel;
+  if (scriptLevelChange == 0) {
+    *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize;
+    // Constraint #3 says that we cannot change size, and #1 and #2 are always
+    // satisfied with no change. It's important this be fast because it covers
+    // all non-MathML content.
+    return aParentFont->mSize;
+  }
+
+  // Compute actual value of minScriptSize
+  nscoord minScriptSize =
+    nsStyleFont::ZoomText(aPresContext, aParentFont->mScriptMinSize);
+
+  double scriptLevelScale =
+    pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange);
+  // Compute the size we would have had if minscriptsize had never been applied
+  *aUnconstrainedSize =
+    NSToCoordRound(aParentFont->mScriptUnconstrainedSize*scriptLevelScale);
+  // Compute the size we could get via scriptlevel change
+  nscoord scriptLevelSize =
+    NSToCoordRound(aParentFont->mSize*scriptLevelScale);
+  if (scriptLevelScale <= 1.0) {
+    if (aParentFont->mSize <= minScriptSize) {
+      // We can't decrease the font size at all, so just stick to no change
+      // (authors are allowed to explicitly set the font size smaller than
+      // minscriptsize)
+      return aParentFont->mSize;
+    }
+    // We can decrease, so apply constraint #1
+    return PR_MAX(minScriptSize, scriptLevelSize);
+  } else {
+    // scriptminsize can only make sizes larger than the unconstrained size
+    NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?");
+    // Apply constraint #2
+    return PR_MIN(scriptLevelSize, PR_MAX(*aUnconstrainedSize, minScriptSize));
+  }
+}
+#endif
+
+/* static */ void
+nsRuleNode::SetFontSize(nsPresContext* aPresContext,
+                        const nsRuleDataFont& aFontData,
+                        const nsStyleFont* aFont,
+                        const nsStyleFont* aParentFont,
+                        nscoord* aSize,
+                        const nsFont& aSystemFont,
+                        nscoord aParentSize,
+                        nscoord aScriptLevelAdjustedParentSize,
+                        PRBool aUsedStartStruct,
+                        PRBool& aInherited)
+{
+  PRBool zoom = PR_FALSE;
+  PRInt32 baseSize = (PRInt32) aPresContext->
+    GetDefaultFont(aFont->mFlags & NS_STYLE_FONT_FACE_MASK)->size;
+  if (eCSSUnit_Enumerated == aFontData.mSize.GetUnit()) {
+    PRInt32 value = aFontData.mSize.GetIntValue();
+    PRInt32 scaler = aPresContext->FontScaler();
+    float scaleFactor = nsStyleUtil::GetScalingFactor(scaler);
+
+    zoom = PR_TRUE;
+    if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) && 
+        (value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
+      *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
+                       scaleFactor, aPresContext, eFontSize_CSS);
+    }
+    else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) {
+      // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
+      *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
+                       scaleFactor, aPresContext);
+    }
+    else if (NS_STYLE_FONT_SIZE_LARGER  == value ||
+             NS_STYLE_FONT_SIZE_SMALLER == value) {
+      aInherited = PR_TRUE;
+
+      // Un-zoom so we use the tables correctly.  We'll then rezoom due
+      // to the |zoom = PR_TRUE| above.
+      // Note that relative units here use the parent's size unadjusted
+      // for scriptlevel changes. A scriptlevel change between us and the parent
+      // is simply ignored.
+      nscoord parentSize =
+        nsStyleFont::UnZoomText(aPresContext, aParentSize);
+
+      if (NS_STYLE_FONT_SIZE_LARGER == value) {
+        *aSize = nsStyleUtil::FindNextLargerFontSize(parentSize,
+                         baseSize, scaleFactor, aPresContext, eFontSize_CSS);
+        NS_ASSERTION(*aSize > parentSize,
+                     "FindNextLargerFontSize failed");
+      }
+      else {
+        *aSize = nsStyleUtil::FindNextSmallerFontSize(parentSize,
+                         baseSize, scaleFactor, aPresContext, eFontSize_CSS);
+        NS_ASSERTION(*aSize < parentSize ||
+                     parentSize <= nsPresContext::CSSPixelsToAppUnits(1), 
+                     "FindNextSmallerFontSize failed");
+      }
+    } else {
+      NS_NOTREACHED("unexpected value");
+    }
+  }
+  else if (aFontData.mSize.IsLengthUnit()) {
+    // Note that font-based length units use the parent's size unadjusted
+    // for scriptlevel changes. A scriptlevel change between us and the parent
+    // is simply ignored.
+    *aSize = CalcLengthWith(aFontData.mSize, aParentSize, aParentFont, nsnull,
+                        aPresContext, aInherited);
+    zoom = aFontData.mSize.IsFixedLengthUnit() ||
+           aFontData.mSize.GetUnit() == eCSSUnit_Pixel;
+  }
+  else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) {
+    aInherited = PR_TRUE;
+    // Note that % units use the parent's size unadjusted for scriptlevel
+    // changes. A scriptlevel change between us and the parent is simply
+    // ignored.
+    *aSize = NSToCoordRound(aParentSize *
+                            aFontData.mSize.GetPercentValue());
+    zoom = PR_FALSE;
+  }
+  else if (eCSSUnit_System_Font == aFontData.mSize.GetUnit()) {
+    // this becomes our cascading size
+    *aSize = aSystemFont.size;
+    zoom = PR_TRUE;
+  }
+  else if (eCSSUnit_Inherit == aFontData.mSize.GetUnit()) {
+    aInherited = PR_TRUE;
+    // We apply scriptlevel change for this case, because the default is
+    // to inherit and we don't want explicit "inherit" to differ from the
+    // default.
+    *aSize = aScriptLevelAdjustedParentSize;
+    zoom = PR_FALSE;
+  }
+  else if (eCSSUnit_Initial == aFontData.mSize.GetUnit()) {
+    // The initial value is 'medium', which has magical sizing based on
+    // the generic font family, so do that here too.
+    *aSize = baseSize;
+    zoom = PR_TRUE;
+  } else {
+    NS_ASSERTION(eCSSUnit_Null == aFontData.mSize.GetUnit(),
+                 "What kind of font-size value is this?");
+#ifdef MOZ_MATHML
+    // if aUsedStartStruct is true, then every single property in the
+    // font struct is being set all at once. This means scriptlevel is not
+    // going to have any influence on the font size; there is no need to
+    // do anything here.
+    if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) {
+      // There was no rule affecting the size but the size has been
+      // affected by the parent's size via scriptlevel change. So treat
+      // this as inherited.
+      aInherited = PR_TRUE;
+      *aSize = aScriptLevelAdjustedParentSize;
+    }
+#endif
+  }
+
+  // We want to zoom the cascaded size so that em-based measurements,
+  // line-heights, etc., work.
+  if (zoom) {
+    *aSize = nsStyleFont::ZoomText(aPresContext, *aSize);
+  }
+}
+
+static PRInt8 ClampTo8Bit(PRInt32 aValue) {
+  if (aValue < -128)
+    return -128;
+  if (aValue > 127)
+    return 127;
+  return PRInt8(aValue);
+}
+
 /* static */ void
 nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
                     nscoord aMinFontSize,
                     PRUint8 aGenericFontID, const nsRuleDataFont& aFontData,
                     const nsStyleFont* aParentFont,
-                    nsStyleFont* aFont, PRBool& aInherited)
+                    nsStyleFont* aFont, PRBool aUsedStartStruct,
+                    PRBool& aInherited)
 {
   const nsFont* defaultVariableFont =
     aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID);
 
   // -moz-system-font: enum (never inherit!)
   nsFont systemFont;
   if (eCSSUnit_Enumerated == aFontData.mSystemFont.GetUnit()) {
     nsSystemFontID sysID;
@@ -2077,95 +2314,89 @@ nsRuleNode::SetFont(nsPresContext* aPres
   else if (eCSSUnit_Inherit == aFontData.mWeight.GetUnit()) {
     aInherited = PR_TRUE;
     aFont->mFont.weight = aParentFont->mFont.weight;
   }
   else if (eCSSUnit_Initial == aFontData.mWeight.GetUnit()) {
     aFont->mFont.weight = defaultVariableFont->weight;
   }
 
+#ifdef MOZ_MATHML
+  // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
+  // they're available for font-size computation.
+
+  // -moz-script-min-size: length
+  if (aFontData.mScriptMinSize.IsLengthUnit()) {
+    aFont->mScriptMinSize =
+      CalcLength(aFontData.mScriptMinSize, aContext, aPresContext, aInherited);
+  }
+
+  // -moz-script-size-multiplier: factor, inherit
+  if (eCSSUnit_Number == aFontData.mScriptSizeMultiplier.GetUnit()) {
+    aFont->mScriptSizeMultiplier = aFontData.mScriptSizeMultiplier.GetFloatValue();
+    NS_ASSERTION(aFont->mScriptSizeMultiplier >= 0.0f, "Cannot have negative script size multiplier");
+  }
+  else if (eCSSUnit_Inherit == aFontData.mScriptSizeMultiplier.GetUnit()) {
+    aInherited = PR_TRUE;
+    aFont->mScriptSizeMultiplier = aParentFont->mScriptSizeMultiplier;
+  }
+  else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) {
+    aFont->mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
+  }
+  
+  // -moz-script-level: integer, number, inherit
+  if (eCSSUnit_Integer == aFontData.mScriptLevel.GetUnit()) {
+    // "relative"
+    aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + aFontData.mScriptLevel.GetIntValue());
+  }
+  else if (eCSSUnit_Number == aFontData.mScriptLevel.GetUnit()) {
+    // "absolute"
+    aFont->mScriptLevel = ClampTo8Bit(PRInt32(aFontData.mScriptLevel.GetFloatValue()));
+  }
+  else if (eCSSUnit_Inherit == aFontData.mScriptSizeMultiplier.GetUnit()) {
+    aInherited = PR_TRUE;
+    aFont->mScriptLevel = aParentFont->mScriptLevel;
+  }
+  else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) {
+    aFont->mScriptLevel = 0;
+  }
+#endif
+
   // font-size: enum, length, percent, inherit
-  PRBool zoom = PR_FALSE;
-  PRInt32 baseSize = (PRInt32) aPresContext->
-    GetDefaultFont(aFont->mFlags & NS_STYLE_FONT_FACE_MASK)->size;
-  if (eCSSUnit_Enumerated == aFontData.mSize.GetUnit()) {
-    PRInt32 value = aFontData.mSize.GetIntValue();
-    PRInt32 scaler = aPresContext->FontScaler();
-    float scaleFactor = nsStyleUtil::GetScalingFactor(scaler);
-
-    zoom = PR_TRUE;
-    if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) && 
-        (value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
-      aFont->mSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
-                       scaleFactor, aPresContext, eFontSize_CSS);
-    }
-    else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) {
-      // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
-      aFont->mSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
-                       scaleFactor, aPresContext);
-    }
-    else if (NS_STYLE_FONT_SIZE_LARGER      == value ||
-             NS_STYLE_FONT_SIZE_SMALLER     == value) {
-
-      aInherited = PR_TRUE;
-
-      // Un-zoom so we use the tables correctly.  We'll then rezoom due
-      // to the |zoom = PR_TRUE| above.
-      nscoord parentSize =
-          nsStyleFont::UnZoomText(aPresContext, aParentFont->mSize);
-
-      if (NS_STYLE_FONT_SIZE_LARGER == value) {
-        aFont->mSize = nsStyleUtil::FindNextLargerFontSize(parentSize,
-                         baseSize, scaleFactor, aPresContext, eFontSize_CSS);
-        NS_ASSERTION(aFont->mSize > parentSize,
-                     "FindNextLargerFontSize failed");
-      } 
-      else {
-        aFont->mSize = nsStyleUtil::FindNextSmallerFontSize(parentSize,
-                         baseSize, scaleFactor, aPresContext, eFontSize_CSS);
-        NS_ASSERTION(aFont->mSize < parentSize ||
-                     parentSize <= nsPresContext::CSSPixelsToAppUnits(1), 
-                     "FindNextSmallerFontSize failed");
-      }
-    } else {
-      NS_NOTREACHED("unexpected value");
-    }
-  }
-  else if (aFontData.mSize.IsLengthUnit()) {
-    aFont->mSize = CalcLength(aFontData.mSize, &aParentFont->mFont, nsnull, aPresContext, aInherited);
-    zoom = aFontData.mSize.IsFixedLengthUnit() ||
-           aFontData.mSize.GetUnit() == eCSSUnit_Pixel;
-  }
-  else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) {
-    aInherited = PR_TRUE;
-    aFont->mSize = NSToCoordRound(float(aParentFont->mSize) *
-                                  aFontData.mSize.GetPercentValue());
-    zoom = PR_FALSE;
-  }
-  else if (eCSSUnit_System_Font == aFontData.mSize.GetUnit()) {
-    // this becomes our cascading size
-    aFont->mSize = systemFont.size;
-    zoom = PR_TRUE;
-  }
-  else if (eCSSUnit_Inherit == aFontData.mSize.GetUnit()) {
-    aInherited = PR_TRUE;
-    aFont->mSize = aParentFont->mSize;
-    zoom = PR_FALSE;
-  }
-  else if (eCSSUnit_Initial == aFontData.mSize.GetUnit()) {
-    // The initial value is 'medium', which has magical sizing based on
-    // the generic font family, so do that here too.
-    aFont->mSize = baseSize;
-    zoom = PR_TRUE;
-  }
-
-  // We want to zoom the cascaded size so that em-based measurements,
-  // line-heights, etc., work.
-  if (zoom)
-    aFont->mSize = nsStyleFont::ZoomText(aPresContext, aFont->mSize);
+  nscoord scriptLevelAdjustedParentSize = aParentFont->mSize;
+#ifdef MOZ_MATHML
+  nscoord scriptLevelAdjustedUnconstrainedParentSize;
+  scriptLevelAdjustedParentSize =
+    ComputeScriptLevelSize(aFont, aParentFont, aPresContext,
+                           &scriptLevelAdjustedUnconstrainedParentSize);
+  NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
+               "If we have a start struct, we should have reset everything coming in here");
+#endif
+  SetFontSize(aPresContext, aFontData, aFont, aParentFont, &aFont->mSize,
+              systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
+              aUsedStartStruct, aInherited);
+#ifdef MOZ_MATHML
+  if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize &&
+      scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) {
+    // Fast path: we have not been affected by scriptminsize so we don't
+    // need to call SetFontSize again to compute the
+    // scriptminsize-unconstrained size. This is OK even if we have a
+    // start struct, because if we have a start struct then 'font-size'
+    // was specified and so scriptminsize has no effect.
+    aFont->mScriptUnconstrainedSize = aFont->mSize;
+  } else {
+    SetFontSize(aPresContext, aFontData, aFont, aParentFont,
+                &aFont->mScriptUnconstrainedSize, systemFont,
+                aParentFont->mScriptUnconstrainedSize,
+                scriptLevelAdjustedUnconstrainedParentSize,
+                aUsedStartStruct, aInherited);
+  }
+  NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
+               "scriptminsize should never be making things bigger");
+#endif
 
   // enforce the user' specified minimum font-size on the value that we expose
   aFont->mFont.size = PR_MAX(aFont->mSize, aMinFontSize);
 
   // font-size-adjust: number, none, inherit
   if (eCSSUnit_Number == aFontData.mSizeAdjust.GetUnit()) {
     aFont->mFont.sizeAdjust = aFontData.mSizeAdjust.GetFloatValue();
   }
@@ -2208,28 +2439,22 @@ nsRuleNode::SetGenericFont(nsPresContext
   }
 
   // re-apply the cascading rules, starting from the higher context
 
   // If we stopped earlier because we reached the root of the style tree,
   // we will start with the default generic font from the presentation
   // context. Otherwise we start with the higher context.
   const nsFont* defaultFont = aPresContext->GetDefaultFont(aGenericFontID);
-  nsStyleFont parentFont(*defaultFont);
-  parentFont.mSize = parentFont.mFont.size
-      = nsStyleFont::ZoomText(aPresContext, parentFont.mSize);
+  nsStyleFont parentFont(*defaultFont, aPresContext);
   if (higherContext) {
     const nsStyleFont* tmpFont = higherContext->GetStyleFont();
-    parentFont.mFlags = tmpFont->mFlags;
-    parentFont.mFont = tmpFont->mFont;
-    parentFont.mSize = tmpFont->mSize;
-  }
-  aFont->mFlags = parentFont.mFlags;
-  aFont->mFont = parentFont.mFont;
-  aFont->mSize = parentFont.mSize;
+    parentFont = *tmpFont;
+  }
+  *aFont = parentFont;
 
   PRBool dummy;
   PRUint32 fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font);
   
   for (PRInt32 i = contextPath.Count() - 1; i >= 0; --i) {
     nsStyleContext* context = (nsStyleContext*)contextPath[i];
     nsRuleDataFont fontData; // Declare a struct with null CSS values.
     nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), aPresContext, context);
@@ -2256,26 +2481,25 @@ nsRuleNode::SetGenericFont(nsPresContext
     // Compute the delta from the information that the rules specified
 
     // Avoid unnecessary operations in SetFont().  But we care if it's
     // the final value that we're computing.
     if (i != 0)
       fontData.mFamily.Reset();
 
     nsRuleNode::SetFont(aPresContext, context, aMinFontSize,
-                        aGenericFontID, fontData, &parentFont, aFont, dummy);
+                        aGenericFontID, fontData, &parentFont, aFont,
+                        PR_FALSE, dummy);
 
     // XXX Not sure if we need to do this here
     // If we have a post-resolve callback, handle that now.
     if (ruleData.mPostResolveCallback)
       (ruleData.mPostResolveCallback)((nsStyleStruct*)aFont, &ruleData);
 
-    parentFont.mFlags = aFont->mFlags;
-    parentFont.mFont = aFont->mFont;
-    parentFont.mSize = aFont->mSize;
+    parentFont = *aFont;
   }
 }
 
 static PRBool ExtractGeneric(const nsString& aFamily, PRBool aGeneric,
                              void *aData)
 {
   nsAutoString *data = static_cast<nsAutoString*>(aData);
 
@@ -2303,17 +2527,17 @@ nsRuleNode::ComputeFontData(nsStyleStruc
   // walk further up the tree.  So this means that when the font struct
   // is fully specified using *longhand* properties (excluding
   // -moz-system-font), we won't cache in the rule tree even though we
   // could.  However, it's pretty unlikely authors will do that
   // (although there is a pretty good chance they'll fully specify it
   // using the 'font' shorthand).
 
   // See if there is a minimum font-size constraint to honor
-  nscoord minimumFontSize = 
+  nscoord minimumFontSize =
     mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
 
   if (minimumFontSize < 0)
     minimumFontSize = 0;
 
   PRBool useDocumentFonts =
     mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
 
@@ -2361,17 +2585,18 @@ nsRuleNode::ComputeFontData(nsStyleStruc
       }
     }
   }
 
   // Now compute our font struct
   if (generic == kGenericFont_NONE) {
     // continue the normal processing
     nsRuleNode::SetFont(mPresContext, aContext, minimumFontSize, generic,
-                        fontData, parentFont, font, inherited);
+                        fontData, parentFont, font,
+                        aStartStruct != nsnull, inherited);
   }
   else {
     // re-calculate the font as a generic font
     inherited = PR_TRUE;
     nsRuleNode::SetGenericFont(mPresContext, aContext, generic,
                                minimumFontSize, font);
   }
 
@@ -2938,48 +3163,48 @@ nsRuleNode::ComputeDisplayData(nsStyleSt
 
     display->mClipFlags = 0; // clear it
 
     if (eCSSUnit_Auto == displayData.mClip.mTop.GetUnit()) {
       display->mClip.y = 0;
       display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
     } 
     else if (displayData.mClip.mTop.IsLengthUnit()) {
-      display->mClip.y = CalcLength(displayData.mClip.mTop, nsnull, aContext, mPresContext, inherited);
+      display->mClip.y = CalcLength(displayData.mClip.mTop, aContext, mPresContext, inherited);
       fullAuto = PR_FALSE;
     }
     if (eCSSUnit_Auto == displayData.mClip.mBottom.GetUnit()) {
       // Setting to NS_MAXSIZE for the 'auto' case ensures that
       // the clip rect is nonempty. It is important that mClip be
       // nonempty if the actual clip rect could be nonempty.
       display->mClip.height = NS_MAXSIZE;
       display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
     } 
     else if (displayData.mClip.mBottom.IsLengthUnit()) {
-      display->mClip.height = CalcLength(displayData.mClip.mBottom, nsnull, aContext, mPresContext, inherited) -
+      display->mClip.height = CalcLength(displayData.mClip.mBottom, aContext, mPresContext, inherited) -
                               display->mClip.y;
       fullAuto = PR_FALSE;
     }
     if (eCSSUnit_Auto == displayData.mClip.mLeft.GetUnit()) {
       display->mClip.x = 0;
       display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
     } 
     else if (displayData.mClip.mLeft.IsLengthUnit()) {
-      display->mClip.x = CalcLength(displayData.mClip.mLeft, nsnull, aContext, mPresContext, inherited);
+      display->mClip.x = CalcLength(displayData.mClip.mLeft, aContext, mPresContext, inherited);
       fullAuto = PR_FALSE;
     }
     if (eCSSUnit_Auto == displayData.mClip.mRight.GetUnit()) {
       // Setting to NS_MAXSIZE for the 'auto' case ensures that
       // the clip rect is nonempty. It is important that mClip be
       // nonempty if the actual clip rect could be nonempty.
       display->mClip.width = NS_MAXSIZE;
       display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
     } 
     else if (displayData.mClip.mRight.IsLengthUnit()) {
-      display->mClip.width = CalcLength(displayData.mClip.mRight, nsnull, aContext, mPresContext, inherited) -
+      display->mClip.width = CalcLength(displayData.mClip.mRight, aContext, mPresContext, inherited) -
                              display->mClip.x;
       fullAuto = PR_FALSE;
     }
     display->mClipFlags &= ~NS_STYLE_CLIP_TYPE_MASK;
     if (fullAuto) {
       display->mClipFlags |= NS_STYLE_CLIP_AUTO;
     }
     else {
@@ -3272,17 +3497,17 @@ nsRuleNode::ComputeBackgroundData(nsStyl
 
   // background-position: enum, length, percent (flags), inherit
   if (eCSSUnit_Percent == colorData.mBackPosition.mXValue.GetUnit()) {
     bg->mBackgroundXPosition.mFloat = colorData.mBackPosition.mXValue.GetPercentValue();
     bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT;
     bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH;
   }
   else if (colorData.mBackPosition.mXValue.IsLengthUnit()) {
-    bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue, nsnull, 
+    bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue, 
                                                  aContext, mPresContext, inherited);
     bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_LENGTH;
     bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_PERCENT;
   }
   else if (eCSSUnit_Enumerated == colorData.mBackPosition.mXValue.GetUnit()) {
     switch (colorData.mBackPosition.mXValue.GetIntValue()) {
       case NS_STYLE_BG_POSITION_LEFT:
         bg->mBackgroundXPosition.mFloat = 0.0f;
@@ -3311,17 +3536,17 @@ nsRuleNode::ComputeBackgroundData(nsStyl
   }
 
   if (eCSSUnit_Percent == colorData.mBackPosition.mYValue.GetUnit()) {
     bg->mBackgroundYPosition.mFloat = colorData.mBackPosition.mYValue.GetPercentValue();
     bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT;
     bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH;
   }
   else if (colorData.mBackPosition.mYValue.IsLengthUnit()) {
-    bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue, nsnull,
+    bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue,
                                                  aContext, mPresContext, inherited);
     bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_LENGTH;
     bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_PERCENT;
   }
   else if (eCSSUnit_Enumerated == colorData.mBackPosition.mYValue.GetUnit()) {
     switch (colorData.mBackPosition.mYValue.GetIntValue()) {
       case NS_STYLE_BG_POSITION_TOP:
         bg->mBackgroundYPosition.mFloat = 0.0f;
@@ -3774,33 +3999,33 @@ nsRuleNode::ComputeListData(nsStyleStruc
   // if one is -moz-initial, they all are
   else if (eCSSUnit_Initial == listData.mImageRegion.mTop.GetUnit()) {
     list->mImageRegion.Empty();
   }
   else {
     if (eCSSUnit_Auto == listData.mImageRegion.mTop.GetUnit())
       list->mImageRegion.y = 0;
     else if (listData.mImageRegion.mTop.IsLengthUnit())
-      list->mImageRegion.y = CalcLength(listData.mImageRegion.mTop, nsnull, aContext, mPresContext, inherited);
+      list->mImageRegion.y = CalcLength(listData.mImageRegion.mTop, aContext, mPresContext, inherited);
       
     if (eCSSUnit_Auto == listData.mImageRegion.mBottom.GetUnit())
       list->mImageRegion.height = 0;
     else if (listData.mImageRegion.mBottom.IsLengthUnit())
-      list->mImageRegion.height = CalcLength(listData.mImageRegion.mBottom, nsnull, aContext, 
+      list->mImageRegion.height = CalcLength(listData.mImageRegion.mBottom, aContext, 
                                             mPresContext, inherited) - list->mImageRegion.y;
   
     if (eCSSUnit_Auto == listData.mImageRegion.mLeft.GetUnit())
       list->mImageRegion.x = 0;
     else if (listData.mImageRegion.mLeft.IsLengthUnit())
-      list->mImageRegion.x = CalcLength(listData.mImageRegion.mLeft, nsnull, aContext, mPresContext, inherited);
+      list->mImageRegion.x = CalcLength(listData.mImageRegion.mLeft, aContext, mPresContext, inherited);
       
     if (eCSSUnit_Auto == listData.mImageRegion.mRight.GetUnit())
       list->mImageRegion.width = 0;
     else if (listData.mImageRegion.mRight.IsLengthUnit())
-      list->mImageRegion.width = CalcLength(listData.mImageRegion.mRight, nsnull, aContext, mPresContext, inherited) -
+      list->mImageRegion.width = CalcLength(listData.mImageRegion.mRight, aContext, mPresContext, inherited) -
                                 list->mImageRegion.x;
   }
 
   COMPUTE_END_INHERITED(List, list)
 }
 
 const nsStyleStruct* 
 nsRuleNode::ComputePositionData(nsStyleStruct* aStartStruct,
--- a/layout/style/nsRuleNode.h
+++ b/layout/style/nsRuleNode.h
@@ -595,23 +595,35 @@ protected:
   NS_HIDDEN_(const nsStyleStruct*)
     ComputeSVGResetData(nsStyleStruct* aStartStruct,
                         const nsRuleDataStruct& aData, 
                         nsStyleContext* aContext, nsRuleNode* aHighestNode,
                         RuleDetail aRuleDetail, PRBool aInherited);
 #endif
 
   // helpers for |ComputeFontData| that need access to |mNoneBits|:
+  static NS_HIDDEN_(void) SetFontSize(nsPresContext* aPresContext,
+                                      const nsRuleDataFont& aFontData,
+                                      const nsStyleFont* aFont,
+                                      const nsStyleFont* aParentFont,
+                                      nscoord* aSize,
+                                      const nsFont& aSystemFont,
+                                      nscoord aParentSize,
+                                      nscoord aScriptLevelAdjustedParentSize,
+                                      PRBool aUsedStartStruct,
+                                      PRBool& aInherited);
+
   static NS_HIDDEN_(void) SetFont(nsPresContext* aPresContext,
                                   nsStyleContext* aContext,
                                   nscoord aMinFontSize,
                                   PRUint8 aGenericFontID,
                                   const nsRuleDataFont& aFontData,
                                   const nsStyleFont* aParentFont,
-                                  nsStyleFont* aFont, PRBool& aInherited);
+                                  nsStyleFont* aFont,
+                                  PRBool aStartStruct, PRBool& aInherited);
 
   static NS_HIDDEN_(void) SetGenericFont(nsPresContext* aPresContext,
                                          nsStyleContext* aContext,
                                          PRUint8 aGenericFontID,
                                          nscoord aMinFontSize,
                                          nsStyleFont* aFont);
 
   NS_HIDDEN_(void) AdjustLogicalBoxProp(nsStyleContext* aContext,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -101,43 +101,55 @@ static PRBool EqualImages(imgIRequest *a
   aImage1->GetURI(getter_AddRefs(uri1));
   aImage2->GetURI(getter_AddRefs(uri2));
   return EqualURIs(uri1, uri2);
 }
 
 // --------------------
 // nsStyleFont
 //
-nsStyleFont::nsStyleFont()
-  : mFlags(NS_STYLE_FONT_DEFAULT),
-    mFont(nsnull, NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
-          NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE, 0),
-    mSize(0)
-{ }
+nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext)
+  : mFont(aFont),
+    mFlags(NS_STYLE_FONT_DEFAULT)
+{
+  mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
+#ifdef MOZ_MATHML
+  mScriptUnconstrainedSize = mSize;
+  mScriptMinSize = aPresContext->TwipsToAppUnits(
+      NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
+  mScriptLevel = 0;
+  mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
+#endif
+}
 
-nsStyleFont::nsStyleFont(const nsFont& aFont)
-  : mFlags(NS_STYLE_FONT_DEFAULT),
-    mFont(aFont),
-    mSize(aFont.size)
+nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
+  : mFont(aSrc.mFont)
+  , mSize(aSrc.mSize)
+  , mFlags(aSrc.mFlags)
+#ifdef MOZ_MATHML
+  , mScriptLevel(aSrc.mScriptLevel)
+  , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
+  , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
+  , mScriptMinSize(aSrc.mScriptMinSize)
+#endif
 {
 }
 
-nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
-  : mFlags(aSrc.mFlags),
-    mFont(aSrc.mFont),
-    mSize(aSrc.mSize)
-{
-}
-
-
 nsStyleFont::nsStyleFont(nsPresContext* aPresContext)
-  : mFlags(NS_STYLE_FONT_DEFAULT),
-    mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID)))
+  : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID))),
+    mFlags(NS_STYLE_FONT_DEFAULT)
 {
   mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
+#ifdef MOZ_MATHML
+  mScriptUnconstrainedSize = mSize;
+  mScriptMinSize = aPresContext->TwipsToAppUnits(
+      NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
+  mScriptLevel = 0;
+  mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
+#endif
 }
 
 void* 
 nsStyleFont::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
   void* result = aContext->AllocateFromShell(sz);
   if (result)
     memset(result, 0, sz);
   return result;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -84,40 +84,48 @@ class imgIRequest;
 
 // The actual structs start here
 struct nsStyleStruct {
 };
 
 // The lifetime of these objects is managed by the presshell's arena.
 
 struct nsStyleFont : public nsStyleStruct {
-  nsStyleFont(void);
-  nsStyleFont(const nsFont& aFont);
+  nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext);
   nsStyleFont(const nsStyleFont& aStyleFont);
   nsStyleFont(nsPresContext *aPresContext);
   ~nsStyleFont(void) {}
 
   nsChangeHint CalcDifference(const nsStyleFont& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static nsChangeHint CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2);
 
   static nscoord ZoomText(nsPresContext* aPresContext, nscoord aSize);
   static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
-  
+
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
   void Destroy(nsPresContext* aContext);
 
-  PRUint8 mFlags;       // [inherited] See nsStyleConsts.h
   nsFont  mFont;        // [inherited]
   nscoord mSize;        // [inherited] Our "computed size". Can be different from mFont.size
                         // which is our "actual size" and is enforced to be >= the user's
                         // preferred min-size. mFont.size should be used for display purposes
                         // while mSize is the value to return in getComputedStyle() for example.
+  PRUint8 mFlags;       // [inherited] See nsStyleConsts.h
+
+#ifdef MOZ_MATHML
+  // MathML scriptlevel support
+  PRInt8  mScriptLevel;          // [inherited]
+  // The value mSize would have had if scriptminsize had never been applied
+  nscoord mScriptUnconstrainedSize;
+  nscoord mScriptMinSize;        // [inherited] length
+  float   mScriptSizeMultiplier; // [inherited]
+#endif
 };
 
 struct nsStyleColor : public nsStyleStruct {
   nsStyleColor(nsPresContext* aPresContext);
   nsStyleColor(const nsStyleColor& aOther);
   ~nsStyleColor(void) {}
 
   nsChangeHint CalcDifference(const nsStyleColor& aOther) const;
--- a/layout/style/test/ListCSSProperties.cpp
+++ b/layout/style/test/ListCSSProperties.cpp
@@ -147,17 +147,20 @@ const char *gInaccessibleProperties[] = 
     "margin-right-rtl-source",
     "padding-end-value",
     "padding-left-value",
     "padding-right-value",
     "padding-start-value",
     "padding-left-ltr-source",
     "padding-left-rtl-source",
     "padding-right-ltr-source",
-    "padding-right-rtl-source"
+    "padding-right-rtl-source",
+    "-moz-script-level", // parsed by UA sheets only
+    "-moz-script-size-multiplier",
+    "-moz-script-min-size"
 };
 
 inline int
 is_inaccessible(const char* aPropName)
 {
     for (unsigned j = 0; j < ARRAY_LENGTH(gInaccessibleProperties); ++j) {
         if (strcmp(aPropName, gInaccessibleProperties[j]) == 0)
             return 1;