LCOV - code coverage report
Current view: top level - layout/mathml - nsMathMLmfencedFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 360 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "gfxContext.h"
       7             : #include "nsMathMLmfencedFrame.h"
       8             : #include "nsMathMLChar.h"
       9             : #include <algorithm>
      10             : 
      11             : using namespace mozilla;
      12             : 
      13             : //
      14             : // <mfenced> -- surround content with a pair of fences
      15             : //
      16             : 
      17             : nsIFrame*
      18           0 : NS_NewMathMLmfencedFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      19             : {
      20           0 :   return new (aPresShell) nsMathMLmfencedFrame(aContext);
      21             : }
      22             : 
      23           0 : NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmfencedFrame)
      24             : 
      25           0 : nsMathMLmfencedFrame::~nsMathMLmfencedFrame()
      26             : {
      27           0 :   RemoveFencesAndSeparators();
      28           0 : }
      29             : 
      30             : NS_IMETHODIMP
      31           0 : nsMathMLmfencedFrame::InheritAutomaticData(nsIFrame* aParent)
      32             : {
      33             :   // let the base class get the default from our parent
      34           0 :   nsMathMLContainerFrame::InheritAutomaticData(aParent);
      35             : 
      36           0 :   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
      37             : 
      38           0 :   RemoveFencesAndSeparators();
      39           0 :   CreateFencesAndSeparators(PresContext());
      40             : 
      41           0 :   return NS_OK;
      42             : }
      43             : 
      44             : void
      45           0 : nsMathMLmfencedFrame::SetInitialChildList(ChildListID     aListID,
      46             :                                           nsFrameList&    aChildList)
      47             : {
      48             :   // First, let the base class do its work
      49           0 :   nsMathMLContainerFrame::SetInitialChildList(aListID, aChildList);
      50             : 
      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           0 :   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           0 :   CreateFencesAndSeparators(PresContext());
      59           0 : }
      60             : 
      61             : nsresult
      62           0 : nsMathMLmfencedFrame::AttributeChanged(int32_t         aNameSpaceID,
      63             :                                        nsIAtom*        aAttribute,
      64             :                                        int32_t         aModType)
      65             : {
      66           0 :   RemoveFencesAndSeparators();
      67           0 :   CreateFencesAndSeparators(PresContext());
      68             : 
      69             :   return nsMathMLContainerFrame::
      70           0 :          AttributeChanged(aNameSpaceID, aAttribute, aModType);
      71             : }
      72             : 
      73             : nsresult
      74           0 : nsMathMLmfencedFrame::ChildListChanged(int32_t aModType)
      75             : {
      76           0 :   RemoveFencesAndSeparators();
      77           0 :   CreateFencesAndSeparators(PresContext());
      78             : 
      79           0 :   return nsMathMLContainerFrame::ChildListChanged(aModType);
      80             : }
      81             : 
      82             : void
      83           0 : nsMathMLmfencedFrame::RemoveFencesAndSeparators()
      84             : {
      85           0 :   delete mOpenChar;
      86           0 :   delete mCloseChar;
      87           0 :   if (mSeparatorsChar) delete[] mSeparatorsChar;
      88             : 
      89           0 :   mOpenChar = nullptr;
      90           0 :   mCloseChar = nullptr;
      91           0 :   mSeparatorsChar = nullptr;
      92           0 :   mSeparatorsCount = 0;
      93           0 : }
      94             : 
      95             : void
      96           0 : nsMathMLmfencedFrame::CreateFencesAndSeparators(nsPresContext* aPresContext)
      97             : {
      98           0 :   nsAutoString value;
      99             : 
     100             :   //////////////
     101             :   // see if the opening fence is there ...
     102           0 :   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::open, value)) {
     103           0 :     value = char16_t('('); // default as per the MathML REC
     104             :   } else {
     105           0 :     value.CompressWhitespace();
     106             :   }
     107             : 
     108           0 :   if (!value.IsEmpty()) {
     109           0 :     mOpenChar = new nsMathMLChar;
     110           0 :     mOpenChar->SetData(value);
     111           0 :     ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mOpenChar);
     112             :   }
     113             : 
     114             :   //////////////
     115             :   // see if the closing fence is there ...
     116           0 :   if(!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::close, value)) {
     117           0 :     value = char16_t(')'); // default as per the MathML REC
     118             :   } else {
     119           0 :     value.CompressWhitespace();
     120             :   }
     121             : 
     122           0 :   if (!value.IsEmpty()) {
     123           0 :     mCloseChar = new nsMathMLChar;
     124           0 :     mCloseChar->SetData(value);
     125           0 :     ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mCloseChar);
     126             :   }
     127             : 
     128             :   //////////////
     129             :   // see if separators are there ...
     130           0 :   if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::separators_, value)) {
     131           0 :     value = char16_t(','); // default as per the MathML REC
     132             :   } else {
     133           0 :     value.StripWhitespace();
     134             :   }
     135             : 
     136           0 :   mSeparatorsCount = value.Length();
     137           0 :   if (0 < mSeparatorsCount) {
     138           0 :     int32_t sepCount = mFrames.GetLength() - 1;
     139           0 :     if (0 < sepCount) {
     140           0 :       mSeparatorsChar = new nsMathMLChar[sepCount];
     141           0 :       nsAutoString sepChar;
     142           0 :       for (int32_t i = 0; i < sepCount; i++) {
     143           0 :         if (i < mSeparatorsCount) {
     144           0 :           sepChar = value[i];
     145             :         }
     146             :         else {
     147           0 :           sepChar = value[mSeparatorsCount-1];
     148             :         }
     149           0 :         mSeparatorsChar[i].SetData(sepChar);
     150           0 :         ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSeparatorsChar[i]);
     151             :       }
     152           0 :       mSeparatorsCount = sepCount;
     153             :     } else {
     154             :       // No separators.  Note that sepCount can be -1 here, so don't
     155             :       // set mSeparatorsCount to it.
     156           0 :       mSeparatorsCount = 0;
     157             :     }
     158             :   }
     159           0 : }
     160             : 
     161             : void
     162           0 : nsMathMLmfencedFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     163             :                                        const nsRect&           aDirtyRect,
     164             :                                        const nsDisplayListSet& aLists)
     165             : {
     166             :   /////////////
     167             :   // display the content
     168           0 :   nsMathMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
     169             : 
     170             :   ////////////
     171             :   // display fences and separators
     172           0 :   uint32_t count = 0;
     173           0 :   if (mOpenChar) {
     174           0 :     mOpenChar->Display(aBuilder, this, aLists, count++);
     175             :   }
     176             : 
     177           0 :   if (mCloseChar) {
     178           0 :     mCloseChar->Display(aBuilder, this, aLists, count++);
     179             :   }
     180             : 
     181           0 :   for (int32_t i = 0; i < mSeparatorsCount; i++) {
     182           0 :     mSeparatorsChar[i].Display(aBuilder, this, aLists, count++);
     183             :   }
     184           0 : }
     185             : 
     186             : /* @param aMetrics is an IN/OUT.  Provide the current metrics for the mFenced
     187             :           frame and it will be enlarged as necessary.
     188             : For simplicity the width of the container is always incremented by the width
     189             : of the nsMathMLChar.  As we only stretch fences and separators in the vertical
     190             : direction, this has no impact on overall appearance.
     191             : */
     192             : static void
     193           0 : ApplyUnstretchedMetrics(nsPresContext*      aPresContext,
     194             :                         DrawTarget*         aDrawTarget,
     195             :                         float               aFontSizeInflation,
     196             :                         nsMathMLChar*       aMathMLChar,
     197             :                         nsBoundingMetrics&  aMetrics,
     198             :                         bool                aIsRTL)
     199             : {
     200           0 :   if (aMathMLChar && 0 < aMathMLChar->Length()) {
     201           0 :     nsBoundingMetrics charSize;
     202           0 :     aMathMLChar->Stretch(aPresContext, aDrawTarget, aFontSizeInflation,
     203             :                          NS_STRETCH_DIRECTION_DEFAULT,
     204             :                          aMetrics, // size is unimportant as we aren't stretching
     205           0 :                          charSize, NS_STRETCH_NONE, aIsRTL);
     206           0 :     aMetrics += charSize;
     207             :   }
     208           0 : }
     209             : 
     210             : void
     211           0 : nsMathMLmfencedFrame::Reflow(nsPresContext*          aPresContext,
     212             :                              ReflowOutput&     aDesiredSize,
     213             :                              const ReflowInput& aReflowInput,
     214             :                              nsReflowStatus&          aStatus)
     215             : {
     216           0 :   MarkInReflow();
     217           0 :   mPresentationData.flags &= ~NS_MATHML_ERROR;
     218           0 :   aDesiredSize.ClearSize();
     219           0 :   aDesiredSize.SetBlockStartAscent(0);
     220           0 :   aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
     221             : 
     222             :   int32_t i;
     223           0 :   const nsStyleFont* font = StyleFont();
     224           0 :   float fontSizeInflation = nsLayoutUtils::FontSizeInflationFor(this);
     225             :   RefPtr<nsFontMetrics> fm =
     226           0 :     nsLayoutUtils::GetFontMetricsForFrame(this, fontSizeInflation);
     227             :   nscoord axisHeight, em;
     228           0 :   GetAxisHeight(aReflowInput.mRenderingContext->GetDrawTarget(), fm, axisHeight);
     229           0 :   GetEmHeight(fm, em);
     230             :   // leading to be left at the top and the bottom of stretched chars
     231           0 :   nscoord leading = NSToCoordRound(0.2f * em);
     232             : 
     233             :   /////////////
     234             :   // Reflow children
     235             :   // Asking each child to cache its bounding metrics
     236             : 
     237             :   // Note that we don't use the base method nsMathMLContainerFrame::Reflow()
     238             :   // because we want to stretch our fences, separators and stretchy frames using
     239             :   // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base
     240             :   // method here, our stretchy frames will be stretched and placed, and we may
     241             :   // end up stretching our fences/separators with a different aDesiredSize.
     242             :   // XXX The above decision was revisited in bug 121748 and this code can be
     243             :   // refactored to use nsMathMLContainerFrame::Reflow() at some stage.
     244             : 
     245           0 :   nsReflowStatus childStatus;
     246           0 :   nsIFrame* firstChild = PrincipalChildList().FirstChild();
     247           0 :   nsIFrame* childFrame = firstChild;
     248           0 :   nscoord ascent = 0, descent = 0;
     249           0 :   if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) {
     250             :     // We use the ASCII metrics to get our minimum height. This way,
     251             :     // if we have borders or a background, they will fit better with
     252             :     // other elements on the line.
     253           0 :     ascent = fm->MaxAscent();
     254           0 :     descent = fm->MaxDescent();
     255             :   }
     256           0 :   while (childFrame) {
     257             :     ReflowOutput childDesiredSize(aReflowInput,
     258           0 :                                          aDesiredSize.mFlags
     259           0 :                                          | NS_REFLOW_CALC_BOUNDING_METRICS);
     260           0 :     WritingMode wm = childFrame->GetWritingMode();
     261           0 :     LogicalSize availSize = aReflowInput.ComputedSize(wm);
     262           0 :     availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
     263             :     ReflowInput childReflowInput(aPresContext, aReflowInput,
     264           0 :                                        childFrame, availSize);
     265           0 :     ReflowChild(childFrame, aPresContext, childDesiredSize,
     266           0 :                 childReflowInput, childStatus);
     267             :     //NS_ASSERTION(childStatus.IsComplete(), "bad status");
     268             :     SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
     269           0 :                                     childDesiredSize.mBoundingMetrics);
     270             : 
     271           0 :     mozilla::WritingMode outerWM = aReflowInput.GetWritingMode();
     272           0 :     nscoord childDescent = childDesiredSize.BSize(outerWM) -
     273           0 :                            childDesiredSize.BlockStartAscent();
     274           0 :     if (descent < childDescent)
     275           0 :       descent = childDescent;
     276           0 :     if (ascent < childDesiredSize.BlockStartAscent())
     277           0 :       ascent = childDesiredSize.BlockStartAscent();
     278             : 
     279           0 :     childFrame = childFrame->GetNextSibling();
     280             :   }
     281             : 
     282             :   /////////////
     283             :   // Ask stretchy children to stretch themselves
     284             : 
     285           0 :   nsBoundingMetrics containerSize;
     286           0 :   nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
     287             : 
     288           0 :   DrawTarget* drawTarget = aReflowInput.mRenderingContext->GetDrawTarget();
     289             : 
     290           0 :   GetPreferredStretchSize(drawTarget,
     291             :                           0, /* i.e., without embellishments */
     292           0 :                           stretchDir, containerSize);
     293           0 :   childFrame = firstChild;
     294           0 :   while (childFrame) {
     295           0 :     nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame);
     296           0 :     if (mathmlChild) {
     297           0 :       ReflowOutput childDesiredSize(aReflowInput);
     298             :       // retrieve the metrics that was stored at the previous pass
     299             :       GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
     300           0 :                                      childDesiredSize.mBoundingMetrics);
     301             : 
     302             :       mathmlChild->Stretch(drawTarget,
     303           0 :                            stretchDir, containerSize, childDesiredSize);
     304             :       // store the updated metrics
     305             :       SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
     306           0 :                                       childDesiredSize.mBoundingMetrics);
     307             : 
     308           0 :       nscoord childDescent = childDesiredSize.Height() - childDesiredSize.BlockStartAscent();
     309           0 :       if (descent < childDescent)
     310           0 :         descent = childDescent;
     311           0 :       if (ascent < childDesiredSize.BlockStartAscent())
     312           0 :         ascent = childDesiredSize.BlockStartAscent();
     313             :     }
     314           0 :     childFrame = childFrame->GetNextSibling();
     315             :   }
     316             : 
     317             :   // bug 121748: for surrounding fences & separators, use a size that covers everything
     318           0 :   GetPreferredStretchSize(drawTarget, STRETCH_CONSIDER_EMBELLISHMENTS,
     319           0 :                           stretchDir, containerSize);
     320             : 
     321           0 :   bool isRTL = StyleVisibility()->mDirection;
     322             : 
     323             :   // To achieve a minimum size of "1", the container should be enlarged by the
     324             :   // unstretched metrics of the fences and separators.
     325           0 :   ApplyUnstretchedMetrics(aPresContext, drawTarget,
     326             :                           fontSizeInflation, mOpenChar,
     327           0 :                           containerSize, isRTL);
     328           0 :   for (i = 0; i < mSeparatorsCount; i++) {
     329           0 :     ApplyUnstretchedMetrics(aPresContext, drawTarget,
     330           0 :                             fontSizeInflation, &mSeparatorsChar[i],
     331           0 :                             containerSize, isRTL);
     332             :   }
     333           0 :   ApplyUnstretchedMetrics(aPresContext, drawTarget,
     334             :                           fontSizeInflation, mCloseChar,
     335           0 :                           containerSize, isRTL);
     336             : 
     337             :   //////////////////////////////////////////
     338             :   // Prepare the opening fence, separators, and closing fence, and
     339             :   // adjust the origin of children.
     340             : 
     341             :   // we need to center around the axis
     342           0 :   nscoord delta = std::max(containerSize.ascent - axisHeight,
     343           0 :                          containerSize.descent + axisHeight);
     344           0 :   containerSize.ascent = delta + axisHeight;
     345           0 :   containerSize.descent = delta - axisHeight;
     346             : 
     347             :   /////////////////
     348             :   // opening fence ...
     349           0 :   ReflowChar(aPresContext, drawTarget, *fm,
     350             :              fontSizeInflation, mOpenChar,
     351           0 :              NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel,
     352           0 :              axisHeight, leading, em, containerSize, ascent, descent, isRTL);
     353             :   /////////////////
     354             :   // separators ...
     355           0 :   for (i = 0; i < mSeparatorsCount; i++) {
     356           0 :     ReflowChar(aPresContext, drawTarget, *fm,
     357           0 :                fontSizeInflation, &mSeparatorsChar[i],
     358           0 :                NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
     359           0 :                axisHeight, leading, em, containerSize, ascent, descent, isRTL);
     360             :   }
     361             :   /////////////////
     362             :   // closing fence ...
     363           0 :   ReflowChar(aPresContext, drawTarget, *fm,
     364             :              fontSizeInflation, mCloseChar,
     365           0 :              NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
     366           0 :              axisHeight, leading, em, containerSize, ascent, descent, isRTL);
     367             : 
     368             :   //////////////////
     369             :   // Adjust the origins of each child.
     370             :   // and update our bounding metrics
     371             : 
     372           0 :   i = 0;
     373           0 :   nscoord dx = 0;
     374           0 :   nsBoundingMetrics bm;
     375           0 :   bool firstTime = true;
     376             :   nsMathMLChar *leftChar, *rightChar;
     377           0 :   if (isRTL) {
     378           0 :     leftChar = mCloseChar;
     379           0 :     rightChar = mOpenChar;
     380             :   } else {
     381           0 :     leftChar = mOpenChar;
     382           0 :     rightChar = mCloseChar;
     383             :   }
     384             : 
     385           0 :   if (leftChar) {
     386           0 :     PlaceChar(leftChar, ascent, bm, dx);
     387           0 :     aDesiredSize.mBoundingMetrics = bm;
     388           0 :     firstTime = false;
     389             :   }
     390             : 
     391           0 :   if (isRTL) {
     392           0 :     childFrame = this->GetChildList(nsIFrame::kPrincipalList).LastChild();
     393             :   } else {
     394           0 :     childFrame = firstChild;
     395             :   }
     396           0 :   while (childFrame) {
     397           0 :     ReflowOutput childSize(aReflowInput);
     398           0 :     GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
     399           0 :     if (firstTime) {
     400           0 :       firstTime = false;
     401           0 :       aDesiredSize.mBoundingMetrics  = bm;
     402             :     }
     403             :     else
     404           0 :       aDesiredSize.mBoundingMetrics += bm;
     405             : 
     406           0 :     FinishReflowChild(childFrame, aPresContext, childSize, nullptr,
     407           0 :                       dx, ascent - childSize.BlockStartAscent(), 0);
     408           0 :     dx += childSize.Width();
     409             : 
     410           0 :     if (i < mSeparatorsCount) {
     411           0 :       PlaceChar(&mSeparatorsChar[isRTL ? mSeparatorsCount - 1 - i : i],
     412           0 :                 ascent, bm, dx);
     413           0 :       aDesiredSize.mBoundingMetrics += bm;
     414             :     }
     415           0 :     i++;
     416             : 
     417           0 :     if (isRTL) {
     418           0 :       childFrame = childFrame->GetPrevSibling();
     419             :     } else {
     420           0 :       childFrame = childFrame->GetNextSibling();
     421             :     }
     422             :   }
     423             : 
     424           0 :   if (rightChar) {
     425           0 :     PlaceChar(rightChar, ascent, bm, dx);
     426           0 :     if (firstTime)
     427           0 :       aDesiredSize.mBoundingMetrics  = bm;
     428             :     else
     429           0 :       aDesiredSize.mBoundingMetrics += bm;
     430             :   }
     431             : 
     432           0 :   aDesiredSize.Width() = aDesiredSize.mBoundingMetrics.width;
     433           0 :   aDesiredSize.Height() = ascent + descent;
     434           0 :   aDesiredSize.SetBlockStartAscent(ascent);
     435             : 
     436           0 :   SetBoundingMetrics(aDesiredSize.mBoundingMetrics);
     437           0 :   SetReference(nsPoint(0, aDesiredSize.BlockStartAscent()));
     438             : 
     439             :   // see if we should fix the spacing
     440           0 :   FixInterFrameSpacing(aDesiredSize);
     441             : 
     442             :   // Finished with these:
     443           0 :   ClearSavedChildMetrics();
     444             : 
     445             :   // Set our overflow area
     446           0 :   GatherAndStoreOverflow(&aDesiredSize);
     447             : 
     448           0 :   aStatus.Reset();
     449           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     450           0 : }
     451             : 
     452             : static void
     453           0 : GetCharSpacing(nsMathMLChar*        aMathMLChar,
     454             :                nsOperatorFlags      aForm,
     455             :                int32_t              aScriptLevel,
     456             :                nscoord              em,
     457             :                nscoord&             aLeftSpace,
     458             :                nscoord&             aRightSpace)
     459             : {
     460           0 :   nsAutoString data;
     461           0 :   aMathMLChar->GetData(data);
     462           0 :   nsOperatorFlags flags = 0;
     463           0 :   float lspace = 0.0f;
     464           0 :   float rspace = 0.0f;
     465             :   bool found = nsMathMLOperators::LookupOperator(data, aForm,
     466           0 :                                                    &flags, &lspace, &rspace);
     467             : 
     468             :   // We don't want extra space when we are a script
     469           0 :   if (found && aScriptLevel > 0) {
     470           0 :     lspace /= 2.0f;
     471           0 :     rspace /= 2.0f;
     472             :   }
     473             : 
     474           0 :   aLeftSpace = NSToCoordRound(lspace * em);
     475           0 :   aRightSpace = NSToCoordRound(rspace * em);
     476           0 : }
     477             : 
     478             : // helper functions to perform the common task of formatting our chars
     479             : /*static*/ nsresult
     480           0 : nsMathMLmfencedFrame::ReflowChar(nsPresContext*       aPresContext,
     481             :                                  DrawTarget*          aDrawTarget,
     482             :                                  nsFontMetrics&       aFontMetrics,
     483             :                                  float                aFontSizeInflation,
     484             :                                  nsMathMLChar*        aMathMLChar,
     485             :                                  nsOperatorFlags      aForm,
     486             :                                  int32_t              aScriptLevel,
     487             :                                  nscoord              axisHeight,
     488             :                                  nscoord              leading,
     489             :                                  nscoord              em,
     490             :                                  nsBoundingMetrics&   aContainerSize,
     491             :                                  nscoord&             aAscent,
     492             :                                  nscoord&             aDescent,
     493             :                                  bool                 aRTL)
     494             : {
     495           0 :   if (aMathMLChar && 0 < aMathMLChar->Length()) {
     496             :     nscoord leftSpace;
     497             :     nscoord rightSpace;
     498           0 :     GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
     499             : 
     500             :     // stretch the char to the appropriate height if it is not big enough.
     501           0 :     nsBoundingMetrics charSize;
     502           0 :     nsresult res = aMathMLChar->Stretch(aPresContext, aDrawTarget,
     503             :                                         aFontSizeInflation,
     504             :                                         NS_STRETCH_DIRECTION_VERTICAL,
     505             :                                         aContainerSize, charSize,
     506           0 :                                         NS_STRETCH_NORMAL, aRTL);
     507             : 
     508           0 :     if (NS_STRETCH_DIRECTION_UNSUPPORTED != aMathMLChar->GetStretchDirection()) {
     509             :       // has changed... so center the char around the axis
     510           0 :       nscoord height = charSize.ascent + charSize.descent;
     511           0 :       charSize.ascent = height/2 + axisHeight;
     512           0 :       charSize.descent = height - charSize.ascent;
     513             :     }
     514             :     else {
     515             :       // either it hasn't changed or stretching the char failed (i.e.,
     516             :       // nsLayoutUtils::AppUnitBoundsOfString failed)
     517           0 :       leading = 0;
     518           0 :       if (NS_FAILED(res)) {
     519           0 :         nsAutoString data;
     520           0 :         aMathMLChar->GetData(data);
     521             :         nsBoundingMetrics metrics =
     522             :           nsLayoutUtils::AppUnitBoundsOfString(data.get(), data.Length(),
     523           0 :                                                aFontMetrics, aDrawTarget);
     524           0 :         charSize.ascent = metrics.ascent;
     525           0 :         charSize.descent = metrics.descent;
     526           0 :         charSize.width = metrics.width;
     527             :         // Set this as the bounding metrics of the MathMLChar to leave
     528             :         // the necessary room to paint the char.
     529           0 :         aMathMLChar->SetBoundingMetrics(charSize);
     530             :       }
     531             :     }
     532             : 
     533           0 :     if (aAscent < charSize.ascent + leading)
     534           0 :       aAscent = charSize.ascent + leading;
     535           0 :     if (aDescent < charSize.descent + leading)
     536           0 :       aDescent = charSize.descent + leading;
     537             : 
     538             :     // account the spacing
     539           0 :     charSize.width += leftSpace + rightSpace;
     540             : 
     541             :     // x-origin is used to store lspace ...
     542             :     // y-origin is used to stored the ascent ...
     543           0 :     aMathMLChar->SetRect(nsRect(leftSpace,
     544             :                                 charSize.ascent, charSize.width,
     545           0 :                                 charSize.ascent + charSize.descent));
     546             :   }
     547           0 :   return NS_OK;
     548             : }
     549             : 
     550             : /*static*/ void
     551           0 : nsMathMLmfencedFrame::PlaceChar(nsMathMLChar*      aMathMLChar,
     552             :                                 nscoord            aDesiredAscent,
     553             :                                 nsBoundingMetrics& bm,
     554             :                                 nscoord&           dx)
     555             : {
     556           0 :   aMathMLChar->GetBoundingMetrics(bm);
     557             : 
     558             :   // the char's x-origin was used to store lspace ...
     559             :   // the char's y-origin was used to store the ascent ...
     560             :   // the char's width was used to store the advance with (with spacing) ...
     561           0 :   nsRect rect;
     562           0 :   aMathMLChar->GetRect(rect);
     563             : 
     564           0 :   nscoord dy = aDesiredAscent - rect.y;
     565           0 :   if (aMathMLChar->GetStretchDirection() != NS_STRETCH_DIRECTION_UNSUPPORTED) {
     566             :     // the stretchy char will be centered around the axis
     567             :     // so we adjust the returned bounding metrics accordingly
     568           0 :     bm.descent = (bm.ascent + bm.descent) - rect.y;
     569           0 :     bm.ascent = rect.y;
     570             :   }
     571             : 
     572           0 :   aMathMLChar->SetRect(nsRect(dx + rect.x, dy, bm.width, rect.height));
     573             : 
     574           0 :   bm.leftBearing += rect.x;
     575           0 :   bm.rightBearing += rect.x;
     576             : 
     577             :   // return rect.width since it includes lspace and rspace
     578           0 :   bm.width = rect.width;
     579           0 :   dx += rect.width;
     580           0 : }
     581             : 
     582             : static nscoord
     583           0 : GetMaxCharWidth(nsPresContext*       aPresContext,
     584             :                 DrawTarget*          aDrawTarget,
     585             :                 float                aFontSizeInflation,
     586             :                 nsMathMLChar*        aMathMLChar,
     587             :                 nsOperatorFlags      aForm,
     588             :                 int32_t              aScriptLevel,
     589             :                 nscoord              em)
     590             : {
     591             :   nscoord width = aMathMLChar->GetMaxWidth(aPresContext, aDrawTarget,
     592           0 :                                            aFontSizeInflation);
     593             : 
     594           0 :   if (0 < aMathMLChar->Length()) {
     595             :     nscoord leftSpace;
     596             :     nscoord rightSpace;
     597           0 :     GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
     598             : 
     599           0 :     width += leftSpace + rightSpace;
     600             :   }
     601             : 
     602           0 :   return width;
     603             : }
     604             : 
     605             : /* virtual */ void
     606           0 : nsMathMLmfencedFrame::GetIntrinsicISizeMetrics(gfxContext* aRenderingContext, ReflowOutput& aDesiredSize)
     607             : {
     608           0 :   nscoord width = 0;
     609             : 
     610           0 :   nsPresContext* presContext = PresContext();
     611           0 :   const nsStyleFont* font = StyleFont();
     612           0 :   float fontSizeInflation = nsLayoutUtils:: FontSizeInflationFor(this);
     613             :   RefPtr<nsFontMetrics> fm =
     614           0 :     nsLayoutUtils::GetFontMetricsForFrame(this, fontSizeInflation);
     615             :   nscoord em;
     616           0 :   GetEmHeight(fm, em);
     617             : 
     618           0 :   if (mOpenChar) {
     619           0 :     width +=
     620           0 :       GetMaxCharWidth(presContext, aRenderingContext->GetDrawTarget(),
     621             :                       fontSizeInflation, mOpenChar,
     622           0 :                       NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, em);
     623             :   }
     624             : 
     625           0 :   int32_t i = 0;
     626           0 :   for (nsIFrame* childFrame : PrincipalChildList()) {
     627             :     // XXX This includes margin while Reflow currently doesn't consider
     628             :     // margin, so we may end up with too much space, but, with stretchy
     629             :     // characters, this is an approximation anyway.
     630           0 :     width += nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
     631             :                                                   nsLayoutUtils::PREF_ISIZE);
     632             : 
     633           0 :     if (i < mSeparatorsCount) {
     634           0 :       width +=
     635           0 :         GetMaxCharWidth(presContext, aRenderingContext->GetDrawTarget(),
     636           0 :                         fontSizeInflation, &mSeparatorsChar[i],
     637           0 :                         NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, em);
     638             :     }
     639           0 :     i++;
     640             :   }
     641             : 
     642           0 :   if (mCloseChar) {
     643           0 :     width +=
     644           0 :       GetMaxCharWidth(presContext, aRenderingContext->GetDrawTarget(),
     645             :                       fontSizeInflation, mCloseChar,
     646           0 :                       NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
     647             :   }
     648             : 
     649           0 :   aDesiredSize.Width() = width;
     650           0 :   aDesiredSize.mBoundingMetrics.width = width;
     651           0 :   aDesiredSize.mBoundingMetrics.leftBearing = 0;
     652           0 :   aDesiredSize.mBoundingMetrics.rightBearing = width;
     653           0 : }
     654             : 
     655             : nscoord
     656           0 : nsMathMLmfencedFrame::FixInterFrameSpacing(ReflowOutput& aDesiredSize)
     657             : {
     658           0 :   nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
     659           0 :   if (!gap) return 0;
     660             : 
     661           0 :   nsRect rect;
     662           0 :   if (mOpenChar) {
     663           0 :     mOpenChar->GetRect(rect);
     664           0 :     rect.MoveBy(gap, 0);
     665           0 :     mOpenChar->SetRect(rect);
     666             :   }
     667           0 :   if (mCloseChar) {
     668           0 :     mCloseChar->GetRect(rect);
     669           0 :     rect.MoveBy(gap, 0);
     670           0 :     mCloseChar->SetRect(rect);
     671             :   }
     672           0 :   for (int32_t i = 0; i < mSeparatorsCount; i++) {
     673           0 :     mSeparatorsChar[i].GetRect(rect);
     674           0 :     rect.MoveBy(gap, 0);
     675           0 :     mSeparatorsChar[i].SetRect(rect);
     676             :   }
     677           0 :   return gap;
     678             : }
     679             : 
     680             : // ----------------------
     681             : // the Style System will use these to pass the proper style context to our MathMLChar
     682             : nsStyleContext*
     683           0 : nsMathMLmfencedFrame::GetAdditionalStyleContext(int32_t aIndex) const
     684             : {
     685           0 :   int32_t openIndex = -1;
     686           0 :   int32_t closeIndex = -1;
     687           0 :   int32_t lastIndex = mSeparatorsCount-1;
     688             : 
     689           0 :   if (mOpenChar) {
     690           0 :     lastIndex++;
     691           0 :     openIndex = lastIndex;
     692             :   }
     693           0 :   if (mCloseChar) {
     694           0 :     lastIndex++;
     695           0 :     closeIndex = lastIndex;
     696             :   }
     697           0 :   if (aIndex < 0 || aIndex > lastIndex) {
     698           0 :     return nullptr;
     699             :   }
     700             : 
     701           0 :   if (aIndex < mSeparatorsCount) {
     702           0 :     return mSeparatorsChar[aIndex].GetStyleContext();
     703             :   }
     704           0 :   else if (aIndex == openIndex) {
     705           0 :     return mOpenChar->GetStyleContext();
     706             :   }
     707           0 :   else if (aIndex == closeIndex) {
     708           0 :     return mCloseChar->GetStyleContext();
     709             :   }
     710           0 :   return nullptr;
     711             : }
     712             : 
     713             : void
     714           0 : nsMathMLmfencedFrame::SetAdditionalStyleContext(int32_t          aIndex,
     715             :                                                 nsStyleContext*  aStyleContext)
     716             : {
     717           0 :   int32_t openIndex = -1;
     718           0 :   int32_t closeIndex = -1;
     719           0 :   int32_t lastIndex = mSeparatorsCount-1;
     720             : 
     721           0 :   if (mOpenChar) {
     722           0 :     lastIndex++;
     723           0 :     openIndex = lastIndex;
     724             :   }
     725           0 :   if (mCloseChar) {
     726           0 :     lastIndex++;
     727           0 :     closeIndex = lastIndex;
     728             :   }
     729           0 :   if (aIndex < 0 || aIndex > lastIndex) {
     730           0 :     return;
     731             :   }
     732             : 
     733           0 :   if (aIndex < mSeparatorsCount) {
     734           0 :     mSeparatorsChar[aIndex].SetStyleContext(aStyleContext);
     735             :   }
     736           0 :   else if (aIndex == openIndex) {
     737           0 :     mOpenChar->SetStyleContext(aStyleContext);
     738             :   }
     739           0 :   else if (aIndex == closeIndex) {
     740           0 :     mCloseChar->SetStyleContext(aStyleContext);
     741             :   }
     742             : }

Generated by: LCOV version 1.13