layout/mathml/nsMathMLmfencedFrame.cpp

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsMathMLmfencedFrame.h"
     8 #include "nsRenderingContext.h"
     9 #include "nsMathMLChar.h"
    10 #include <algorithm>
    12 //
    13 // <mfenced> -- surround content with a pair of fences
    14 //
    16 nsIFrame*
    17 NS_NewMathMLmfencedFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    18 {
    19   return new (aPresShell) nsMathMLmfencedFrame(aContext);
    20 }
    22 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmfencedFrame)
    24 nsMathMLmfencedFrame::~nsMathMLmfencedFrame()
    25 {
    26   RemoveFencesAndSeparators();
    27 }
    29 NS_IMETHODIMP
    30 nsMathMLmfencedFrame::InheritAutomaticData(nsIFrame* aParent)
    31 {
    32   // let the base class get the default from our parent
    33   nsMathMLContainerFrame::InheritAutomaticData(aParent);
    35   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
    37   RemoveFencesAndSeparators();
    38   CreateFencesAndSeparators(PresContext());
    40   return NS_OK;
    41 }
    43 nsresult
    44 nsMathMLmfencedFrame::SetInitialChildList(ChildListID     aListID,
    45                                           nsFrameList&    aChildList)
    46 {
    47   // First, let the base class do its work
    48   nsresult rv = nsMathMLContainerFrame::SetInitialChildList(aListID, aChildList);
    49   if (NS_FAILED(rv)) return rv;
    51   // InheritAutomaticData will not get called if our parent is not a mathml
    52   // frame, so initialize NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY for
    53   // GetPreferredStretchSize() from Reflow().
    54   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
    55   // No need to track the style contexts given to our MathML chars. 
    56   // The Style System will use Get/SetAdditionalStyleContext() to keep them
    57   // up-to-date if dynamic changes arise.
    58   CreateFencesAndSeparators(PresContext());
    59   return NS_OK;
    60 }
    62 nsresult
    63 nsMathMLmfencedFrame::AttributeChanged(int32_t         aNameSpaceID,
    64                                        nsIAtom*        aAttribute,
    65                                        int32_t         aModType)
    66 {
    67   RemoveFencesAndSeparators();
    68   CreateFencesAndSeparators(PresContext());
    70   return nsMathMLContainerFrame::
    71          AttributeChanged(aNameSpaceID, aAttribute, aModType);
    72 }
    74 nsresult
    75 nsMathMLmfencedFrame::ChildListChanged(int32_t aModType)
    76 {
    77   RemoveFencesAndSeparators();
    78   CreateFencesAndSeparators(PresContext());
    80   return nsMathMLContainerFrame::ChildListChanged(aModType);
    81 }
    83 void
    84 nsMathMLmfencedFrame::RemoveFencesAndSeparators()
    85 {
    86   delete mOpenChar;
    87   delete mCloseChar;
    88   if (mSeparatorsChar) delete[] mSeparatorsChar;
    90   mOpenChar = nullptr;
    91   mCloseChar = nullptr;
    92   mSeparatorsChar = nullptr;
    93   mSeparatorsCount = 0;
    94 }
    96 void
    97 nsMathMLmfencedFrame::CreateFencesAndSeparators(nsPresContext* aPresContext)
    98 {
    99   nsAutoString value;
   101   //////////////  
   102   // see if the opening fence is there ...
   103   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::open, value)) {
   104     value = char16_t('('); // default as per the MathML REC
   105   } else {
   106     value.CompressWhitespace();
   107   }
   109   if (!value.IsEmpty()) {
   110     mOpenChar = new nsMathMLChar;
   111     mOpenChar->SetData(aPresContext, value);
   112     ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mOpenChar);
   113   }
   115   //////////////
   116   // see if the closing fence is there ...
   117   if(!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::close, value)) {
   118     value = char16_t(')'); // default as per the MathML REC
   119   } else {
   120     value.CompressWhitespace();
   121   }
   123   if (!value.IsEmpty()) {
   124     mCloseChar = new nsMathMLChar;
   125     mCloseChar->SetData(aPresContext, value);
   126     ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mCloseChar);
   127   }
   129   //////////////
   130   // see if separators are there ...
   131   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::separators_, value)) {
   132     value = char16_t(','); // default as per the MathML REC
   133   } else {
   134     value.StripWhitespace();
   135   }
   137   mSeparatorsCount = value.Length();
   138   if (0 < mSeparatorsCount) {
   139     int32_t sepCount = mFrames.GetLength() - 1;
   140     if (0 < sepCount) {
   141       mSeparatorsChar = new nsMathMLChar[sepCount];
   142       nsAutoString sepChar;
   143       for (int32_t i = 0; i < sepCount; i++) {
   144         if (i < mSeparatorsCount) {
   145           sepChar = value[i];
   146         }
   147         else {
   148           sepChar = value[mSeparatorsCount-1];
   149         }
   150         mSeparatorsChar[i].SetData(aPresContext, sepChar);
   151         ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSeparatorsChar[i]);
   152       }
   153       mSeparatorsCount = sepCount;
   154     } else {
   155       // No separators.  Note that sepCount can be -1 here, so don't
   156       // set mSeparatorsCount to it.
   157       mSeparatorsCount = 0;
   158     }
   159   }
   160 }
   162 void
   163 nsMathMLmfencedFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   164                                        const nsRect&           aDirtyRect,
   165                                        const nsDisplayListSet& aLists)
   166 {
   167   /////////////
   168   // display the content
   169   nsMathMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
   171   ////////////
   172   // display fences and separators
   173   uint32_t count = 0;
   174   if (mOpenChar) {
   175     mOpenChar->Display(aBuilder, this, aLists, count++);
   176   }
   178   if (mCloseChar) {
   179     mCloseChar->Display(aBuilder, this, aLists, count++);
   180   }
   182   for (int32_t i = 0; i < mSeparatorsCount; i++) {
   183     mSeparatorsChar[i].Display(aBuilder, this, aLists, count++);
   184   }
   185 }
   187 nsresult
   188 nsMathMLmfencedFrame::Reflow(nsPresContext*          aPresContext,
   189                              nsHTMLReflowMetrics&     aDesiredSize,
   190                              const nsHTMLReflowState& aReflowState,
   191                              nsReflowStatus&          aStatus)
   192 {
   193   nsresult rv;
   194   aDesiredSize.Width() = aDesiredSize.Height() = 0;
   195   aDesiredSize.SetTopAscent(0);
   196   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
   198   int32_t i;
   199   const nsStyleFont* font = StyleFont();
   200   nsRefPtr<nsFontMetrics> fm;
   201   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   202   aReflowState.rendContext->SetFont(fm);
   203   nscoord axisHeight, em;
   204   GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
   205   GetEmHeight(fm, em);
   206   // leading to be left at the top and the bottom of stretched chars
   207   nscoord leading = NSToCoordRound(0.2f * em); 
   209   /////////////
   210   // Reflow children
   211   // Asking each child to cache its bounding metrics
   213   // Note that we don't use the base method nsMathMLContainerFrame::Reflow()
   214   // because we want to stretch our fences, separators and stretchy frames using
   215   // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base
   216   // method here, our stretchy frames will be stretched and placed, and we may
   217   // end up stretching our fences/separators with a different aDesiredSize.
   218   // XXX The above decision was revisited in bug 121748 and this code can be
   219   // refactored to use nsMathMLContainerFrame::Reflow() at some stage.
   221   nsReflowStatus childStatus;
   222   nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
   223   nsIFrame* firstChild = GetFirstPrincipalChild();
   224   nsIFrame* childFrame = firstChild;
   225   nscoord ascent = 0, descent = 0;
   226   if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) {
   227     // We use the ASCII metrics to get our minimum height. This way,
   228     // if we have borders or a background, they will fit better with
   229     // other elements on the line.
   230     ascent = fm->MaxAscent();
   231     descent = fm->MaxDescent();
   232   }
   233   while (childFrame) {
   234     nsHTMLReflowMetrics childDesiredSize(aReflowState,
   235                                          aDesiredSize.mFlags
   236                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
   237     nsHTMLReflowState childReflowState(aPresContext, aReflowState,
   238                                        childFrame, availSize);
   239     rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
   240                      childReflowState, childStatus);
   241     //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
   242     if (NS_FAILED(rv)) {
   243       // Call DidReflow() for the child frames we successfully did reflow.
   244       DidReflowChildren(firstChild, childFrame);
   245       return rv;
   246     }
   248     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
   249                                     childDesiredSize.mBoundingMetrics);
   251     nscoord childDescent = childDesiredSize.Height() - childDesiredSize.TopAscent();
   252     if (descent < childDescent)
   253       descent = childDescent;
   254     if (ascent < childDesiredSize.TopAscent())
   255       ascent = childDesiredSize.TopAscent();
   257     childFrame = childFrame->GetNextSibling();
   258   }
   260   /////////////
   261   // Ask stretchy children to stretch themselves
   263   nsBoundingMetrics containerSize;
   264   nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
   266   GetPreferredStretchSize(*aReflowState.rendContext,
   267                           0, /* i.e., without embellishments */
   268                           stretchDir, containerSize);
   269   childFrame = firstChild;
   270   while (childFrame) {
   271     nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame);
   272     if (mathmlChild) {
   273       nsHTMLReflowMetrics childDesiredSize(aReflowState);
   274       // retrieve the metrics that was stored at the previous pass
   275       GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
   276                                      childDesiredSize.mBoundingMetrics);
   278       mathmlChild->Stretch(*aReflowState.rendContext, 
   279                            stretchDir, containerSize, childDesiredSize);
   280       // store the updated metrics
   281       SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
   282                                       childDesiredSize.mBoundingMetrics);
   284       nscoord childDescent = childDesiredSize.Height() - childDesiredSize.TopAscent();
   285       if (descent < childDescent)
   286         descent = childDescent;
   287       if (ascent < childDesiredSize.TopAscent())
   288         ascent = childDesiredSize.TopAscent();
   289     }
   290     childFrame = childFrame->GetNextSibling();
   291   }
   293   // bug 121748: for surrounding fences & separators, use a size that covers everything
   294   GetPreferredStretchSize(*aReflowState.rendContext,
   295                           STRETCH_CONSIDER_EMBELLISHMENTS,
   296                           stretchDir, containerSize);
   298   //////////////////////////////////////////
   299   // Prepare the opening fence, separators, and closing fence, and
   300   // adjust the origin of children.
   302   // we need to center around the axis
   303   nscoord delta = std::max(containerSize.ascent - axisHeight, 
   304                          containerSize.descent + axisHeight);
   305   containerSize.ascent = delta + axisHeight;
   306   containerSize.descent = delta - axisHeight;
   308   bool isRTL = StyleVisibility()->mDirection;
   310   /////////////////
   311   // opening fence ...
   312   ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar,
   313              NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, 
   314              axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   315   /////////////////
   316   // separators ...
   317   for (i = 0; i < mSeparatorsCount; i++) {
   318     ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i],
   319                NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
   320                axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   321   }
   322   /////////////////
   323   // closing fence ...
   324   ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar,
   325              NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
   326              axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   328   //////////////////
   329   // Adjust the origins of each child.
   330   // and update our bounding metrics
   332   i = 0;
   333   nscoord dx = 0;
   334   nsBoundingMetrics bm;
   335   bool firstTime = true;
   336   nsMathMLChar *leftChar, *rightChar;
   337   if (isRTL) {
   338     leftChar = mCloseChar;
   339     rightChar = mOpenChar;
   340   } else {
   341     leftChar = mOpenChar;
   342     rightChar = mCloseChar;
   343   }
   345   if (leftChar) {
   346     PlaceChar(leftChar, ascent, bm, dx);
   347     aDesiredSize.mBoundingMetrics = bm;
   348     firstTime = false;
   349   }
   351   if (isRTL) {
   352     childFrame = this->GetLastChild(nsIFrame::kPrincipalList);
   353   } else {
   354     childFrame = firstChild;
   355   }
   356   while (childFrame) {
   357     nsHTMLReflowMetrics childSize(aReflowState);
   358     GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
   359     if (firstTime) {
   360       firstTime = false;
   361       aDesiredSize.mBoundingMetrics  = bm;
   362     }
   363     else  
   364       aDesiredSize.mBoundingMetrics += bm;
   366     FinishReflowChild(childFrame, aPresContext, childSize, nullptr,
   367                       dx, ascent - childSize.TopAscent(), 0);
   368     dx += childSize.Width();
   370     if (i < mSeparatorsCount) {
   371       PlaceChar(&mSeparatorsChar[isRTL ? mSeparatorsCount - 1 - i : i],
   372                 ascent, bm, dx);
   373       aDesiredSize.mBoundingMetrics += bm;
   374     }
   375     i++;
   377     if (isRTL) {
   378       childFrame = childFrame->GetPrevSibling();
   379     } else {
   380       childFrame = childFrame->GetNextSibling();
   381     }
   382   }
   384   if (rightChar) {
   385     PlaceChar(rightChar, ascent, bm, dx);
   386     if (firstTime)
   387       aDesiredSize.mBoundingMetrics  = bm;
   388     else  
   389       aDesiredSize.mBoundingMetrics += bm;
   390   }
   392   aDesiredSize.Width() = aDesiredSize.mBoundingMetrics.width;
   393   aDesiredSize.Height() = ascent + descent;
   394   aDesiredSize.SetTopAscent(ascent);
   396   SetBoundingMetrics(aDesiredSize.mBoundingMetrics);
   397   SetReference(nsPoint(0, aDesiredSize.TopAscent()));
   399   // see if we should fix the spacing
   400   FixInterFrameSpacing(aDesiredSize);
   402   // Finished with these:
   403   ClearSavedChildMetrics();
   405   // Set our overflow area
   406   GatherAndStoreOverflow(&aDesiredSize);
   408   aStatus = NS_FRAME_COMPLETE;
   409   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   410   return NS_OK;
   411 }
   413 static void
   414 GetCharSpacing(nsMathMLChar*        aMathMLChar,
   415                nsOperatorFlags      aForm,
   416                int32_t              aScriptLevel,
   417                nscoord              em,
   418                nscoord&             aLeftSpace,
   419                nscoord&             aRightSpace)
   420 {
   421   nsAutoString data;
   422   aMathMLChar->GetData(data);
   423   nsOperatorFlags flags = 0;
   424   float lspace = 0.0f;
   425   float rspace = 0.0f;
   426   bool found = nsMathMLOperators::LookupOperator(data, aForm,
   427                                                    &flags, &lspace, &rspace);
   429   // We don't want extra space when we are a script
   430   if (found && aScriptLevel > 0) {
   431     lspace /= 2.0f;
   432     rspace /= 2.0f;
   433   }
   435   aLeftSpace = NSToCoordRound(lspace * em);
   436   aRightSpace = NSToCoordRound(rspace * em);
   437 }
   439 // helper functions to perform the common task of formatting our chars
   440 /*static*/ nsresult
   441 nsMathMLmfencedFrame::ReflowChar(nsPresContext*      aPresContext,
   442                                  nsRenderingContext& aRenderingContext,
   443                                  nsMathMLChar*        aMathMLChar,
   444                                  nsOperatorFlags      aForm,
   445                                  int32_t              aScriptLevel,
   446                                  nscoord              axisHeight,
   447                                  nscoord              leading,
   448                                  nscoord              em,
   449                                  nsBoundingMetrics&   aContainerSize,
   450                                  nscoord&             aAscent,
   451                                  nscoord&             aDescent,
   452                                  bool                 aRTL)
   453 {
   454   if (aMathMLChar && 0 < aMathMLChar->Length()) {
   455     nscoord leftSpace;
   456     nscoord rightSpace;
   457     GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
   459     // stretch the char to the appropriate height if it is not big enough.
   460     nsBoundingMetrics charSize;
   461     nsresult res = aMathMLChar->Stretch(aPresContext, aRenderingContext,
   462                                         NS_STRETCH_DIRECTION_VERTICAL,
   463                                         aContainerSize, charSize,
   464                                         NS_STRETCH_NORMAL, aRTL);
   466     if (NS_STRETCH_DIRECTION_UNSUPPORTED != aMathMLChar->GetStretchDirection()) {
   467       // has changed... so center the char around the axis
   468       nscoord height = charSize.ascent + charSize.descent;
   469       charSize.ascent = height/2 + axisHeight;
   470       charSize.descent = height - charSize.ascent;
   471     }
   472     else {
   473       // either it hasn't changed or stretching the char failed (i.e.,
   474       // GetBoundingMetrics failed)
   475       leading = 0;
   476       if (NS_FAILED(res)) {
   477         nsAutoString data;
   478         aMathMLChar->GetData(data);
   479         nsBoundingMetrics metrics =
   480           aRenderingContext.GetBoundingMetrics(data.get(), data.Length());
   481         charSize.ascent = metrics.ascent;
   482         charSize.descent = metrics.descent;
   483         charSize.width = metrics.width;
   484         // Set this as the bounding metrics of the MathMLChar to leave
   485         // the necessary room to paint the char.
   486         aMathMLChar->SetBoundingMetrics(charSize);
   487       }
   488     }
   490     if (aAscent < charSize.ascent + leading) 
   491       aAscent = charSize.ascent + leading;
   492     if (aDescent < charSize.descent + leading) 
   493       aDescent = charSize.descent + leading;
   495     // account the spacing
   496     charSize.width += leftSpace + rightSpace;
   498     // x-origin is used to store lspace ...
   499     // y-origin is used to stored the ascent ... 
   500     aMathMLChar->SetRect(nsRect(leftSpace, 
   501                                 charSize.ascent, charSize.width,
   502                                 charSize.ascent + charSize.descent));
   503   }
   504   return NS_OK;
   505 }
   507 /*static*/ void
   508 nsMathMLmfencedFrame::PlaceChar(nsMathMLChar*      aMathMLChar,
   509                                 nscoord            aDesiredAscent,
   510                                 nsBoundingMetrics& bm,
   511                                 nscoord&           dx)
   512 {
   513   aMathMLChar->GetBoundingMetrics(bm);
   515   // the char's x-origin was used to store lspace ...
   516   // the char's y-origin was used to store the ascent ... 
   517   // the char's width was used to store the advance with (with spacing) ... 
   518   nsRect rect;
   519   aMathMLChar->GetRect(rect);
   521   nscoord dy = aDesiredAscent - rect.y;
   522   if (aMathMLChar->GetStretchDirection() != NS_STRETCH_DIRECTION_UNSUPPORTED) {
   523     // the stretchy char will be centered around the axis
   524     // so we adjust the returned bounding metrics accordingly
   525     bm.descent = (bm.ascent + bm.descent) - rect.y;
   526     bm.ascent = rect.y;
   527   }
   529   aMathMLChar->SetRect(nsRect(dx + rect.x, dy, bm.width, rect.height));
   531   bm.leftBearing += rect.x;
   532   bm.rightBearing += rect.x;
   534   // return rect.width since it includes lspace and rspace
   535   bm.width = rect.width;
   536   dx += rect.width;
   537 }
   539 static nscoord
   540 GetMaxCharWidth(nsPresContext*       aPresContext,
   541                 nsRenderingContext* aRenderingContext,
   542                 nsMathMLChar*        aMathMLChar,
   543                 nsOperatorFlags      aForm,
   544                 int32_t              aScriptLevel,
   545                 nscoord              em)
   546 {
   547   nscoord width = aMathMLChar->GetMaxWidth(aPresContext, *aRenderingContext);
   549   if (0 < aMathMLChar->Length()) {
   550     nscoord leftSpace;
   551     nscoord rightSpace;
   552     GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
   554     width += leftSpace + rightSpace;
   555   }
   557   return width;
   558 }
   560 /* virtual */ void
   561 nsMathMLmfencedFrame::GetIntrinsicWidthMetrics(nsRenderingContext* aRenderingContext, nsHTMLReflowMetrics& aDesiredSize)
   562 {
   563   nscoord width = 0;
   565   nsPresContext* presContext = PresContext();
   566   const nsStyleFont* font = StyleFont();
   567   nsRefPtr<nsFontMetrics> fm;
   568   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
   569   nscoord em;
   570   GetEmHeight(fm, em);
   572   if (mOpenChar) {
   573     width +=
   574       GetMaxCharWidth(presContext, aRenderingContext, mOpenChar,
   575                       NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, em);
   576   }
   578   int32_t i = 0;
   579   nsIFrame* childFrame = GetFirstPrincipalChild();
   580   while (childFrame) {
   581     // XXX This includes margin while Reflow currently doesn't consider
   582     // margin, so we may end up with too much space, but, with stretchy
   583     // characters, this is an approximation anyway.
   584     width += nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
   585                                                   nsLayoutUtils::PREF_WIDTH);
   587     if (i < mSeparatorsCount) {
   588       width +=
   589         GetMaxCharWidth(presContext, aRenderingContext, &mSeparatorsChar[i],
   590                         NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, em);
   591     }
   592     i++;
   594     childFrame = childFrame->GetNextSibling();
   595   }
   597   if (mCloseChar) {
   598     width +=
   599       GetMaxCharWidth(presContext, aRenderingContext, mCloseChar,
   600                       NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
   601   }
   603   aDesiredSize.Width() = width;
   604   aDesiredSize.mBoundingMetrics.width = width;
   605   aDesiredSize.mBoundingMetrics.leftBearing = 0;
   606   aDesiredSize.mBoundingMetrics.rightBearing = width;
   607 }
   609 nscoord
   610 nsMathMLmfencedFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
   611 {
   612   nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
   613   if (!gap) return 0;
   615   nsRect rect;
   616   if (mOpenChar) {
   617     mOpenChar->GetRect(rect);
   618     rect.MoveBy(gap, 0);
   619     mOpenChar->SetRect(rect);
   620   }
   621   if (mCloseChar) {
   622     mCloseChar->GetRect(rect);
   623     rect.MoveBy(gap, 0);
   624     mCloseChar->SetRect(rect);
   625   }
   626   for (int32_t i = 0; i < mSeparatorsCount; i++) {
   627     mSeparatorsChar[i].GetRect(rect);
   628     rect.MoveBy(gap, 0);
   629     mSeparatorsChar[i].SetRect(rect);
   630   }
   631   return gap;
   632 }
   634 // ----------------------
   635 // the Style System will use these to pass the proper style context to our MathMLChar
   636 nsStyleContext*
   637 nsMathMLmfencedFrame::GetAdditionalStyleContext(int32_t aIndex) const
   638 {
   639   int32_t openIndex = -1;
   640   int32_t closeIndex = -1;
   641   int32_t lastIndex = mSeparatorsCount-1;
   643   if (mOpenChar) { 
   644     lastIndex++; 
   645     openIndex = lastIndex; 
   646   }
   647   if (mCloseChar) { 
   648     lastIndex++;
   649     closeIndex = lastIndex;
   650   }
   651   if (aIndex < 0 || aIndex > lastIndex) {
   652     return nullptr;
   653   }
   655   if (aIndex < mSeparatorsCount) {
   656     return mSeparatorsChar[aIndex].GetStyleContext();
   657   }
   658   else if (aIndex == openIndex) {
   659     return mOpenChar->GetStyleContext();
   660   }
   661   else if (aIndex == closeIndex) {
   662     return mCloseChar->GetStyleContext();
   663   }
   664   return nullptr;
   665 }
   667 void
   668 nsMathMLmfencedFrame::SetAdditionalStyleContext(int32_t          aIndex, 
   669                                                 nsStyleContext*  aStyleContext)
   670 {
   671   int32_t openIndex = -1;
   672   int32_t closeIndex = -1;
   673   int32_t lastIndex = mSeparatorsCount-1;
   675   if (mOpenChar) {
   676     lastIndex++;
   677     openIndex = lastIndex;
   678   }
   679   if (mCloseChar) {
   680     lastIndex++;
   681     closeIndex = lastIndex;
   682   }
   683   if (aIndex < 0 || aIndex > lastIndex) {
   684     return;
   685   }
   687   if (aIndex < mSeparatorsCount) {
   688     mSeparatorsChar[aIndex].SetStyleContext(aStyleContext);
   689   }
   690   else if (aIndex == openIndex) {
   691     mOpenChar->SetStyleContext(aStyleContext);
   692   }
   693   else if (aIndex == closeIndex) {
   694     mCloseChar->SetStyleContext(aStyleContext);
   695   }
   696 }

mercurial