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