backing out bug 355548 due to test failures
authorroc+@cs.cmu.edu
Tue, 08 Jan 2008 15:11:27 -0800
changeset 10028 9f8a223acc52c3fbc659a8dbad16611ec091172f
parent 10027 99ce1d01fea100b6de471546d7a377a3a6722cb9
child 10029 5181b7cf429dcd25291ce7e7f7cd4bfabb268194
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
backing out bug 355548 due to test failures
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/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/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/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,20 +48,16 @@ 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 states BidiEnabled and MathMLEnabled should persist across multiple views
+  // The state BidiEnabled 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,29 +292,16 @@ 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;
   }
@@ -973,18 +960,16 @@ 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,19 +175,17 @@ 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,
-    /** nsMathMLElement */
-    eMATHML              = 1 << 13
+    eDATA_NODE           = 1 << 12
   };
 
   /**
    * 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,17 +131,16 @@ 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 "nsMappedAttributeElement.h"
+#include "nsGenericHTMLElement.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,
-                                          nsMappedAttributeElement* aContent,
+                                          nsGenericHTMLElement* 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(nsMappedAttributeElement* aContent,
+nsAttrAndChildArray::GetModifiableMapped(nsGenericHTMLElement* 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 nsMappedAttributeElement;
+class nsGenericHTMLElement;
 
 #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,
-                                nsMappedAttributeElement* aContent,
+                                nsGenericHTMLElement* 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(nsMappedAttributeElement* aContent,
+  nsresult GetModifiableMapped(nsGenericHTMLElement* aContent,
                                nsHTMLStyleSheet* aSheet,
                                PRBool aWillAddAttr,
                                nsMappedAttributes** aModifiable);
   nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
 
   PRUint32 AttrSlotsSize() const
   {
     return AttrSlotCount() * ATTRSIZE;
--- 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 "nsMappedAttributeElement.h"
+#include "nsGenericHTMLElement.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,13 +210,10 @@ 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,16 +1141,23 @@ 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)
 {
@@ -1423,16 +1430,23 @@ 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);
@@ -1521,16 +1535,32 @@ 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,43 +33,48 @@
  * 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 "nsMappedAttributeElement.h"
+#include "nsStyledElement.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 nsMappedAttributeElement nsGenericHTMLElementBase;
+typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, 
+                                          nsRuleData* aData);
+
+typedef nsStyledElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase
 {
 public:
   nsGenericHTMLElement(nsINodeInfo *aNodeInfo)
@@ -229,28 +234,33 @@ 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 nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+  virtual PRBool SetMappedAttribute(nsIDocument* aDocument,
+                                    nsIAtom* aName,
+                                    nsAttrValue& aValue,
+                                    nsresult* aRetval);
 
   /**
    * 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 RebuildStyleData.  Also, holding onto pointers to the
+   * call ClearStyleDataAndReflow.  Also, holding onto pointers to the
    * presentatation through style resolution is potentially dangerous.
    */
   {
     nsIPresShell *shell = GetPrimaryShell();
     if (!shell) {
       return NS_OK;
     }
 
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -904,16 +904,38 @@ 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->RebuildAllStyleData();
+        pcx->ClearStyleDataAndReflow();
       }
 
       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->RebuildAllStyleData();
+      pcx->ClearStyleDataAndReflow();
     }
 
     return NS_OK;
   }
 
   PRBool force_get = PR_FALSE;
 
   PRUint32 argc;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1830,17 +1830,16 @@ 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");
   }
 
@@ -13260,49 +13259,16 @@ 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;
   }
   
@@ -13338,22 +13304,16 @@ 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) {
@@ -13381,24 +13341,16 @@ 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,34 +172,20 @@ 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
@@ -1143,17 +1129,16 @@ 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,16 +696,48 @@ 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) {
@@ -718,23 +750,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);
 
-      RebuildAllStyleData();
+      ClearStyleDataAndReflow();
     }
     return;
   }
   if (!nsCRT::strcmp(aPrefName, sMinFontSizePref)) {
     mAutoQualityMinFontSizePixelsPref = nsContentUtils::GetIntPref(sMinFontSizePref);
-    RebuildAllStyleData();
+    ClearStyleDataAndReflow();
     return;
   }
   // we use a zero-delay timer to coalesce multiple pref updates
   if (!mPrefChangedTimer)
   {
     mPrefChangedTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (!mPrefChangedTimer)
       return;
@@ -759,17 +791,17 @@ nsPresContext::UpdateAfterPreferencesCha
   GetUserPreferences();
 
   // update the presShell: tell it to set the preference style rules up
   if (mShell) {
     mShell->SetPreferenceStyleRules(PR_TRUE);
   }
 
   mDeviceContext->FlushFontCache();
-  RebuildAllStyleData();
+  ClearStyleDataAndReflow();
 }
 
 nsresult
 nsPresContext::Init(nsIDeviceContext* aDeviceContext)
 {
   NS_ASSERTION(!(mInitialized == PR_TRUE), "attempt to reinit pres context");
   NS_ENSURE_ARG(aDeviceContext);
 
@@ -945,17 +977,18 @@ 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();
-    RebuildAllStyleData();
+    ClearStyleDataAndReflow();
+
     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
@@ -1136,17 +1169,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()));
-  RebuildAllStyleData();
+  ClearStyleDataAndReflow();
   mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
 }
 
 imgIRequest*
 nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
 {
   // look and see if we have a loader for the target frame.
   nsCOMPtr<nsImageLoader> loader;
@@ -1246,24 +1279,24 @@ nsPresContext::GetBidiUtils()
 {
   if (!mBidiUtils)
     mBidiUtils = new nsBidiPresUtils;
 
   return mBidiUtils;
 }
 
 void
-nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceRestyle)
+nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow)
 {
   // Don't do all this stuff unless the options have changed.
   if (aSource == GetBidi()) {
     return;
   }
 
-  NS_ASSERTION(!(aForceRestyle && (GetBidi() == 0)), 
+  NS_ASSERTION(!(aForceReflow && (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)) {
@@ -1273,18 +1306,18 @@ nsPresContext::SetBidi(PRUint32 aSource,
     SetVisualMode(PR_FALSE);
   }
   else {
     nsIDocument* doc = mShell->GetDocument();
     if (doc) {
       SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
     }
   }
-  if (aForceRestyle) {
-    RebuildAllStyleData();
+  if (aForceReflow) {
+    ClearStyleDataAndReflow();
   }
 }
 
 PRUint32
 nsPresContext::GetBidi() const
 {
   return Document()->GetBidiOptions();
 }
@@ -1335,17 +1368,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.
-  RebuildAllStyleData();
+  nsPresContext::ClearStyleDataAndReflow();
 }
 
 void
 nsPresContext::SysColorChanged()
 {
   if (!mPendingSysColorChanged) {
     sLookAndFeelChanged = PR_TRUE;
     nsCOMPtr<nsIRunnable> ev =
@@ -1371,31 +1404,17 @@ 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.
-  // 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();
+  ClearStyleDataAndReflow();
 }
 
 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,19 +196,16 @@ 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();
   }
   /**
@@ -236,16 +233,21 @@ 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)
@@ -461,17 +463,17 @@ public:
 
   nsIDeviceContext* DeviceContext() { return mDeviceContext; }
   nsIEventStateManager* EventStateManager() { return mEventManager; }
   nsIAtom* GetLangGroup() { return mLangGroup; }
 
   float TextZoom() { return mTextZoom; }
   void SetTextZoom(float aZoom) {
     mTextZoom = aZoom;
-    RebuildAllStyleData();
+    ClearStyleDataAndReflow();
   }
 
   float GetFullZoom() { return mFullZoom; }
   void SetFullZoom(float aZoom);
 
   nscoord GetAutoQualityMinFontSize() {
     return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
   }
@@ -630,17 +632,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 aForceRestyle = PR_FALSE);
+                           PRBool aForceReflow = 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,20 +423,16 @@
 #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,34 +173,33 @@ 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) \
-		$(DEPTH)/content/mathml/content/src/$(LIB_PREFIX)gkcontentmathml_s.$(LIB_SUFFIX) \
-		$(NULL)
+                ../mathml/content/src/$(LIB_PREFIX)gkmathmlcon_s.$(LIB_SUFFIX) \
+                ../mathml/base/src/$(LIB_PREFIX)gkmathmlbase_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,18 +71,16 @@ 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,74 +221,116 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent) = 0;
 
   NS_IMETHOD
   TransmitAutomaticData() = 0;
 
  /* UpdatePresentationData :
-  * 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).
+  * 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).
   *
   * Note that <mstyle> is the only tag which allows to set
-  * <mstyle displaystyle="true|false">
+  * <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
+  * to reset or increment the scriptlevel in a manual way. 
   * 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(PRUint32        aFlagsValues,
+  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                         PRUint32        aFlagsValues,
                          PRUint32        aWhichFlags) = 0;
 
  /* UpdatePresentationDataFromChildAt :
-  * 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. 
+  * 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. 
   *
   * Note that <mstyle> is the only tag which allows
-  * <mstyle displaystyle="true|false">
+  * <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
+  * to reset or increment the scriptlevel in a manual way.
   * 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 {
@@ -332,20 +374,25 @@ 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
@@ -371,16 +418,22 @@ 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
@@ -406,16 +459,19 @@ 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,17 +59,16 @@
 #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
@@ -565,66 +564,186 @@ 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)
+  if (!aFrame || (!aFlagsToUpdate && !aScriptLevelIncrement))
     return;
   nsIMathMLFrame* mathMLFrame;
   aFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame);
   if (mathMLFrame) {
     // update
-    mathMLFrame->UpdatePresentationData(aFlagsValues,
+    mathMLFrame->UpdatePresentationData(aScriptLevelIncrement, 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,
-      aFlagsValues, aFlagsToUpdate);
+      aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
   }
   else {
     // propagate down the subtrees
     nsIFrame* childFrame = aFrame->GetFirstChild(nsnull);
     while (childFrame) {
       PropagatePresentationDataFor(childFrame,
-        aFlagsValues, aFlagsToUpdate);
+        aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
       childFrame = childFrame->GetNextSibling();
     }
   }
 }
 
 /* static */ void
 nsMathMLContainerFrame::PropagatePresentationDataFromChildAt(nsIFrame*       aParentFrame,
                                                              PRInt32         aFirstChildIndex,
                                                              PRInt32         aLastChildIndex,
+                                                             PRInt32         aScriptLevelIncrement,
                                                              PRUint32        aFlagsValues,
                                                              PRUint32        aFlagsToUpdate)
 {
-  if (!aParentFrame || !aFlagsToUpdate)
+  if (!aParentFrame || (!aFlagsToUpdate && !aScriptLevelIncrement))
     return;
   PRInt32 index = 0;
   nsIFrame* childFrame = aParentFrame->GetFirstChild(nsnull);
   while (childFrame) {
     if ((index >= aFirstChildIndex) &&
         ((aLastChildIndex <= 0) || ((aLastChildIndex > 0) &&
          (index <= aLastChildIndex)))) {
       PropagatePresentationDataFor(childFrame,
-        aFlagsValues, aFlagsToUpdate);
+        aScriptLevelIncrement, 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,
@@ -652,16 +771,32 @@ 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
@@ -687,27 +822,32 @@ 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)
+    if (mathMLFrame) {
+      nsPresentationData parentData;
+      mathMLFrame->GetPresentationData(parentData);
+      parentScriptLevel = parentData.scriptLevel;
       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)
@@ -718,16 +858,32 @@ 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);
@@ -802,16 +958,20 @@ 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);
 }
 
@@ -1138,22 +1298,21 @@ public:
     mChildFrame = mChildFrame->GetNextSibling();
     if (!mChildFrame)
       return *this;
 
     eMathMLFrameType prevFrameType = mChildFrameType;
     InitMetricsForChild();
 
     // add inter frame spacing
-    const nsStyleFont* font = mParentFrame->GetStyleFont();
     nscoord space =
-      GetInterFrameSpacing(font->mScriptLevel,
+      GetInterFrameSpacing(mParentFrame->mPresentationData.scriptLevel,
                            prevFrameType, mChildFrameType,
                            &mFromFrameType, &mCarrySpace);
-    mX += space * GetThinSpace(font);
+    mX += space * GetThinSpace(mParentFrame->GetStyleFont());
     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; }
@@ -1238,48 +1397,16 @@ 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)
 {
@@ -1318,17 +1445,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(GetStyleFont()->mScriptLevel, mParent, this);
+    gap = GetInterFrameSpacingFor(mPresentationData.scriptLevel, 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,16 +56,26 @@
  * 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:
@@ -85,46 +95,47 @@ 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,
-      aFlagsValues, aFlagsToUpdate);
+      aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
     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);
+
+  NS_IMETHOD
+  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
+  {
+    PropagateScriptStyleFor(this, aParentScriptLevel);
+    return NS_OK;
+  }
 
   // --------------------------------------------------------------------------
   // 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);
 
@@ -236,27 +247,35 @@ 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
@@ -328,21 +347,35 @@ 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,
@@ -383,36 +416,59 @@ 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,
@@ -449,11 +505,20 @@ 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,21 +54,29 @@ 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, aFlagsValues, aFlagsToUpdate);
+      aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+    return NS_OK;
+  }
+
+  NS_IMETHOD
+  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
+  {
+    nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel);
     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,36 +112,40 @@ 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 of our parent
+  // by default, just inherit the display & scriptlevel 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(PRUint32        aFlagsValues,
+nsMathMLFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                                      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;
@@ -206,16 +210,17 @@ 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);
@@ -341,16 +346,116 @@ 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()) {
@@ -450,16 +555,257 @@ 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,17 +44,16 @@
 #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 ------
@@ -145,28 +144,36 @@ public:
 
   NS_IMETHOD
   TransmitAutomaticData()
   {
     return NS_OK;
   }
 
   NS_IMETHOD
-  UpdatePresentationData(PRUint32        aFlagsValues,
+  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                         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,
@@ -211,20 +218,18 @@ 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(const nsString& aString,
-                    nsCSSValue&     aCSSValue) {
-    return nsMathMLElement::ParseNumericValue(aString, aCSSValue, PR_FALSE);
-  }
+  ParseNumericValue(nsString&   aString,
+                    nsCSSValue& aCSSValue);
 
   static nscoord 
   CalcLength(nsPresContext*   aPresContext,
              nsStyleContext*   aStyleContext,
              const nsCSSValue& aCSSValue);
 
   static PRBool
   ParseNamedSpaceValue(nsIFrame*   aMathMLmstyleFrame,
@@ -423,16 +428,34 @@ 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,18 +262,17 @@ nsMathMLmfencedFrame::doReflow(nsPresCon
   aDesiredSize.ascent = 0;
   aDesiredSize.mBoundingMetrics.Clear();
 
   nsMathMLContainerFrame* mathMLFrame =
     static_cast<nsMathMLContainerFrame*>(aForFrame);
 
   PRInt32 i;
   nsCOMPtr<nsIFontMetrics> fm;
-  const nsStyleFont* font = aForFrame->GetStyleFont();
-  aReflowState.rendContext->SetFont(font->mFont, nsnull);
+  aReflowState.rendContext->SetFont(aForFrame->GetStyleFont()->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); 
 
   /////////////
@@ -386,29 +385,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, font->mScriptLevel, 
+             NS_MATHML_OPERATOR_FORM_PREFIX, presentationData.scriptLevel, 
              axisHeight, leading, em, containerSize, ascent, descent);
   /////////////////
   // separators ...
   for (i = 0; i < aSeparatorsCount; i++) {
     ReflowChar(aPresContext, *aReflowState.rendContext, &aSeparatorsChar[i],
-               NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
+               NS_MATHML_OPERATOR_FORM_INFIX, presentationData.scriptLevel,
                axisHeight, leading, em, containerSize, ascent, descent);
   }
   /////////////////
   // closing fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, aCloseChar,
-             NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
+             NS_MATHML_OPERATOR_FORM_POSTFIX, presentationData.scriptLevel,
              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,24 +125,23 @@ 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
-  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,
+  PRInt32 increment =
+     NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) ? 0 : 1;
+  mInnerScriptLevel = mPresentationData.scriptLevel + increment;
+  UpdatePresentationDataFromChildAt(0, -1, increment,
     ~NS_MATHML_DISPLAYSTYLE,
      NS_MATHML_DISPLAYSTYLE);
-  UpdatePresentationDataFromChildAt(1,  1,
+  UpdatePresentationDataFromChildAt(1,  1, 0,
      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
@@ -474,18 +473,64 @@ 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.,
@@ -495,17 +540,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,
-      aFlagsValues, aFlagsToUpdate);
+      aScriptLevelIncrement, 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,18 +120,24 @@ 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
@@ -146,13 +152,14 @@ 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,
+  UpdatePresentationDataFromChildAt(1, -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,
+    PropagatePresentationDataFor(childFrame, 0,
       NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED);
   }
 
   return NS_OK;
 }
 
 void
 nsMathMLmmultiscriptsFrame::ProcessAttributes()
@@ -153,18 +153,17 @@ nsMathMLmmultiscriptsFrame::Place(nsIRen
   ////////////////////////////////////////
   // Initialize super/sub shifts that
   // depend only on the current font
   ////////////////////////////////////////
 
   ProcessAttributes();
 
   // get x-height (an ex)
-  const nsStyleFont* font = GetStyleFont();
-  aRenderingContext.SetFont(font->mFont, nsnull);
+  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull);
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord xHeight;
   fm->GetXHeight (xHeight);
 
   nscoord ruleSize;
   GetRuleThickness (aRenderingContext, fm, ruleSize);
@@ -213,17 +212,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 ( font->mScriptLevel == 0 &&
+  if ( mPresentationData.scriptLevel == 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 (GetStyleFont()->mScriptLevel > 0) {
+      if (mPresentationData.scriptLevel > 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,34 +77,37 @@ nsMathMLmoverFrame::AttributeChanged(PRI
     return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
   }
 
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmoverFrame::UpdatePresentationData(PRUint32        aFlagsValues,
+nsMathMLmoverFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                                           PRUint32        aFlagsValues,
                                            PRUint32        aFlagsToUpdate)
 {
-  nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
+  nsMathMLContainerFrame::UpdatePresentationData(
+    aScriptLevelIncrement, 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
@@ -118,17 +121,18 @@ 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, aFlagsValues, aFlagsToUpdate);
+      PropagatePresentationDataFor(childFrame, aScriptLevelIncrement,
+                                   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
@@ -210,20 +214,21 @@ 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.
   */
-  SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags));
+  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,
+  PropagatePresentationDataFor(overscriptFrame, increment,
     ~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,22 +59,24 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRUint32        aFlagsValues,
+  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                         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,
+  UpdatePresentationDataFromChildAt(1, 1, 2,
     ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
      NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
-  UpdatePresentationDataFromChildAt(0, 0,
+  UpdatePresentationDataFromChildAt(0, 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,
+  UpdatePresentationDataFromChildAt(0, -1, 0,
      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,16 +72,33 @@ 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
@@ -90,50 +107,66 @@ 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(PRUint32        aFlagsValues,
+nsMathMLmstyleFrame::UpdatePresentationData(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;
+  }
 
-  return nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aWhichFlags);
+  return nsMathMLContainerFrame::UpdatePresentationData(
+    aScriptLevelIncrement, 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, aFlagsValues, aWhichFlags); 
+      aFirstIndex, aLastIndex, aScriptLevelIncrement,
+      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,22 +58,24 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRUint32        aFlagsValues,
+  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                         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,
+  UpdatePresentationDataFromChildAt(1, -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,
+  UpdatePresentationDataFromChildAt(1, -1, 1,
     ~NS_MATHML_DISPLAYSTYLE,
      NS_MATHML_DISPLAYSTYLE);
-  UpdatePresentationDataFromChildAt(1,  1,
+  UpdatePresentationDataFromChildAt(1,  1, 0,
      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 ( aFrame->GetStyleFont()->mScriptLevel == 0 &&
+  if ( presentationData.scriptLevel == 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,
+  UpdatePresentationDataFromChildAt(1, -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 ( aFrame->GetStyleFont()->mScriptLevel == 0 && 
+  if ( presentationData.scriptLevel == 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,69 +346,86 @@ 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 displaystyle from our parent
+  // let the base class inherit the scriptlevel and 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(PRUint32 aFlagsValues,
+nsMathMLmtableOuterFrame::UpdatePresentationData(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;
   }
 
-  return nsMathMLFrame::UpdatePresentationData(aFlagsValues, aWhichFlags);
+  return nsMathMLFrame::UpdatePresentationData(
+    aScriptLevelIncrement, 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, aFlagsValues, aWhichFlags);
+    aFirstIndex, aLastIndex, aScriptLevelIncrement, 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 
@@ -434,16 +451,17 @@ 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
@@ -684,20 +702,34 @@ 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
@@ -744,16 +776,26 @@ 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;
@@ -787,16 +829,20 @@ 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,28 +55,42 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // Overloaded nsIMathMLFrame methods
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
-  UpdatePresentationData(PRUint32 aFlagsValues,
+  UpdatePresentationData(PRInt32  aScriptLevelIncrement,
+                         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,
@@ -164,16 +178,21 @@ 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)
   {
@@ -228,16 +247,21 @@ 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
   {
@@ -258,21 +282,29 @@ 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, aFlagsValues, aFlagsToUpdate);
+      aFirstIndex, aLastIndex, aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
+    return NS_OK;
+  }
+
+  NS_IMETHOD
+  ReResolveScriptStyle(PRInt32 aParentScriptLevel)
+  {
+    nsMathMLContainerFrame::PropagateScriptStyleFor(this, aParentScriptLevel);
     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,34 +77,37 @@ nsMathMLmunderFrame::AttributeChanged(PR
     return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
   }
 
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmunderFrame::UpdatePresentationData(PRUint32        aFlagsValues,
+nsMathMLmunderFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                                            PRUint32        aFlagsValues,
                                             PRUint32        aFlagsToUpdate)
 {
-  nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
+  nsMathMLContainerFrame::UpdatePresentationData(
+    aScriptLevelIncrement, 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
@@ -118,17 +121,18 @@ 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, aFlagsValues, aFlagsToUpdate);
+      PropagatePresentationDataFor(childFrame,
+        aScriptLevelIncrement, 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
@@ -208,18 +212,19 @@ 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
   */
-  SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags));
-  PropagatePresentationDataFor(underscriptFrame,
+  PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)
+    ? 0 : 1;
+  PropagatePresentationDataFor(underscriptFrame, increment,
     ~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,22 +59,24 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRUint32        aFlagsValues,
+  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                         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,34 +78,37 @@ nsMathMLmunderoverFrame::AttributeChange
     return ReLayoutChildren(mParent, NS_FRAME_IS_DIRTY);
   }
 
   return nsMathMLContainerFrame::
          AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
 
 NS_IMETHODIMP
-nsMathMLmunderoverFrame::UpdatePresentationData(PRUint32        aFlagsValues,
+nsMathMLmunderoverFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                                                PRUint32        aFlagsValues,
                                                 PRUint32        aFlagsToUpdate)
 {
-  nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues, aFlagsToUpdate);
+  nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement,
+    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". 
@@ -124,17 +127,18 @@ 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, aFlagsValues, aFlagsToUpdate);
+      PropagatePresentationDataFor(childFrame,
+        aScriptLevelIncrement, 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
@@ -233,29 +237,31 @@ 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;
-  SetIncrementScriptLevel(2, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags));
-  PropagatePresentationDataFor(overscriptFrame,
+  PropagatePresentationDataFor(overscriptFrame, increment,
     ~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
   */
-  SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags));
-  PropagatePresentationDataFor(underscriptFrame,
+  increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)
+    ? 0 : 1;
+  PropagatePresentationDataFor(underscriptFrame, increment,
     ~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,22 +59,24 @@ public:
 
   NS_IMETHOD
   InheritAutomaticData(nsIFrame* aParent);
 
   NS_IMETHOD
   TransmitAutomaticData();
 
   NS_IMETHOD
-  UpdatePresentationData(PRUint32        aFlagsValues,
+  UpdatePresentationData(PRInt32         aScriptLevelIncrement,
+                         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,16 +79,50 @@ 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 */
@@ -100,25 +134,61 @@ 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
 
@@ -406,26 +476,8 @@ 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; }
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -299,21 +299,16 @@ 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,20 +4613,16 @@ 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);
@@ -4932,26 +4928,16 @@ 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,24 +512,16 @@ 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,20 +89,16 @@ 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,21 +1330,16 @@ 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 &&
@@ -1918,19 +1913,16 @@ 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,22 +205,16 @@ 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,98 +180,80 @@ static void EnsureBlockDisplay(PRUint8& 
 
   default :
     // make it a block
     display = NS_STYLE_DISPLAY_BLOCK;
   }
 }
 
 // XXX This should really be done in the CSS parser.
-static nsString& Unquote(nsString& aString)
+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;
 }
 
-static nscoord CalcLengthWith(const nsCSSValue& aValue,
-                              nscoord aFontSize,
-                              const nsStyleFont* aStyleFont,
-                              nsStyleContext* aStyleContext,
-                              nsPresContext* aPresContext,
-                              PRBool& aInherited)
+nscoord CalcLength(const nsCSSValue& aValue,
+                   const nsFont* aFont, 
+                   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;
-  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;
+  const nsFont* font;
+  if (aStyleContext) {
+    font = &aStyleContext->GetStyleFont()->mFont;
+  } else {
+    font = aFont;
   }
   switch (unit) {
     case eCSSUnit_EM:
     case eCSSUnit_Char: {
-      return NSToCoordRound(aValue.GetFloatValue() * float(aFontSize));
+      return NSToCoordRound(aValue.GetFloatValue() * (float)font->size);
       // XXX scale against font metrics height instead?
     }
     case eCSSUnit_EN: {
-      return NSToCoordRound((aValue.GetFloatValue() * float(aFontSize)) / 2.0f);
+      return NSToCoordRound((aValue.GetFloatValue() * (float)font->size) / 2.0f);
     }
     case eCSSUnit_XHeight: {
-      nsFont font = aStyleFont->mFont;
-      font.size = aFontSize;
-      nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
+      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 = ((aFontSize / 3) * 2); // XXX HACK!
-      return NSToCoordRound(aValue.GetFloatValue() * float(capHeight));
+      nscoord capHeight = ((font->size / 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
@@ -307,18 +289,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, aStyleContext, aPresContext, aInherited));
-  }
+    aCoord.SetCoordValue(CalcLength(aValue, nsnull, 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);
   } 
@@ -689,19 +671,16 @@ 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");
@@ -965,26 +944,16 @@ 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
@@ -1064,43 +1033,25 @@ 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
-#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
-          ) {
+  else if (specified == total) {
     if (inherited == 0)
       result = eRuleFullReset;
     else
       result = eRuleFullMixed;
   } else if (specified == 0)
     result = eRuleNone;
   else if (specified == inherited)
     result = eRulePartialInherited;
@@ -1929,211 +1880,23 @@ 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 aUsedStartStruct,
-                    PRBool& aInherited)
+                    nsStyleFont* aFont, 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;
@@ -2314,89 +2077,95 @@ 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()) {
+  // 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->mScriptLevel = aParentFont->mScriptLevel;
-  }
-  else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) {
-    aFont->mScriptLevel = 0;
-  }
-#endif
-
-  // font-size: enum, length, percent, inherit
-  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
+    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);
 
   // 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();
   }
@@ -2439,22 +2208,28 @@ 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, aPresContext);
+  nsStyleFont parentFont(*defaultFont);
+  parentFont.mSize = parentFont.mFont.size
+      = nsStyleFont::ZoomText(aPresContext, parentFont.mSize);
   if (higherContext) {
     const nsStyleFont* tmpFont = higherContext->GetStyleFont();
-    parentFont = *tmpFont;
-  }
-  *aFont = parentFont;
+    parentFont.mFlags = tmpFont->mFlags;
+    parentFont.mFont = tmpFont->mFont;
+    parentFont.mSize = tmpFont->mSize;
+  }
+  aFont->mFlags = parentFont.mFlags;
+  aFont->mFont = parentFont.mFont;
+  aFont->mSize = parentFont.mSize;
 
   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);
@@ -2481,25 +2256,26 @@ 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,
-                        PR_FALSE, dummy);
+                        aGenericFontID, fontData, &parentFont, aFont, 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 = *aFont;
+    parentFont.mFlags = aFont->mFlags;
+    parentFont.mFont = aFont->mFont;
+    parentFont.mSize = aFont->mSize;
   }
 }
 
 static PRBool ExtractGeneric(const nsString& aFamily, PRBool aGeneric,
                              void *aData)
 {
   nsAutoString *data = static_cast<nsAutoString*>(aData);
 
@@ -2527,17 +2303,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);
 
@@ -2585,18 +2361,17 @@ 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,
-                        aStartStruct != nsnull, inherited);
+                        fontData, parentFont, font, inherited);
   }
   else {
     // re-calculate the font as a generic font
     inherited = PR_TRUE;
     nsRuleNode::SetGenericFont(mPresContext, aContext, generic,
                                minimumFontSize, font);
   }
 
@@ -3163,48 +2938,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, aContext, mPresContext, inherited);
+      display->mClip.y = CalcLength(displayData.mClip.mTop, nsnull, 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, aContext, mPresContext, inherited) -
+      display->mClip.height = CalcLength(displayData.mClip.mBottom, nsnull, 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, aContext, mPresContext, inherited);
+      display->mClip.x = CalcLength(displayData.mClip.mLeft, nsnull, 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, aContext, mPresContext, inherited) -
+      display->mClip.width = CalcLength(displayData.mClip.mRight, nsnull, 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 {
@@ -3497,17 +3272,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, 
+    bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue, nsnull, 
                                                  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;
@@ -3536,17 +3311,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,
+    bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue, nsnull,
                                                  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;
@@ -3999,33 +3774,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, aContext, mPresContext, inherited);
+      list->mImageRegion.y = CalcLength(listData.mImageRegion.mTop, nsnull, 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, aContext, 
+      list->mImageRegion.height = CalcLength(listData.mImageRegion.mBottom, nsnull, 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, aContext, mPresContext, inherited);
+      list->mImageRegion.x = CalcLength(listData.mImageRegion.mLeft, nsnull, 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, aContext, mPresContext, inherited) -
+      list->mImageRegion.width = CalcLength(listData.mImageRegion.mRight, nsnull, 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,35 +595,23 @@ 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 aStartStruct, PRBool& aInherited);
+                                  nsStyleFont* aFont, 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,55 +101,43 @@ static PRBool EqualImages(imgIRequest *a
   aImage1->GetURI(getter_AddRefs(uri1));
   aImage2->GetURI(getter_AddRefs(uri2));
   return EqualURIs(uri1, uri2);
 }
 
 // --------------------
 // nsStyleFont
 //
-nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext)
-  : mFont(aFont),
-    mFlags(NS_STYLE_FONT_DEFAULT)
+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)
+  : mFlags(NS_STYLE_FONT_DEFAULT),
+    mFont(aFont),
+    mSize(aFont.size)
 {
-  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 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
+  : mFlags(aSrc.mFlags),
+    mFont(aSrc.mFont),
+    mSize(aSrc.mSize)
 {
 }
 
+
 nsStyleFont::nsStyleFont(nsPresContext* aPresContext)
-  : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID))),
-    mFlags(NS_STYLE_FONT_DEFAULT)
+  : mFlags(NS_STYLE_FONT_DEFAULT),
+    mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID)))
 {
   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,48 +84,40 @@ 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(const nsFont& aFont, nsPresContext *aPresContext);
+  nsStyleFont(void);
+  nsStyleFont(const nsFont& aFont);
   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,20 +147,17 @@ 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",
-    "-moz-script-level", // parsed by UA sheets only
-    "-moz-script-size-multiplier",
-    "-moz-script-min-size"
+    "padding-right-rtl-source"
 };
 
 inline int
 is_inaccessible(const char* aPropName)
 {
     for (unsigned j = 0; j < ARRAY_LENGTH(gInaccessibleProperties); ++j) {
         if (strcmp(aPropName, gInaccessibleProperties[j]) == 0)
             return 1;