Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / layout / mathml / nsMathMLmfencedFrame.cpp
blob117e84067474c296f46c8428294811727bbdb5f6
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
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/
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.
15 * The Original Code is Mozilla MathML Project.
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.
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>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
43 #include "nsCOMPtr.h"
44 #include "nsFrame.h"
45 #include "nsPresContext.h"
46 #include "nsStyleContext.h"
47 #include "nsStyleConsts.h"
48 #include "nsIRenderingContext.h"
49 #include "nsIFontMetrics.h"
51 #include "nsMathMLmfencedFrame.h"
54 // <mfenced> -- surround content with a pair of fences
57 nsIFrame*
58 NS_NewMathMLmfencedFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
60 return new (aPresShell) nsMathMLmfencedFrame(aContext);
63 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmfencedFrame)
65 nsMathMLmfencedFrame::~nsMathMLmfencedFrame()
67 RemoveFencesAndSeparators();
70 NS_IMETHODIMP
71 nsMathMLmfencedFrame::InheritAutomaticData(nsIFrame* aParent)
73 // let the base class get the default from our parent
74 nsMathMLContainerFrame::InheritAutomaticData(aParent);
76 mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
78 return NS_OK;
81 NS_IMETHODIMP
82 nsMathMLmfencedFrame::SetInitialChildList(nsIAtom* aListName,
83 nsFrameList& aChildList)
85 // First, let the base class do its work
86 nsresult rv = nsMathMLContainerFrame::SetInitialChildList(aListName, aChildList);
87 if (NS_FAILED(rv)) return rv;
89 // No need to track the style contexts given to our MathML chars.
90 // The Style System will use Get/SetAdditionalStyleContext() to keep them
91 // up-to-date if dynamic changes arise.
92 CreateFencesAndSeparators(PresContext());
93 return NS_OK;
96 NS_IMETHODIMP
97 nsMathMLmfencedFrame::AttributeChanged(PRInt32 aNameSpaceID,
98 nsIAtom* aAttribute,
99 PRInt32 aModType)
101 RemoveFencesAndSeparators();
102 CreateFencesAndSeparators(PresContext());
104 return nsMathMLContainerFrame::
105 AttributeChanged(aNameSpaceID, aAttribute, aModType);
108 nsresult
109 nsMathMLmfencedFrame::ChildListChanged(PRInt32 aModType)
111 RemoveFencesAndSeparators();
112 CreateFencesAndSeparators(PresContext());
114 return nsMathMLContainerFrame::ChildListChanged(aModType);
117 void
118 nsMathMLmfencedFrame::RemoveFencesAndSeparators()
120 if (mOpenChar) delete mOpenChar;
121 if (mCloseChar) delete mCloseChar;
122 if (mSeparatorsChar) delete[] mSeparatorsChar;
124 mOpenChar = nsnull;
125 mCloseChar = nsnull;
126 mSeparatorsChar = nsnull;
127 mSeparatorsCount = 0;
130 void
131 nsMathMLmfencedFrame::CreateFencesAndSeparators(nsPresContext* aPresContext)
133 nsAutoString value;
134 PRBool isMutable = PR_FALSE;
136 //////////////
137 // see if the opening fence is there ...
138 if (!GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::open,
139 value)) {
140 value = PRUnichar('('); // default as per the MathML REC
141 } else {
142 value.CompressWhitespace();
145 if (!value.IsEmpty()) {
146 mOpenChar = new nsMathMLChar;
147 mOpenChar->SetData(aPresContext, value);
148 isMutable = nsMathMLOperators::IsMutableOperator(value);
149 ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mOpenChar, isMutable);
152 //////////////
153 // see if the closing fence is there ...
154 if(!GetAttribute(mContent, mPresentationData.mstyle,
155 nsGkAtoms::close, value)) {
156 value = PRUnichar(')'); // default as per the MathML REC
157 } else {
158 value.CompressWhitespace();
161 if (!value.IsEmpty()) {
162 mCloseChar = new nsMathMLChar;
163 mCloseChar->SetData(aPresContext, value);
164 isMutable = nsMathMLOperators::IsMutableOperator(value);
165 ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, mCloseChar, isMutable);
168 //////////////
169 // see if separators are there ...
170 if (!GetAttribute(mContent, mPresentationData.mstyle,
171 nsGkAtoms::separators_, value)) {
172 value = PRUnichar(','); // default as per the MathML REC
173 } else {
174 value.StripWhitespace();
177 mSeparatorsCount = value.Length();
178 if (0 < mSeparatorsCount) {
179 PRInt32 sepCount = mFrames.GetLength() - 1;
180 if (0 < sepCount) {
181 mSeparatorsChar = new nsMathMLChar[sepCount];
182 nsAutoString sepChar;
183 for (PRInt32 i = 0; i < sepCount; i++) {
184 if (i < mSeparatorsCount) {
185 sepChar = value[i];
186 isMutable = nsMathMLOperators::IsMutableOperator(sepChar);
188 else {
189 sepChar = value[mSeparatorsCount-1];
190 // keep the value of isMutable that was set earlier
192 mSeparatorsChar[i].SetData(aPresContext, sepChar);
193 ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSeparatorsChar[i], isMutable);
195 mSeparatorsCount = sepCount;
196 } else {
197 // No separators. Note that sepCount can be -1 here, so don't
198 // set mSeparatorsCount to it.
199 mSeparatorsCount = 0;
204 NS_IMETHODIMP
205 nsMathMLmfencedFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
206 const nsRect& aDirtyRect,
207 const nsDisplayListSet& aLists)
209 /////////////
210 // display the content
211 nsresult rv = nsMathMLContainerFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
212 NS_ENSURE_SUCCESS(rv, rv);
214 ////////////
215 // display fences and separators
216 if (mOpenChar) {
217 rv = mOpenChar->Display(aBuilder, this, aLists);
218 NS_ENSURE_SUCCESS(rv, rv);
221 if (mCloseChar) {
222 rv = mCloseChar->Display(aBuilder, this, aLists);
223 NS_ENSURE_SUCCESS(rv, rv);
226 for (PRInt32 i = 0; i < mSeparatorsCount; i++) {
227 rv = mSeparatorsChar[i].Display(aBuilder, this, aLists);
228 NS_ENSURE_SUCCESS(rv, rv);
230 return NS_OK;
233 NS_IMETHODIMP
234 nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext,
235 nsHTMLReflowMetrics& aDesiredSize,
236 const nsHTMLReflowState& aReflowState,
237 nsReflowStatus& aStatus)
239 nsresult rv;
240 aDesiredSize.width = aDesiredSize.height = 0;
241 aDesiredSize.ascent = 0;
242 aDesiredSize.mBoundingMetrics.Clear();
244 PRInt32 i;
245 nsCOMPtr<nsIFontMetrics> fm;
246 const nsStyleFont* font = GetStyleFont();
247 aReflowState.rendContext->SetFont(font->mFont,
248 aPresContext->GetUserFontSet());
249 aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
250 nscoord axisHeight, em;
251 GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
252 GetEmHeight(fm, em);
253 // leading to be left at the top and the bottom of stretched chars
254 nscoord leading = NSToCoordRound(0.2f * em);
256 /////////////
257 // Reflow children
258 // Asking each child to cache its bounding metrics
260 // Note that we don't use the base method nsMathMLContainerFrame::Reflow()
261 // because we want to stretch our fences, separators and stretchy frames using
262 // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base
263 // method here, our stretchy frames will be stretched and placed, and we may
264 // end up stretching our fences/separators with a different aDesiredSize.
265 // XXX The above decision was revisited in bug 121748 and this code can be
266 // refactored to use nsMathMLContainerFrame::Reflow() at some stage.
268 nsReflowStatus childStatus;
269 nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
270 nsIFrame* firstChild = GetFirstChild(nsnull);
271 nsIFrame* childFrame = firstChild;
272 nscoord ascent = 0, descent = 0;
273 if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) {
274 // We use the ASCII metrics to get our minimum height. This way, if we have
275 // borders or a background, they will fit better with other elements on the line
276 fm->GetMaxAscent(ascent);
277 fm->GetMaxDescent(descent);
279 while (childFrame) {
280 nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags
281 | NS_REFLOW_CALC_BOUNDING_METRICS);
282 nsHTMLReflowState childReflowState(aPresContext, aReflowState,
283 childFrame, availSize);
284 rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
285 childReflowState, childStatus);
286 //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
287 if (NS_FAILED(rv)) {
288 // Call DidReflow() for the child frames we successfully did reflow.
289 DidReflowChildren(firstChild, childFrame);
290 return rv;
293 SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
294 childDesiredSize.mBoundingMetrics);
296 nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent;
297 if (descent < childDescent)
298 descent = childDescent;
299 if (ascent < childDesiredSize.ascent)
300 ascent = childDesiredSize.ascent;
302 childFrame = childFrame->GetNextSibling();
305 /////////////
306 // Ask stretchy children to stretch themselves
308 nsBoundingMetrics containerSize;
309 nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
311 nsPresentationData presentationData;
312 GetPresentationData(presentationData);
313 GetPreferredStretchSize(*aReflowState.rendContext,
314 0, /* i.e., without embellishments */
315 stretchDir, containerSize);
316 childFrame = firstChild;
317 while (childFrame) {
318 nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame);
319 if (mathmlChild) {
320 nsHTMLReflowMetrics childDesiredSize;
321 // retrieve the metrics that was stored at the previous pass
322 GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
323 childDesiredSize.mBoundingMetrics);
325 mathmlChild->Stretch(*aReflowState.rendContext,
326 stretchDir, containerSize, childDesiredSize);
327 // store the updated metrics
328 SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
329 childDesiredSize.mBoundingMetrics);
331 nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent;
332 if (descent < childDescent)
333 descent = childDescent;
334 if (ascent < childDesiredSize.ascent)
335 ascent = childDesiredSize.ascent;
337 childFrame = childFrame->GetNextSibling();
340 // bug 121748: for surrounding fences & separators, use a size that covers everything
341 GetPreferredStretchSize(*aReflowState.rendContext,
342 STRETCH_CONSIDER_EMBELLISHMENTS,
343 stretchDir, containerSize);
345 //////////////////////////////////////////
346 // Prepare the opening fence, separators, and closing fence, and
347 // adjust the origin of children.
349 // we need to center around the axis
350 if (firstChild) { // do nothing for an empty <mfenced></mfenced>
351 nscoord delta = NS_MAX(containerSize.ascent - axisHeight,
352 containerSize.descent + axisHeight);
353 containerSize.ascent = delta + axisHeight;
354 containerSize.descent = delta - axisHeight;
357 /////////////////
358 // opening fence ...
359 ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar,
360 NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel,
361 axisHeight, leading, em, containerSize, ascent, descent);
362 /////////////////
363 // separators ...
364 for (i = 0; i < mSeparatorsCount; i++) {
365 ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i],
366 NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
367 axisHeight, leading, em, containerSize, ascent, descent);
369 /////////////////
370 // closing fence ...
371 ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar,
372 NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
373 axisHeight, leading, em, containerSize, ascent, descent);
375 //////////////////
376 // Adjust the origins of each child.
377 // and update our bounding metrics
379 i = 0;
380 nscoord dx = 0;
381 nsBoundingMetrics bm;
382 PRBool firstTime = PR_TRUE;
383 if (mOpenChar) {
384 PlaceChar(mOpenChar, ascent, bm, dx);
385 aDesiredSize.mBoundingMetrics = bm;
386 firstTime = PR_FALSE;
389 childFrame = firstChild;
390 while (childFrame) {
391 nsHTMLReflowMetrics childSize;
392 GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
393 if (firstTime) {
394 firstTime = PR_FALSE;
395 aDesiredSize.mBoundingMetrics = bm;
397 else
398 aDesiredSize.mBoundingMetrics += bm;
400 FinishReflowChild(childFrame, aPresContext, nsnull, childSize,
401 dx, ascent - childSize.ascent, 0);
402 dx += childSize.width;
404 if (i < mSeparatorsCount) {
405 PlaceChar(&mSeparatorsChar[i], ascent, bm, dx);
406 aDesiredSize.mBoundingMetrics += bm;
408 i++;
410 childFrame = childFrame->GetNextSibling();
413 if (mCloseChar) {
414 PlaceChar(mCloseChar, ascent, bm, dx);
415 if (firstTime)
416 aDesiredSize.mBoundingMetrics = bm;
417 else
418 aDesiredSize.mBoundingMetrics += bm;
421 aDesiredSize.width = aDesiredSize.mBoundingMetrics.width;
422 aDesiredSize.height = ascent + descent;
423 aDesiredSize.ascent = ascent;
425 SetBoundingMetrics(aDesiredSize.mBoundingMetrics);
426 SetReference(nsPoint(0, aDesiredSize.ascent));
428 // see if we should fix the spacing
429 FixInterFrameSpacing(aDesiredSize);
431 // Finished with these:
432 ClearSavedChildMetrics();
434 // Set our overflow area
435 GatherAndStoreOverflow(&aDesiredSize);
437 aStatus = NS_FRAME_COMPLETE;
438 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
439 return NS_OK;
442 static void
443 GetCharSpacing(nsMathMLChar* aMathMLChar,
444 nsOperatorFlags aForm,
445 PRInt32 aScriptLevel,
446 nscoord em,
447 nscoord& aLeftSpace,
448 nscoord& aRightSpace)
450 nsAutoString data;
451 aMathMLChar->GetData(data);
452 nsOperatorFlags flags = 0;
453 float lspace = 0.0f;
454 float rspace = 0.0f;
455 PRBool found = nsMathMLOperators::LookupOperator(data, aForm,
456 &flags, &lspace, &rspace);
458 // We don't want extra space when we are a script
459 if (found && aScriptLevel > 0) {
460 lspace /= 2.0f;
461 rspace /= 2.0f;
464 aLeftSpace = NSToCoordRound(lspace * em);
465 aRightSpace = NSToCoordRound(rspace * em);
468 // helper functions to perform the common task of formatting our chars
469 /*static*/ nsresult
470 nsMathMLmfencedFrame::ReflowChar(nsPresContext* aPresContext,
471 nsIRenderingContext& aRenderingContext,
472 nsMathMLChar* aMathMLChar,
473 nsOperatorFlags aForm,
474 PRInt32 aScriptLevel,
475 nscoord axisHeight,
476 nscoord leading,
477 nscoord em,
478 nsBoundingMetrics& aContainerSize,
479 nscoord& aAscent,
480 nscoord& aDescent)
482 if (aMathMLChar && 0 < aMathMLChar->Length()) {
483 nscoord leftSpace;
484 nscoord rightSpace;
485 GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
487 // stretch the char to the appropriate height if it is not big enough.
488 nsBoundingMetrics charSize;
489 nsresult res = aMathMLChar->Stretch(aPresContext, aRenderingContext,
490 NS_STRETCH_DIRECTION_VERTICAL,
491 aContainerSize, charSize);
493 if (NS_STRETCH_DIRECTION_UNSUPPORTED != aMathMLChar->GetStretchDirection()) {
494 // has changed... so center the char around the axis
495 nscoord height = charSize.ascent + charSize.descent;
496 charSize.ascent = height/2 + axisHeight;
497 charSize.descent = height - charSize.ascent;
499 else {
500 // either it hasn't changed or stretching the char failed (i.e.,
501 // GetBoundingMetrics failed)
502 leading = 0;
503 if (NS_FAILED(res)) {
504 nsAutoString data;
505 aMathMLChar->GetData(data);
506 nsTextDimensions dimensions;
507 aRenderingContext.GetTextDimensions(data.get(), data.Length(), dimensions);
508 charSize.ascent = dimensions.ascent;
509 charSize.descent = dimensions.descent;
510 charSize.width = dimensions.width;
511 // Set this as the bounding metrics of the MathMLChar to leave
512 // the necessary room to paint the char.
513 aMathMLChar->SetBoundingMetrics(charSize);
517 if (aAscent < charSize.ascent + leading)
518 aAscent = charSize.ascent + leading;
519 if (aDescent < charSize.descent + leading)
520 aDescent = charSize.descent + leading;
522 // account the spacing
523 charSize.width += leftSpace + rightSpace;
525 // x-origin is used to store lspace ...
526 // y-origin is used to stored the ascent ...
527 aMathMLChar->SetRect(nsRect(leftSpace,
528 charSize.ascent, charSize.width,
529 charSize.ascent + charSize.descent));
531 return NS_OK;
534 /*static*/ void
535 nsMathMLmfencedFrame::PlaceChar(nsMathMLChar* aMathMLChar,
536 nscoord aDesiredAscent,
537 nsBoundingMetrics& bm,
538 nscoord& dx)
540 aMathMLChar->GetBoundingMetrics(bm);
542 // the char's x-origin was used to store lspace ...
543 // the char's y-origin was used to store the ascent ...
544 // the char's width was used to store the advance with (with spacing) ...
545 nsRect rect;
546 aMathMLChar->GetRect(rect);
548 nscoord dy = aDesiredAscent - rect.y;
549 if (aMathMLChar->GetStretchDirection() != NS_STRETCH_DIRECTION_UNSUPPORTED) {
550 // the stretchy char will be centered around the axis
551 // so we adjust the returned bounding metrics accordingly
552 bm.descent = (bm.ascent + bm.descent) - rect.y;
553 bm.ascent = rect.y;
556 aMathMLChar->SetRect(nsRect(dx + rect.x, dy, bm.width, rect.height));
558 bm.leftBearing += rect.x;
559 bm.rightBearing += rect.x;
561 // return rect.width since it includes lspace and rspace
562 bm.width = rect.width;
563 dx += rect.width;
566 static nscoord
567 GetMaxCharWidth(nsPresContext* aPresContext,
568 nsIRenderingContext* aRenderingContext,
569 nsMathMLChar* aMathMLChar,
570 nsOperatorFlags aForm,
571 PRInt32 aScriptLevel,
572 nscoord em)
574 nscoord width = aMathMLChar->GetMaxWidth(aPresContext, *aRenderingContext);
576 if (0 < aMathMLChar->Length()) {
577 nscoord leftSpace;
578 nscoord rightSpace;
579 GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
581 width += leftSpace + rightSpace;
584 return width;
587 /* virtual */ nscoord
588 nsMathMLmfencedFrame::GetIntrinsicWidth(nsIRenderingContext* aRenderingContext)
590 nscoord width = 0;
592 nsPresContext* presContext = PresContext();
593 const nsStyleFont* font = GetStyleFont();
594 nsCOMPtr<nsIFontMetrics> fm = presContext->GetMetricsFor(font->mFont);
595 nscoord em;
596 GetEmHeight(fm, em);
598 if (mOpenChar) {
599 width +=
600 GetMaxCharWidth(presContext, aRenderingContext, mOpenChar,
601 NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, em);
604 PRInt32 i = 0;
605 nsIFrame* childFrame = GetFirstChild(nsnull);
606 while (childFrame) {
607 // XXX This includes margin while Reflow currently doesn't consider
608 // margin, so we may end up with too much space, but, with stretchy
609 // characters, this is an approximation anyway.
610 width += nsLayoutUtils::IntrinsicForContainer(aRenderingContext, childFrame,
611 nsLayoutUtils::PREF_WIDTH);
613 if (i < mSeparatorsCount) {
614 width +=
615 GetMaxCharWidth(presContext, aRenderingContext, &mSeparatorsChar[i],
616 NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, em);
618 i++;
620 childFrame = childFrame->GetNextSibling();
623 if (mCloseChar) {
624 width +=
625 GetMaxCharWidth(presContext, aRenderingContext, mCloseChar,
626 NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, em);
629 return width;
632 nscoord
633 nsMathMLmfencedFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
635 nscoord gap = nsMathMLContainerFrame::FixInterFrameSpacing(aDesiredSize);
636 if (!gap) return 0;
638 nsRect rect;
639 if (mOpenChar) {
640 mOpenChar->GetRect(rect);
641 rect.MoveBy(gap, 0);
642 mOpenChar->SetRect(rect);
644 if (mCloseChar) {
645 mCloseChar->GetRect(rect);
646 rect.MoveBy(gap, 0);
647 mCloseChar->SetRect(rect);
649 for (PRInt32 i = 0; i < mSeparatorsCount; i++) {
650 mSeparatorsChar[i].GetRect(rect);
651 rect.MoveBy(gap, 0);
652 mSeparatorsChar[i].SetRect(rect);
654 return gap;
657 // ----------------------
658 // the Style System will use these to pass the proper style context to our MathMLChar
659 nsStyleContext*
660 nsMathMLmfencedFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
662 PRInt32 openIndex = -1;
663 PRInt32 closeIndex = -1;
664 PRInt32 lastIndex = mSeparatorsCount-1;
666 if (mOpenChar) {
667 lastIndex++;
668 openIndex = lastIndex;
670 if (mCloseChar) {
671 lastIndex++;
672 closeIndex = lastIndex;
674 if (aIndex < 0 || aIndex > lastIndex) {
675 return nsnull;
678 if (aIndex < mSeparatorsCount) {
679 return mSeparatorsChar[aIndex].GetStyleContext();
681 else if (aIndex == openIndex) {
682 return mOpenChar->GetStyleContext();
684 else if (aIndex == closeIndex) {
685 return mCloseChar->GetStyleContext();
687 return nsnull;
690 void
691 nsMathMLmfencedFrame::SetAdditionalStyleContext(PRInt32 aIndex,
692 nsStyleContext* aStyleContext)
694 PRInt32 openIndex = -1;
695 PRInt32 closeIndex = -1;
696 PRInt32 lastIndex = mSeparatorsCount-1;
698 if (mOpenChar) {
699 lastIndex++;
700 openIndex = lastIndex;
702 if (mCloseChar) {
703 lastIndex++;
704 closeIndex = lastIndex;
706 if (aIndex < 0 || aIndex > lastIndex) {
707 return;
710 if (aIndex < mSeparatorsCount) {
711 mSeparatorsChar[aIndex].SetStyleContext(aStyleContext);
713 else if (aIndex == openIndex) {
714 mOpenChar->SetStyleContext(aStyleContext);
716 else if (aIndex == closeIndex) {
717 mCloseChar->SetStyleContext(aStyleContext);