NS_IMETHODIMP nsMathMLmunderoverFrame::TransmitAutomaticData() { // At this stage, all our children are in sync and we can fully // resolve our own mEmbellishData struct //--------------------------------------------------------------------- /* The REC says: As regards munder (respectively mover) : The default value of accentunder is false, unless underscript is an <mo> element or an embellished operator. If underscript is an <mo> element, the value of its accent attribute is used as the default value of accentunder. If underscript is an embellished operator, the accent attribute of the <mo> element at its core is used as the default value. As with all attributes, an explicitly given value overrides the default. XXX The winner is the outermost setting in conflicting settings like these: <munder accentunder='true'> <mi>...</mi> <mo accentunder='false'> ... </mo> </munder> As regards munderover: The accent and accentunder attributes have the same effect as the attributes with the same names on <mover> and <munder>, respectively. Their default values are also computed in the same manner as described for those elements, with the default value of accent depending on overscript and the default value of accentunder depending on underscript. */ nsIFrame* overscriptFrame = nullptr; nsIFrame* underscriptFrame = nullptr; nsIFrame* baseFrame = mFrames.FirstChild(); nsIAtom* tag = mContent->Tag(); if (baseFrame) { if (tag == nsGkAtoms::munder_ || tag == nsGkAtoms::munderover_) { underscriptFrame = baseFrame->GetNextSibling(); } else { NS_ASSERTION(tag == nsGkAtoms::mover_, "mContent->Tag() not recognized"); overscriptFrame = baseFrame->GetNextSibling(); } } if (underscriptFrame && tag == nsGkAtoms::munderover_) { overscriptFrame = underscriptFrame->GetNextSibling(); } // if our base is an embellished operator, let its state bubble to us (in particular, // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags // are reset to the default values of false if the base frame isn't embellished. mPresentationData.baseFrame = baseFrame; GetEmbellishDataFrom(baseFrame, mEmbellishData); // The default value of accentunder is false, unless the underscript is embellished // and its core <mo> is an accent nsEmbellishData embellishData; nsAutoString value; if (tag == nsGkAtoms::munder_ || tag == nsGkAtoms::munderover_) { GetEmbellishDataFrom(underscriptFrame, embellishData); if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) { mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; } else { mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; } // if we have an accentunder attribute, it overrides what the underscript said if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accentunder_, value)) { if (value.EqualsLiteral("true")) { mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; } else if (value.EqualsLiteral("false")) { mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; } } } // The default value of accent is false, unless the overscript is embellished // and its core <mo> is an accent if (tag == nsGkAtoms::mover_ || tag == nsGkAtoms::munderover_) { GetEmbellishDataFrom(overscriptFrame, embellishData); if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) { mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; } else { mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; } // if we have an accent attribute, it overrides what the overscript said if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accent_, value)) { if (value.EqualsLiteral("true")) { mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; } else if (value.EqualsLiteral("false")) { mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; } } } bool subsupDisplay = NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && StyleFont()->mMathDisplay == NS_MATHML_DISPLAYSTYLE_INLINE; // disable the stretch-all flag if we are going to act like a superscript if (subsupDisplay) { mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; } // Now transmit any change that we want to our children so that they // can update their mPresentationData structs //--------------------------------------------------------------------- /* The REC says: Within underscript, <munderover> always sets displaystyle to "false", but increments scriptlevel by 1 only when accentunder is "false". Within overscript, <munderover> always sets displaystyle to "false", but increments scriptlevel by 1 only when accent is "false". Within subscript and superscript it increments scriptlevel by 1, and sets displaystyle to "false", but leaves both attributes unchanged within base. The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a say it shouldn't be compressed. However, The TeXBook says that math accents and \overline change uncramped styles to their cramped counterparts. */ if (tag == nsGkAtoms::mover_ || tag == nsGkAtoms::munderover_) { uint32_t compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ? NS_MATHML_COMPRESSED : 0; mIncrementOver = !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) || subsupDisplay; SetIncrementScriptLevel(tag == nsGkAtoms::mover_ ? 1 : 2, mIncrementOver); if (mIncrementOver) { PropagateFrameFlagFor(overscriptFrame, NS_FRAME_MATHML_SCRIPT_DESCENDANT); } PropagatePresentationDataFor(overscriptFrame, compress, compress); } /* The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a say it should be compressed */ if (tag == nsGkAtoms::munder_ || tag == nsGkAtoms::munderover_) { mIncrementUnder = !NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) || subsupDisplay; SetIncrementScriptLevel(1, mIncrementUnder); if (mIncrementUnder) { PropagateFrameFlagFor(underscriptFrame, NS_FRAME_MATHML_SCRIPT_DESCENDANT); } PropagatePresentationDataFor(underscriptFrame, NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED); } /* Set flags for dtls font feature settings. dtls Dotless Forms This feature provides dotless forms for Math Alphanumeric characters, such as U+1D422 MATHEMATICAL BOLD SMALL I, U+1D423 MATHEMATICAL BOLD SMALL J, U+1D456 U+MATHEMATICAL ITALIC SMALL I, U+1D457 MATHEMATICAL ITALIC SMALL J, and so on. The dotless forms are to be used as base forms for placing mathematical accents over them. To opt out of this change, add the following to the stylesheet: "font-feature-settings: 'dtls' 0" */ if (overscriptFrame && NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) && !NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags)) { PropagatePresentationDataFor(baseFrame, NS_MATHML_DTLS, NS_MATHML_DTLS); } return NS_OK; }
NS_IMETHODIMP nsMathMLmoverFrame::TransmitAutomaticData() { // At this stage, all our children are in sync and we can fully // resolve our own mEmbellishData struct //--------------------------------------------------------------------- /* The REC says: The default value of accent is false, unless overscript is an <mo> element or an embellished operator. If overscript is an <mo> element, the value of its accent attribute is used as the default value of accent. If overscript is an embellished operator, the accent attribute of the <mo> element at its core is used as the default value. As with all attributes, an explicitly given value overrides the default. XXX The winner is the outermost in conflicting settings like these: <mover accent='true'> <mi>...</mi> <mo accent='false'> ... </mo> </mover> */ nsIFrame* overscriptFrame = nsnull; nsIFrame* baseFrame = mFrames.FirstChild(); if (baseFrame) overscriptFrame = baseFrame->GetNextSibling(); // if our base is an embellished operator, let its state bubble to us (in particular, // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags // are reset to the default values of false if the base frame isn't embellished. mPresentationData.baseFrame = baseFrame; GetEmbellishDataFrom(baseFrame, mEmbellishData); // The default value of accent is false, unless the overscript is embellished // and its core <mo> is an accent nsEmbellishData embellishData; GetEmbellishDataFrom(overscriptFrame, embellishData); if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; else mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; // if we have an accent attribute, it overrides what the overscript said static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::_true, &nsGkAtoms::_false, nsnull}; switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::accent_, strings, eCaseMatters)) { case 0: mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; break; case 1: mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; break; } // disable the stretch-all flag if we are going to act like a superscript if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; // Now transmit any change that we want to our children so that they // can update their mPresentationData structs //--------------------------------------------------------------------- /* The REC says: Within overscript, <mover> always sets displaystyle to "false", but increments scriptlevel by 1 only when accent is "false". The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a say it shouldn't be compressed. However, The TeXBook says that math accents and \overline change uncramped styles to their cramped counterparts. */ SetIncrementScriptLevel(1, !NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)); PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ? NS_MATHML_COMPRESSED : 0; PropagatePresentationDataFor(overscriptFrame, ~NS_MATHML_DISPLAYSTYLE | compress, NS_MATHML_DISPLAYSTYLE | compress); return NS_OK; }
NS_IMETHODIMP nsMathMLmunderoverFrame::TransmitAutomaticData() { // At this stage, all our children are in sync and we can fully // resolve our own mEmbellishData struct //--------------------------------------------------------------------- /* The REC says: The accent and accentunder attributes have the same effect as the attributes with the same names on <mover> and <munder>, respectively. Their default values are also computed in the same manner as described for those elements, with the default value of accent depending on overscript and the default value of accentunder depending on underscript. */ nsIFrame* overscriptFrame = nsnull; nsIFrame* underscriptFrame = nsnull; nsIFrame* baseFrame = mFrames.FirstChild(); if (baseFrame) underscriptFrame = baseFrame->GetNextSibling(); if (underscriptFrame) overscriptFrame = underscriptFrame->GetNextSibling(); // if our base is an embellished operator, let its state bubble to us (in particular, // this is where we get the flag for NS_MATHML_EMBELLISH_MOVABLELIMITS). Our flags // are reset to the default values of false if the base frame isn't embellished. mPresentationData.baseFrame = baseFrame; GetEmbellishDataFrom(baseFrame, mEmbellishData); nsAutoString value; // The default value of accentunder is false, unless the underscript is embellished // and its core <mo> is an accent nsEmbellishData embellishData; GetEmbellishDataFrom(underscriptFrame, embellishData); if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; else mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; // if we have an accentunder attribute, it overrides what the underscript said if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsMathMLAtoms::accentunder_, value)) { if (value.EqualsLiteral("true")) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTUNDER; else if (value.EqualsLiteral("false")) mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTUNDER; } // The default value of accent is false, unless the overscript is embellished // and its core <mo> is an accent GetEmbellishDataFrom(overscriptFrame, embellishData); if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; else mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; // if we have an accent attribute, it overrides what the overscript said if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsMathMLAtoms::accent_, value)) { if (value.EqualsLiteral("true")) mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENTOVER; else if (value.EqualsLiteral("false")) mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENTOVER; } // disable the stretch-all flag if we are going to act like a superscript if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) mPresentationData.flags &= ~NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; // Now transmit any change that we want to our children so that they // can update their mPresentationData structs //--------------------------------------------------------------------- /* The REC says: Within underscript, <munderover> always sets displaystyle to "false", but increments scriptlevel by 1 only when accentunder is "false". Within overscript, <munderover> always sets displaystyle to "false", but increments scriptlevel by 1 only when accent is "false". The TeXBook treats 'over' like a superscript, so p.141 or Rule 13a say it shouldn't be compressed. However, The TeXBook says that math accents and \overline change uncramped styles to their cramped counterparts. */ PRInt32 increment = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ? 0 : 1; PRUint32 compress = NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags) ? NS_MATHML_COMPRESSED : 0; PropagatePresentationDataFor(overscriptFrame, increment, ~NS_MATHML_DISPLAYSTYLE | compress, NS_MATHML_DISPLAYSTYLE | compress); /* The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a say it should be compressed */ increment = NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags) ? 0 : 1; PropagatePresentationDataFor(underscriptFrame, increment, ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); return NS_OK; }
// NOTE: aDesiredStretchSize is an IN/OUT parameter // On input - it contains our current size // On output - the same size or the new size that we want NS_IMETHODIMP nsMathMLmoFrame::Stretch(nsRenderingContext& aRenderingContext, nsStretchDirection aStretchDirection, nsBoundingMetrics& aContainerSize, nsHTMLReflowMetrics& aDesiredStretchSize) { if (NS_MATHML_STRETCH_WAS_DONE(mPresentationData.flags)) { NS_WARNING("it is wrong to fire stretch more than once on a frame"); return NS_OK; } mPresentationData.flags |= NS_MATHML_STRETCH_DONE; nsIFrame* firstChild = mFrames.FirstChild(); // get the axis height; nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); aRenderingContext.SetFont(fm); nscoord axisHeight, height; GetAxisHeight(aRenderingContext, fm, axisHeight); // get the leading to be left at the top and the bottom of the stretched char // this seems more reliable than using fm->GetLeading() on suspicious fonts nscoord em; GetEmHeight(fm, em); nscoord leading = NSToCoordRound(0.2f * em); // Operators that are stretchy, or those that are to be centered // to cater for fonts that are not math-aware, are handled by the MathMLChar // ('form' is reset if stretch fails -- i.e., we don't bother to stretch next time) bool useMathMLChar = UseMathMLChar(); nsBoundingMetrics charSize; nsBoundingMetrics container = aDesiredStretchSize.mBoundingMetrics; bool isVertical = false; if (((aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) || (aStretchDirection == NS_STRETCH_DIRECTION_DEFAULT)) && (mEmbellishData.direction == NS_STRETCH_DIRECTION_VERTICAL)) { isVertical = true; } uint32_t stretchHint = GetStretchHint(mFlags, mPresentationData, isVertical); if (useMathMLChar) { nsBoundingMetrics initialSize = aDesiredStretchSize.mBoundingMetrics; if (stretchHint != NS_STRETCH_NONE) { container = aContainerSize; // some adjustments if the operator is symmetric and vertical if (isVertical && NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags)) { // we need to center about the axis nscoord delta = std::max(container.ascent - axisHeight, container.descent + axisHeight); container.ascent = delta + axisHeight; container.descent = delta - axisHeight; // get ready in case we encounter user-desired min-max size delta = std::max(initialSize.ascent - axisHeight, initialSize.descent + axisHeight); initialSize.ascent = delta + axisHeight; initialSize.descent = delta - axisHeight; } // check for user-desired min-max size if (mMaxSize != NS_MATHML_OPERATOR_SIZE_INFINITY && mMaxSize > 0.0f) { // if we are here, there is a user defined maxsize ... //XXX Set stretchHint = NS_STRETCH_NORMAL? to honor the maxsize as close as possible? if (NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(mFlags)) { // there is an explicit value like maxsize="20pt" // try to maintain the aspect ratio of the char float aspect = mMaxSize / float(initialSize.ascent + initialSize.descent); container.ascent = std::min(container.ascent, nscoord(initialSize.ascent * aspect)); container.descent = std::min(container.descent, nscoord(initialSize.descent * aspect)); // below we use a type cast instead of a conversion to avoid a VC++ bug // see http://support.microsoft.com/support/kb/articles/Q115/7/05.ASP container.width = std::min(container.width, (nscoord)mMaxSize); } else { // multiplicative value container.ascent = std::min(container.ascent, nscoord(initialSize.ascent * mMaxSize)); container.descent = std::min(container.descent, nscoord(initialSize.descent * mMaxSize)); container.width = std::min(container.width, nscoord(initialSize.width * mMaxSize)); } if (isVertical && !NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags)) { // re-adjust to align the char with the bottom of the initial container height = container.ascent + container.descent; container.descent = aContainerSize.descent; container.ascent = height - container.descent; } } if (mMinSize > 0.0f) { // if we are here, there is a user defined minsize ... // always allow the char to stretch in its natural direction, // even if it is different from the caller's direction if (aStretchDirection != NS_STRETCH_DIRECTION_DEFAULT && aStretchDirection != mEmbellishData.direction) { aStretchDirection = NS_STRETCH_DIRECTION_DEFAULT; // but when we are not honoring the requested direction // we should not use the caller's container size either container = initialSize; } if (NS_MATHML_OPERATOR_MINSIZE_IS_ABSOLUTE(mFlags)) { // there is an explicit value like minsize="20pt" // try to maintain the aspect ratio of the char float aspect = mMinSize / float(initialSize.ascent + initialSize.descent); container.ascent = std::max(container.ascent, nscoord(initialSize.ascent * aspect)); container.descent = std::max(container.descent, nscoord(initialSize.descent * aspect)); container.width = std::max(container.width, (nscoord)mMinSize); } else { // multiplicative value container.ascent = std::max(container.ascent, nscoord(initialSize.ascent * mMinSize)); container.descent = std::max(container.descent, nscoord(initialSize.descent * mMinSize)); container.width = std::max(container.width, nscoord(initialSize.width * mMinSize)); } if (isVertical && !NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags)) { // re-adjust to align the char with the bottom of the initial container height = container.ascent + container.descent; container.descent = aContainerSize.descent; container.ascent = height - container.descent; } } } // let the MathMLChar stretch itself... nsresult res = mMathMLChar.Stretch(PresContext(), aRenderingContext, aStretchDirection, container, charSize, stretchHint, StyleVisibility()->mDirection); if (NS_FAILED(res)) { // gracefully handle cases where stretching the char failed (i.e., GetBoundingMetrics failed) // clear our 'form' to behave as if the operator wasn't in the dictionary mFlags &= ~NS_MATHML_OPERATOR_FORM; useMathMLChar = false; } } // Child frames of invisble operators are not reflowed if (!NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) { // Place our children using the default method // This will allow our child text frame to get its DidReflow() nsresult rv = Place(aRenderingContext, true, aDesiredStretchSize); if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) { // Make sure the child frames get their DidReflow() calls. DidReflowChildren(mFrames.FirstChild()); } } if (useMathMLChar) { // update our bounding metrics... it becomes that of our MathML char mBoundingMetrics = charSize; // if the returned direction is 'unsupported', the char didn't actually change. // So we do the centering only if necessary if (mMathMLChar.GetStretchDirection() != NS_STRETCH_DIRECTION_UNSUPPORTED || NS_MATHML_OPERATOR_IS_CENTERED(mFlags)) { bool largeopOnly = (NS_STRETCH_LARGEOP & stretchHint) != 0 && (NS_STRETCH_VARIABLE_MASK & stretchHint) == 0; if (isVertical || NS_MATHML_OPERATOR_IS_CENTERED(mFlags)) { // the desired size returned by mMathMLChar maybe different // from the size of the container. // the mMathMLChar.mRect.y calculation is subtle, watch out!!! height = mBoundingMetrics.ascent + mBoundingMetrics.descent; if (NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags) || NS_MATHML_OPERATOR_IS_CENTERED(mFlags)) { // For symmetric and vertical operators, or for operators that are always // centered ('+', '*', etc) we want to center about the axis of the container mBoundingMetrics.descent = height/2 - axisHeight; } else if (!largeopOnly) { // Align the center of the char with the center of the container mBoundingMetrics.descent = height/2 + (container.ascent + container.descent)/2 - container.ascent; } // else align the baselines mBoundingMetrics.ascent = height - mBoundingMetrics.descent; } } } // Fixup for the final height. // On one hand, our stretchy height can sometimes be shorter than surrounding // ASCII chars, e.g., arrow symbols have |mBoundingMetrics.ascent + leading| // that is smaller than the ASCII's ascent, hence when painting the background // later, it won't look uniform along the line. // On the other hand, sometimes we may leave too much gap when our glyph happens // to come from a font with tall glyphs. For example, since CMEX10 has very tall // glyphs, its natural font metrics are large, even if we pick a small glyph // whose size is comparable to the size of a normal ASCII glyph. // So to avoid uneven spacing in either of these two cases, we use the height // of the ASCII font as a reference and try to match it if possible. // special case for accents... keep them short to improve mouse operations... // an accent can only be the non-first child of <mover>, <munder>, <munderover> bool isAccent = NS_MATHML_EMBELLISH_IS_ACCENT(mEmbellishData.flags); if (isAccent) { nsEmbellishData parentData; GetEmbellishDataFrom(mParent, parentData); isAccent = (NS_MATHML_EMBELLISH_IS_ACCENTOVER(parentData.flags) || NS_MATHML_EMBELLISH_IS_ACCENTUNDER(parentData.flags)) && parentData.coreFrame != this; } if (isAccent && firstChild) { // see bug 188467 for what is going on here nscoord dy = aDesiredStretchSize.ascent - (mBoundingMetrics.ascent + leading); aDesiredStretchSize.ascent = mBoundingMetrics.ascent + leading; aDesiredStretchSize.height = aDesiredStretchSize.ascent + mBoundingMetrics.descent; firstChild->SetPosition(firstChild->GetPosition() - nsPoint(0, dy)); } else if (useMathMLChar) { nscoord ascent = fm->MaxAscent(); nscoord descent = fm->MaxDescent(); aDesiredStretchSize.ascent = std::max(mBoundingMetrics.ascent + leading, ascent); aDesiredStretchSize.height = aDesiredStretchSize.ascent + std::max(mBoundingMetrics.descent + leading, descent); } aDesiredStretchSize.width = mBoundingMetrics.width; aDesiredStretchSize.mBoundingMetrics = mBoundingMetrics; mReference.x = 0; mReference.y = aDesiredStretchSize.ascent; // Place our mMathMLChar, its origin is in our coordinate system if (useMathMLChar) { nscoord dy = aDesiredStretchSize.ascent - mBoundingMetrics.ascent; mMathMLChar.SetRect(nsRect(0, dy, charSize.width, charSize.ascent + charSize.descent)); } // Before we leave... there is a last item in the check-list: // If our parent is not embellished, it means we are the outermost embellished // container and so we put the spacing, otherwise we don't include the spacing, // the outermost embellished container will take care of it. if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { // Account the spacing if we are not an accent with explicit attributes nscoord leadingSpace = mEmbellishData.leadingSpace; if (isAccent && !NS_MATHML_OPERATOR_HAS_LSPACE_ATTR(mFlags)) { leadingSpace = 0; } nscoord trailingSpace = mEmbellishData.trailingSpace; if (isAccent && !NS_MATHML_OPERATOR_HAS_RSPACE_ATTR(mFlags)) { trailingSpace = 0; } mBoundingMetrics.width += leadingSpace + trailingSpace; aDesiredStretchSize.width = mBoundingMetrics.width; aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width; nscoord dx = (StyleVisibility()->mDirection ? trailingSpace : leadingSpace); if (dx) { // adjust the offsets mBoundingMetrics.leftBearing += dx; mBoundingMetrics.rightBearing += dx; aDesiredStretchSize.mBoundingMetrics.leftBearing += dx; aDesiredStretchSize.mBoundingMetrics.rightBearing += dx; if (useMathMLChar) { nsRect rect; mMathMLChar.GetRect(rect); mMathMLChar.SetRect(nsRect(rect.x + dx, rect.y, rect.width, rect.height)); } else { nsIFrame* childFrame = firstChild; while (childFrame) { childFrame->SetPosition(childFrame->GetPosition() + nsPoint(dx, 0)); childFrame = childFrame->GetNextSibling(); } } } } // Finished with these: ClearSavedChildMetrics(); // Set our overflow area GatherAndStoreOverflow(&aDesiredStretchSize); // There used to be code here to change the height of the child frame to // change the caret height, but the text frame that manages the caret is now // not a direct child but wrapped in a block frame. See also bug 412033. return NS_OK; }