LCOV - code coverage report
Current view: directory - layout/mathml - nsMathMLmfencedFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 327 0 0.0 %
Date: 2012-06-02 Functions: 21 0 0.0 %

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

Generated by: LCOV version 1.7