Back to index

lightning-sunbird  0.9+nobinonly
nsMathMLmunderoverFrame.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla MathML Project.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * The University Of Queensland.
00018  * Portions created by the Initial Developer are Copyright (C) 1999
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Roger B. Sidje <rbs@maths.uq.edu.au>
00023  *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
00024  *   Shyjan Mahamud <mahamud@cs.cmu.edu>
00025  *   Pierre Phaneuf <pp@ludusdesign.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 
00042 #include "nsCOMPtr.h"
00043 #include "nsFrame.h"
00044 #include "nsPresContext.h"
00045 #include "nsUnitConversion.h"
00046 #include "nsStyleContext.h"
00047 #include "nsStyleConsts.h"
00048 #include "nsINameSpaceManager.h"
00049 #include "nsIRenderingContext.h"
00050 #include "nsIFontMetrics.h"
00051 
00052 #include "nsMathMLmunderoverFrame.h"
00053 #include "nsMathMLmsubsupFrame.h"
00054 
00055 //
00056 // <munderover> -- attach an underscript-overscript pair to a base - implementation
00057 //
00058 
00059 nsresult
00060 NS_NewMathMLmunderoverFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
00061 {
00062   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00063   if (nsnull == aNewFrame) {
00064     return NS_ERROR_NULL_POINTER;
00065   }
00066   nsMathMLmunderoverFrame* it = new (aPresShell) nsMathMLmunderoverFrame;
00067   if (nsnull == it) {
00068     return NS_ERROR_OUT_OF_MEMORY;
00069   }
00070   *aNewFrame = it;
00071   return NS_OK;
00072 }
00073 
00074 nsMathMLmunderoverFrame::nsMathMLmunderoverFrame()
00075 {
00076 }
00077 
00078 nsMathMLmunderoverFrame::~nsMathMLmunderoverFrame()
00079 {
00080 }
00081 
00082 NS_IMETHODIMP
00083 nsMathMLmunderoverFrame::AttributeChanged(nsIContent*     aContent,
00084                                           PRInt32         aNameSpaceID,
00085                                           nsIAtom*        aAttribute,
00086                                           PRInt32         aModType)
00087 {
00088   if (nsMathMLAtoms::accent_ == aAttribute ||
00089       nsMathMLAtoms::accentunder_ == aAttribute) {
00090     // When we have automatic data to update within ourselves, we ask our
00091     // parent to re-layout its children
00092     return ReLayoutChildren(mParent);
00093   }
00094 
00095   return nsMathMLContainerFrame::
00096          AttributeChanged(aContent, aNameSpaceID,
00097                           aAttribute, aModType);
00098 }
00099 
00100 NS_IMETHODIMP
00101 nsMathMLmunderoverFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
00102                                                 PRUint32        aFlagsValues,
00103                                                 PRUint32        aFlagsToUpdate)
00104 {
00105   nsMathMLContainerFrame::UpdatePresentationData(aScriptLevelIncrement,
00106     aFlagsValues, aFlagsToUpdate);
00107   // disable the stretch-all flag if we are going to act like a subscript-superscript pair
00108   if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
00109       !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
00110     mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
00111   }
00112   else {
00113     mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
00114   }
00115   return NS_OK;
00116 }
00117 
00118 NS_IMETHODIMP
00119 nsMathMLmunderoverFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
00120                                                            PRInt32         aLastIndex,
00121                                                            PRInt32         aScriptLevelIncrement,
00122                                                            PRUint32        aFlagsValues,
00123                                                            PRUint32        aFlagsToUpdate)
00124 {
00125   // munderover is special... The REC says:
00126   // Within underscript, <munder> always sets displaystyle to "false", 
00127   // but increments scriptlevel by 1 only when accentunder is "false".
00128   // Within underscript, <munderover> always sets displaystyle to "false",
00129   // but increments scriptlevel by 1 only when accentunder is "false". 
00130   // This means that
00131   // 1. don't allow displaystyle to change in the underscript & overscript
00132   // 2a if the value of the accent is changed, we need to recompute the
00133   //    scriptlevel of the underscript. The problem is that the accent
00134   //    can change in the <mo> deep down the embellished hierarchy
00135   // 2b if the value of the accent is changed, we need to recompute the
00136   //    scriptlevel of the overscript. The problem is that the accent
00137   //    can change in the <mo> deep down the embellished hierarchy
00138 
00139   // Do #1 here, prevent displaystyle to be changed in the underscript & overscript
00140   PRInt32 index = 0;
00141   nsIFrame* childFrame = mFrames.FirstChild();
00142   while (childFrame) {
00143     if ((index >= aFirstIndex) &&
00144         ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) {
00145       if (index > 0) {
00146         // disable the flag
00147         aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
00148         aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
00149       }
00150       PropagatePresentationDataFor(childFrame,
00151         aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
00152     }
00153     index++;
00154     childFrame = childFrame->GetNextSibling();
00155   }
00156   return NS_OK;
00157 
00158   // For #2, changing the accent attribute will trigger a re-build of
00159   // all automatic data in the embellished hierarchy
00160 }
00161 
00162 NS_IMETHODIMP
00163 nsMathMLmunderoverFrame::InheritAutomaticData(nsIFrame* aParent)
00164 {
00165   // let the base class get the default from our parent
00166   nsMathMLContainerFrame::InheritAutomaticData(aParent);
00167 
00168   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
00169 
00170   return NS_OK;
00171 }
00172 
00173 NS_IMETHODIMP
00174 nsMathMLmunderoverFrame::TransmitAutomaticData()
00175 {
00176   // At this stage, all our children are in sync and we can fully
00177   // resolve our own mEmbellishData struct
00178   //---------------------------------------------------------------------
00179 
00180   /* 
00181   The REC says:
00182 
00183   The accent and accentunder attributes have the same effect as
00184   the attributes with the same names on <mover>  and <munder>, 
00185   respectively. Their default values are also computed in the 
00186   same manner as described for those elements, with the default
00187   value of accent depending on overscript and the default value
00188   of accentunder depending on underscript.
00189   */
00190 
00191   nsIFrame* overscriptFrame = nsnull;
00192   nsIFrame* underscriptFrame = nsnull;
00193   nsIFrame* baseFrame = mFrames.FirstChild();
00194   if (baseFrame)
00195     underscriptFrame = baseFrame->GetNextSibling();
00196   if (underscriptFrame)
00197     overscriptFrame = underscriptFrame->GetNextSibling();
00198 
00199   // if our base is an embellished operator, let its state bubble to us (in particular,
00200   // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags
00201   // are reset to the default values of false if the base frame isn't embellished.
00202   mPresentationData.baseFrame = baseFrame;
00203   GetEmbellishDataFrom(baseFrame, mEmbellishData);
00204 
00205   nsAutoString value;
00206 
00207   // The default value of accentunder is false, unless the underscript is embellished
00208   // and its core <mo> is an accent
00209   nsEmbellishData embellishData;
00210   GetEmbellishDataFrom(underscriptFrame, embellishData);
00211   if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags))
00212     mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER;
00213   else
00214     mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER;
00215 
00216   // if we have an accentunder attribute, it overrides what the underscript said
00217   if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, 
00218                    nsMathMLAtoms::accentunder_, value)) {
00219     if (value.EqualsLiteral("true"))
00220       mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER;
00221     else if (value.EqualsLiteral("false")) 
00222       mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER;
00223   }
00224 
00225   // The default value of accent is false, unless the overscript is embellished
00226   // and its core <mo> is an accent
00227   GetEmbellishDataFrom(overscriptFrame, embellishData);
00228   if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags))
00229     mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER;
00230   else
00231     mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER;
00232 
00233   // if we have an accent attribute, it overrides what the overscript said
00234   if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, 
00235                    nsMathMLAtoms::accent_, value)) {
00236     if (value.EqualsLiteral("true"))
00237       mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER;
00238     else if (value.EqualsLiteral("false")) 
00239       mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER;
00240   }
00241 
00242   // disable the stretch-all flag if we are going to act like a superscript
00243   if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
00244       !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags))
00245     mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY;
00246 
00247   // Now transmit any change that we want to our children so that they
00248   // can update their mPresentationData structs
00249   //---------------------------------------------------------------------
00250 
00251   /* The REC says:
00252      Within underscript, <munderover> always sets displaystyle to "false",
00253      but increments scriptlevel by 1 only when accentunder is "false". 
00254 
00255      Within overscript, <munderover> always sets displaystyle to "false", 
00256      but increments scriptlevel by 1 only when accent is "false".
00257  
00258      The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a
00259      say it shouldn't be compressed. However, The TeXBook says
00260      that math accents and \overline change uncramped styles to their
00261      cramped counterparts.
00262   */
00263   PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
00264     ? 0 : 1;
00265   PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)
00266     ? NS_MATHML_COMPRESSED : 0;
00267   PropagatePresentationDataFor(overscriptFrame, increment,
00268     ~NS_MATHML_DISPLAYSTYLE | compress,
00269      NS_MATHML_DISPLAYSTYLE | compress);
00270 
00271   /*
00272      The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a 
00273      say it should be compressed
00274   */
00275   increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)
00276     ? 0 : 1;
00277   PropagatePresentationDataFor(underscriptFrame, increment,
00278     ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
00279      NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
00280 
00281   return NS_OK;
00282 }
00283 
00284 /*
00285 The REC says:
00286 *  If the base is an operator with movablelimits="true" (or an embellished
00287    operator whose <mo> element core has movablelimits="true"), and
00288    displaystyle="false", then underscript and overscript are drawn in
00289    a subscript and superscript position, respectively. In this case, 
00290    the accent and accentunder attributes are ignored. This is often
00291    used for limits on symbols such as &sum;.
00292 
00293 i.e.,:
00294  if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishDataflags) &&
00295      !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
00296   // place like subscript-superscript pair
00297  }
00298  else {
00299   // place like underscript-overscript pair
00300  }
00301 */
00302 
00303 NS_IMETHODIMP
00304 nsMathMLmunderoverFrame::Place(nsIRenderingContext& aRenderingContext,
00305                                PRBool               aPlaceOrigin,
00306                                nsHTMLReflowMetrics& aDesiredSize)
00307 {
00308   if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) &&
00309       !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
00310     // place like sub-superscript pair
00311     return nsMathMLmsubsupFrame::PlaceSubSupScript(GetPresContext(),
00312                                                    aRenderingContext,
00313                                                    aPlaceOrigin,
00314                                                    aDesiredSize,
00315                                                    this);
00316   }
00317 
00319   // Get the children's desired sizes
00320 
00321   nsBoundingMetrics bmBase, bmUnder, bmOver;
00322   nsHTMLReflowMetrics baseSize (nsnull);
00323   nsHTMLReflowMetrics underSize (nsnull);
00324   nsHTMLReflowMetrics overSize (nsnull);
00325   nsIFrame* overFrame = nsnull;
00326   nsIFrame* underFrame = nsnull;
00327   nsIFrame* baseFrame = mFrames.FirstChild();
00328   if (baseFrame)
00329     underFrame = baseFrame->GetNextSibling();
00330   if (underFrame)
00331     overFrame = underFrame->GetNextSibling();
00332   if (!baseFrame || !underFrame || !overFrame || overFrame->GetNextSibling()) {
00333     // report an error, encourage people to get their markups in order
00334     NS_WARNING("invalid markup");
00335     return ReflowError(aRenderingContext, aDesiredSize);
00336   }
00337   GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
00338   GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder);
00339   GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver);
00340 
00341   nscoord onePixel = GetPresContext()->IntScaledPixelsToTwips(1);
00342 
00344   // Place Children
00345 
00346   aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull);
00347   nsCOMPtr<nsIFontMetrics> fm;
00348   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
00349 
00350   nscoord xHeight = 0;
00351   fm->GetXHeight (xHeight);
00352 
00353   nscoord ruleThickness;
00354   GetRuleThickness (aRenderingContext, fm, ruleThickness);
00355 
00356   nscoord correction = 0;
00357   GetItalicCorrection (bmBase, correction);
00358 
00359   // there are 2 different types of placement depending on 
00360   // whether we want an accented under or not
00361 
00362   nscoord underDelta1 = 0; // gap between base and underscript
00363   nscoord underDelta2 = 0; // extra space beneath underscript
00364 
00365   if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
00366     // Rule 13a, App. G, TeXbook
00367     nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy; 
00368     GetBigOpSpacings (fm, 
00369                       dummy, bigOpSpacing2, 
00370                       dummy, bigOpSpacing4, 
00371                       bigOpSpacing5);
00372     underDelta1 = PR_MAX(bigOpSpacing2, (bigOpSpacing4 - bmUnder.ascent));
00373     underDelta2 = bigOpSpacing5;
00374   }
00375   else {
00376     // No corresponding rule in TeXbook - we are on our own here
00377     // XXX tune the gap delta between base and underscript 
00378 
00379     // Should we use Rule 10 like \underline does?
00380     underDelta1 = ruleThickness + onePixel/2;
00381     underDelta2 = ruleThickness;
00382   }
00383   // empty under?
00384   if (!(bmUnder.ascent + bmUnder.descent)) underDelta1 = 0;
00385 
00386   nscoord overDelta1 = 0; // gap between base and overscript
00387   nscoord overDelta2 = 0; // extra space above overscript
00388 
00389   if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {    
00390     // Rule 13a, App. G, TeXbook
00391     nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy; 
00392     GetBigOpSpacings (fm, 
00393                       bigOpSpacing1, dummy, 
00394                       bigOpSpacing3, dummy, 
00395                       bigOpSpacing5);
00396     overDelta1 = PR_MAX(bigOpSpacing1, (bigOpSpacing3 - bmOver.descent));
00397     overDelta2 = bigOpSpacing5;
00398 
00399     // XXX This is not a TeX rule... 
00400     // delta1 (as computed abvove) can become really big when bmOver.descent is
00401     // negative,  e.g., if the content is &OverBar. In such case, we use the height
00402     if (bmOver.descent < 0)    
00403       overDelta1 = PR_MAX(bigOpSpacing1, (bigOpSpacing3 - (bmOver.ascent + bmOver.descent)));
00404   }
00405   else {
00406     // Rule 12, App. G, TeXbook
00407     overDelta1 = ruleThickness + onePixel/2;
00408     if (bmBase.ascent < xHeight) { 
00409       overDelta1 += xHeight - bmBase.ascent;
00410     }
00411     overDelta2 = ruleThickness;
00412   }
00413   // empty over?
00414   if (!(bmOver.ascent + bmOver.descent)) overDelta1 = 0;
00415 
00416   nscoord dxBase, dxOver = 0, dxUnder = 0;
00417 
00419   // pass 1, do what <mover> does: attach the overscript on the base
00420 
00421   // Ad-hoc - This is to override fonts which have ready-made _accent_
00422   // glyphs with negative lbearing and rbearing. We want to position
00423   // the overscript ourselves
00424   nscoord overWidth = bmOver.width;
00425   if (!overWidth && (bmOver.rightBearing - bmOver.leftBearing > 0)) {
00426     overWidth = bmOver.rightBearing - bmOver.leftBearing;
00427     dxOver = -bmOver.leftBearing;
00428   }
00429 
00430   if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {
00431     mBoundingMetrics.width = bmBase.width; 
00432     dxOver += correction + (mBoundingMetrics.width - overWidth)/2;
00433   }
00434   else {
00435     mBoundingMetrics.width = PR_MAX(bmBase.width, overWidth);
00436     dxOver += correction/2 + (mBoundingMetrics.width - overWidth)/2;
00437   }
00438   dxBase = (mBoundingMetrics.width - bmBase.width)/2;
00439 
00440   mBoundingMetrics.ascent = 
00441     bmBase.ascent + overDelta1 + bmOver.ascent + bmOver.descent;
00442   mBoundingMetrics.descent = 
00443     bmBase.descent + underDelta1 + bmUnder.ascent + bmUnder.descent;
00444   mBoundingMetrics.leftBearing = 
00445     PR_MIN(dxBase + bmBase.leftBearing, dxOver + bmOver.leftBearing);
00446   mBoundingMetrics.rightBearing = 
00447     PR_MAX(dxBase + bmBase.rightBearing, dxOver + bmOver.rightBearing);
00448 
00450   // pass 2, do what <munder> does: attach the underscript on the previous
00451   // result. We conceptually view the previous result as an "anynomous base" 
00452   // from where to attach the underscript. Hence if the underscript is empty,
00453   // we should end up like <mover>. If the overscript is empty, we should
00454   // end up like <munder>.
00455 
00456   nsBoundingMetrics bmAnonymousBase = mBoundingMetrics;
00457   nscoord ascentAnonymousBase =
00458     PR_MAX(mBoundingMetrics.ascent + overDelta2,
00459            overSize.ascent + bmOver.descent + overDelta1 + bmBase.ascent);
00460 
00461   GetItalicCorrection(bmAnonymousBase, correction);
00462 
00463   nscoord maxWidth = PR_MAX(bmAnonymousBase.width, bmUnder.width);
00464   if (NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {    
00465     dxUnder = (maxWidth - bmUnder.width)/2;;
00466   }
00467   else {
00468     dxUnder = -correction/2 + (maxWidth - bmUnder.width)/2;
00469   }
00470   nscoord dxAnonymousBase = (maxWidth - bmAnonymousBase.width)/2;
00471 
00472   // adjust the offsets of the real base and overscript since their
00473   // final offsets should be relative to us...
00474   dxOver += dxAnonymousBase;
00475   dxBase += dxAnonymousBase;
00476 
00477   mBoundingMetrics.width =
00478     PR_MAX(dxAnonymousBase + bmAnonymousBase.width, dxUnder + bmUnder.width);
00479   mBoundingMetrics.leftBearing =
00480     PR_MIN(dxAnonymousBase + bmAnonymousBase.leftBearing, dxUnder + bmUnder.leftBearing);
00481   mBoundingMetrics.rightBearing = 
00482     PR_MAX(dxAnonymousBase + bmAnonymousBase.rightBearing, dxUnder + bmUnder.rightBearing);
00483 
00484   aDesiredSize.ascent = ascentAnonymousBase;
00485   aDesiredSize.descent = 
00486     PR_MAX(mBoundingMetrics.descent + underDelta2,
00487            bmAnonymousBase.descent + underDelta1 + bmUnder.ascent + underSize.descent);
00488   aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
00489   aDesiredSize.width = mBoundingMetrics.width;
00490   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
00491 
00492   mReference.x = 0;
00493   mReference.y = aDesiredSize.ascent;
00494 
00495   if (aPlaceOrigin) {
00496     nscoord dy;
00497     // place overscript
00498     dy = aDesiredSize.ascent - mBoundingMetrics.ascent + bmOver.ascent - overSize.ascent;
00499     FinishReflowChild (overFrame, GetPresContext(), nsnull, overSize, dxOver, dy, 0);
00500     // place base
00501     dy = aDesiredSize.ascent - baseSize.ascent;
00502     FinishReflowChild (baseFrame, GetPresContext(), nsnull, baseSize, dxBase, dy, 0);
00503     // place underscript
00504     dy = aDesiredSize.ascent + mBoundingMetrics.descent - bmUnder.descent - underSize.ascent;
00505     FinishReflowChild (underFrame, GetPresContext(), nsnull, underSize, dxUnder, dy, 0);
00506   }
00507   return NS_OK;
00508 }