// Only place the selected child ... /* virtual */ nsresult nsMathMLmactionFrame::Place(nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { nsIFrame* childFrame = GetSelectedFrame(); if (mSelection == -1) { return ReflowError(aRenderingContext, aDesiredSize); } aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; mBoundingMetrics = nsBoundingMetrics(); if (childFrame) { GetReflowAndBoundingMetricsFor(childFrame, aDesiredSize, mBoundingMetrics); if (aPlaceOrigin) { FinishReflowChild(childFrame, PresContext(), nullptr, aDesiredSize, 0, 0, 0); } mReference.x = 0; mReference.y = aDesiredSize.ascent; } aDesiredSize.mBoundingMetrics = mBoundingMetrics; return NS_OK; }
NS_IMETHODIMP nsMathMLmoFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { // certain values use units that depend on our style context, so // it is safer to just process the whole lot here ProcessOperatorData(); // play safe by not passing invisible operators to the font subsystem because // some platforms risk selecting strange glyphs for them and give bad inter-space if (NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags)) { // return empty space for now, but this is not yet final since there // can be lspace and rspace attributes that reclaim some room. // These will be dealt with later in Stretch(). aDesiredSize.width = 0; aDesiredSize.height = 0; aDesiredSize.ascent = 0; aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; } return nsMathMLTokenFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); }
void nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { // initializations needed for empty markup like <mtag></mtag> aDesiredSize.Width() = aDesiredSize.Height() = 0; aDesiredSize.SetTopAscent(0); aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsIFrame* childFrame = GetFirstPrincipalChild(); while (childFrame) { // ask our children to compute their bounding metrics nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(), aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, aStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); childFrame = childFrame->GetNextSibling(); } // place and size children FinalizeReflow(*aReflowState.rendContext, aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
// Only reflow the selected child ... NS_IMETHODIMP nsMathMLmactionFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsresult rv = NS_OK; aStatus = NS_FRAME_COMPLETE; aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; mBoundingMetrics = nsBoundingMetrics(); nsIFrame* childFrame = GetSelectedFrame(); if (childFrame) { nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, aDesiredSize, childReflowState, aStatus); SaveReflowAndBoundingMetricsFor(childFrame, aDesiredSize, aDesiredSize.mBoundingMetrics); mBoundingMetrics = aDesiredSize.mBoundingMetrics; } FinalizeReflow(*aReflowState.rendContext, aDesiredSize); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return rv; }
void nsMathMLmspaceFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { MarkInReflow(); mPresentationData.flags &= ~NS_MATHML_ERROR; ProcessAttributes(aPresContext); mBoundingMetrics = nsBoundingMetrics(); mBoundingMetrics.width = mWidth; mBoundingMetrics.ascent = mHeight; mBoundingMetrics.descent = mDepth; mBoundingMetrics.leftBearing = 0; mBoundingMetrics.rightBearing = mBoundingMetrics.width; aDesiredSize.SetBlockStartAscent(mHeight); aDesiredSize.Width() = std::max(0, mBoundingMetrics.width); aDesiredSize.Height() = aDesiredSize.BlockStartAscent() + mDepth; // Also return our bounding metrics aDesiredSize.mBoundingMetrics = mBoundingMetrics; aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); }
/* virtual */ nsresult nsMathMLmspaceFrame::MeasureForWidth(nsRenderingContext& aRenderingContext, nsHTMLReflowMetrics& aDesiredSize) { ProcessAttributes(PresContext()); mBoundingMetrics = nsBoundingMetrics(); mBoundingMetrics.width = mWidth; aDesiredSize.Width() = std::max(0, mBoundingMetrics.width); aDesiredSize.mBoundingMetrics = mBoundingMetrics; return NS_OK; }
// For token elements, mBoundingMetrics is computed at the ReflowToken // pass, it is not computed here because our children may be text frames // that do not implement the GetBoundingMetrics() interface. /* virtual */ nsresult nsMathMLTokenFrame::Place(nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { mBoundingMetrics = nsBoundingMetrics(); for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame; childFrame = childFrame->GetNextSibling()) { nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode()); GetReflowAndBoundingMetricsFor(childFrame, childSize, childSize.mBoundingMetrics, nullptr); // compute and cache the bounding metrics mBoundingMetrics += childSize.mBoundingMetrics; } nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); nscoord ascent = fm->MaxAscent(); nscoord descent = fm->MaxDescent(); aDesiredSize.mBoundingMetrics = mBoundingMetrics; aDesiredSize.Width() = mBoundingMetrics.width; aDesiredSize.SetTopAscent(std::max(mBoundingMetrics.ascent, ascent)); aDesiredSize.Height() = aDesiredSize.TopAscent() + std::max(mBoundingMetrics.descent, descent); if (aPlaceOrigin) { nscoord dy, dx = 0; for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame; childFrame = childFrame->GetNextSibling()) { nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode()); GetReflowAndBoundingMetricsFor(childFrame, childSize, childSize.mBoundingMetrics); // place and size the child; (dx,0) makes the caret happy - bug 188146 dy = childSize.Height() == 0 ? 0 : aDesiredSize.TopAscent() - childSize.TopAscent(); FinishReflowChild(childFrame, PresContext(), childSize, nullptr, dx, dy, 0); dx += childSize.Width(); } } SetReference(nsPoint(0, aDesiredSize.TopAscent())); return NS_OK; }
nsresult nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsresult rv = NS_OK; // initializations needed for empty markup like <mtag></mtag> aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsIFrame* childFrame = GetFirstPrincipalChild(); while (childFrame) { // ask our children to compute their bounding metrics nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, aStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); if (NS_FAILED(rv)) { // Call DidReflow() for the child frames we successfully did reflow. DidReflowChildren(GetFirstPrincipalChild(), childFrame); return rv; } SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); childFrame = childFrame->GetNextSibling(); } // place and size children FinalizeReflow(*aReflowState.rendContext, aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
nsBoundingMetrics nsFontMetrics::GetBoundingMetrics(const PRUnichar *aString, PRUint32 aLength, nsRenderingContext *aContext) { if (aLength == 0) return nsBoundingMetrics(); StubPropertyProvider provider; AutoTextRun textRun(this, aContext, aString, aLength); gfxTextRun::Metrics theMetrics = textRun->MeasureText(0, aLength, gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS, aContext->ThebesContext(), &provider); nsBoundingMetrics m; m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.ascent = NSToCoordCeil( -theMetrics.mBoundingBox.Y()); m.descent = NSToCoordCeil( theMetrics.mBoundingBox.YMost()); m.width = NSToCoordRound( theMetrics.mAdvanceWidth); return m; }
static nsBoundingMetrics GetTextBoundingMetrics(nsFontMetrics* aMetrics, const char16_t* aString, uint32_t aLength, mozilla::gfx::DrawTarget* aDrawTarget, gfxFont::BoundingBoxType aType) { if (aLength == 0) return nsBoundingMetrics(); StubPropertyProvider provider; AutoTextRun textRun(aMetrics, aDrawTarget, aString, aLength); nsBoundingMetrics m; if (textRun.get()) { gfxTextRun::Metrics theMetrics = textRun->MeasureText( gfxTextRun::Range(0, aLength), aType, aDrawTarget, &provider); m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.ascent = NSToCoordCeil( -theMetrics.mBoundingBox.Y()); m.descent = NSToCoordCeil( theMetrics.mBoundingBox.YMost()); m.width = NSToCoordRound( theMetrics.mAdvanceWidth); } return m; }
static nsBoundingMetrics GetTextBoundingMetrics(nsFontMetrics* aMetrics, const PRUnichar *aString, uint32_t aLength, nsRenderingContext *aContext, gfxFont::BoundingBoxType aType) { if (aLength == 0) return nsBoundingMetrics(); StubPropertyProvider provider; AutoTextRun textRun(aMetrics, aContext, aString, aLength); nsBoundingMetrics m; if (textRun.get()) { gfxTextRun::Metrics theMetrics = textRun->MeasureText(0, aLength, aType, aContext->ThebesContext(), &provider); m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.ascent = NSToCoordCeil( -theMetrics.mBoundingBox.Y()); m.descent = NSToCoordCeil( theMetrics.mBoundingBox.YMost()); m.width = NSToCoordRound( theMetrics.mAdvanceWidth); } return m; }
NS_IMETHODIMP nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsresult rv; aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); PRInt32 i; const nsStyleFont* font = GetStyleFont(); nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); aReflowState.rendContext->SetFont(fm); nscoord axisHeight, em; GetAxisHeight(*aReflowState.rendContext, fm, axisHeight); GetEmHeight(fm, em); // leading to be left at the top and the bottom of stretched chars nscoord leading = NSToCoordRound(0.2f * em); ///////////// // Reflow children // Asking each child to cache its bounding metrics // Note that we don't use the base method nsMathMLContainerFrame::Reflow() // because we want to stretch our fences, separators and stretchy frames using // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base // method here, our stretchy frames will be stretched and placed, and we may // end up stretching our fences/separators with a different aDesiredSize. // XXX The above decision was revisited in bug 121748 and this code can be // refactored to use nsMathMLContainerFrame::Reflow() at some stage. nsReflowStatus childStatus; nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsIFrame* firstChild = GetFirstChild(nsnull); nsIFrame* childFrame = firstChild; nscoord ascent = 0, descent = 0; if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) { // We use the ASCII metrics to get our minimum height. This way, // if we have borders or a background, they will fit better with // other elements on the line. ascent = fm->MaxAscent(); descent = fm->MaxDescent(); } while (childFrame) { nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); if (NS_FAILED(rv)) { // Call DidReflow() for the child frames we successfully did reflow. DidReflowChildren(firstChild, childFrame); return rv; } SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) descent = childDescent; if (ascent < childDesiredSize.ascent) ascent = childDesiredSize.ascent; childFrame = childFrame->GetNextSibling(); } ///////////// // Ask stretchy children to stretch themselves nsBoundingMetrics containerSize; nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL; GetPreferredStretchSize(*aReflowState.rendContext, 0, /* i.e., without embellishments */ stretchDir, containerSize); childFrame = firstChild; while (childFrame) { nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame); if (mathmlChild) { nsHTMLReflowMetrics childDesiredSize; // retrieve the metrics that was stored at the previous pass GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); mathmlChild->Stretch(*aReflowState.rendContext, stretchDir, containerSize, childDesiredSize); // store the updated metrics SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) descent = childDescent; if (ascent < childDesiredSize.ascent) ascent = childDesiredSize.ascent; } childFrame = childFrame->GetNextSibling(); } // bug 121748: for surrounding fences & separators, use a size that covers everything GetPreferredStretchSize(*aReflowState.rendContext, STRETCH_CONSIDER_EMBELLISHMENTS, stretchDir, containerSize); ////////////////////////////////////////// // Prepare the opening fence, separators, and closing fence, and // adjust the origin of children. // we need to center around the axis nscoord delta = NS_MAX(containerSize.ascent - axisHeight, containerSize.descent + axisHeight); containerSize.ascent = delta + axisHeight; containerSize.descent = delta - axisHeight; ///////////////// // opening fence ... ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar, NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ///////////////// // separators ... for (i = 0; i < mSeparatorsCount; i++) { ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i], NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); } ///////////////// // closing fence ... ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar, NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ////////////////// // Adjust the origins of each child. // and update our bounding metrics i = 0; nscoord dx = 0; nsBoundingMetrics bm; PRBool firstTime = PR_TRUE; if (mOpenChar) { PlaceChar(mOpenChar, ascent, bm, dx); aDesiredSize.mBoundingMetrics = bm; firstTime = PR_FALSE; } childFrame = firstChild; while (childFrame) { nsHTMLReflowMetrics childSize; GetReflowAndBoundingMetricsFor(childFrame, childSize, bm); if (firstTime) { firstTime = PR_FALSE; aDesiredSize.mBoundingMetrics = bm; } else aDesiredSize.mBoundingMetrics += bm; FinishReflowChild(childFrame, aPresContext, nsnull, childSize, dx, ascent - childSize.ascent, 0); dx += childSize.width; if (i < mSeparatorsCount) { PlaceChar(&mSeparatorsChar[i], ascent, bm, dx); aDesiredSize.mBoundingMetrics += bm; } i++; childFrame = childFrame->GetNextSibling(); } if (mCloseChar) { PlaceChar(mCloseChar, ascent, bm, dx); if (firstTime) aDesiredSize.mBoundingMetrics = bm; else aDesiredSize.mBoundingMetrics += bm; } aDesiredSize.width = aDesiredSize.mBoundingMetrics.width; aDesiredSize.height = ascent + descent; aDesiredSize.ascent = ascent; SetBoundingMetrics(aDesiredSize.mBoundingMetrics); SetReference(nsPoint(0, aDesiredSize.ascent)); // see if we should fix the spacing FixInterFrameSpacing(aDesiredSize); // Finished with these: ClearSavedChildMetrics(); // Set our overflow area GatherAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }