LCOV - app.info - layout/mathml/nsMathMLmfencedFrame.cpp

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-07-07 | 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