Back to index

lightning-sunbird  0.9+nobinonly
nsMathMLmfracFrame.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  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 
00041 #include "nsCOMPtr.h"
00042 #include "nsFrame.h"
00043 #include "nsPresContext.h"
00044 #include "nsUnitConversion.h"
00045 #include "nsStyleContext.h"
00046 #include "nsStyleConsts.h"
00047 #include "nsIRenderingContext.h"
00048 #include "nsIFontMetrics.h"
00049 
00050 #include "nsMathMLmfencedFrame.h"
00051 #include "nsMathMLmfracFrame.h"
00052 
00053 //
00054 // <mfrac> -- form a fraction from two subexpressions - implementation
00055 //
00056 
00057 // various fraction line thicknesses (multiplicative values of the default rule thickness)
00058 
00059 #define THIN_FRACTION_LINE                   0.5f
00060 #define THIN_FRACTION_LINE_MINIMUM_PIXELS    1  // minimum of 1 pixel
00061 
00062 #define MEDIUM_FRACTION_LINE                 1.5f
00063 #define MEDIUM_FRACTION_LINE_MINIMUM_PIXELS  2  // minimum of 2 pixels
00064 
00065 #define THICK_FRACTION_LINE                  2.0f
00066 #define THICK_FRACTION_LINE_MINIMUM_PIXELS   4  // minimum of 4 pixels
00067 
00068 // additional style context to be used by our MathMLChar.
00069 #define NS_SLASH_CHAR_STYLE_CONTEXT_INDEX   0
00070 
00071 static const PRUnichar kSlashChar = PRUnichar('/');
00072 
00073 nsresult
00074 NS_NewMathMLmfracFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
00075 {
00076   NS_PRECONDITION(aNewFrame, "null OUT ptr");
00077   if (nsnull == aNewFrame) {
00078     return NS_ERROR_NULL_POINTER;
00079   }
00080   nsMathMLmfracFrame* it = new (aPresShell) nsMathMLmfracFrame;
00081   if (nsnull == it) {
00082     return NS_ERROR_OUT_OF_MEMORY;
00083   }
00084   *aNewFrame = it;
00085   return NS_OK;
00086 }
00087 
00088 nsMathMLmfracFrame::nsMathMLmfracFrame()
00089 {
00090 }
00091 
00092 nsMathMLmfracFrame::~nsMathMLmfracFrame()
00093 {
00094   if (mSlashChar) {
00095     delete mSlashChar;
00096     mSlashChar = nsnull;
00097   }
00098 }
00099 
00100 PRBool
00101 nsMathMLmfracFrame::IsBevelled()
00102 {
00103   nsAutoString value;
00104   if (NS_CONTENT_ATTR_HAS_VALUE == 
00105       GetAttribute(mContent, mPresentationData.mstyle,
00106                    nsMathMLAtoms::bevelled_, value)) {
00107     if (value.EqualsLiteral("true")) {
00108       return PR_TRUE;
00109     }
00110   }
00111   return PR_FALSE;
00112 }
00113 
00114 NS_IMETHODIMP
00115 nsMathMLmfracFrame::Init(nsPresContext*  aPresContext,
00116                          nsIContent*      aContent,
00117                          nsIFrame*        aParent,
00118                          nsStyleContext*  aContext,
00119                          nsIFrame*        aPrevInFlow)
00120 {
00121   nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
00122   if (NS_FAILED(rv)) return rv;
00123 
00124   if (IsBevelled()) {
00125     // enable the bevelled rendering
00126     mSlashChar = new nsMathMLChar();
00127     if (mSlashChar) {
00128       nsAutoString slashChar; slashChar.Assign(kSlashChar);
00129       mSlashChar->SetData(aPresContext, slashChar);
00130       ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mSlashChar, PR_TRUE);
00131     }
00132   }
00133 
00134   return rv;
00135 }
00136 
00137 eMathMLFrameType
00138 nsMathMLmfracFrame::GetMathMLFrameType()
00139 {
00140   // frac is "inner" in TeXBook, Appendix G, rule 15e. See also page 170.
00141   return eMathMLFrameType_Inner;
00142 }
00143 
00144 NS_IMETHODIMP
00145 nsMathMLmfracFrame::TransmitAutomaticData()
00146 {
00147   // 1. The REC says:
00148   //    The <mfrac> element sets displaystyle to "false", or if it was already
00149   //    false increments scriptlevel by 1, within numerator and denominator.
00150   // 2. The TeXbook (Ch 17. p.141) says the numerator inherits the compression
00151   //    while the denominator is compressed
00152   PRInt32 increment =
00153      NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) ? 0 : 1;
00154   mInnerScriptLevel = mPresentationData.scriptLevel + increment;
00155   UpdatePresentationDataFromChildAt(0, -1, increment,
00156     ~NS_MATHML_DISPLAYSTYLE,
00157      NS_MATHML_DISPLAYSTYLE);
00158   UpdatePresentationDataFromChildAt(1,  1, 0,
00159      NS_MATHML_COMPRESSED,
00160      NS_MATHML_COMPRESSED);
00161 
00162   // if our numerator is an embellished operator, let its state bubble to us
00163   GetEmbellishDataFrom(mFrames.FirstChild(), mEmbellishData);
00164   if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) {
00165     // even when embellished, we need to record that <mfrac> won't fire
00166     // Stretch() on its embellished child
00167     mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
00168   }
00169 
00170   return NS_OK;
00171 }
00172 
00173 nscoord 
00174 nsMathMLmfracFrame::CalcLineThickness(nsPresContext*  aPresContext,
00175                                       nsStyleContext*  aStyleContext,
00176                                       nsString&        aThicknessAttribute,
00177                                       nscoord          onePixel,
00178                                       nscoord          aDefaultRuleThickness)
00179 {
00180   nscoord defaultThickness = aDefaultRuleThickness;
00181   nscoord lineThickness = aDefaultRuleThickness;
00182   nscoord minimumThickness = onePixel;
00183 
00184   if (!aThicknessAttribute.IsEmpty()) {
00185     if (aThicknessAttribute.EqualsLiteral("thin")) {
00186       lineThickness = NSToCoordFloor(defaultThickness * THIN_FRACTION_LINE);
00187       minimumThickness = onePixel * THIN_FRACTION_LINE_MINIMUM_PIXELS;
00188       // should visually decrease by at least one pixel, if default is not a pixel
00189       if (defaultThickness > onePixel && lineThickness > defaultThickness - onePixel)
00190         lineThickness = defaultThickness - onePixel;
00191     }
00192     else if (aThicknessAttribute.EqualsLiteral("medium")) {
00193       lineThickness = NSToCoordRound(defaultThickness * MEDIUM_FRACTION_LINE);
00194       minimumThickness = onePixel * MEDIUM_FRACTION_LINE_MINIMUM_PIXELS;
00195       // should visually increase by at least one pixel
00196       if (lineThickness < defaultThickness + onePixel)
00197         lineThickness = defaultThickness + onePixel;
00198     }
00199     else if (aThicknessAttribute.EqualsLiteral("thick")) {
00200       lineThickness = NSToCoordCeil(defaultThickness * THICK_FRACTION_LINE);
00201       minimumThickness = onePixel * THICK_FRACTION_LINE_MINIMUM_PIXELS;
00202       // should visually increase by at least two pixels
00203       if (lineThickness < defaultThickness + 2*onePixel)
00204         lineThickness = defaultThickness + 2*onePixel;
00205     }
00206     else { // see if it is a plain number, or a percentage, or a h/v-unit like 1ex, 2px, 1em
00207       nsCSSValue cssValue;
00208       if (ParseNumericValue(aThicknessAttribute, cssValue)) {
00209         nsCSSUnit unit = cssValue.GetUnit();
00210         if (eCSSUnit_Number == unit)
00211           lineThickness = nscoord(float(defaultThickness) * cssValue.GetFloatValue());
00212         else if (eCSSUnit_Percent == unit)
00213           lineThickness = nscoord(float(defaultThickness) * cssValue.GetPercentValue());
00214         else if (eCSSUnit_Null != unit)
00215           lineThickness = CalcLength(aPresContext, aStyleContext, cssValue);
00216       }
00217     }
00218   }
00219 
00220   // use minimum if the lineThickness is a non-zero value less than minimun
00221   if (lineThickness && lineThickness < minimumThickness) 
00222     lineThickness = minimumThickness;
00223 
00224   return lineThickness;
00225 }
00226 
00227 NS_IMETHODIMP
00228 nsMathMLmfracFrame::Paint(nsPresContext*      aPresContext,
00229                           nsIRenderingContext& aRenderingContext,
00230                           const nsRect&        aDirtyRect,
00231                           nsFramePaintLayer    aWhichLayer,
00232                           PRUint32             aFlags)
00233 {
00235   // paint the numerator and denominator
00236   nsresult rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext,
00237                                               aDirtyRect, aWhichLayer);
00239   // paint the fraction line
00240   if (mSlashChar) {
00241     // bevelled rendering
00242     mSlashChar->Paint(aPresContext, aRenderingContext,
00243                       aDirtyRect, aWhichLayer, this);
00244   }
00245   else if ((NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) &&
00246            mStyleContext->GetStyleVisibility()->IsVisible() &&
00247            !NS_MATHML_HAS_ERROR(mPresentationData.flags) &&
00248            !mLineRect.IsEmpty()) {
00249     // paint the fraction line with the current text color
00250     aRenderingContext.SetColor(GetStyleColor()->mColor);
00251     aRenderingContext.FillRect(mLineRect.x, mLineRect.y, 
00252                                mLineRect.width, mLineRect.height);
00253   }
00254 
00255   return rv;
00256 }
00257 
00258 NS_IMETHODIMP
00259 nsMathMLmfracFrame::Reflow(nsPresContext*          aPresContext,
00260                              nsHTMLReflowMetrics&     aDesiredSize,
00261                              const nsHTMLReflowState& aReflowState,
00262                              nsReflowStatus&          aStatus)
00263 {
00264   if (mSlashChar) {
00265     // bevelled rendering
00266     return nsMathMLmfencedFrame::doReflow(aPresContext, aReflowState,
00267                                           aDesiredSize, aStatus, this,
00268                                           nsnull, nsnull, mSlashChar, 1);
00269   }
00270 
00271   // default rendering
00272   return nsMathMLContainerFrame::Reflow(aPresContext, aDesiredSize,
00273                                         aReflowState, aStatus);
00274 }
00275 
00276 nscoord
00277 nsMathMLmfracFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
00278 {
00279   nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
00280   if (!gap) return 0;
00281 
00282   if (mSlashChar) {
00283     nsRect rect;
00284     mSlashChar->GetRect(rect);
00285     rect.MoveBy(gap, 0);
00286     mSlashChar->SetRect(rect);
00287   }
00288   else {
00289     mLineRect.MoveBy(gap, 0);
00290   }
00291   return gap;
00292 }
00293 
00294 NS_IMETHODIMP
00295 nsMathMLmfracFrame::Place(nsIRenderingContext& aRenderingContext,
00296                           PRBool               aPlaceOrigin,
00297                           nsHTMLReflowMetrics& aDesiredSize)
00298 {
00300   // Get the children's desired sizes
00301   nsBoundingMetrics bmNum, bmDen;
00302   nsHTMLReflowMetrics sizeNum (nsnull);
00303   nsHTMLReflowMetrics sizeDen (nsnull);
00304   nsIFrame* frameDen = nsnull;
00305   nsIFrame* frameNum = mFrames.FirstChild();
00306   if (frameNum) 
00307     frameDen = frameNum->GetNextSibling();
00308   if (!frameNum || !frameDen || frameDen->GetNextSibling()) {
00309     // report an error, encourage people to get their markups in order
00310     NS_WARNING("invalid markup");
00311     return ReflowError(aRenderingContext, aDesiredSize);
00312   }
00313   GetReflowAndBoundingMetricsFor(frameNum, sizeNum, bmNum);
00314   GetReflowAndBoundingMetricsFor(frameDen, sizeDen, bmDen);
00315 
00317   // Get shifts
00318 
00319   nsPresContext* presContext = GetPresContext();
00320   nscoord onePixel = presContext->IntScaledPixelsToTwips(1);
00321 
00322   aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull);
00323   nsCOMPtr<nsIFontMetrics> fm;
00324   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
00325 
00326   nscoord defaultRuleThickness, axisHeight;
00327   GetRuleThickness(aRenderingContext, fm, defaultRuleThickness);
00328   GetAxisHeight(aRenderingContext, fm, axisHeight);
00329 
00330   // by default, leave at least one-pixel padding at either end, or use
00331   // lspace & rspace that may come from <mo> if we are an embellished container
00332   // (we fetch values from the core since they may use units that depend
00333   // on style data, and style changes could have occured in the core since
00334   // our last visit there)
00335   nsEmbellishData coreData;
00336   GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData);
00337   nscoord leftSpace = PR_MAX(onePixel, coreData.leftSpace);
00338   nscoord rightSpace = PR_MAX(onePixel, coreData.rightSpace);
00339 
00340   // see if the linethickness attribute is there 
00341   nsAutoString value;
00342   GetAttribute(mContent, mPresentationData.mstyle, nsMathMLAtoms::linethickness_, value);
00343   mLineRect.height = CalcLineThickness(presContext, mStyleContext, value,
00344                                        onePixel, defaultRuleThickness);
00345   nscoord numShift = 0;
00346   nscoord denShift = 0;
00347 
00348   // Rule 15b, App. G, TeXbook
00349   nscoord numShift1, numShift2, numShift3;
00350   nscoord denShift1, denShift2;
00351 
00352   GetNumeratorShifts(fm, numShift1, numShift2, numShift3);
00353   GetDenominatorShifts(fm, denShift1, denShift2);
00354   if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) {
00355     // C > T
00356     numShift = numShift1;
00357     denShift = denShift1;
00358   }
00359   else {
00360     numShift = (0 < mLineRect.height) ? numShift2 : numShift3;
00361     denShift = denShift2;
00362   }
00363 
00364   nscoord minClearance = 0;
00365   nscoord actualClearance = 0;
00366 
00367   nscoord actualRuleThickness =  mLineRect.height;
00368 
00369   if (0 == actualRuleThickness) {
00370     // Rule 15c, App. G, TeXbook
00371 
00372     // min clearance between numerator and denominator
00373     minClearance = (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) ?
00374       7 * defaultRuleThickness : 3 * defaultRuleThickness;
00375     actualClearance =
00376       (numShift - bmNum.descent) - (bmDen.ascent - denShift);
00377     // actualClearance should be >= minClearance
00378     if (actualClearance < minClearance) {
00379       nscoord halfGap = (minClearance - actualClearance)/2;
00380       numShift += halfGap;
00381       denShift += halfGap;
00382     }
00383   }
00384   else {
00385     // Rule 15d, App. G, TeXbook
00386 
00387     // min clearance between numerator or denominator and middle of bar
00388 
00389     // TeX has a different interpretation of the thickness.
00390     // Try $a \above10pt b$ to see. Here is what TeX does:
00391 //     minClearance = (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) ?
00392 //      3 * actualRuleThickness : actualRuleThickness;
00393  
00394     // we slightly depart from TeX here. We use the defaultRuleThickness instead
00395     // of the value coming from the linethickness attribute, i.e., we recover what
00396     // TeX does if the user hasn't set linethickness. But when the linethickness
00397     // is set, we avoid the wide gap problem.
00398      minClearance = (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) ?
00399       3 * defaultRuleThickness : defaultRuleThickness + onePixel;
00400 
00401     // adjust numShift to maintain minClearance if needed
00402     actualClearance =
00403       (numShift - bmNum.descent) - (axisHeight + actualRuleThickness/2);
00404     if (actualClearance < minClearance) {
00405       numShift += (minClearance - actualClearance);
00406     }
00407     // adjust denShift to maintain minClearance if needed
00408     actualClearance =
00409       (axisHeight - actualRuleThickness/2) - (bmDen.ascent - denShift);
00410     if (actualClearance < minClearance) {
00411       denShift += (minClearance - actualClearance);
00412     }
00413   }
00414 
00416   // Place Children
00417 
00418   // XXX Need revisiting the width. TeX uses the exact width
00419   // e.g. in $$\huge\frac{\displaystyle\int}{i}$$
00420   nscoord width = PR_MAX(bmNum.width, bmDen.width);
00421   nscoord dxNum = leftSpace + (width - sizeNum.width)/2;
00422   nscoord dxDen = leftSpace + (width - sizeDen.width)/2;
00423   width += leftSpace + rightSpace;
00424 
00425   // see if the numalign attribute is there 
00426   if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, 
00427                    nsMathMLAtoms::numalign_, value)) {
00428     if (value.EqualsLiteral("left"))
00429       dxNum = leftSpace;
00430     else if (value.EqualsLiteral("right"))
00431       dxNum = width - rightSpace - sizeNum.width;
00432   }
00433   // see if the denomalign attribute is there 
00434   if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle, 
00435                    nsMathMLAtoms::denomalign_, value)) {
00436     if (value.EqualsLiteral("left"))
00437       dxDen = leftSpace;
00438     else if (value.EqualsLiteral("right"))
00439       dxDen = width - rightSpace - sizeDen.width;
00440   }
00441 
00442   mBoundingMetrics.rightBearing =
00443     PR_MAX(dxNum + bmNum.rightBearing, dxDen + bmDen.rightBearing);
00444   if (mBoundingMetrics.rightBearing < width - rightSpace)
00445     mBoundingMetrics.rightBearing = width - rightSpace;
00446   mBoundingMetrics.leftBearing =
00447     PR_MIN(dxNum + bmNum.leftBearing, dxDen + bmDen.leftBearing);
00448   if (mBoundingMetrics.leftBearing > leftSpace)
00449     mBoundingMetrics.leftBearing = leftSpace;
00450   mBoundingMetrics.ascent = bmNum.ascent + numShift;
00451   mBoundingMetrics.descent = bmDen.descent + denShift;
00452   mBoundingMetrics.width = width;
00453 
00454   aDesiredSize.ascent = sizeNum.ascent + numShift;
00455   aDesiredSize.descent = sizeDen.descent + denShift;
00456   aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
00457   aDesiredSize.width = mBoundingMetrics.width;
00458   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
00459 
00460   mReference.x = 0;
00461   mReference.y = aDesiredSize.ascent;
00462 
00463   if (aPlaceOrigin) {
00464     nscoord dy;
00465     // place numerator
00466     dy = 0;
00467     FinishReflowChild(frameNum, presContext, nsnull, sizeNum, dxNum, dy, 0);
00468     // place denominator
00469     dy = aDesiredSize.height - sizeDen.height;
00470     FinishReflowChild(frameDen, presContext, nsnull, sizeDen, dxDen, dy, 0);
00471     // place the fraction bar - dy is top of bar
00472     dy = aDesiredSize.ascent - (axisHeight + actualRuleThickness/2);
00473     mLineRect.SetRect(leftSpace, dy, width - (leftSpace + rightSpace), actualRuleThickness);
00474   }
00475 
00476   return NS_OK;
00477 }
00478 
00479 NS_IMETHODIMP
00480 nsMathMLmfracFrame::AttributeChanged(nsIContent*     aContent,
00481                                      PRInt32         aNameSpaceID,
00482                                      nsIAtom*        aAttribute,
00483                                      PRInt32         aModType)
00484 {
00485   if (nsMathMLAtoms::bevelled_ == aAttribute) {
00486     if (!IsBevelled()) {
00487       // disable the bevelled rendering
00488       if (mSlashChar) {
00489         delete mSlashChar;
00490         mSlashChar = nsnull;
00491       }
00492     }
00493     else {
00494       // enable the bevelled rendering
00495       if (!mSlashChar) {
00496         mSlashChar = new nsMathMLChar();
00497         if (mSlashChar) {
00498           nsPresContext* presContext = GetPresContext();
00499           nsAutoString slashChar; slashChar.Assign(kSlashChar);
00500           mSlashChar->SetData(presContext, slashChar);
00501           ResolveMathMLCharStyle(presContext, mContent, mStyleContext, mSlashChar, PR_TRUE);
00502         }
00503       }
00504     }
00505   }
00506   return nsMathMLContainerFrame::
00507          AttributeChanged(aContent, aNameSpaceID,
00508                           aAttribute, aModType);
00509 }
00510 
00511 NS_IMETHODIMP
00512 nsMathMLmfracFrame::UpdatePresentationData(PRInt32         aScriptLevelIncrement,
00513                                            PRUint32        aFlagsValues,
00514                                            PRUint32        aFlagsToUpdate)
00515 {
00516   // mfrac is special... The REC says:
00517   // The <mfrac> element sets displaystyle to "false", or if it was already
00518   // false increments scriptlevel by 1, within numerator and denominator.
00519   // @see similar peculiarities for <mover>, <munder>, <munderover>
00520 
00521   // This means that
00522   // 1. If our displaystyle is being changed from true to false, we have
00523   //    to propagate an inner scriptlevel increment to our children
00524   // 2. If the displaystyle is changed from false to true, we have to undo
00525   //    any incrementation that was done on the inner scriptlevel
00526 
00527   if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsToUpdate)) {
00528     if (mInnerScriptLevel > mPresentationData.scriptLevel) {
00529       // we get here if our displaystyle is currently false
00530       NS_ASSERTION(!NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags), "out of sync");
00531       if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
00532         // ...and is being set to true, so undo the inner increment now
00533         mInnerScriptLevel = mPresentationData.scriptLevel;
00534         UpdatePresentationDataFromChildAt(0, -1, -1, 0, 0);
00535       }
00536     }
00537     else {
00538       // case of mInnerScriptLevel == mPresentationData.scriptLevel, our
00539       // current displaystyle is true; we increment the inner scriptlevel if
00540       // our displaystyle is about to be set to false; since mInnerScriptLevel
00541       // is changed, we can only get here once
00542       NS_ASSERTION(NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags), "out of sync");
00543       if (!NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
00544         mInnerScriptLevel = mPresentationData.scriptLevel + 1;
00545         UpdatePresentationDataFromChildAt(0, -1, 1, 0, 0);
00546       }
00547     }
00548   }
00549 
00550   mInnerScriptLevel += aScriptLevelIncrement;
00551   return nsMathMLContainerFrame::
00552     UpdatePresentationData(aScriptLevelIncrement, aFlagsValues,
00553                            aFlagsToUpdate);
00554 }
00555 
00556 NS_IMETHODIMP
00557 nsMathMLmfracFrame::UpdatePresentationDataFromChildAt(PRInt32         aFirstIndex,
00558                                                       PRInt32         aLastIndex,
00559                                                       PRInt32         aScriptLevelIncrement,
00560                                                       PRUint32        aFlagsValues,
00561                                                       PRUint32        aFlagsToUpdate)
00562 {
00563   // The REC says "The <mfrac> element sets displaystyle to "false" within
00564   // numerator and denominator"
00565 #if 0
00566   // At one point I thought that it meant that the displaystyle state of
00567   // the numerator and denominator cannot be modified by an ancestor, i.e.,
00568   // to change the displaystlye, one has to use displaystyle="true" with mstyle: 
00569   // <mfrac> <mstyle>numerator</mstyle> <mstyle>denominator</mstyle> </mfrac>
00570 
00571   // Commenting out for now until it is clear what the intention really is.
00572   // See also the variants for <mover>, <munder>, <munderover>
00573 
00574   aFlagsToUpdate &= ~NS_MATHML_DISPLAYSTYLE;
00575   aFlagsValues &= ~NS_MATHML_DISPLAYSTYLE;
00576 #endif
00577   return nsMathMLContainerFrame::
00578     UpdatePresentationDataFromChildAt(aFirstIndex, aLastIndex,
00579       aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate);
00580 }
00581 
00582 // ----------------------
00583 // the Style System will use these to pass the proper style context to our MathMLChar
00584 nsStyleContext*
00585 nsMathMLmfracFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
00586 {
00587   if (!mSlashChar) {
00588     return nsnull;
00589   }
00590   switch (aIndex) {
00591   case NS_SLASH_CHAR_STYLE_CONTEXT_INDEX:
00592     return mSlashChar->GetStyleContext();
00593     break;
00594   default:
00595     return nsnull;
00596   }
00597 }
00598 
00599 void
00600 nsMathMLmfracFrame::SetAdditionalStyleContext(PRInt32          aIndex, 
00601                                               nsStyleContext*  aStyleContext)
00602 {
00603   if (!mSlashChar) {
00604     return;
00605   }
00606   switch (aIndex) {
00607   case NS_SLASH_CHAR_STYLE_CONTEXT_INDEX:
00608     mSlashChar->SetStyleContext(aStyleContext);
00609     break;
00610   }
00611 }