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/. */
6 #include "nsMathMLmunderoverFrame.h"
7 #include "nsPresContext.h"
8 #include "nsRenderingContext.h"
9 #include "nsMathMLmmultiscriptsFrame.h"
13 // <munderover> -- attach an underscript-overscript pair to a base - implementation
14 // <mover> -- attach an overscript to a base - implementation
15 // <munder> -- attach an underscript to a base - implementation
19 NS_NewMathMLmunderoverFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
21 return new (aPresShell
) nsMathMLmunderoverFrame(aContext
);
24 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmunderoverFrame
)
26 nsMathMLmunderoverFrame::~nsMathMLmunderoverFrame()
31 nsMathMLmunderoverFrame::AttributeChanged(int32_t aNameSpaceID
,
35 if (nsGkAtoms::accent_
== aAttribute
||
36 nsGkAtoms::accentunder_
== aAttribute
) {
37 // When we have automatic data to update within ourselves, we ask our
38 // parent to re-layout its children
39 return ReLayoutChildren(GetParent());
42 return nsMathMLContainerFrame::
43 AttributeChanged(aNameSpaceID
, aAttribute
, aModType
);
47 nsMathMLmunderoverFrame::UpdatePresentationData(uint32_t aFlagsValues
,
48 uint32_t aFlagsToUpdate
)
50 nsMathMLContainerFrame::UpdatePresentationData(aFlagsValues
, aFlagsToUpdate
);
51 // disable the stretch-all flag if we are going to act like a subscript-superscript pair
52 if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData
.flags
) &&
53 StyleFont()->mMathDisplay
== NS_MATHML_DISPLAYSTYLE_INLINE
) {
54 mPresentationData
.flags
&= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY
;
57 mPresentationData
.flags
|= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY
;
63 nsMathMLmunderoverFrame::InheritAutomaticData(nsIFrame
* aParent
)
65 // let the base class get the default from our parent
66 nsMathMLContainerFrame::InheritAutomaticData(aParent
);
68 mPresentationData
.flags
|= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY
;
74 nsMathMLmunderoverFrame::ScriptIncrement(nsIFrame
* aFrame
)
76 nsIFrame
* child
= mFrames
.FirstChild();
77 if (!aFrame
|| aFrame
== child
) {
80 child
= child
->GetNextSibling();
81 if (aFrame
== child
) {
82 if (mContent
->Tag() == nsGkAtoms::mover_
) {
83 return mIncrementOver
? 1 : 0;
85 return mIncrementUnder
? 1 : 0;
87 if (child
&& aFrame
== child
->GetNextSibling()) {
88 // must be a over frame of munderover
89 return mIncrementOver
? 1 : 0;
91 return 0; // frame not found
95 nsMathMLmunderoverFrame::TransmitAutomaticData()
97 // At this stage, all our children are in sync and we can fully
98 // resolve our own mEmbellishData struct
99 //---------------------------------------------------------------------
104 As regards munder (respectively mover) :
105 The default value of accentunder is false, unless underscript
106 is an <mo> element or an embellished operator. If underscript is
107 an <mo> element, the value of its accent attribute is used as the
108 default value of accentunder. If underscript is an embellished
109 operator, the accent attribute of the <mo> element at its
110 core is used as the default value. As with all attributes, an
111 explicitly given value overrides the default.
113 XXX The winner is the outermost setting in conflicting settings like these:
114 <munder accentunder='true'>
116 <mo accentunder='false'> ... </mo>
119 As regards munderover:
120 The accent and accentunder attributes have the same effect as
121 the attributes with the same names on <mover> and <munder>,
122 respectively. Their default values are also computed in the
123 same manner as described for those elements, with the default
124 value of accent depending on overscript and the default value
125 of accentunder depending on underscript.
128 nsIFrame
* overscriptFrame
= nullptr;
129 nsIFrame
* underscriptFrame
= nullptr;
130 nsIFrame
* baseFrame
= mFrames
.FirstChild();
131 nsIAtom
* tag
= mContent
->Tag();
134 if (tag
== nsGkAtoms::munder_
||
135 tag
== nsGkAtoms::munderover_
) {
136 underscriptFrame
= baseFrame
->GetNextSibling();
138 NS_ASSERTION(tag
== nsGkAtoms::mover_
, "mContent->Tag() not recognized");
139 overscriptFrame
= baseFrame
->GetNextSibling();
142 if (underscriptFrame
&&
143 tag
== nsGkAtoms::munderover_
) {
144 overscriptFrame
= underscriptFrame
->GetNextSibling();
148 // if our base is an embellished operator, let its state bubble to us (in particular,
149 // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags
150 // are reset to the default values of false if the base frame isn't embellished.
151 mPresentationData
.baseFrame
= baseFrame
;
152 GetEmbellishDataFrom(baseFrame
, mEmbellishData
);
154 // The default value of accentunder is false, unless the underscript is embellished
155 // and its core <mo> is an accent
156 nsEmbellishData embellishData
;
158 if (tag
== nsGkAtoms::munder_
||
159 tag
== nsGkAtoms::munderover_
) {
160 GetEmbellishDataFrom(underscriptFrame
, embellishData
);
161 if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData
.flags
)) {
162 mEmbellishData
.flags
|= NS_MATHML_EMBELLISH_ACCENTUNDER
;
164 mEmbellishData
.flags
&= ~NS_MATHML_EMBELLISH_ACCENTUNDER
;
167 // if we have an accentunder attribute, it overrides what the underscript said
168 if (mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::accentunder_
, value
)) {
169 if (value
.EqualsLiteral("true")) {
170 mEmbellishData
.flags
|= NS_MATHML_EMBELLISH_ACCENTUNDER
;
171 } else if (value
.EqualsLiteral("false")) {
172 mEmbellishData
.flags
&= ~NS_MATHML_EMBELLISH_ACCENTUNDER
;
177 // The default value of accent is false, unless the overscript is embellished
178 // and its core <mo> is an accent
179 if (tag
== nsGkAtoms::mover_
||
180 tag
== nsGkAtoms::munderover_
) {
181 GetEmbellishDataFrom(overscriptFrame
, embellishData
);
182 if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData
.flags
)) {
183 mEmbellishData
.flags
|= NS_MATHML_EMBELLISH_ACCENTOVER
;
185 mEmbellishData
.flags
&= ~NS_MATHML_EMBELLISH_ACCENTOVER
;
188 // if we have an accent attribute, it overrides what the overscript said
189 if (mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::accent_
, value
)) {
190 if (value
.EqualsLiteral("true")) {
191 mEmbellishData
.flags
|= NS_MATHML_EMBELLISH_ACCENTOVER
;
192 } else if (value
.EqualsLiteral("false")) {
193 mEmbellishData
.flags
&= ~NS_MATHML_EMBELLISH_ACCENTOVER
;
199 NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData
.flags
) &&
200 StyleFont()->mMathDisplay
== NS_MATHML_DISPLAYSTYLE_INLINE
;
202 // disable the stretch-all flag if we are going to act like a superscript
204 mPresentationData
.flags
&= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY
;
207 // Now transmit any change that we want to our children so that they
208 // can update their mPresentationData structs
209 //---------------------------------------------------------------------
212 Within underscript, <munderover> always sets displaystyle to "false",
213 but increments scriptlevel by 1 only when accentunder is "false".
215 Within overscript, <munderover> always sets displaystyle to "false",
216 but increments scriptlevel by 1 only when accent is "false".
218 Within subscript and superscript it increments scriptlevel by 1, and
219 sets displaystyle to "false", but leaves both attributes unchanged within
222 The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a
223 say it shouldn't be compressed. However, The TeXBook says
224 that math accents and \overline change uncramped styles to their
225 cramped counterparts.
227 if (tag
== nsGkAtoms::mover_
||
228 tag
== nsGkAtoms::munderover_
) {
229 uint32_t compress
= NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData
.flags
)
230 ? NS_MATHML_COMPRESSED
: 0;
232 !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData
.flags
) ||
234 SetIncrementScriptLevel(tag
== nsGkAtoms::mover_
? 1 : 2, mIncrementOver
);
235 if (mIncrementOver
) {
236 PropagateFrameFlagFor(overscriptFrame
,
237 NS_FRAME_MATHML_SCRIPT_DESCENDANT
);
239 PropagatePresentationDataFor(overscriptFrame
, compress
, compress
);
242 The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a
243 say it should be compressed
245 if (tag
== nsGkAtoms::munder_
||
246 tag
== nsGkAtoms::munderover_
) {
248 !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData
.flags
) ||
250 SetIncrementScriptLevel(1, mIncrementUnder
);
251 if (mIncrementUnder
) {
252 PropagateFrameFlagFor(underscriptFrame
,
253 NS_FRAME_MATHML_SCRIPT_DESCENDANT
);
255 PropagatePresentationDataFor(underscriptFrame
,
256 NS_MATHML_COMPRESSED
,
257 NS_MATHML_COMPRESSED
);
264 * If the base is an operator with movablelimits="true" (or an embellished
265 operator whose <mo> element core has movablelimits="true"), and
266 displaystyle="false", then underscript and overscript are drawn in
267 a subscript and superscript position, respectively. In this case,
268 the accent and accentunder attributes are ignored. This is often
269 used for limits on symbols such as ∑.
272 if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishDataflags) &&
273 StyleFont()->mMathDisplay == NS_MATHML_DISPLAYSTYLE_INLINE) {
274 // place like subscript-superscript pair
277 // place like underscript-overscript pair
281 /* virtual */ nsresult
282 nsMathMLmunderoverFrame::Place(nsRenderingContext
& aRenderingContext
,
284 nsHTMLReflowMetrics
& aDesiredSize
)
286 nsIAtom
* tag
= mContent
->Tag();
287 if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData
.flags
) &&
288 StyleFont()->mMathDisplay
== NS_MATHML_DISPLAYSTYLE_INLINE
) {
289 //place like sub sup or subsup
290 if (tag
== nsGkAtoms::munderover_
) {
291 return nsMathMLmmultiscriptsFrame::PlaceMultiScript(PresContext(),
296 } else if (tag
== nsGkAtoms::munder_
) {
297 return nsMathMLmmultiscriptsFrame::PlaceMultiScript(PresContext(),
303 NS_ASSERTION(tag
== nsGkAtoms::mover_
, "mContent->Tag() not recognized");
304 return nsMathMLmmultiscriptsFrame::PlaceMultiScript(PresContext(),
313 ////////////////////////////////////
314 // Get the children's desired sizes
316 nsBoundingMetrics bmBase
, bmUnder
, bmOver
;
317 nsHTMLReflowMetrics
baseSize(aDesiredSize
.GetWritingMode());
318 nsHTMLReflowMetrics
underSize(aDesiredSize
.GetWritingMode());
319 nsHTMLReflowMetrics
overSize(aDesiredSize
.GetWritingMode());
320 nsIFrame
* overFrame
= nullptr;
321 nsIFrame
* underFrame
= nullptr;
322 nsIFrame
* baseFrame
= mFrames
.FirstChild();
323 underSize
.SetBlockStartAscent(0);
324 overSize
.SetBlockStartAscent(0);
325 bool haveError
= false;
327 if (tag
== nsGkAtoms::munder_
||
328 tag
== nsGkAtoms::munderover_
) {
329 underFrame
= baseFrame
->GetNextSibling();
330 } else if (tag
== nsGkAtoms::mover_
) {
331 overFrame
= baseFrame
->GetNextSibling();
334 if (underFrame
&& tag
== nsGkAtoms::munderover_
) {
335 overFrame
= underFrame
->GetNextSibling();
338 if (tag
== nsGkAtoms::munder_
) {
339 if (!baseFrame
|| !underFrame
|| underFrame
->GetNextSibling()) {
340 // report an error, encourage people to get their markups in order
344 if (tag
== nsGkAtoms::mover_
) {
345 if (!baseFrame
|| !overFrame
|| overFrame
->GetNextSibling()) {
346 // report an error, encourage people to get their markups in order
350 if (tag
== nsGkAtoms::munderover_
) {
351 if (!baseFrame
|| !underFrame
|| !overFrame
|| overFrame
->GetNextSibling()) {
352 // report an error, encourage people to get their markups in order
358 ReportChildCountError();
360 return ReflowError(aRenderingContext
, aDesiredSize
);
362 GetReflowAndBoundingMetricsFor(baseFrame
, baseSize
, bmBase
);
364 GetReflowAndBoundingMetricsFor(underFrame
, underSize
, bmUnder
);
367 GetReflowAndBoundingMetricsFor(overFrame
, overSize
, bmOver
);
370 nscoord onePixel
= nsPresContext::CSSPixelsToAppUnits(1);
375 nsRefPtr
<nsFontMetrics
> fm
;
376 nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm
));
377 aRenderingContext
.SetFont(fm
);
379 nscoord xHeight
= fm
->XHeight();
380 nscoord oneDevPixel
= fm
->AppUnitsPerDevPixel();
381 gfxFont
* mathFont
= fm
->GetThebesFontGroup()->GetFirstMathFont();
383 nscoord ruleThickness
;
384 GetRuleThickness (aRenderingContext
, fm
, ruleThickness
);
386 nscoord correction
= 0;
387 GetItalicCorrection (bmBase
, correction
);
389 // there are 2 different types of placement depending on
390 // whether we want an accented under or not
392 nscoord underDelta1
= 0; // gap between base and underscript
393 nscoord underDelta2
= 0; // extra space beneath underscript
395 if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData
.flags
)) {
396 // Rule 13a, App. G, TeXbook
397 nscoord bigOpSpacing2
, bigOpSpacing4
, bigOpSpacing5
, dummy
;
398 GetBigOpSpacings (fm
,
399 dummy
, bigOpSpacing2
,
400 dummy
, bigOpSpacing4
,
403 // XXXfredw The Open Type MATH table has some StretchStack* parameters
404 // that we may use when the base is a stretchy horizontal operator. See
407 mathFont
->GetMathConstant(gfxFontEntry::LowerLimitGapMin
,
410 mathFont
->GetMathConstant(gfxFontEntry::LowerLimitBaselineDropMin
,
414 underDelta1
= std::max(bigOpSpacing2
, (bigOpSpacing4
- bmUnder
.ascent
));
415 underDelta2
= bigOpSpacing5
;
418 // No corresponding rule in TeXbook - we are on our own here
419 // XXX tune the gap delta between base and underscript
420 // XXX Should we use Rule 10 like \underline does?
421 // XXXfredw Perhaps use the Underbar* parameters of the MATH table. See
423 underDelta1
= ruleThickness
+ onePixel
/2;
424 underDelta2
= ruleThickness
;
427 if (!(bmUnder
.ascent
+ bmUnder
.descent
)) {
432 nscoord overDelta1
= 0; // gap between base and overscript
433 nscoord overDelta2
= 0; // extra space above overscript
435 if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData
.flags
)) {
436 // Rule 13a, App. G, TeXbook
437 // XXXfredw The Open Type MATH table has some StretchStack* parameters
438 // that we may use when the base is a stretchy horizontal operator. See
440 nscoord bigOpSpacing1
, bigOpSpacing3
, bigOpSpacing5
, dummy
;
441 GetBigOpSpacings (fm
,
442 bigOpSpacing1
, dummy
,
443 bigOpSpacing3
, dummy
,
446 // XXXfredw The Open Type MATH table has some StretchStack* parameters
447 // that we may use when the base is a stretchy horizontal operator. See
450 mathFont
->GetMathConstant(gfxFontEntry::UpperLimitGapMin
,
453 mathFont
->GetMathConstant(gfxFontEntry::UpperLimitBaselineRiseMin
,
457 overDelta1
= std::max(bigOpSpacing1
, (bigOpSpacing3
- bmOver
.descent
));
458 overDelta2
= bigOpSpacing5
;
460 // XXX This is not a TeX rule...
461 // delta1 (as computed abvove) can become really big when bmOver.descent is
462 // negative, e.g., if the content is &OverBar. In such case, we use the height
463 if (bmOver
.descent
< 0)
464 overDelta1
= std::max(bigOpSpacing1
, (bigOpSpacing3
- (bmOver
.ascent
+ bmOver
.descent
)));
467 // Rule 12, App. G, TeXbook
468 // We are going to modify this rule to make it more general.
469 // The idea behind Rule 12 in the TeXBook is to keep the accent
470 // as close to the base as possible, while ensuring that the
471 // distance between the *baseline* of the accent char and
472 // the *baseline* of the base is atleast x-height.
473 // The idea is that for normal use, we would like all the accents
474 // on a line to line up atleast x-height above the baseline
476 // When the ascent of the base is >= x-height,
477 // the baseline of the accent char is placed just above the base
478 // (specifically, the baseline of the accent char is placed
479 // above the baseline of the base by the ascent of the base).
480 // For ease of implementation,
481 // this assumes that the font-designer designs accents
482 // in such a way that the bottom of the accent is atleast x-height
483 // above its baseline, otherwise there will be collisions
484 // with the base. Also there should be proper padding between
485 // the bottom of the accent char and its baseline.
486 // The above rule may not be obvious from a first
487 // reading of rule 12 in the TeXBook !!!
488 // The mathml <mover> tag can use accent chars that
489 // do not follow this convention. So we modify TeX's rule
490 // so that TeX's rule gets subsumed for accents that follow
492 // while also allowing accents that do not follow the convention :
493 // we try to keep the *bottom* of the accent char atleast x-height
494 // from the baseline of the base char. we also slap on an extra
495 // padding between the accent and base chars.
496 overDelta1
= ruleThickness
+ onePixel
/2;
497 nscoord accentBaseHeight
= xHeight
;
500 mathFont
->GetMathConstant(gfxFontEntry::AccentBaseHeight
,
503 if (bmBase
.ascent
< accentBaseHeight
) {
504 // also ensure at least accentBaseHeight above the baseline of the base
505 overDelta1
+= accentBaseHeight
- bmBase
.ascent
;
507 overDelta2
= ruleThickness
;
510 if (!(bmOver
.ascent
+ bmOver
.descent
)) {
515 nscoord dxBase
= 0, dxOver
= 0, dxUnder
= 0;
516 nsAutoString valueAlign
;
521 } alignPosition
= center
;
523 if (mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::align
, valueAlign
)) {
524 if (valueAlign
.EqualsLiteral("left")) {
525 alignPosition
= left
;
526 } else if (valueAlign
.EqualsLiteral("right")) {
527 alignPosition
= right
;
532 // pass 1, do what <mover> does: attach the overscript on the base
534 // Ad-hoc - This is to override fonts which have ready-made _accent_
535 // glyphs with negative lbearing and rbearing. We want to position
536 // the overscript ourselves
537 nscoord overWidth
= bmOver
.width
;
538 if (!overWidth
&& (bmOver
.rightBearing
- bmOver
.leftBearing
> 0)) {
539 overWidth
= bmOver
.rightBearing
- bmOver
.leftBearing
;
540 dxOver
= -bmOver
.leftBearing
;
543 if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData
.flags
)) {
544 mBoundingMetrics
.width
= bmBase
.width
;
545 if (alignPosition
== center
) {
546 dxOver
+= correction
;
550 mBoundingMetrics
.width
= std::max(bmBase
.width
, overWidth
);
551 if (alignPosition
== center
) {
552 dxOver
+= correction
/2;
556 if (alignPosition
== center
) {
557 dxOver
+= (mBoundingMetrics
.width
- overWidth
)/2;
558 dxBase
= (mBoundingMetrics
.width
- bmBase
.width
)/2;
559 } else if (alignPosition
== right
) {
560 dxOver
+= mBoundingMetrics
.width
- overWidth
;
561 dxBase
= mBoundingMetrics
.width
- bmBase
.width
;
564 mBoundingMetrics
.ascent
=
565 bmBase
.ascent
+ overDelta1
+ bmOver
.ascent
+ bmOver
.descent
;
566 mBoundingMetrics
.descent
= bmBase
.descent
;
567 mBoundingMetrics
.leftBearing
=
568 std::min(dxBase
+ bmBase
.leftBearing
, dxOver
+ bmOver
.leftBearing
);
569 mBoundingMetrics
.rightBearing
=
570 std::max(dxBase
+ bmBase
.rightBearing
, dxOver
+ bmOver
.rightBearing
);
573 // pass 2, do what <munder> does: attach the underscript on the previous
574 // result. We conceptually view the previous result as an "anynomous base"
575 // from where to attach the underscript. Hence if the underscript is empty,
576 // we should end up like <mover>. If the overscript is empty, we should
577 // end up like <munder>.
579 nsBoundingMetrics bmAnonymousBase
= mBoundingMetrics
;
580 nscoord ascentAnonymousBase
=
581 std::max(mBoundingMetrics
.ascent
+ overDelta2
,
582 overSize
.BlockStartAscent() + bmOver
.descent
+
583 overDelta1
+ bmBase
.ascent
);
584 ascentAnonymousBase
= std::max(ascentAnonymousBase
,
585 baseSize
.BlockStartAscent());
587 // Width of non-spacing marks is zero so use left and right bearing.
588 nscoord underWidth
= bmUnder
.width
;
590 underWidth
= bmUnder
.rightBearing
- bmUnder
.leftBearing
;
591 dxUnder
= -bmUnder
.leftBearing
;
594 nscoord maxWidth
= std::max(bmAnonymousBase
.width
, underWidth
);
595 if (alignPosition
== center
&&
596 !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData
.flags
)) {
597 GetItalicCorrection(bmAnonymousBase
, correction
);
598 dxUnder
+= -correction
/2;
600 nscoord dxAnonymousBase
= 0;
601 if (alignPosition
== center
) {
602 dxUnder
+= (maxWidth
- underWidth
)/2;
603 dxAnonymousBase
= (maxWidth
- bmAnonymousBase
.width
)/2;
604 } else if (alignPosition
== right
) {
605 dxUnder
+= maxWidth
- underWidth
;
606 dxAnonymousBase
= maxWidth
- bmAnonymousBase
.width
;
609 // adjust the offsets of the real base and overscript since their
610 // final offsets should be relative to us...
611 dxOver
+= dxAnonymousBase
;
612 dxBase
+= dxAnonymousBase
;
614 mBoundingMetrics
.width
=
615 std::max(dxAnonymousBase
+ bmAnonymousBase
.width
, dxUnder
+ bmUnder
.width
);
616 // At this point, mBoundingMetrics.ascent = bmAnonymousBase.ascent
617 mBoundingMetrics
.descent
=
618 bmAnonymousBase
.descent
+ underDelta1
+ bmUnder
.ascent
+ bmUnder
.descent
;
619 mBoundingMetrics
.leftBearing
=
620 std::min(dxAnonymousBase
+ bmAnonymousBase
.leftBearing
, dxUnder
+ bmUnder
.leftBearing
);
621 mBoundingMetrics
.rightBearing
=
622 std::max(dxAnonymousBase
+ bmAnonymousBase
.rightBearing
, dxUnder
+ bmUnder
.rightBearing
);
624 aDesiredSize
.SetBlockStartAscent(ascentAnonymousBase
);
625 aDesiredSize
.Height() = aDesiredSize
.BlockStartAscent() +
626 std::max(mBoundingMetrics
.descent
+ underDelta2
,
627 bmAnonymousBase
.descent
+ underDelta1
+ bmUnder
.ascent
+
628 underSize
.Height() - underSize
.BlockStartAscent());
629 aDesiredSize
.Height() = std::max(aDesiredSize
.Height(),
630 aDesiredSize
.BlockStartAscent() +
631 baseSize
.Height() - baseSize
.BlockStartAscent());
632 aDesiredSize
.Width() = mBoundingMetrics
.width
;
633 aDesiredSize
.mBoundingMetrics
= mBoundingMetrics
;
636 mReference
.y
= aDesiredSize
.BlockStartAscent();
642 dy
= aDesiredSize
.BlockStartAscent() -
643 mBoundingMetrics
.ascent
+ bmOver
.ascent
-
644 overSize
.BlockStartAscent();
645 FinishReflowChild (overFrame
, PresContext(), overSize
, nullptr, dxOver
, dy
, 0);
648 dy
= aDesiredSize
.BlockStartAscent() - baseSize
.BlockStartAscent();
649 FinishReflowChild (baseFrame
, PresContext(), baseSize
, nullptr, dxBase
, dy
, 0);
652 dy
= aDesiredSize
.BlockStartAscent() +
653 mBoundingMetrics
.descent
- bmUnder
.descent
-
654 underSize
.BlockStartAscent();
655 FinishReflowChild (underFrame
, PresContext(), underSize
, nullptr,