b=297467 menclose r=karlt rs=roc
authorFrédéric Wang <fred.wang@free.fr>
Fri, 29 May 2009 13:08:35 +0200
changeset 31351 dc8ef04fc9537e0b9573871b7fd68e900a85aa3a
parent 31350 57611d381ef492c14d059c6e6ae11d502bce25c6
child 31352 6f957b8818b90a654ac94b1a396b200f4f3b00c1
push idunknown
push userunknown
push dateunknown
reviewerskarlt, roc
bugs297467
milestone1.9.2a2pre
b=297467 menclose r=karlt rs=roc
layout/base/nsCSSFrameConstructor.cpp
layout/mathml/Makefile.in
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLContainerFrame.h
layout/mathml/nsMathMLParts.h
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmencloseFrame.h
layout/mathml/nsMathMLmsqrtFrame.cpp
layout/mathml/nsMathMLmsqrtFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -4817,17 +4817,18 @@ nsCSSFrameConstructor::FindMathMLData(ns
     SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmspaceFrame),
     SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmfencedFrame),
     SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame),
     SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmstyleFrame),
     SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmsqrtFrame),
     SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame),
     SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmactionFrame),
     SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame),
-    SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame)
+    SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame),
+    SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame)
   };
 
   return FindDataByTag(aTag, aContent, aStyleContext, sMathMLData,
                        NS_ARRAY_LENGTH(sMathMLData));
 }
 #endif // MOZ_MATHML
 
 #ifdef MOZ_SVG
--- a/layout/mathml/Makefile.in
+++ b/layout/mathml/Makefile.in
@@ -98,16 +98,17 @@ CPPSRCS =         nsMathMLChar.cpp		    
                   nsMathMLmoverFrame.cpp		\
                   nsMathMLmunderoverFrame.cpp		\
                   nsMathMLmpaddedFrame.cpp		\
                   nsMathMLmspaceFrame.cpp		\
                   nsMathMLmstyleFrame.cpp		\
                   nsMathMLmsqrtFrame.cpp		\
                   nsMathMLmrootFrame.cpp		\
                   nsMathMLmactionFrame.cpp		\
+                  nsMathMLmencloseFrame.cpp		\
                   $(NULL)
 
 include $(topsrcdir)/config/config.mk
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 # do we still want this? - DJF
 FORCE_STATIC_LIB = 1
 
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -1058,29 +1058,29 @@ nsMathMLContainerFrame::GetIntrinsicWidt
     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
                                     childDesiredSize.mBoundingMetrics);
 
     childFrame = childFrame->GetNextSibling();
   }
 
   // Measure
   nsHTMLReflowMetrics desiredSize;
-  nsresult rv = MeasureChildFrames(*aRenderingContext, desiredSize);
+  nsresult rv = MeasureForWidth(*aRenderingContext, desiredSize);
   if (NS_FAILED(rv)) {
     ReflowError(*aRenderingContext, desiredSize);
   }
 
   ClearSavedChildMetrics();
 
   return desiredSize.width;
 }
 
 /* virtual */ nsresult
-nsMathMLContainerFrame::MeasureChildFrames(nsIRenderingContext& aRenderingContext,
-                                           nsHTMLReflowMetrics& aDesiredSize)
+nsMathMLContainerFrame::MeasureForWidth(nsIRenderingContext& aRenderingContext,
+                                        nsHTMLReflowMetrics& aDesiredSize)
 {
   return Place(aRenderingContext, PR_FALSE, aDesiredSize);
 }
 
 
 // see spacing table in Chapter 18, TeXBook (p.170)
 // Our table isn't quite identical to TeX because operators have 
 // built-in values for lspace & rspace in the Operator Dictionary.
--- a/layout/mathml/nsMathMLContainerFrame.h
+++ b/layout/mathml/nsMathMLContainerFrame.h
@@ -224,27 +224,27 @@ protected:
    *        any space you want for border/padding in the desired size you
    *        return.
    */
   virtual nsresult
   Place(nsIRenderingContext& aRenderingContext,
         PRBool               aPlaceOrigin,
         nsHTMLReflowMetrics& aDesiredSize);
 
-  // MeasureChildFrames:
+  // MeasureForWidth:
   //
   // A method used by nsMathMLContainerFrame::GetIntrinsicWidth to get the
   // width that a particular Place method desires.  For most frames, this will
-  // just call the object's Place method.  However <msqrt> uses
+  // just call the object's Place method.  However <msqrt> and <menclose> use
   // nsMathMLContainerFrame::GetIntrinsicWidth to measure the child frames as
-  // if in an <mrow>, and so <msqrt> frames implement MeasureChildFrames to
-  // use nsMathMLContainerFrame::Place.
+  // if in an <mrow>, and so their frames implement MeasureForWidth to use
+  // nsMathMLContainerFrame::Place.
   virtual nsresult
-  MeasureChildFrames(nsIRenderingContext& aRenderingContext,
-                     nsHTMLReflowMetrics& aDesiredSize);
+  MeasureForWidth(nsIRenderingContext& aRenderingContext,
+                  nsHTMLReflowMetrics& aDesiredSize);
 
 
   // helper to re-sync the automatic data in our children and notify our parent to
   // reflow us when changes (e.g., append/insert/remove) happen in our child list
   virtual nsresult
   ChildListChanged(PRInt32 aModType);
 
   // helper to get the preferred size that a container frame should use to fire
--- a/layout/mathml/nsMathMLParts.h
+++ b/layout/mathml/nsMathMLParts.h
@@ -64,16 +64,17 @@ nsIFrame* NS_NewMathMLmstyleFrame(nsIPre
 nsIFrame* NS_NewMathMLmtableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmtableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmtrFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmtdFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmtdInnerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmsqrtFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmrootFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame* NS_NewMathMLmactionFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame* NS_NewMathMLmencloseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 nsIFrame* NS_NewMathMLmathBlockFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
 nsIFrame* NS_NewMathMLmathInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 inline nsIFrame* NS_CreateNewMathMLmathBlockFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return NS_NewMathMLmathBlockFrame(aPresShell, aContext, 0);
 }
 #endif /* nsMathMLParts_h___ */
new file mode 100644
--- /dev/null
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -0,0 +1,826 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla MathML Project.
+ *
+ * The Initial Developer of the Original Code is
+ * The University Of Queensland.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Roger B. Sidje <rbs@maths.uq.edu.au>
+ *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
+ *   Vilya Harvey <vilya@nag.co.uk>
+ *   Shyjan Mahamud <mahamud@cs.cmu.edu>
+ *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
+ *   Frederic Wang <fred.wang@free.fr> - extension of <msqrt/> to <menclose/>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsCOMPtr.h"
+#include "nsFrame.h"
+#include "nsPresContext.h"
+#include "nsStyleContext.h"
+#include "nsStyleConsts.h"
+#include "nsIRenderingContext.h"
+#include "nsIFontMetrics.h"
+#include "nsWhitespaceTokenizer.h"
+
+#include "nsMathMLmencloseFrame.h"
+#include "nsDisplayList.h"
+#include "gfxContext.h"
+
+//
+// <menclose> -- enclose content with a stretching symbol such
+// as a long division sign. - implementation
+
+// longdiv:
+// Unicode 5.1 assigns U+27CC to LONG DIVISION, but a right parenthesis
+// renders better with current font support.
+static const PRUnichar kLongDivChar = ')';
+
+// radical: 'SQUARE ROOT'
+static const PRUnichar kRadicalChar = 0x221A;
+
+nsIFrame*
+NS_NewMathMLmencloseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) nsMathMLmencloseFrame(aContext);
+}
+
+nsMathMLmencloseFrame::nsMathMLmencloseFrame(nsStyleContext* aContext) :
+  nsMathMLContainerFrame(aContext), mNotationsToDraw(0),
+  mLongDivCharIndex(-1), mRadicalCharIndex(-1), mContentWidth(0)
+{
+}
+
+nsMathMLmencloseFrame::~nsMathMLmencloseFrame()
+{
+}
+
+nsresult nsMathMLmencloseFrame::AllocateMathMLChar(nsMencloseNotation mask)
+{
+  // Is the char already allocated?
+  if ((mask == NOTATION_LONGDIV && mLongDivCharIndex >= 0) ||
+      (mask == NOTATION_RADICAL && mRadicalCharIndex >= 0))
+    return NS_OK;
+
+  // No need to track the style context given to our MathML chars.
+  // The Style System will use Get/SetAdditionalStyleContext() to keep it
+  // up-to-date if dynamic changes arise.
+  PRUint32 i = mMathMLChar.Length();
+  nsAutoString Char;
+
+  if (!mMathMLChar.AppendElement())
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  if (mask == NOTATION_LONGDIV) {
+    Char.Assign(kLongDivChar);
+    mLongDivCharIndex = i;
+  } else if (mask == NOTATION_RADICAL) {
+    Char.Assign(kRadicalChar);
+    mRadicalCharIndex = i;
+  }
+
+  nsPresContext *presContext = PresContext();
+  mMathMLChar[i].SetData(presContext, Char);
+  ResolveMathMLCharStyle(presContext, mContent, mStyleContext,
+                         &mMathMLChar[i],
+                         PR_TRUE);
+
+  return NS_OK;
+}
+
+/*
+ * Add a notation to draw, if the argument is the name of a known notation.
+ * @param aNotation string name of a notation
+ */
+nsresult nsMathMLmencloseFrame::AddNotation(const nsAString& aNotation)
+{
+  nsresult rv;
+
+  if (aNotation.EqualsLiteral("longdiv")) {
+    rv = AllocateMathMLChar(NOTATION_LONGDIV);
+    NS_ENSURE_SUCCESS(rv, rv);
+    mNotationsToDraw |= NOTATION_LONGDIV;
+  } else if (aNotation.EqualsLiteral("actuarial")) {
+    mNotationsToDraw |= (NOTATION_RIGHT | NOTATION_TOP);
+  } else if (aNotation.EqualsLiteral("radical")) {
+    rv = AllocateMathMLChar(NOTATION_RADICAL);
+    NS_ENSURE_SUCCESS(rv, rv);
+    mNotationsToDraw |= NOTATION_RADICAL;
+  } else if (aNotation.EqualsLiteral("box")) {
+    mNotationsToDraw |= (NOTATION_LEFT | NOTATION_RIGHT |
+                         NOTATION_TOP | NOTATION_BOTTOM);
+  } else if (aNotation.EqualsLiteral("roundedbox")) {
+    mNotationsToDraw |= NOTATION_ROUNDEDBOX;
+  } else if (aNotation.EqualsLiteral("circle")) {
+    mNotationsToDraw |= NOTATION_CIRCLE;
+  } else if (aNotation.EqualsLiteral("left")) {
+    mNotationsToDraw |= NOTATION_LEFT;
+  } else if (aNotation.EqualsLiteral("right")) {
+    mNotationsToDraw |= NOTATION_RIGHT;
+  } else if (aNotation.EqualsLiteral("top")) {
+    mNotationsToDraw |= NOTATION_TOP;
+  } else if (aNotation.EqualsLiteral("bottom")) {
+    mNotationsToDraw |= NOTATION_BOTTOM;
+  } else if (aNotation.EqualsLiteral("updiagonalstrike")) {
+    mNotationsToDraw |= NOTATION_UPDIAGONALSTRIKE;
+  } else if (aNotation.EqualsLiteral("downdiagonalstrike")) {
+    mNotationsToDraw |= NOTATION_DOWNDIAGONALSTRIKE;
+  } else if (aNotation.EqualsLiteral("verticalstrike")) {
+    mNotationsToDraw |= NOTATION_VERTICALSTRIKE;
+  } else if (aNotation.EqualsLiteral("horizontalstrike")) {
+    mNotationsToDraw |= NOTATION_HORIZONTALSTRIKE;
+  }
+
+  return NS_OK;
+}
+
+/*
+ * Initialize the list of notations to draw
+ */
+void nsMathMLmencloseFrame::InitNotations()
+{
+  nsAutoString value;
+
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::notation_, value)) {
+    // parse the notation attribute
+    nsWhitespaceTokenizer tokenizer(value);
+
+    while (tokenizer.hasMoreTokens())
+      AddNotation(tokenizer.nextToken());
+  } else {
+    // default: longdiv
+    if (NS_FAILED(AllocateMathMLChar(NOTATION_LONGDIV)))
+      return;
+    mNotationsToDraw = NOTATION_LONGDIV;
+  }
+}
+
+NS_IMETHODIMP
+nsMathMLmencloseFrame::Init(nsIContent*      aContent,
+                            nsIFrame*        aParent,
+                            nsIFrame*        aPrevInFlow)
+{
+  nsresult rv = nsMathMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  InitNotations();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMathMLmencloseFrame::InheritAutomaticData(nsIFrame* aParent)
+{
+  // let the base class get the default from our parent
+  nsMathMLContainerFrame::InheritAutomaticData(aParent);
+
+  mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMathMLmencloseFrame::TransmitAutomaticData()
+{
+  if (IsToDraw(NOTATION_RADICAL)) {
+    // The TeXBook (Ch 17. p.141) says that \sqrt is cramped 
+    UpdatePresentationDataFromChildAt(0, -1,
+                                      NS_MATHML_COMPRESSED,
+                                      NS_MATHML_COMPRESSED);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMathMLmencloseFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                        const nsRect&           aDirtyRect,
+                                        const nsDisplayListSet& aLists)
+{
+  /////////////
+  // paint the menclosed content
+  nsresult rv = nsMathMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect,
+                                                         aLists);
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (NS_MATHML_HAS_ERROR(mPresentationData.flags))
+    return rv;
+
+  nsRect mencloseRect = nsIFrame::GetRect();
+  mencloseRect.x = mencloseRect.y = 0;
+
+  if (IsToDraw(NOTATION_RADICAL)) {
+    rv = mMathMLChar[mRadicalCharIndex].Display(aBuilder, this, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsRect rect;
+    mMathMLChar[mRadicalCharIndex].GetRect(rect);
+    rect.MoveBy(rect.width, 0);
+    rect.SizeTo(mContentWidth, mRuleThickness);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_LONGDIV)) {
+    rv = mMathMLChar[mLongDivCharIndex].Display(aBuilder, this, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsRect rect;
+    mMathMLChar[mLongDivCharIndex].GetRect(rect);
+    rect.SizeTo(rect.width + mContentWidth, mRuleThickness);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_TOP)) {
+    nsRect rect(0, 0, mencloseRect.width, mRuleThickness);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_BOTTOM)) {
+    nsRect rect(0, mencloseRect.height - mRuleThickness,
+                mencloseRect.width, mRuleThickness);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_LEFT)) {
+    nsRect rect(0, 0, mRuleThickness, mencloseRect.height);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_RIGHT)) {
+    nsRect rect(mencloseRect.width - mRuleThickness, 0,
+                mRuleThickness, mencloseRect.height);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_ROUNDEDBOX)) {
+    rv = DisplayNotation(aBuilder, this, mencloseRect, aLists,
+                         mRuleThickness, NOTATION_ROUNDEDBOX);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_CIRCLE)) {
+    rv = DisplayNotation(aBuilder, this, mencloseRect, aLists,
+                         mRuleThickness, NOTATION_CIRCLE);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_UPDIAGONALSTRIKE)) {
+    rv = DisplayNotation(aBuilder, this, mencloseRect, aLists,
+                         mRuleThickness, NOTATION_UPDIAGONALSTRIKE);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_DOWNDIAGONALSTRIKE)) {
+    rv = DisplayNotation(aBuilder, this, mencloseRect, aLists,
+                         mRuleThickness, NOTATION_DOWNDIAGONALSTRIKE);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_HORIZONTALSTRIKE)) {
+    nsRect rect(0, mencloseRect.height / 2 - mRuleThickness / 2,
+                mencloseRect.width, mRuleThickness);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (IsToDraw(NOTATION_VERTICALSTRIKE)) {
+    nsRect rect(mencloseRect.width / 2 - mRuleThickness / 2, 0,
+                mRuleThickness, mencloseRect.height);
+    rv = DisplayBar(aBuilder, this, rect, aLists);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return rv;
+}
+
+/* virtual */ nsresult
+nsMathMLmencloseFrame::MeasureForWidth(nsIRenderingContext& aRenderingContext,
+                                       nsHTMLReflowMetrics& aDesiredSize)
+{
+  return PlaceInternal(aRenderingContext, PR_FALSE, aDesiredSize, PR_TRUE);
+}
+
+/* virtual */ nsresult
+nsMathMLmencloseFrame::Place(nsIRenderingContext& aRenderingContext,
+                             PRBool               aPlaceOrigin,
+                             nsHTMLReflowMetrics& aDesiredSize)
+{
+  return PlaceInternal(aRenderingContext, aPlaceOrigin, aDesiredSize, PR_FALSE);
+}
+
+/* virtual */ nsresult
+nsMathMLmencloseFrame::PlaceInternal(nsIRenderingContext& aRenderingContext,
+                                     PRBool               aPlaceOrigin,
+                                     nsHTMLReflowMetrics& aDesiredSize,
+                                     PRBool               aWidthOnly)
+{
+  ///////////////
+  // Measure the size of our content using the base class to format like an
+  // inferred mrow.
+  nsHTMLReflowMetrics baseSize;
+  nsresult rv =
+    nsMathMLContainerFrame::Place(aRenderingContext, PR_FALSE, baseSize);
+
+  if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
+      DidReflowChildren(GetFirstChild(nsnull));
+      return rv;
+    }
+
+  nsBoundingMetrics bmBase = baseSize.mBoundingMetrics;
+  nscoord dx_left = 0, dx_right = 0;
+  nsBoundingMetrics bmLongdivChar, bmRadicalChar;
+  nscoord radicalAscent = 0, radicalDescent = 0;
+  nscoord longdivAscent = 0, longdivDescent = 0;
+  nscoord psi = 0;
+
+  ///////////////
+  // Thickness of bars and font metrics
+  nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
+  nsCOMPtr<nsIFontMetrics> fm;
+  nscoord mEmHeight;
+  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+                            PresContext()->GetUserFontSet());
+  aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
+  GetRuleThickness(aRenderingContext, fm, mRuleThickness);
+  GetEmHeight(fm, mEmHeight);
+
+  nsBoundingMetrics bmOne;
+  aRenderingContext.GetBoundingMetrics(NS_LITERAL_STRING("1").get(), 1, bmOne);
+
+  ///////////////
+  // General rules: the menclose element takes the size of the enclosed content.
+  // We add a padding when needed.
+
+  // determine padding & psi
+  nscoord padding = 3 * mRuleThickness;
+  nscoord delta = padding % onePixel;
+  if (delta)
+    padding += onePixel - delta; // round up
+
+  if (IsToDraw(NOTATION_LONGDIV) || IsToDraw(NOTATION_RADICAL)) {
+      nscoord phi;
+      // Rule 11, App. G, TeXbook
+      // psi = clearance between rule and content
+      if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags))
+        fm->GetXHeight(phi);
+      else
+        phi = mRuleThickness;
+      psi = mRuleThickness + phi / 4;
+
+      delta = psi % onePixel;
+      if (delta)
+        psi += onePixel - delta; // round up
+    }
+
+  if (mRuleThickness < onePixel)
+    mRuleThickness = onePixel;
+ 
+  // Set horizontal parameters
+  if (IsToDraw(NOTATION_ROUNDEDBOX) ||
+      IsToDraw(NOTATION_TOP) ||
+      IsToDraw(NOTATION_LEFT) ||
+      IsToDraw(NOTATION_BOTTOM) ||
+      IsToDraw(NOTATION_CIRCLE))
+    dx_left = padding;
+
+  if (IsToDraw(NOTATION_ROUNDEDBOX) ||
+      IsToDraw(NOTATION_TOP) ||
+      IsToDraw(NOTATION_RIGHT) ||
+      IsToDraw(NOTATION_BOTTOM) ||
+      IsToDraw(NOTATION_CIRCLE))
+    dx_right = padding;
+
+  // Set vertical parameters
+  if (IsToDraw(NOTATION_RIGHT) ||
+      IsToDraw(NOTATION_LEFT) ||
+      IsToDraw(NOTATION_UPDIAGONALSTRIKE) ||
+      IsToDraw(NOTATION_DOWNDIAGONALSTRIKE) ||
+      IsToDraw(NOTATION_VERTICALSTRIKE) ||
+      IsToDraw(NOTATION_CIRCLE) ||
+      IsToDraw(NOTATION_ROUNDEDBOX) ||
+      IsToDraw(NOTATION_RADICAL) ||
+      IsToDraw(NOTATION_LONGDIV)) {
+      // set a minimal value for the base height
+      bmBase.ascent = PR_MAX(bmOne.ascent, bmBase.ascent);
+      bmBase.descent = PR_MAX(0, bmBase.descent);
+  }
+
+  mBoundingMetrics.ascent = bmBase.ascent;
+  mBoundingMetrics.descent = bmBase.descent;
+    
+  if (IsToDraw(NOTATION_ROUNDEDBOX) ||
+      IsToDraw(NOTATION_TOP) ||
+      IsToDraw(NOTATION_LEFT) ||
+      IsToDraw(NOTATION_RIGHT) ||
+      IsToDraw(NOTATION_CIRCLE))
+    mBoundingMetrics.ascent += padding;
+  
+  if (IsToDraw(NOTATION_ROUNDEDBOX) ||
+      IsToDraw(NOTATION_LEFT) ||
+      IsToDraw(NOTATION_RIGHT) ||
+      IsToDraw(NOTATION_BOTTOM) ||
+      IsToDraw(NOTATION_CIRCLE))
+    mBoundingMetrics.descent += padding;
+
+  ///////////////
+  // circle notation: we don't want the ellipse to overlap the enclosed
+  // content. Hence, we need to increase the size of the bounding box by a
+  // factor of at least sqrt(2).
+  if (IsToDraw(NOTATION_CIRCLE)) {
+    double ratio = (sqrt(2) - 1) / 2;
+    nscoord padding2;
+
+    // Update horizontal parameters
+    padding2 = ratio * bmBase.width;
+
+    dx_left = PR_MAX(dx_left, padding2);
+    dx_right = PR_MAX(dx_right, padding2);
+
+    // Update vertical parameters
+    padding2 = ratio * (bmBase.ascent + bmBase.descent);
+
+    mBoundingMetrics.ascent = PR_MAX(mBoundingMetrics.ascent,
+                                     bmBase.ascent + padding2);
+    mBoundingMetrics.descent = PR_MAX(mBoundingMetrics.descent,
+                                      bmBase.descent + padding2);
+  }
+
+  ///////////////
+  // longdiv notation:
+  if (IsToDraw(NOTATION_LONGDIV)) {
+    if (aWidthOnly) {
+        nscoord longdiv_width = mMathMLChar[mLongDivCharIndex].
+          GetMaxWidth(PresContext(), aRenderingContext);
+
+        // Update horizontal parameters
+        dx_left = PR_MAX(dx_left, longdiv_width);
+    } else {
+      // Stretch the parenthesis to the appropriate height if it is not
+      // big enough.
+      nsBoundingMetrics contSize = bmBase;
+      contSize.ascent = mRuleThickness;
+      contSize.descent = bmBase.ascent + bmBase.descent + psi;
+
+      // height(longdiv) should be >= height(base) + psi + mRuleThickness
+      mMathMLChar[mLongDivCharIndex].Stretch(PresContext(), aRenderingContext,
+                                             NS_STRETCH_DIRECTION_VERTICAL,
+                                             contSize, bmLongdivChar,
+                                             NS_STRETCH_LARGER);
+      mMathMLChar[mLongDivCharIndex].GetBoundingMetrics(bmLongdivChar);
+
+      // Update horizontal parameters
+      dx_left = PR_MAX(dx_left, bmLongdivChar.width);
+
+      // Update vertical parameters
+      longdivAscent = bmBase.ascent + psi + mRuleThickness;
+      longdivDescent = PR_MAX(bmBase.descent,
+                              (bmLongdivChar.ascent + bmLongdivChar.descent -
+                               longdivAscent));
+
+      mBoundingMetrics.ascent = PR_MAX(mBoundingMetrics.ascent,
+                                       longdivAscent);
+      mBoundingMetrics.descent = PR_MAX(mBoundingMetrics.descent,
+                                        longdivDescent);
+    }
+  }
+
+  ///////////////
+  // radical notation:
+  if (IsToDraw(NOTATION_RADICAL)) {
+    if (aWidthOnly) {
+      nscoord radical_width = mMathMLChar[mRadicalCharIndex].
+        GetMaxWidth(PresContext(), aRenderingContext);
+      
+      // Update horizontal parameters
+      dx_left = PR_MAX(dx_left, radical_width);
+    } else {
+      // Stretch the radical symbol to the appropriate height if it is not
+      // big enough.
+      nsBoundingMetrics contSize = bmBase;
+      contSize.ascent = mRuleThickness;
+      contSize.descent = bmBase.ascent + bmBase.descent + psi;
+
+      // height(radical) should be >= height(base) + psi + mRuleThickness
+      mMathMLChar[mRadicalCharIndex].Stretch(PresContext(), aRenderingContext,
+                                             NS_STRETCH_DIRECTION_VERTICAL,
+                                             contSize, bmRadicalChar,
+                                             NS_STRETCH_LARGER);
+      mMathMLChar[mRadicalCharIndex].GetBoundingMetrics(bmRadicalChar);
+
+      // Update horizontal parameters
+      dx_left = PR_MAX(dx_left, bmRadicalChar.width);
+
+      // Update vertical parameters
+      radicalAscent = bmBase.ascent + psi + mRuleThickness;
+      radicalDescent = PR_MAX(bmBase.descent,
+                              (bmRadicalChar.ascent + bmRadicalChar.descent -
+                               radicalAscent));
+
+      mBoundingMetrics.ascent = PR_MAX(mBoundingMetrics.ascent,
+                                       radicalAscent);
+      mBoundingMetrics.descent = PR_MAX(mBoundingMetrics.descent,
+                                        radicalDescent);
+    }
+  }
+
+  ///////////////
+  //
+  if (IsToDraw(NOTATION_CIRCLE) ||
+      IsToDraw(NOTATION_ROUNDEDBOX) ||
+      (IsToDraw(NOTATION_LEFT) && IsToDraw(NOTATION_RIGHT))) {
+    // center the menclose around the content (horizontally)
+    dx_left = dx_right = PR_MAX(dx_left, dx_right);
+  }
+
+  ///////////////
+  // The maximum size is now computed: set the remaining parameters
+  mBoundingMetrics.width = dx_left + bmBase.width + dx_right;
+
+  mBoundingMetrics.leftBearing = PR_MIN(0, dx_left + bmBase.leftBearing);
+  mBoundingMetrics.rightBearing =
+    PR_MAX(mBoundingMetrics.width, dx_left + bmBase.rightBearing);
+  
+  aDesiredSize.width = mBoundingMetrics.width;
+
+  aDesiredSize.ascent = PR_MAX(mBoundingMetrics.ascent, baseSize.ascent);
+  aDesiredSize.height = aDesiredSize.ascent +
+    PR_MAX(mBoundingMetrics.descent, baseSize.height - baseSize.ascent);
+
+  if (IsToDraw(NOTATION_LONGDIV) || IsToDraw(NOTATION_RADICAL)) {
+    // get the leading to be left at the top of the resulting frame
+    // this seems more reliable than using fm->GetLeading() on suspicious
+    // fonts
+    nscoord leading = nscoord(0.2f * mEmHeight);
+    nscoord desiredSizeAscent = aDesiredSize.ascent;
+    nscoord desiredSizeDescent = aDesiredSize.height - aDesiredSize.ascent;
+    
+    if (IsToDraw(NOTATION_LONGDIV)) {
+      desiredSizeAscent = PR_MAX(desiredSizeAscent,
+                                 longdivAscent + leading);
+      desiredSizeDescent = PR_MAX(desiredSizeDescent,
+                                  longdivDescent + mRuleThickness);
+    }
+    
+    if (IsToDraw(NOTATION_RADICAL)) {
+      desiredSizeAscent = PR_MAX(desiredSizeAscent,
+                                 radicalAscent + leading);
+      desiredSizeDescent = PR_MAX(desiredSizeDescent,
+                                  radicalDescent + mRuleThickness);
+    }
+
+    aDesiredSize.ascent = desiredSizeAscent;
+    aDesiredSize.height = desiredSizeAscent + desiredSizeDescent;
+  }
+    
+  if (IsToDraw(NOTATION_CIRCLE) ||
+      IsToDraw(NOTATION_ROUNDEDBOX) ||
+      (IsToDraw(NOTATION_TOP) && IsToDraw(NOTATION_BOTTOM))) {
+    // center the menclose around the content (vertically)
+    nscoord dy = PR_MAX(aDesiredSize.ascent - bmBase.ascent,
+                        aDesiredSize.height - aDesiredSize.ascent -
+                        bmBase.descent);
+
+    aDesiredSize.ascent = bmBase.ascent + dy;
+    aDesiredSize.height = aDesiredSize.ascent + bmBase.descent + dy;
+  }
+
+  // Update mBoundingMetrics ascent/descent
+  if (IsToDraw(NOTATION_TOP) ||
+      IsToDraw(NOTATION_RIGHT) ||
+      IsToDraw(NOTATION_LEFT) ||
+      IsToDraw(NOTATION_UPDIAGONALSTRIKE) ||
+      IsToDraw(NOTATION_DOWNDIAGONALSTRIKE) ||
+      IsToDraw(NOTATION_VERTICALSTRIKE) ||
+      IsToDraw(NOTATION_CIRCLE) ||
+      IsToDraw(NOTATION_ROUNDEDBOX))
+    mBoundingMetrics.ascent = aDesiredSize.ascent;
+  
+  if (IsToDraw(NOTATION_BOTTOM) ||
+      IsToDraw(NOTATION_RIGHT) ||
+      IsToDraw(NOTATION_LEFT) ||
+      IsToDraw(NOTATION_UPDIAGONALSTRIKE) ||
+      IsToDraw(NOTATION_DOWNDIAGONALSTRIKE) ||
+      IsToDraw(NOTATION_VERTICALSTRIKE) ||
+      IsToDraw(NOTATION_CIRCLE) ||
+      IsToDraw(NOTATION_ROUNDEDBOX))
+    mBoundingMetrics.descent = aDesiredSize.height - aDesiredSize.ascent;
+
+  aDesiredSize.mBoundingMetrics = mBoundingMetrics;
+  
+  mReference.x = 0;
+  mReference.y = aDesiredSize.ascent;
+
+  if (aPlaceOrigin) {
+    //////////////////
+    // Set position and size of MathMLChars
+    if (IsToDraw(NOTATION_LONGDIV))
+      mMathMLChar[mLongDivCharIndex].SetRect(nsRect(dx_left -
+                                                    bmLongdivChar.width,
+                                                    aDesiredSize.ascent -
+                                                    longdivAscent,
+                                                    bmLongdivChar.width,
+                                                    bmLongdivChar.ascent +
+                                                    bmLongdivChar.descent));
+
+    if (IsToDraw(NOTATION_RADICAL))
+      mMathMLChar[mRadicalCharIndex].SetRect(nsRect(dx_left -
+                                                    bmRadicalChar.width,
+                                                    aDesiredSize.ascent -
+                                                    radicalAscent,
+                                                    bmRadicalChar.width,
+                                                    bmRadicalChar.ascent +
+                                                    bmRadicalChar.descent));
+
+    mContentWidth = bmBase.width;
+
+    //////////////////
+    // Finish reflowing child frames
+    PositionRowChildFrames(dx_left, aDesiredSize.ascent);
+  }
+
+  return NS_OK;
+}
+
+nscoord
+nsMathMLmencloseFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
+{
+  nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
+  if (!gap)
+    return 0;
+
+  // Move the MathML characters
+  nsRect rect;
+  for (PRUint32 i = 0; i < mMathMLChar.Length(); i++) {
+    mMathMLChar[i].GetRect(rect);
+    rect.MoveBy(gap, 0);
+    mMathMLChar[i].SetRect(rect);
+  }
+
+  return gap;
+}
+
+NS_IMETHODIMP
+nsMathMLmencloseFrame::AttributeChanged(PRInt32         aNameSpaceID,
+                                        nsIAtom*        aAttribute,
+                                        PRInt32         aModType)
+{
+  if (aAttribute == nsGkAtoms::notation_) {
+    mNotationsToDraw = 0;
+    mLongDivCharIndex = mRadicalCharIndex = -1;
+    mMathMLChar.Clear();
+    
+    InitNotations();
+  }
+
+  return nsMathMLContainerFrame::
+    AttributeChanged(aNameSpaceID, aAttribute, aModType);
+}
+
+//////////////////
+// the Style System will use these to pass the proper style context to our
+// MathMLChar
+nsStyleContext*
+nsMathMLmencloseFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
+{
+  PRInt32 len = mMathMLChar.Length();
+  if (aIndex >= 0 && aIndex < len)
+    return mMathMLChar[aIndex].GetStyleContext();
+  else
+    return nsnull;
+}
+
+void
+nsMathMLmencloseFrame::SetAdditionalStyleContext(PRInt32          aIndex, 
+                                                 nsStyleContext*  aStyleContext)
+{
+  PRInt32 len = mMathMLChar.Length();
+  if (aIndex >= 0 && aIndex < len)
+    mMathMLChar[aIndex].SetStyleContext(aStyleContext);
+}
+
+class nsDisplayNotation : public nsDisplayItem
+{
+public:
+  nsDisplayNotation(nsIFrame* aFrame, const nsRect& aRect,
+                    nscoord aThickness, nsMencloseNotation aType)
+    : nsDisplayItem(aFrame), mRect(aRect), 
+      mThickness(aThickness), mType(aType) {
+    MOZ_COUNT_CTOR(nsDisplayNotation);
+  }
+#ifdef NS_BUILD_REFCNT_LOGGING
+  virtual ~nsDisplayNotation() {
+    MOZ_COUNT_DTOR(nsDisplayNotation);
+  }
+#endif
+
+  virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx,
+                     const nsRect& aDirtyRect);
+  NS_DISPLAY_DECL_NAME("MathMLMencloseNotation")
+
+private:
+  nsRect             mRect;
+  nscoord            mThickness;
+  nsMencloseNotation mType;
+};
+
+void nsDisplayNotation::Paint(nsDisplayListBuilder* aBuilder,
+                              nsIRenderingContext* aCtx,
+                              const nsRect& aDirtyRect)
+{
+  // get the gfxRect
+  nsPresContext* presContext = mFrame->PresContext();
+  gfxRect rect = presContext->
+    AppUnitsToGfxUnits(mRect + aBuilder->ToReferenceFrame(mFrame));
+
+  // paint the frame with the current text color
+  aCtx->SetColor(mFrame->GetStyleColor()->mColor);
+
+  // change line width to mThickness
+  gfxContext *gfxCtx = aCtx->ThebesContext();
+  gfxFloat currentLineWidth = gfxCtx->CurrentLineWidth();
+  gfxFloat e = presContext->AppUnitsToGfxUnits(mThickness);
+  gfxCtx->SetLineWidth(e);
+
+  rect.Inset(e / 2.0);
+
+  gfxCtx->NewPath();
+
+  switch(mType)
+    {
+    case NOTATION_CIRCLE:
+      gfxCtx->Ellipse(rect.pos + rect.size / 2.0, rect.size);
+      break;
+
+    case NOTATION_ROUNDEDBOX:
+      gfxCtx->RoundedRectangle(rect, gfxCornerSizes(3 * e), PR_TRUE);
+      break;
+
+    case NOTATION_UPDIAGONALSTRIKE:
+      gfxCtx->Line(rect.BottomLeft(), rect.TopRight());
+      break;
+
+    case NOTATION_DOWNDIAGONALSTRIKE:
+      gfxCtx->Line(rect.TopLeft(), rect.BottomRight());
+      break;
+
+    default:
+      NS_NOTREACHED("This notation can not be drawn using nsDisplayNotation");
+      break;
+    }
+
+  gfxCtx->Stroke();
+
+  // restore previous line width
+  gfxCtx->SetLineWidth(currentLineWidth);
+}
+
+nsresult
+nsMathMLmencloseFrame::DisplayNotation(nsDisplayListBuilder* aBuilder,
+                                       nsIFrame* aFrame, const nsRect& aRect,
+                                       const nsDisplayListSet& aLists,
+                                       nscoord aThickness,
+                                       nsMencloseNotation aType)
+{
+  if (!aFrame->GetStyleVisibility()->IsVisible() || aRect.IsEmpty() ||
+      aThickness <= 0)
+    return NS_OK;
+
+  return aLists.Content()->AppendNewToTop(new (aBuilder)
+                                          nsDisplayNotation(aFrame, aRect,
+                                                            aThickness,
+                                                            aType));
+}
new file mode 100644
--- /dev/null
+++ b/layout/mathml/nsMathMLmencloseFrame.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla MathML Project.
+ *
+ * The Initial Developer of the Original Code is
+ * The University Of Queensland.
+ * Portions created by the Initial Developer are Copyright (C) 1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Roger B. Sidje <rbs@maths.uq.edu.au>
+ *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
+ *   Vilya Harvey <vilya@nag.co.uk>
+ *   Shyjan Mahamud <mahamud@cs.cmu.edu>
+ *   Frederic Wang <fred.wang@free.fr> - extension of <msqrt/> to <menclose/>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#ifndef nsMathMLmencloseFrame_h___
+#define nsMathMLmencloseFrame_h___
+
+#include "nsCOMPtr.h"
+#include "nsMathMLContainerFrame.h"
+
+//
+// <menclose> -- enclose content with a stretching symbol such
+// as a long division sign.
+//
+
+/*
+  The MathML REC describes:
+
+  The menclose element renders its content inside the enclosing notation
+  specified by its notation attribute. menclose accepts any number of arguments;
+  if this number is not 1, its contents are treated as a single "inferred mrow"
+  containing its arguments, as described in Section 3.1.3 Required Arguments. 
+*/
+
+enum nsMencloseNotation
+  {
+    NOTATION_LONGDIV = 0x1,
+    NOTATION_RADICAL = 0x2,
+    NOTATION_ROUNDEDBOX = 0x4,
+    NOTATION_CIRCLE = 0x8,
+    NOTATION_LEFT = 0x10,
+    NOTATION_RIGHT = 0x20,
+    NOTATION_TOP = 0x40,
+    NOTATION_BOTTOM = 0x80,
+    NOTATION_UPDIAGONALSTRIKE = 0x100,
+    NOTATION_DOWNDIAGONALSTRIKE = 0x200,
+    NOTATION_VERTICALSTRIKE = 0x400,
+    NOTATION_HORIZONTALSTRIKE = 0x800
+    // NOTATION_MADRUWB = 0x1000
+  };
+
+class nsMathMLmencloseFrame : public nsMathMLContainerFrame {
+public:
+  friend nsIFrame* NS_NewMathMLmencloseFrame(nsIPresShell*   aPresShell,
+                                             nsStyleContext* aContext);
+  
+  virtual nsresult
+  Place(nsIRenderingContext& aRenderingContext,
+        PRBool               aPlaceOrigin,
+        nsHTMLReflowMetrics& aDesiredSize);
+  
+  virtual nsresult
+  MeasureForWidth(nsIRenderingContext& aRenderingContext,
+                  nsHTMLReflowMetrics& aDesiredSize);
+  
+  NS_IMETHOD
+  AttributeChanged(PRInt32         aNameSpaceID,
+                   nsIAtom*        aAttribute,
+                   PRInt32         aModType);
+  
+  virtual void
+  SetAdditionalStyleContext(PRInt32          aIndex, 
+                            nsStyleContext*  aStyleContext);
+  virtual nsStyleContext*
+  GetAdditionalStyleContext(PRInt32 aIndex) const;
+
+  NS_IMETHOD
+  Init(nsIContent* aContent,
+       nsIFrame*   aParent,
+       nsIFrame*   aPrevInFlow);
+
+  NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                              const nsRect&           aDirtyRect,
+                              const nsDisplayListSet& aLists);
+
+  NS_IMETHOD
+  InheritAutomaticData(nsIFrame* aParent);
+
+  NS_IMETHOD
+  TransmitAutomaticData();
+
+  virtual nscoord
+  FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize);
+
+protected:
+  nsMathMLmencloseFrame(nsStyleContext* aContext);
+  virtual ~nsMathMLmencloseFrame();
+
+  nsresult PlaceInternal(nsIRenderingContext& aRenderingContext,
+                         PRBool               aPlaceOrigin,
+                         nsHTMLReflowMetrics& aDesiredSize,
+                         PRBool               aWidthOnly);
+  
+  // functions to parse the "notation" attribute.
+  nsresult AddNotation(const nsAString& aNotation);
+  void InitNotations();
+
+  // Description of the notations to draw
+  PRUint32 mNotationsToDraw;
+  PRBool IsToDraw(nsMencloseNotation mask)
+  {
+    return mask & mNotationsToDraw;
+  }
+
+  nscoord mRuleThickness;
+  nsTArray<nsMathMLChar> mMathMLChar;
+  PRInt8 mLongDivCharIndex, mRadicalCharIndex;
+  nscoord mContentWidth;
+  nsresult AllocateMathMLChar(nsMencloseNotation mask);
+
+  // Display a frame of the specified type.
+  // @param aType Type of frame to display
+  nsresult DisplayNotation(nsDisplayListBuilder* aBuilder,
+                           nsIFrame* aFrame, const nsRect& aRect,
+                           const nsDisplayListSet& aLists,
+                           nscoord aThickness, nsMencloseNotation aType);
+};
+
+#endif /* nsMathMLmencloseFrame_h___ */
--- a/layout/mathml/nsMathMLmsqrtFrame.cpp
+++ b/layout/mathml/nsMathMLmsqrtFrame.cpp
@@ -35,309 +35,58 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-
-#include "nsCOMPtr.h"
-#include "nsFrame.h"
-#include "nsPresContext.h"
-#include "nsStyleContext.h"
-#include "nsStyleConsts.h"
-#include "nsIRenderingContext.h"
-#include "nsIFontMetrics.h"
-
 #include "nsMathMLmsqrtFrame.h"
 
 //
-// <msqrt> and <mroot> -- form a radical - implementation
+// <msqrt> -- form a radical - implementation
 //
 
 //NOTE:
 //  The code assumes that TeX fonts are picked.
 //  There is no fall-back to draw the branches of the sqrt explicitly
 //  in the case where TeX fonts are not there. In general, there are no
 //  fall-back(s) in MathML when some (freely-downloadable) fonts are missing.
 //  Otherwise, this will add much work and unnecessary complexity to the core
 //  MathML  engine. Assuming that authors have the free fonts is part of the
 //  deal. We are not responsible for cases of misconfigurations out there.
 
-// additional style context to be used by our MathMLChar.
-#define NS_SQR_CHAR_STYLE_CONTEXT_INDEX   0
-
-static const PRUnichar kSqrChar = PRUnichar(0x221A);
-
 nsIFrame*
 NS_NewMathMLmsqrtFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsMathMLmsqrtFrame(aContext);
 }
 
 nsMathMLmsqrtFrame::nsMathMLmsqrtFrame(nsStyleContext* aContext) :
-  nsMathMLContainerFrame(aContext),
-  mSqrChar(),
-  mBarRect()
+  nsMathMLmencloseFrame(aContext)
 {
 }
 
 nsMathMLmsqrtFrame::~nsMathMLmsqrtFrame()
 {
 }
 
 NS_IMETHODIMP
 nsMathMLmsqrtFrame::Init(nsIContent*      aContent,
                          nsIFrame*        aParent,
                          nsIFrame*        aPrevInFlow)
 {
   nsresult rv = nsMathMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
-                                             
-  nsPresContext *presContext = PresContext();
-
-  // No need to tract the style context given to our MathML char. 
-  // The Style System will use Get/SetAdditionalStyleContext() to keep it
-  // up-to-date if dynamic changes arise.
-  nsAutoString sqrChar; sqrChar.Assign(kSqrChar);
-  mSqrChar.SetData(presContext, sqrChar);
-  ResolveMathMLCharStyle(presContext, mContent, mStyleContext, &mSqrChar, PR_TRUE);
+  AllocateMathMLChar(NOTATION_RADICAL);
+  mNotationsToDraw |= NOTATION_RADICAL;
 
   return rv;
 }
 
 NS_IMETHODIMP
-nsMathMLmsqrtFrame::InheritAutomaticData(nsIFrame* aParent)
-{
-  // let the base class get the default from our parent
-  nsMathMLContainerFrame::InheritAutomaticData(aParent);
-
-  mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
-
-  return NS_OK;
-}
-
-
-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,
-     NS_MATHML_COMPRESSED,
-     NS_MATHML_COMPRESSED);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsMathMLmsqrtFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
-                                     const nsRect&           aDirtyRect,
-                                     const nsDisplayListSet& aLists)
-{
-  /////////////
-  // paint the content we are square-rooting
-  nsresult rv = nsMathMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  /////////////
-  // paint the sqrt symbol
-  if (!NS_MATHML_HAS_ERROR(mPresentationData.flags)) {
-    rv = mSqrChar.Display(aBuilder, this, aLists);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = DisplayBar(aBuilder, this, mBarRect, aLists);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
-    // for visual debug
-    nsRect rect;
-    mSqrChar.GetRect(rect);
-    nsBoundingMetrics bm;
-    mSqrChar.GetBoundingMetrics(bm);
-    rv = DisplayBoundingMetrics(aBuilder, this, rect.TopLeft(), bm, aLists);
-#endif
-  }
-
-  return rv;
-}
-
-/* virtual */ nsresult
-nsMathMLmsqrtFrame::Place(nsIRenderingContext& aRenderingContext,
-                          PRBool               aPlaceOrigin,
-                          nsHTMLReflowMetrics& aDesiredSize)
+nsMathMLmsqrtFrame::AttributeChanged(PRInt32         aNameSpaceID,
+                                     nsIAtom*        aAttribute,
+                                     PRInt32         aModType)
 {
-  ///////////////
-  // Measure the size of our content using the base class to format like an
-  // inferred mrow.
-  nsHTMLReflowMetrics baseSize;
-  nsresult rv =
-    nsMathMLContainerFrame::Place(aRenderingContext, PR_FALSE, baseSize);
-  if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
-    DidReflowChildren(GetFirstChild(nsnull));
-    return rv;
-  }
-
-  nsBoundingMetrics bmSqr, bmBase;
-  bmBase = baseSize.mBoundingMetrics;
-
-  ////////////
-  // Prepare the radical symbol and the overline bar
-
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
-                            PresContext()->GetUserFontSet());
-  nsCOMPtr<nsIFontMetrics> fm;
-  aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
-
-  // For radical glyphs from TeX fonts and some of the radical glyphs from
-  // Mathematica fonts, the thickness of the overline can be obtained from the
-  // ascent of the glyph.  Most fonts however have radical glyphs above the
-  // baseline so no assumption can be made about the meaning of the ascent.
-  nscoord ruleThickness, leading, em;
-  GetRuleThickness(aRenderingContext, fm, ruleThickness);
-
-  nsBoundingMetrics bmOne;
-  aRenderingContext.GetBoundingMetrics(NS_LITERAL_STRING("1").get(), 1, bmOne);
-
-  // get the leading to be left at the top of the resulting frame
-  // this seems more reliable than using fm->GetLeading() on suspicious fonts
-  GetEmHeight(fm, em);
-  leading = nscoord(0.2f * em); 
-
-  // Rule 11, App. G, TeXbook
-  // psi = clearance between rule and content
-  nscoord phi = 0, psi = 0;
-  if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags))
-    fm->GetXHeight(phi);
-  else
-    phi = ruleThickness;
-  psi = ruleThickness + phi/4;
-
-  // built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131)
-  if (bmOne.ascent > bmBase.ascent)
-    psi += bmOne.ascent - bmBase.ascent;
-
-  // make sure that the rule appears on the screen
-  nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
-  if (ruleThickness < onePixel) {
-    ruleThickness = onePixel;
-  }
-
-  // adjust clearance psi to get an exact number of pixels -- this
-  // gives a nicer & uniform look on stacked radicals (bug 130282)
-  nscoord delta = psi % onePixel;
-  if (delta)
-    psi += onePixel - delta; // round up
-
-  // Stretch the radical symbol to the appropriate height if it is not big enough.
-  nsBoundingMetrics contSize = bmBase;
-  contSize.ascent = ruleThickness;
-  contSize.descent = bmBase.ascent + bmBase.descent + psi;
-
-  // height(radical) should be >= height(base) + psi + ruleThickness
-  nsBoundingMetrics radicalSize;
-  mSqrChar.Stretch(PresContext(), aRenderingContext,
-                   NS_STRETCH_DIRECTION_VERTICAL, 
-                   contSize, radicalSize,
-                   NS_STRETCH_LARGER);
-  // radicalSize have changed at this point, and should match with
-  // the bounding metrics of the char
-  mSqrChar.GetBoundingMetrics(bmSqr);
-
-  nscoord dx = 0, dy = 0;
-  // place the radical symbol and the radical bar
-  dy = leading; // leave a leading at the top
-  mSqrChar.SetRect(nsRect(dx, dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
-  dx = bmSqr.width;
-  mBarRect.SetRect(dx, dy, bmBase.width, ruleThickness);
-
-  // Update the desired size for the container.
-  // the baseline will be that of the base.
-  mBoundingMetrics.ascent = bmBase.ascent + psi + ruleThickness;
-  mBoundingMetrics.descent = 
-    PR_MAX(bmBase.descent,
-           (bmSqr.ascent + bmSqr.descent - mBoundingMetrics.ascent));
-  mBoundingMetrics.width = bmSqr.width + bmBase.width;
-  mBoundingMetrics.leftBearing = bmSqr.leftBearing;
-  mBoundingMetrics.rightBearing = bmSqr.width + 
-    PR_MAX(bmBase.width, bmBase.rightBearing); // take also care of the rule
-
-  aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
-  aDesiredSize.height = aDesiredSize.ascent +
-    PR_MAX(baseSize.height - baseSize.ascent,
-           mBoundingMetrics.descent + ruleThickness);
-  aDesiredSize.width = mBoundingMetrics.width;
-  aDesiredSize.mBoundingMetrics = mBoundingMetrics;
-
-  mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
-
-  if (aPlaceOrigin) {
-    //////////////////
-    // Finish reflowing child frames, positioning their origins so as to leave
-    // room for the sqrt char and the overline bar.
-    PositionRowChildFrames(radicalSize.width, aDesiredSize.ascent);
-  }
-
-  return NS_OK;
+  return nsMathMLContainerFrame::
+    AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
-
-/* virtual */ nscoord
-nsMathMLmsqrtFrame::GetIntrinsicWidth(nsIRenderingContext* aRenderingContext)
-{
-  // The child frames form an mrow
-  nscoord width = nsMathMLContainerFrame::GetIntrinsicWidth(aRenderingContext);
-  // Add the width of the radical symbol
-  width += mSqrChar.GetMaxWidth(PresContext(), *aRenderingContext);
-
-  return width;
-}
-
-/* virtual */ nsresult
-nsMathMLmsqrtFrame::MeasureChildFrames(nsIRenderingContext& aRenderingContext,
-                                       nsHTMLReflowMetrics& aDesiredSize)
-{
-  return nsMathMLContainerFrame::Place(aRenderingContext, PR_FALSE,
-                                       aDesiredSize);
-}
-
-
-nscoord
-nsMathMLmsqrtFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
-{
-  nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
-  if (!gap) return 0;
-
-  nsRect rect;
-  mSqrChar.GetRect(rect);
-  rect.MoveBy(gap, 0);
-  mSqrChar.SetRect(rect);
-  mBarRect.MoveBy(gap, 0);
-  return gap;
-}
-
-// ----------------------
-// the Style System will use these to pass the proper style context to our MathMLChar
-nsStyleContext*
-nsMathMLmsqrtFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
-{
-  switch (aIndex) {
-  case NS_SQR_CHAR_STYLE_CONTEXT_INDEX:
-    return mSqrChar.GetStyleContext();
-    break;
-  default:
-    return nsnull;
-  }
-}
-
-void
-nsMathMLmsqrtFrame::SetAdditionalStyleContext(PRInt32          aIndex, 
-                                              nsStyleContext*  aStyleContext)
-{
-  switch (aIndex) {
-  case NS_SQR_CHAR_STYLE_CONTEXT_INDEX:
-    mSqrChar.SetStyleContext(aStyleContext);
-    break;
-  }
-}
--- a/layout/mathml/nsMathMLmsqrtFrame.h
+++ b/layout/mathml/nsMathMLmsqrtFrame.h
@@ -37,21 +37,20 @@
  * 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 nsMathMLmsqrtFrame_h___
 #define nsMathMLmsqrtFrame_h___
 
-#include "nsCOMPtr.h"
-#include "nsMathMLContainerFrame.h"
+#include "nsMathMLmencloseFrame.h"
 
 //
-// <msqrt> -- form a fraction from two subexpressions 
+// <msqrt> -- form a radical
 //
 
 /*
 The MathML REC describes:
 
 The <msqrt> element is used to display square roots.
 The syntax for <msqrt> is:
   <msqrt> base </msqrt>
@@ -63,68 +62,30 @@ 2.3.4).
 
 The <mroot> element increments scriptlevel by 2, and sets displaystyle to
 "false", within index, but leaves both attributes unchanged within base. The
 <msqrt> element leaves both attributes unchanged within all its arguments.
 These attributes are inherited by every element from its rendering environment,
 but can be set explicitly only on <mstyle>. (See Section 3.3.4.) 
 */
 
-/*
-TODO:
-*/
-
-class nsMathMLmsqrtFrame : public nsMathMLContainerFrame {
+class nsMathMLmsqrtFrame : public nsMathMLmencloseFrame {
 public:
-  friend nsIFrame* NS_NewMathMLmsqrtFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
-
-  virtual void
-  SetAdditionalStyleContext(PRInt32          aIndex, 
-                            nsStyleContext*  aStyleContext);
-  virtual nsStyleContext*
-  GetAdditionalStyleContext(PRInt32 aIndex) const;
+  friend nsIFrame* NS_NewMathMLmsqrtFrame(nsIPresShell*   aPresShell,
+                                          nsStyleContext* aContext);
 
   NS_IMETHOD
   Init(nsIContent* aContent,
        nsIFrame*   aParent,
        nsIFrame*   aPrevInFlow);
 
-  virtual nsresult
-  Place(nsIRenderingContext& aRenderingContext,
-        PRBool               aPlaceOrigin,
-        nsHTMLReflowMetrics& aDesiredSize);
-
-  virtual nscoord
-  GetIntrinsicWidth(nsIRenderingContext* aRenderingContext);
-
-  NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
-                              const nsRect&           aDirtyRect,
-                              const nsDisplayListSet& aLists);
-
   NS_IMETHOD
-  InheritAutomaticData(nsIFrame* aParent);
-
-  NS_IMETHOD
-  TransmitAutomaticData();
-
-  // the base method doesn't deal fully with <msqrt> because it only
-  // slides child frames and has no idea that we have a sqrt glyph that
-  // is part of the flow without being a frame. We need to shift our
-  // sqrt glyph too. 
-  virtual nscoord
-  FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize);
+  AttributeChanged(PRInt32         aNameSpaceID,
+                   nsIAtom*        aAttribute,
+                   PRInt32         aModType);
 
 protected:
   nsMathMLmsqrtFrame(nsStyleContext* aContext);
   virtual ~nsMathMLmsqrtFrame();
-  
-  virtual PRIntn GetSkipSides() const { return 0; }
-
-  virtual nsresult
-  MeasureChildFrames(nsIRenderingContext& aRenderingContext,
-                     nsHTMLReflowMetrics& aDesiredSize);
-
-  nsMathMLChar mSqrChar;
-  nsRect       mBarRect;
 };
 
 #endif /* nsMathMLmsqrtFrame_h___ */