From c02cea1786ad5845dcc9caf29de345ae91804a81 Mon Sep 17 00:00:00 2001 From: "rbs%maths.uq.edu.au" Date: Fri, 2 Feb 2001 09:37:14 +0000 Subject: [PATCH] [not part of default build] Merged my tree with Shyjan changes, enabling the italic correction, the inter-frame spacing, and the support for moveablimits. Updated the returned bounding metrics to keep the bounding boxes aligned in the visual debug mode --- .../base/src/nsMathMLContainerFrame.cpp | 263 ++++++++++++++---- .../mathml/base/src/nsMathMLContainerFrame.h | 29 +- .../base/src/nsMathMLmmultiscriptsFrame.cpp | 219 +++++++-------- .../base/src/nsMathMLmmultiscriptsFrame.h | 8 +- layout/mathml/base/src/nsMathMLmoverFrame.cpp | 140 +++++++--- layout/mathml/base/src/nsMathMLmsubFrame.cpp | 115 +++++--- layout/mathml/base/src/nsMathMLmsubFrame.h | 17 +- .../mathml/base/src/nsMathMLmsubsupFrame.cpp | 234 +++++++++------- layout/mathml/base/src/nsMathMLmsubsupFrame.h | 23 +- layout/mathml/base/src/nsMathMLmsupFrame.cpp | 119 +++++--- layout/mathml/base/src/nsMathMLmsupFrame.h | 18 +- .../mathml/base/src/nsMathMLmunderFrame.cpp | 48 +++- .../base/src/nsMathMLmunderoverFrame.cpp | 93 +++++-- 13 files changed, 890 insertions(+), 436 deletions(-) diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/layout/mathml/base/src/nsMathMLContainerFrame.cpp index 8d8ba28a8999..ca3a962fff08 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -191,7 +191,7 @@ nsMathMLContainerFrame::GetRuleThickness(nsIRenderingContext& aRenderingContext, // fall-back to the other version GetRuleThickness(aFontMetrics, aRuleThickness); } - + #if 0 nscoord oldRuleThickness; GetRuleThickness(aFontMetrics, oldRuleThickness); @@ -902,42 +902,58 @@ nsMathMLContainerFrame::SetPresentationData(const nsPresentationData& aPresentat } NS_IMETHODIMP -nsMathMLContainerFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRBool aDisplayStyle, - PRBool aCompressed) +nsMathMLContainerFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) { mPresentationData.scriptLevel += aScriptLevelIncrement; - if (aDisplayStyle) - mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; - else - mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; - if (aCompressed) { - // 'compressed' means 'prime' style in App. G, TeXbook - // (the flag retains its value once it is set) - mPresentationData.flags |= NS_MATHML_COMPRESSED; + // update flags that are relevant to this call + if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsToUpdate)) { + // updating the displaystyle flag is allowed + if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) { + mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; + } + else { + mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; + } + } + if (NS_MATHML_IS_COMPRESSED(aFlagsToUpdate)) { + // updating the compression flag is allowed + if (NS_MATHML_IS_COMPRESSED(aFlagsValues)) { + // 'compressed' means 'prime' style in App. G, TeXbook + mPresentationData.flags |= NS_MATHML_COMPRESSED; + } + // no else. the flag is sticky. it retains its value once it is set } return NS_OK; } NS_IMETHODIMP -nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(PRInt32 aIndex, - PRInt32 aScriptLevelIncrement, - PRBool aDisplayStyle, - PRBool aCompressed) +nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, + PRInt32 aLastIndex, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate) { + PRInt32 index = 0; nsIFrame* childFrame = mFrames.FirstChild(); - while (nsnull != childFrame) { - if (!IsOnlyWhitespace(childFrame)) { - if (0 >= aIndex--) { - nsIMathMLFrame* aMathMLFrame = nsnull; - nsresult rv = childFrame->QueryInterface(NS_GET_IID(nsIMathMLFrame), (void**)&aMathMLFrame); - if (NS_SUCCEEDED(rv) && nsnull != aMathMLFrame) { + while (childFrame) { + if (!IsOnlyWhitespace(childFrame)) { + if ((index >= aFirstIndex) && + ((aLastIndex <= 0) || ((aLastIndex > 0) && (index <= aLastIndex)))) { + nsIMathMLFrame* mathMLFrame = nsnull; + nsresult rv = childFrame->QueryInterface( + NS_GET_IID(nsIMathMLFrame), (void**)&mathMLFrame); + if (NS_SUCCEEDED(rv) && mathMLFrame) { // update - aMathMLFrame->UpdatePresentationData(aScriptLevelIncrement, aDisplayStyle, aCompressed); + mathMLFrame->UpdatePresentationData( + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); // propagate down the subtrees - aMathMLFrame->UpdatePresentationDataFromChildAt(0, aScriptLevelIncrement, aDisplayStyle, aCompressed); + mathMLFrame->UpdatePresentationDataFromChildAt(0, -1, + aScriptLevelIncrement, aFlagsValues, aFlagsToUpdate); } } + index++; } childFrame->GetNextSibling(&childFrame); } @@ -1403,7 +1419,7 @@ printf("\n"); aFrame)->ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); if (NS_FAILED(rv)) return rv; // origins are used as placeholders to store the child's ascent and descent. @@ -1563,7 +1579,7 @@ printf("\n"); childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); + //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); if (NS_FAILED(rv)) return rv; // At this stage, the origin points of the children have no use, so we will use the @@ -1639,63 +1655,194 @@ printf("\n"); return NS_OK; } +// For MathML, the 'type' will be used to determine the spacing between frames +// Subclasses can override this method to return a 'type' that will give +// them a particular spacing +NS_IMETHODIMP +nsMathMLContainerFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + // see if this is an embellished operator (mapped to 'Op' in TeX) + if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { + *aType = nsMathMLAtoms::operatorMathMLFrame; + } + else { + nsCOMPtr tag; + mContent->GetTag(*getter_AddRefs(tag)); + // see if this a token element (mapped to 'Ord'in TeX) + if (tag.get() == nsMathMLAtoms::mi_ || + tag.get() == nsMathMLAtoms::mn_ || + tag.get() == nsMathMLAtoms::ms_ || + tag.get() == nsMathMLAtoms::mtext_) { + *aType = nsMathMLAtoms::ordinaryMathMLFrame; + } + else { + // everything else is a schematta element (mapped to 'Inner' in TeX) + *aType = nsMathMLAtoms::schemataMathMLFrame; + } + } + NS_ADDREF(*aType); + return NS_OK; +} + +enum nsMathMLFrameTypeEnum { + eMathMLFrameType_UNKNOWN = -1, + eMathMLFrameType_Ordinary, + eMathMLFrameType_Operator, + eMathMLFrameType_Punctuation, + eMathMLFrameType_Inner +}; + +// see spacing table in Chapter 18, TeXBook (p.170) +static PRInt32 interFrameSpacingTable[4][4] = +{ + // in units of muspace. + // upper half of the byte is set if the + // spacing is not to be used for scriptlevel > 0 + /* Ord Op Punc Inner */ + /*Ord */ {0x00, 0x00, 0x00, 0x11}, + /*Op */ {0x00, 0x00, 0x00, 0x00}, + /*Punc */ {0x11, 0x00, 0x11, 0x11}, + /*Inner*/ {0x11, 0x00, 0x11, 0x11} +}; + +static nscoord +GetInterFrameSpacing(PRInt32 aScriptLevel, + nsIAtom* aFirstFrameType, + nsIAtom* aSecondFrameType) +{ + nsMathMLFrameTypeEnum firstType = eMathMLFrameType_UNKNOWN; + nsMathMLFrameTypeEnum secondType = eMathMLFrameType_UNKNOWN; + + // do the mapping for the first frame + if (aFirstFrameType == nsMathMLAtoms::ordinaryMathMLFrame) + firstType = eMathMLFrameType_Ordinary; + else if (aFirstFrameType == nsMathMLAtoms::operatorMathMLFrame) + firstType = eMathMLFrameType_Operator; + else if (aFirstFrameType == nsMathMLAtoms::schemataMathMLFrame) + firstType = eMathMLFrameType_Inner; + + // do the mapping for the second frame + if (aSecondFrameType == nsMathMLAtoms::ordinaryMathMLFrame) + secondType = eMathMLFrameType_Ordinary; + else if (aSecondFrameType == nsMathMLAtoms::operatorMathMLFrame) + secondType = eMathMLFrameType_Operator; + else if (aSecondFrameType == nsMathMLAtoms::operatorMathMLFrame) + secondType = eMathMLFrameType_Inner; + + // return 0 if there is a frame that we know nothing about + if (firstType == eMathMLFrameType_UNKNOWN || + secondType == eMathMLFrameType_UNKNOWN) { + return 0; + } + + PRInt32 space = interFrameSpacingTable[firstType][secondType]; + if (aScriptLevel > 0 && (space & 0xF0)) { + // spacing is disabled + return 0; + } + else { + return (space & 0x0F); + } +} + NS_IMETHODIMP nsMathMLContainerFrame::Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { + nsresult rv = NS_OK; + + // these are needed in case this frame is empty (i.e., we don't enter the loop) aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = aDesiredSize.descent = 0; mBoundingMetrics.Clear(); - - PRInt32 count = 0; - nsBoundingMetrics bm; - nsHTMLReflowMetrics childSize(nsnull); + + // cache away thinspace + nsStyleFont font; + mStyleContext->GetStyle(eStyleStruct_Font, font); + nscoord thinSpace = NSToCoordRound(float(font.mFont.size)*float(3) / float(18)); + + PRInt32 count = 0; + nsHTMLReflowMetrics childSize (nsnull); + nsBoundingMetrics bmChild; + nscoord italicCorrection = 0; + nsCOMPtr prevFrameType; + nsIFrame* childFrame = mFrames.FirstChild(); while (childFrame) { if (!IsOnlyWhitespace(childFrame)) { - GetReflowAndBoundingMetricsFor(childFrame, childSize, bm); - - aDesiredSize.width += childSize.width; - if (aDesiredSize.descent < childSize.descent) - aDesiredSize.descent = childSize.descent; - if (aDesiredSize.ascent < childSize.ascent) + nsCOMPtr childFrameType; + childFrame->GetFrameType(getter_AddRefs(childFrameType)); + GetReflowAndBoundingMetricsFor(childFrame, childSize, bmChild); + if (0 == count) { aDesiredSize.ascent = childSize.ascent; - - // Compute and cache our bounding metrics - if (0 == count) - mBoundingMetrics = bm; - else - mBoundingMetrics += bm; - - count++; + aDesiredSize.descent = childSize.descent; + mBoundingMetrics = bmChild; + } + else { + if (aDesiredSize.descent < childSize.descent) + aDesiredSize.descent = childSize.descent; + if (aDesiredSize.ascent < childSize.ascent) + aDesiredSize.ascent = childSize.ascent; + // add inter frame spacing + nscoord space = GetInterFrameSpacing(mPresentationData.scriptLevel, + prevFrameType, childFrameType); + mBoundingMetrics.width += space * thinSpace; + // add the child size + mBoundingMetrics += bmChild; + } + prevFrameType = childFrameType; + // add the italic correction at the end (including the last child). + // this gives a nice gap between math and non-math frames, and still + // gives the same math inter-spacing in case this frame connects to + // another math frame + GetItalicCorrection(bmChild, italicCorrection); + mBoundingMetrics.width += italicCorrection; } + count++; childFrame->GetNextSibling(&childFrame); } + aDesiredSize.width = mBoundingMetrics.width; aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.mBoundingMetrics = mBoundingMetrics; + + mReference.x = 0; + mReference.y = aDesiredSize.ascent; + + ////////////////// + // Place Children if (aPlaceOrigin) { - nsRect rect; - nscoord dy, dx = 0; + count = 0; + nscoord dx = 0, dy = 0; + italicCorrection = 0; childFrame = mFrames.FirstChild(); while (childFrame) { - childFrame->GetRect(rect); - childSize.width = rect.width; - childSize.height = rect.height; - - // Place and size the child - dy = aDesiredSize.ascent - rect.y; - FinishReflowChild(childFrame, aPresContext, childSize, dx, dy, 0); - - dx += rect.width; + if (!IsOnlyWhitespace(childFrame)) { + nsCOMPtr childFrameType; + childFrame->GetFrameType(getter_AddRefs(childFrameType)); + GetReflowAndBoundingMetricsFor(childFrame, childSize, bmChild); + dy = aDesiredSize.ascent - childSize.ascent; + if (0 < count) { + // add inter frame spacing + nscoord space = GetInterFrameSpacing(mPresentationData.scriptLevel, + prevFrameType, childFrameType); + dx += space * thinSpace; + } + prevFrameType = childFrameType; + FinishReflowChild(childFrame, aPresContext, childSize, dx, dy, 0); + // add child size + dx += bmChild.width; + // add italic correction + GetItalicCorrection(bmChild, italicCorrection); + dx += italicCorrection; + } + count++; childFrame->GetNextSibling(&childFrame); } } - mReference.x = 0; - mReference.y = aDesiredSize.ascent; return NS_OK; } diff --git a/layout/mathml/base/src/nsMathMLContainerFrame.h b/layout/mathml/base/src/nsMathMLContainerFrame.h index 6d0a0aabb8f6..efeb7fba0ec9 100644 --- a/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -117,18 +117,22 @@ public: SetPresentationData(const nsPresentationData& aPresentationData); NS_IMETHOD - UpdatePresentationData(PRInt32 aScriptLevelIncrement, - PRBool aDisplayStyle, - PRBool aCompressed); + UpdatePresentationData(PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); NS_IMETHOD - UpdatePresentationDataFromChildAt(PRInt32 aIndex, - PRInt32 aScriptLevelIncrement, - PRBool aDisplayStyle, - PRBool aCompressed); + UpdatePresentationDataFromChildAt(PRInt32 aFirstIndex, + PRInt32 aLastIndex, + PRInt32 aScriptLevelIncrement, + PRUint32 aFlagsValues, + PRUint32 aFlagsToUpdate); // nsHTMLContainerFrame methods + NS_IMETHOD + GetFrameType(nsIAtom** aType) const; + NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -289,6 +293,17 @@ public: nsString& aString, nsCSSValue& aCSSValue); + // estimate of the italic correction + static void + GetItalicCorrection(nsBoundingMetrics& aBoundingMetrics, + nscoord& aItalicCorrection) + { + aItalicCorrection = aBoundingMetrics.rightBearing - aBoundingMetrics.width; + if (0 > aItalicCorrection) { + aItalicCorrection = 0; + } + } + // helper methods for getting sup/subdrop's from a child static void GetSubDropFromChild (nsIPresContext* aPresContext, diff --git a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp index 3231ee89de6d..2fb002e41f65 100644 --- a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp @@ -69,10 +69,10 @@ nsMathMLmmultiscriptsFrame::~nsMathMLmmultiscriptsFrame() NS_IMETHODIMP nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { nsresult rv = nsMathMLContainerFrame::Init (aPresContext, aContent, aParent, aContext, aPrevInFlow); @@ -228,6 +228,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, PRBool firstPrescriptsPair = PR_FALSE; nsBoundingMetrics bmBase, bmSubScript, bmSupScript; + nscoord italicCorrection = 0; // XXX is there an NSPR macro for int_max ??? mBoundingMetrics.ascent = mBoundingMetrics.descent = -10000000; @@ -251,75 +252,76 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, } else { - if (childTag.get() == nsMathMLAtoms::none_) { - // we need to record the presence of none tag explicitly - // for correct negotiation between sup/sub shifts later - if (isSubScript) { - isSubScriptPresent = PR_FALSE; + if (childTag.get() == nsMathMLAtoms::none_) { + // we need to record the presence of none tag explicitly + // for correct negotiation between sup/sub shifts later + if (isSubScript) { + isSubScriptPresent = PR_FALSE; bmSubScript.Clear(); bmSubScript.leftBearing = 10000000; - } - else { - isSupScriptPresent = PR_FALSE; + } + else { + isSupScriptPresent = PR_FALSE; bmSupScript.Clear(); bmSupScript.leftBearing = 10000000; - } - } + } + } if (0 == count) { - // base - baseFrame = aChildFrame; + // base + baseFrame = aChildFrame; GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + GetItalicCorrection(bmBase, italicCorrection); - // we update mBoundingMetrics.{ascent,descent} with that - // of the baseFrame only after processing all the sup/sub pairs + // we update mBoundingMetrics.{ascent,descent} with that + // of the baseFrame only after processing all the sup/sub pairs // XXX need italic correction only *if* there are postscripts ? - mBoundingMetrics.width = bmBase.width + bmBase.supItalicCorrection; - mBoundingMetrics.rightBearing = bmBase.rightBearing; + mBoundingMetrics.width = bmBase.width + italicCorrection; + mBoundingMetrics.rightBearing = bmBase.rightBearing; mBoundingMetrics.leftBearing = bmBase.leftBearing; // until overwritten - } + } else { - // super/subscript block - if (isSubScript) { - if (isSubScriptPresent) { - // subscript - subScriptFrame = aChildFrame; + // super/subscript block + if (isSubScript) { + if (isSubScriptPresent) { + // subscript + subScriptFrame = aChildFrame; GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); - // get the subdrop from the subscript font - GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); - // parameter v, Rule 18a, App. G, TeXbook - minSubScriptShift = bmBase.descent + aSubDrop; - trySubScriptShift = PR_MAX(minSubScriptShift,aSubScriptShift); - mBoundingMetrics.descent = - PR_MAX(mBoundingMetrics.descent,bmSubScript.descent); - aDesiredSize.descent = - PR_MAX(aDesiredSize.descent,subScriptSize.ascent); + // get the subdrop from the subscript font + GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); + // parameter v, Rule 18a, App. G, TeXbook + minSubScriptShift = bmBase.descent + aSubDrop; + trySubScriptShift = PR_MAX(minSubScriptShift,aSubScriptShift); + mBoundingMetrics.descent = + PR_MAX(mBoundingMetrics.descent,bmSubScript.descent); + aDesiredSize.descent = + PR_MAX(aDesiredSize.descent,subScriptSize.descent); width = bmSubScript.width + mScriptSpace; rightBearing = bmSubScript.rightBearing + mScriptSpace; - } - } - else { - if (isSupScriptPresent) { - // supscript - supScriptFrame = aChildFrame; + } + } + else { + if (isSupScriptPresent) { + // supscript + supScriptFrame = aChildFrame; GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); - // get the supdrop from the supscript font - GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); - // parameter u, Rule 18a, App. G, TeXbook - minSupScriptShift = bmBase.ascent - aSupDrop; - // get min supscript shift limit from x-height - // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook - minShiftFromXHeight = NSToCoordRound - ((bmSupScript.descent + (1.0f/4.0f) * xHeight)); - trySupScriptShift = - PR_MAX(minSupScriptShift,PR_MAX(minShiftFromXHeight,aSupScriptShift)); - mBoundingMetrics.ascent = - PR_MAX(mBoundingMetrics.ascent,bmSupScript.ascent); - aDesiredSize.ascent = - PR_MAX(aDesiredSize.ascent,supScriptSize.ascent); - width = PR_MAX(width, bmSupScript.width + mScriptSpace); - rightBearing = PR_MAX(rightBearing, bmSupScript.rightBearing + mScriptSpace); - } + // get the supdrop from the supscript font + GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); + // parameter u, Rule 18a, App. G, TeXbook + minSupScriptShift = bmBase.ascent - aSupDrop; + // get min supscript shift limit from x-height + // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook + minShiftFromXHeight = NSToCoordRound + ((bmSupScript.descent + (1.0f/4.0f) * xHeight)); + trySupScriptShift = + PR_MAX(minSupScriptShift,PR_MAX(minShiftFromXHeight,aSupScriptShift)); + mBoundingMetrics.ascent = + PR_MAX(mBoundingMetrics.ascent,bmSupScript.ascent); + aDesiredSize.ascent = + PR_MAX(aDesiredSize.ascent,supScriptSize.ascent); + width = PR_MAX(width, bmSupScript.width + mScriptSpace); + rightBearing = PR_MAX(rightBearing, bmSupScript.rightBearing + mScriptSpace); + } if (!isSubScriptPresent && !isSupScriptPresent) { // report an error, encourage people to get their markups in order @@ -328,21 +330,21 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, if (!mprescriptsFrame) { // we are still looping over base & postscripts mBoundingMetrics.rightBearing = mBoundingMetrics.width + rightBearing; - mBoundingMetrics.width += width; + mBoundingMetrics.width += width; } else { prescriptsWidth += width; if (firstPrescriptsPair) { - firstPrescriptsPair = PR_FALSE; + firstPrescriptsPair = PR_FALSE; mBoundingMetrics.leftBearing = PR_MIN(bmSubScript.leftBearing, bmSupScript.leftBearing); } } - width = rightBearing = 0; + width = rightBearing = 0; - if (isSubScriptPresent && isSupScriptPresent) { - // negotiate between the various shifts so that - // there is enough gap between the sup and subscripts + if (isSubScriptPresent && isSupScriptPresent) { + // negotiate between the various shifts so that + // there is enough gap between the sup and subscripts // Rule 18e, App. G, TeXbook nscoord gap = (trySupScriptShift - bmSupScript.descent) - @@ -360,14 +362,14 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, trySupScriptShift += gap; trySubScriptShift -= gap; } - } - maxSubScriptShift = PR_MAX(maxSubScriptShift, trySubScriptShift); - maxSupScriptShift = PR_MAX(maxSupScriptShift, trySupScriptShift); + } + maxSubScriptShift = PR_MAX(maxSubScriptShift, trySubScriptShift); + maxSupScriptShift = PR_MAX(maxSupScriptShift, trySupScriptShift); - trySubScriptShift = aSubScriptShift; - trySupScriptShift = aSupScriptShift; - isSubScriptPresent = PR_TRUE; - isSupScriptPresent = PR_TRUE; + trySubScriptShift = aSubScriptShift; + trySupScriptShift = aSupScriptShift; + isSubScriptPresent = PR_TRUE; + isSupScriptPresent = PR_TRUE; } } @@ -376,8 +378,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, } } - rv = aChildFrame->GetNextSibling(&aChildFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + aChildFrame->GetNextSibling(&aChildFrame); } // note: width=0 if all sup-sub pairs match correctly if ((0 != width) || !baseFrame || !subScriptFrame || !supScriptFrame) { @@ -421,57 +422,49 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, aChildFrame = mprescriptsFrame; do { if (nsnull == aChildFrame) { // end of prescripts, - // place the base ... - aChildFrame = baseFrame; + // place the base ... + aChildFrame = baseFrame; dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); - dx += baseSize.width + bmBase.supItalicCorrection; + dx += bmBase.width + mScriptSpace + italicCorrection; } else if (mprescriptsFrame != aChildFrame) { - // process each sup/sub pair - if (!IsOnlyWhitespace (aChildFrame)) { - if (0 == count) { - subScriptFrame = aChildFrame; - count++; - } - else if (1 == count) { - supScriptFrame = aChildFrame; - count = 0; - - // get the ascent/descent of sup/subscripts stored in their rects - // rect.x = descent, rect.y = ascent - subScriptFrame->GetRect (aRect); - subScriptSize.ascent = aRect.y; - subScriptSize.width = aRect.width; - subScriptSize.height = aRect.height; - - supScriptFrame->GetRect (aRect); - supScriptSize.ascent = aRect.y; - supScriptSize.width = aRect.width; - supScriptSize.height = aRect.height; + // process each sup/sub pair + if (!IsOnlyWhitespace (aChildFrame)) { + if (0 == count) { + subScriptFrame = aChildFrame; + count++; + } + else if (1 == count) { + supScriptFrame = aChildFrame; + count = 0; + + // get the ascent/descent of sup/subscripts stored in their rects + // rect.x = descent, rect.y = ascent + GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); + GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); // center w.r.t. largest width - width = PR_MAX(subScriptSize.width, supScriptSize.width); + width = PR_MAX(subScriptSize.width, supScriptSize.width); - dy = aDesiredSize.ascent - - subScriptSize.ascent + - maxSubScriptShift; - FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, - dx + (width-subScriptSize.width)/2, dy, 0); + dy = aDesiredSize.ascent - + subScriptSize.ascent + + maxSubScriptShift; + FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, + dx + (width-subScriptSize.width)/2, dy, 0); - dy = aDesiredSize.ascent - - supScriptSize.ascent - - maxSupScriptShift; - FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, - dx + (width-supScriptSize.width)/2, dy, 0); + dy = aDesiredSize.ascent - + supScriptSize.ascent - + maxSupScriptShift; + FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, + dx + (width-supScriptSize.width)/2, dy, 0); - dx += mScriptSpace + width; - } - } + dx += mScriptSpace + width; + } + } } - rv = aChildFrame->GetNextSibling(&aChildFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + aChildFrame->GetNextSibling(&aChildFrame); } while (mprescriptsFrame != aChildFrame); } diff --git a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h index ed10039dacf4..e36796558fc5 100644 --- a/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h +++ b/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h @@ -55,7 +55,13 @@ public: { nsresult rv; rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE, PR_FALSE); + // The REC says: + // The element increments scriptlevel by 1, and sets + // displaystyle to "false", within each of its arguments except base, but + // leaves both attributes unchanged within base. + // XXX Need to update the compression flags in the sub/sup pairs as per TeX + UpdatePresentationDataFromChildAt(1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE, NS_MATHML_DISPLAYSTYLE); // switch the style of the postscripts and prescripts InsertScriptLevelStyleContext(aPresContext); // check whether or not this is an embellished operator diff --git a/layout/mathml/base/src/nsMathMLmoverFrame.cpp b/layout/mathml/base/src/nsMathMLmoverFrame.cpp index 77d9c6784a85..d48947d8bf2e 100644 --- a/layout/mathml/base/src/nsMathMLmoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmoverFrame.cpp @@ -40,6 +40,7 @@ #include "nsStyleUtil.h" #include "nsMathMLmoverFrame.h" +#include "nsMathMLmsupFrame.h" // // -- attach an overscript to a base - implementation @@ -186,18 +187,27 @@ XXX The winner is the outermost in conflicting settings like these: } } - //The REC says: - /* - Within overscript, always sets displaystyle to "false", - but increments scriptlevel by 1 only when accent is "false". + /* The REC says: + Within overscript, 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 incrementScriptLevel; - if (overscriptMathMLFrame) { - incrementScriptLevel = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)? 0 : 1; - overscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE, PR_FALSE); - overscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE, PR_FALSE); + PRInt32 increment = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) + ? 0 : 1; + PRUint32 compress = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) + ? NS_MATHML_COMPRESSED : 0; + overscriptMathMLFrame->UpdatePresentationData(increment, + ~NS_MATHML_DISPLAYSTYLE | compress, + NS_MATHML_DISPLAYSTYLE | compress); + overscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, -1, increment, + ~NS_MATHML_DISPLAYSTYLE | compress, + NS_MATHML_DISPLAYSTYLE | compress); } // switch the style of the overscript @@ -214,13 +224,13 @@ The REC says: position. In this case, the accent attribute is ignored. This is often used for limits on symbols such as ∑. -TODO: +i.e.: if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like superscript } else { - // place like accent + // place like overscript } */ @@ -231,6 +241,16 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize) { nsresult rv = NS_OK; + + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + // place like superscript + return nsMathMLmsupFrame::PlaceSuperScript(aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this); + } //////////////////////////////////// // Get the children's desired sizes @@ -257,12 +277,11 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, } count++; } - rv = childFrame->GetNextSibling(&childFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + childFrame->GetNextSibling(&childFrame); } if ((2 != count) || !baseFrame || !overFrame) { #ifdef NS_DEBUG - printf("mover: invalid markup"); + printf("mover: invalid markup\n"); #endif // report an error, encourage people to get their markups in order return ReflowError(aPresContext, aRenderingContext, aDesiredSize); @@ -291,7 +310,7 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, nscoord delta2 = 0; // extra space above overscript if (!NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { // Rule 13a, App. G, TeXbook -// GetItalicCorrectionFromChild (baseFrame, correction); + GetItalicCorrection (bmBase, correction); nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy; GetBigOpSpacings (fm, bigOpSpacing1, dummy, @@ -309,29 +328,46 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, else { // Rule 12, App. G, TeXbook GetSkewCorrectionFromChild (aPresContext, baseFrame, correction); -#if 0 - delta1 = -PR_MIN(bmBase.ascent, xHeight); -#endif - // We don't follow Rule 12 here since TeX has some implicit - // assumptions in the computation of delta1. - // Should we use Rule 9 like \overline does? - delta1 = ruleThickness; + // We are going to modify this rule to make it more general. + // The idea behind Rule 12 in the TeXBook is to keep the accent + // as close to the base as possible, while ensuring that the + // distance between the *baseline* of the accent char and + // the *baseline* of the base is atleast x-height. + // The idea is that for normal use, we would like all the accents + // on a line to line up atleast x-height above the baseline + // if possible. + // When the ascent of the base is >= x-height, + // the baseline of the accent char is placed just above the base + // (specifically, the baseline of the accent char is placed + // above the baseline of the base by the ascent of the base). + // For ease of implementation, + // this assumes that the font-designer designs accents + // in such a way that the bottom of the accent is atleast x-height + // above its baseline, otherwise there will be collisions + // with the base. Also there should be proper padding between + // the bottom of the accent char and its baseline. + // The above rule may not be obvious from a first + // reading of rule 12 in the TeXBook !!! + // The mathml tag can use accent chars that + // do not follow this convention. So we modify TeX's rule + // so that TeX's rule gets subsumed for accents that follow + // TeX's convention, + // while also allowing accents that do not follow the convention : + // we try to keep the *bottom* of the accent char atleast x-height + // from the baseline of the base char. we also slap on an extra + // padding between the accent and base chars. + delta1 = ruleThickness; // we have atleast the padding + if (bmBase.ascent < xHeight) { + // also ensure atleast x-height above the baseline of the base + delta1 += xHeight - bmBase.ascent; + } delta2 = ruleThickness; } // empty over? if (0 == (bmOver.ascent + bmOver.descent)) delta1 = 0; mBoundingMetrics.ascent = - bmOver.ascent + bmOver.descent + delta1 + bmBase.ascent; - -#if 0 - // Rule 12 (cont.) - if (NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { - // delta1 is -ve for an accent - // hence as per Rule 12, App. G, TeXbook, we should ... - mBoundingMetrics.ascent = PR_MAX(mBoundingMetrics.ascent, bmBase.ascent); - } -#endif + bmOver.ascent + bmOver.descent + delta1 + bmBase.ascent; mBoundingMetrics.descent = bmBase.descent; if (NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { @@ -344,7 +380,9 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, } aDesiredSize.descent = baseSize.descent; - aDesiredSize.ascent = mBoundingMetrics.ascent + delta2; + aDesiredSize.ascent = + PR_MAX(mBoundingMetrics.ascent + delta2, + overSize.ascent + bmOver.descent + delta1 + bmBase.ascent); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; aDesiredSize.width = mBoundingMetrics.width; @@ -361,7 +399,8 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, dxOver = correction/2 + (mBoundingMetrics.width - bmOver.width)/2; } - dyOver = aDesiredSize.ascent - mBoundingMetrics.ascent + bmOver.ascent - overSize.ascent; + dyOver = aDesiredSize.ascent - + mBoundingMetrics.ascent + bmOver.ascent - overSize.ascent; mReference.x = 0; mReference.y = aDesiredSize.ascent; @@ -379,3 +418,34 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, } return NS_OK; } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/mathml/base/src/nsMathMLmsubFrame.cpp b/layout/mathml/base/src/nsMathMLmsubFrame.cpp index 34a993a5df96..acacbcb6994b 100644 --- a/layout/mathml/base/src/nsMathMLmsubFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsubFrame.cpp @@ -69,10 +69,10 @@ nsMathMLmsubFrame::~nsMathMLmsubFrame() NS_IMETHODIMP nsMathMLmsubFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { nsresult rv = nsMathMLContainerFrame::Init (aPresContext, aContent, aParent, aContext, aPrevInFlow); @@ -91,19 +91,50 @@ nsMathMLmsubFrame::Init(nsIPresContext* aPresContext, } #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) -// mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; #endif return rv; } NS_IMETHODIMP -nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - PRBool aPlaceOrigin, - nsHTMLReflowMetrics& aDesiredSize) +nsMathMLmsubFrame::Place (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize) +{ + return nsMathMLmsubFrame::PlaceSubScript(aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this, + mSubScriptShift, + mScriptSpace); +} + +// exported routine that both munder and msub share. +// munder uses this when movablelimits is set. +nsresult +nsMathMLmsubFrame::PlaceSubScript (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aFrame, + nscoord aUserSubScriptShift, + nscoord aScriptSpace) { nsresult rv = NS_OK; + // the caller better be a mathml frame + nsIMathMLFrame* mathMLFrame = nsnull; + rv = aFrame->QueryInterface (NS_GET_IID(nsIMathMLFrame), + (void**)&mathMLFrame); + if (NS_FAILED(rv) || !mathMLFrame) return rv; + + // force the scriptSpace to be atleast 1 pixel + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + aScriptSpace = PR_MAX(NSIntPixelsToTwips(1, p2t), aScriptSpace); + //////////////////////////////////// // Get the children's desired sizes @@ -117,36 +148,42 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, nsBoundingMetrics bmBase, bmSubScript; - nsIFrame* aChildFrame = mFrames.FirstChild(); + nsIFrame* aChildFrame = nsnull; + rv = aFrame->FirstChild (aPresContext, nsnull, &aChildFrame); + if (!NS_SUCCEEDED(rv) || (nsnull == aChildFrame)) { + return rv; + } while (nsnull != aChildFrame) { if (!IsOnlyWhitespace(aChildFrame)) { if (0 == count) { - // base - baseFrame = aChildFrame; + // base + baseFrame = aChildFrame; GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); } else if (1 == count) { - // subscript - subScriptFrame = aChildFrame; + // subscript + subScriptFrame = aChildFrame; GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); - // get the subdrop from the subscript font - nscoord aSubDrop; - GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); - // parameter v, Rule 18a, App. G, TeXbook - minSubScriptShift = bmBase.descent + aSubDrop; + // get the subdrop from the subscript font + nscoord aSubDrop; + GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); + // parameter v, Rule 18a, App. G, TeXbook + minSubScriptShift = bmBase.descent + aSubDrop; } count++; } - rv = aChildFrame->GetNextSibling(&aChildFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + aChildFrame->GetNextSibling(&aChildFrame); } #ifdef NS_DEBUG - if (2 != count) printf("msub: invalid markup"); + if (2 != count) printf("msub: invalid markup\n"); #endif if ((2 != count) || !baseFrame || !subScriptFrame) { // report an error, encourage people to get their markups in order - return ReflowError(aPresContext, aRenderingContext, aDesiredSize); + return NS_STATIC_CAST(nsMathMLContainerFrame*, + aFrame)->ReflowError(aPresContext, + aRenderingContext, + aDesiredSize); } ////////////////// @@ -177,21 +214,29 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, GetSubScriptShifts (fm, aSubScriptShift, dummy); aSubScriptShift = - PR_MAX(aSubScriptShift, mSubScriptShift); + PR_MAX(aSubScriptShift, aUserSubScriptShift); // get actual subscriptshift to be used // Rule 18b, App. G, TeXbook nscoord actualSubScriptShift = PR_MAX(minSubScriptShift,PR_MAX(aSubScriptShift,minShiftFromXHeight)); // get bounding box for base + subscript - mBoundingMetrics.ascent = + nsBoundingMetrics boundingMetrics; + boundingMetrics.ascent = PR_MAX(bmBase.ascent, bmSubScript.ascent - actualSubScriptShift); - mBoundingMetrics.descent = + boundingMetrics.descent = PR_MAX(bmBase.descent, bmSubScript.descent + actualSubScriptShift); - // add mScriptSpace between base and supscript - mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSubScript.width; - mBoundingMetrics.leftBearing = bmBase.leftBearing; - mBoundingMetrics.rightBearing = baseSize.width + mScriptSpace + bmSubScript.rightBearing; + // add aScriptSpace between base and supscript + boundingMetrics.width = + bmBase.width + + aScriptSpace + + bmSubScript.width; + boundingMetrics.leftBearing = bmBase.leftBearing; + boundingMetrics.rightBearing = + bmBase.width + + aScriptSpace + + bmSubScript.rightBearing; + mathMLFrame->SetBoundingMetrics (boundingMetrics); // reflow metrics aDesiredSize.ascent = @@ -199,10 +244,9 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, aDesiredSize.descent = PR_MAX(baseSize.descent, subScriptSize.descent + actualSubScriptShift); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width; + aDesiredSize.width = bmBase.width + aScriptSpace + subScriptSize.width; - mReference.x = 0; - mReference.y = aDesiredSize.ascent; + mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); if (aPlaceOrigin) { nscoord dx, dy; @@ -210,11 +254,12 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); // ... and subscript - dx = baseSize.width; + // XXX adding mScriptSpace seems to add more space than i like + // may want to remove later. + dx = bmBase.width + aScriptSpace; dy = aDesiredSize.ascent - (subScriptSize.ascent - actualSubScriptShift); FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0); } return NS_OK; } - diff --git a/layout/mathml/base/src/nsMathMLmsubFrame.h b/layout/mathml/base/src/nsMathMLmsubFrame.h index 32c1a38fdb91..59963cf238b1 100644 --- a/layout/mathml/base/src/nsMathMLmsubFrame.h +++ b/layout/mathml/base/src/nsMathMLmsubFrame.h @@ -48,6 +48,15 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + static nsresult + PlaceSubScript (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aForFrame, + nscoord aUserSubScriptShift = 0, + nscoord aScriptSpace = NSFloatPointsToTwips(0.5f)); + NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -55,7 +64,13 @@ public: { nsresult rv; rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE, PR_FALSE); + // 1. The REC says: + // The element increments scriptlevel by 1, and sets displaystyle to + // "false", within subscript, but leaves both attributes unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says the subscript is compressed + UpdatePresentationDataFromChildAt(1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); // switch the style of the subscript InsertScriptLevelStyleContext(aPresContext); // check whether or not this is an embellished operator diff --git a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp index a47d888ecf9f..ed91521e4292 100644 --- a/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp @@ -3,7 +3,7 @@ * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ - * + * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing @@ -11,11 +11,11 @@ * * The Original Code is Mozilla MathML Project. * - * The Initial Developer of the Original Code is The University Of + * The Initial Developer of the Original Code is The University Of * Queensland. Portions created by The University Of Queensland are * Copyright (C) 1999 The University Of Queensland. All Rights Reserved. * - * Contributor(s): + * Contributor(s): * Roger B. Sidje * David J. Fiddes * Shyjan Mahamud (added TeX rendering rules) @@ -69,10 +69,10 @@ nsMathMLmsubsupFrame::~nsMathMLmsubsupFrame() NS_IMETHODIMP nsMathMLmsubsupFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { nsresult rv = nsMathMLContainerFrame::Init (aPresContext, aContent, aParent, aContext, aPrevInFlow); @@ -100,19 +100,52 @@ nsMathMLmsubsupFrame::Init(nsIPresContext* aPresContext, } #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) -// mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; #endif return rv; } + NS_IMETHODIMP -nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - PRBool aPlaceOrigin, - nsHTMLReflowMetrics& aDesiredSize) +nsMathMLmsubsupFrame::Place (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize) +{ + return nsMathMLmsubsupFrame::PlaceSubSupScript (aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this, + mSubScriptShift, + mScriptSpace); +} + +// exported routine that both munderover and msubsup share. +// munderover uses this when movablelimits is set. +nsresult +nsMathMLmsubsupFrame::PlaceSubSupScript (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aFrame, + nscoord aUserSubScriptShift, + nscoord aUserSupScriptShift, + nscoord aScriptSpace) { nsresult rv = NS_OK; + // the caller better be a mathml frame + nsIMathMLFrame* mathMLFrame = nsnull; + rv = aFrame->QueryInterface (NS_GET_IID(nsIMathMLFrame), + (void**)&mathMLFrame); + if (NS_FAILED(rv) || !mathMLFrame) return rv; + + // force the scriptSpace to be atleast 1 pixel + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + aScriptSpace = PR_MAX(NSIntPixelsToTwips(1, p2t), aScriptSpace); + //////////////////////////////////// // Get the children's desired sizes @@ -124,65 +157,70 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, nsIFrame* subScriptFrame = nsnull; nsIFrame* supScriptFrame = nsnull; // parameter v, Rule 18a, Appendix G of the TeXbook - nscoord minSubScriptShift = 0; + nscoord minSubScriptShift = 0; // parameter u in Rule 18a, Appendix G of the TeXbook - nscoord minSupScriptShift = 0; + nscoord minSupScriptShift = 0; nsBoundingMetrics bmBase, bmSubScript, bmSupScript; - nsIFrame* aChildFrame = mFrames.FirstChild(); - while (nsnull != aChildFrame) - { + nsIFrame* aChildFrame = nsnull; + rv = aFrame->FirstChild (aPresContext, nsnull, &aChildFrame); + if (!NS_SUCCEEDED(rv) || (nsnull == aChildFrame)) { + return rv; + } + while (nsnull != aChildFrame) { if (!IsOnlyWhitespace(aChildFrame)) { if (0 == count) { - // base - baseFrame = aChildFrame; + // base + baseFrame = aChildFrame; GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); } else if (1 == count) { - // subscript - subScriptFrame = aChildFrame; + // subscript + subScriptFrame = aChildFrame; GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); - // get the subdrop from the subscript font - nscoord aSubDrop; - GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); - // parameter v, Rule 18a, App. G, TeXbook - minSubScriptShift = bmBase.descent + aSubDrop; + // get the subdrop from the subscript font + nscoord aSubDrop; + GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); + // parameter v, Rule 18a, App. G, TeXbook + minSubScriptShift = bmBase.descent + aSubDrop; } else if (2 == count) { - // superscript - supScriptFrame = aChildFrame; + // superscript + supScriptFrame = aChildFrame; GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); - // get the supdrop from the supscript font - nscoord aSupDrop; - GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); - // parameter u, Rule 18a, App. G, TeXbook - minSupScriptShift = bmBase.ascent - aSupDrop; + // get the supdrop from the supscript font + nscoord aSupDrop; + GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); + // parameter u, Rule 18a, App. G, TeXbook + minSupScriptShift = bmBase.ascent - aSupDrop; } count++; } - rv = aChildFrame->GetNextSibling(&aChildFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + aChildFrame->GetNextSibling(&aChildFrame); } #ifdef NS_DEBUG - if (3 != count) printf("msubsup: invalid markup"); + if (3 != count) printf("msubsup: invalid markup\n"); #endif if ((3 != count) || !baseFrame || !subScriptFrame || !supScriptFrame) { // report an error, encourage people to get their markups in order - return ReflowError(aPresContext, aRenderingContext, aDesiredSize); + return NS_STATIC_CAST(nsMathMLContainerFrame*, + aFrame)->ReflowError(aPresContext, + aRenderingContext, + aDesiredSize); } ////////////////// - // Place Children + // Place Children ////////////////// ////////////////////////////////////////////////// // Get subscript shift // slightly different from nsMathMLmsubFrame.cpp ////////////////////////////////////////////////// - + // aSubScriptShift{1,2} - // = minimum amount to shift the subscript down + // = minimum amount to shift the subscript down // = sub{1,2} in TeXbook // aSubScriptShift1 = subscriptshift attribute * x-height nscoord aSubScriptShift1, aSubScriptShift2; @@ -202,31 +240,30 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, nscoord aRuleSize; GetRuleThickness (aRenderingContext, fm, aRuleSize); - + // Get aSubScriptShift{1,2} default from font GetSubScriptShifts (fm, aSubScriptShift1, aSubScriptShift2); - if (0 < mSubScriptShift) { + if (0 < aUserSubScriptShift) { // the user has set the subscriptshift attribute float aFactor = ((float) aSubScriptShift2) / aSubScriptShift1; - aSubScriptShift1 = PR_MAX(aSubScriptShift1, mSubScriptShift); + aSubScriptShift1 = PR_MAX(aSubScriptShift1, aUserSubScriptShift); aSubScriptShift2 = NSToCoordRound(aFactor * aSubScriptShift1); } // get a tentative value for subscriptshift // Rule 18d, App. G, TeXbook - nscoord aSubScriptShift = + nscoord aSubScriptShift = PR_MAX(minSubScriptShift,PR_MAX(aSubScriptShift1,aSubScriptShift2)); - ////////////////////////////////////////////////// // Get supscript shift // same code from nsMathMLmsupFrame.cpp ////////////////////////////////////////////////// - + // get min supscript shift limit from x-height // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook - nscoord minShiftFromXHeight = (nscoord) + nscoord minShiftFromXHeight = (nscoord) (bmSupScript.descent + (1.0f/4.0f) * xHeight); // aSupScriptShift{1,2,3} @@ -238,11 +275,11 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3; // Set aSupScriptShift{1,2,3} default from font GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3); - if (0 < mSupScriptShift) { + if (0 < aUserSupScriptShift) { // the user has set the superscriptshift attribute float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1; float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1; - aSupScriptShift1 = PR_MAX(aSupScriptShift1, mSupScriptShift); + aSupScriptShift1 = PR_MAX(aSupScriptShift1, aUserSupScriptShift); aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1); aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1); } @@ -250,13 +287,15 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord aSupScriptShift; - if ( mPresentationData.scriptLevel == 0 && - NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && - !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { + nsPresentationData presentationData; + mathMLFrame->GetPresentationData(presentationData); + if ( presentationData.scriptLevel == 0 && + NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) && + !NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style D in TeXbook aSupScriptShift = aSupScriptShift1; } - else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { + else if (NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' aSupScriptShift = aSupScriptShift3; } @@ -265,20 +304,19 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, aSupScriptShift = aSupScriptShift2; } - // get tentative value for superscriptshift + // get tentative value for superscriptshift // Rule 18c, App. G, TeXbook - aSupScriptShift = + aSupScriptShift = PR_MAX(minSupScriptShift,PR_MAX(aSupScriptShift,minShiftFromXHeight)); - ////////////////////////////////////////////////// // Negotiate between aSupScriptShift and aSubScriptShift // so that there will be enough gap between them // Rule 18e, App. G, TeXbook ////////////////////////////////////////////////// - nscoord gap = - (aSupScriptShift - bmSupScript.descent) - + nscoord gap = + (aSupScriptShift - bmSupScript.descent) - (bmSubScript.ascent - aSubScriptShift); if (gap < 4.0f * aRuleSize) { // adjust aSubScriptShift to get a gap of (4.0 * aRuleSize) @@ -286,9 +324,9 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, } // next we want to ensure that the bottom of the superscript - // will be > (4/5) * x-height above baseline - gap = NSToCoordRound ((4.0f/5.0f) * xHeight - - (aSupScriptShift - bmSupScript.descent)); + // will be > (4/5) * x-height above baseline + gap = NSToCoordRound ((4.0f/5.0f) * xHeight - + (aSupScriptShift - bmSupScript.descent)); if (gap > 0.0f) { aSupScriptShift += gap; aSubScriptShift -= gap; @@ -299,57 +337,51 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, ////////////////////////////////////////////////// // get bounding box for base + subscript + superscript - mBoundingMetrics.ascent = - PR_MAX(bmBase.ascent,(bmSupScript.ascent+aSupScriptShift)); - mBoundingMetrics.descent = - PR_MAX(bmBase.descent,(bmSubScript.descent+aSubScriptShift)); + nsBoundingMetrics boundingMetrics; + boundingMetrics.ascent = + PR_MAX(bmBase.ascent, (bmSupScript.ascent + aSupScriptShift)); + boundingMetrics.descent = + PR_MAX(bmBase.descent, (bmSubScript.descent + aSubScriptShift)); - // add mScriptSpace to both super/subscript + // add aScriptSpace to both super/subscript // add italicCorrection only to superscript - // XXX this will be handled properly later ... - nscoord italicCorrection = 0; - mBoundingMetrics.width = bmBase.width + mScriptSpace + - PR_MAX((bmBase.supItalicCorrection + bmSupScript.width), - (bmBase.subItalicCorrection + bmSubScript.width)); + nscoord italicCorrection; + GetItalicCorrection(bmBase, italicCorrection); + boundingMetrics.width = bmBase.width + aScriptSpace + + PR_MAX((italicCorrection + bmSupScript.width), bmSubScript.width); + boundingMetrics.leftBearing = bmBase.leftBearing; + boundingMetrics.rightBearing = bmBase.width + aScriptSpace + + PR_MAX((italicCorrection + bmSupScript.rightBearing), bmSubScript.rightBearing); + mathMLFrame->SetBoundingMetrics(boundingMetrics); - // to be simplified later - nscoord dyBase = mBoundingMetrics.ascent - bmBase.ascent; - nscoord dySubScript = mBoundingMetrics.ascent - bmSubScript.ascent + aSubScriptShift; - nscoord dySupScript = mBoundingMetrics.ascent - bmSupScript.ascent - aSupScriptShift; - - nscoord baseTop = mBoundingMetrics.ascent - dyBase - bmBase.ascent + baseSize.ascent; - nscoord subScriptTop = mBoundingMetrics.ascent - dySubScript - bmSubScript.ascent + subScriptSize.ascent; - nscoord supScriptTop = mBoundingMetrics.ascent - dySupScript - bmSupScript.ascent + supScriptSize.ascent; - - aDesiredSize.ascent = - PR_MAX(baseTop, PR_MAX(subScriptTop, supScriptTop)); - aDesiredSize.descent = - PR_MAX(baseSize.height-baseTop, - PR_MAX(subScriptSize.height-subScriptTop, supScriptSize.height-supScriptTop)); + // reflow metrics + aDesiredSize.ascent = + PR_MAX(baseSize.ascent, + PR_MAX(subScriptSize.ascent - aSubScriptShift, + supScriptSize.ascent + aSupScriptShift)); + aDesiredSize.descent = + PR_MAX(baseSize.descent, + PR_MAX(subScriptSize.descent + aSubScriptShift, + supScriptSize.descent - aSupScriptShift)); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; + aDesiredSize.width = bmBase.width + aScriptSpace + + PR_MAX((italicCorrection + supScriptSize.width), subScriptSize.width); - mReference.x = 0; - mReference.y = aDesiredSize.ascent; - mBoundingMetrics.leftBearing = bmBase.leftBearing; - mBoundingMetrics.rightBearing = bmBase.width + mScriptSpace + - PR_MAX((bmBase.supItalicCorrection + bmSupScript.rightBearing), - (bmBase.subItalicCorrection + bmSubScript.rightBearing)); - - aDesiredSize.width = mBoundingMetrics.width; + mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); if (aPlaceOrigin) { nscoord dx, dy; // now place the base ... - dx = 0; dy = aDesiredSize.ascent - baseTop; - FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); + dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; + FinishReflowChild(baseFrame, aPresContext, baseSize, dx, dy, 0); // ... and subscript - dx = bmBase.width + bmBase.subItalicCorrection; - dy = aDesiredSize.ascent - subScriptTop; - FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0); + dx = bmBase.width + aScriptSpace; + dy = aDesiredSize.ascent - (subScriptSize.ascent - aSubScriptShift); + FinishReflowChild(subScriptFrame, aPresContext, subScriptSize, dx, dy, 0); // ... and the superscript - dx = bmBase.width + bmBase.supItalicCorrection; - dy = aDesiredSize.ascent - supScriptTop; - FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0); + dx = bmBase.width + aScriptSpace + italicCorrection; + dy = aDesiredSize.ascent - (supScriptSize.ascent + aSupScriptShift); + FinishReflowChild(supScriptFrame, aPresContext, supScriptSize, dx, dy, 0); } return NS_OK; diff --git a/layout/mathml/base/src/nsMathMLmsubsupFrame.h b/layout/mathml/base/src/nsMathMLmsubsupFrame.h index cc2fef995fdd..03ffa8eef38d 100644 --- a/layout/mathml/base/src/nsMathMLmsubsupFrame.h +++ b/layout/mathml/base/src/nsMathMLmsubsupFrame.h @@ -48,6 +48,16 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + static nsresult + PlaceSubSupScript(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aForFrame, + nscoord aUserSubScriptShift = 0, + nscoord aUserSupScriptShift = 0, + nscoord aScriptSpace = NSFloatPointsToTwips(0.5f)); + NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -55,7 +65,18 @@ public: { nsresult rv; rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE, PR_FALSE); + // 1. The REC says: + // The element increments scriptlevel by 1, and sets displaystyle to + // "false", within subscript and superscript, but leaves both attributes + // unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says the superscript inherits the compression + // while the subscript is compressed + UpdatePresentationDataFromChildAt(1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE, + NS_MATHML_DISPLAYSTYLE); + UpdatePresentationDataFromChildAt(1, 1, 0, + NS_MATHML_COMPRESSED, + NS_MATHML_COMPRESSED); // switch the style of the subscript and superscript InsertScriptLevelStyleContext(aPresContext); // check whether or not this is an embellished operator diff --git a/layout/mathml/base/src/nsMathMLmsupFrame.cpp b/layout/mathml/base/src/nsMathMLmsupFrame.cpp index 1798e09de99d..b66ca0ac417b 100644 --- a/layout/mathml/base/src/nsMathMLmsupFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmsupFrame.cpp @@ -90,24 +90,55 @@ nsMathMLmsupFrame::Init(nsIPresContext* aPresContext, } #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) -// mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; #endif return rv; } NS_IMETHODIMP -nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - PRBool aPlaceOrigin, - nsHTMLReflowMetrics& aDesiredSize) +nsMathMLmsupFrame::Place (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize) +{ + return nsMathMLmsupFrame::PlaceSuperScript (aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this, + mSupScriptShift, + mScriptSpace); +} + +// exported routine that both mover and msup share. +// mover uses this when movablelimits is set. +nsresult +nsMathMLmsupFrame::PlaceSuperScript(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aFrame, + nscoord aUserSupScriptShift, + nscoord aScriptSpace) { nsresult rv = NS_OK; + // the caller better be a mathml frame + nsIMathMLFrame* mathMLFrame = nsnull; + rv = aFrame->QueryInterface (NS_GET_IID(nsIMathMLFrame), + (void**)&mathMLFrame); + if (NS_FAILED(rv) || !mathMLFrame) return rv; + + // force the scriptSpace to be at least 1 pixel + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + aScriptSpace = PR_MAX(onePixel, aScriptSpace); + //////////////////////////////////// // Get the children's desired sizes PRInt32 count = 0; - nsRect aRect; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics supScriptSize (nsnull); nsIFrame* baseFrame = nsnull; @@ -117,36 +148,38 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, nsBoundingMetrics bmBase, bmSupScript; - nsIFrame* aChildFrame = mFrames.FirstChild(); - while (nsnull != aChildFrame) - { + nsIFrame* aChildFrame = nsnull; + aFrame->FirstChild(aPresContext, nsnull, &aChildFrame); + while (nsnull != aChildFrame) { if (!IsOnlyWhitespace(aChildFrame)) { if (0 == count) { - // base - baseFrame = aChildFrame; + // base + baseFrame = aChildFrame; GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); } else if (1 == count) { - // superscript - supScriptFrame = aChildFrame; + // superscript + supScriptFrame = aChildFrame; GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); - // get the supdrop from the supscript font - nscoord aSupDrop; - GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); - // parameter u, Rule 18a, App. G, TeXbook - minSupScriptShift = bmBase.ascent - aSupDrop; + // get the supdrop from the supscript font + nscoord aSupDrop; + GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); + // parameter u, Rule 18a, App. G, TeXbook + minSupScriptShift = bmBase.ascent - aSupDrop; } count++; } - rv = aChildFrame->GetNextSibling(&aChildFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + aChildFrame->GetNextSibling(&aChildFrame); } #ifdef NS_DEBUG - if (2 != count) printf("msup: invalid markup"); + if (2 != count) printf("msup: invalid markup\n"); #endif if ((2 != count) || !baseFrame || !supScriptFrame) { // report an error, encourage people to get their markups in order - return ReflowError(aPresContext, aRenderingContext, aDesiredSize); + return NS_STATIC_CAST(nsMathMLContainerFrame*, + aFrame)->ReflowError(aPresContext, + aRenderingContext, + aDesiredSize); } ////////////////// @@ -158,7 +191,7 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, nsCOMPtr fm; // const nsStyleFont* aFont = -// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); +// (const nsStyleFont*) aStyleContext->GetStyleData (eStyleStruct_Font); const nsStyleFont *aFont; baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont); @@ -167,6 +200,8 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, fm->GetXHeight (xHeight); nscoord minShiftFromXHeight = (nscoord) (bmSupScript.descent + (1.0f/4.0f) * xHeight); + nscoord italicCorrection; + GetItalicCorrection(bmBase, italicCorrection); // aSupScriptShift{1,2,3} // = minimum amount to shift the supscript up @@ -178,12 +213,12 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, // Set aSupScriptShift{1,2,3} default from font GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3); - if (0 < mSupScriptShift) { + if (0 < aUserSupScriptShift) { // the user has set the superscriptshift attribute float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1; float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1; aSupScriptShift1 = - PR_MAX(aSupScriptShift1, mSupScriptShift); + PR_MAX(aSupScriptShift1, aUserSupScriptShift); aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1); aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1); } @@ -191,13 +226,15 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord aSupScriptShift; - if ( mPresentationData.scriptLevel == 0 && - NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && - !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { + nsPresentationData presentationData; + mathMLFrame->GetPresentationData (presentationData); + if ( presentationData.scriptLevel == 0 && + NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) && + !NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style D in TeXbook aSupScriptShift = aSupScriptShift1; } - else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { + else if (NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' aSupScriptShift = aSupScriptShift3; } @@ -212,14 +249,18 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, PR_MAX(minSupScriptShift,PR_MAX(aSupScriptShift,minShiftFromXHeight)); // bounding box - mBoundingMetrics.ascent = + nsBoundingMetrics boundingMetrics; + boundingMetrics.ascent = PR_MAX(bmBase.ascent, (bmSupScript.ascent + actualSupScriptShift)); - mBoundingMetrics.descent = + boundingMetrics.descent = PR_MAX(bmBase.descent, (bmSupScript.descent - actualSupScriptShift)); - // add mScriptSpace between base and supscript - mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSupScript.width; - mBoundingMetrics.leftBearing = bmBase.leftBearing; - mBoundingMetrics.rightBearing = bmBase.width + mScriptSpace + bmSupScript.rightBearing; + // add scriptSpace between base and supscript + boundingMetrics.width = bmBase.width + aScriptSpace + + italicCorrection + bmSupScript.width; + boundingMetrics.leftBearing = bmBase.leftBearing; + boundingMetrics.rightBearing = bmBase.width + aScriptSpace + + italicCorrection + bmSupScript.rightBearing; + mathMLFrame->SetBoundingMetrics(boundingMetrics); // reflow metrics aDesiredSize.ascent = @@ -227,10 +268,10 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, aDesiredSize.descent = PR_MAX(baseSize.descent, (supScriptSize.descent - actualSupScriptShift)); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width; + aDesiredSize.width = bmBase.width + aScriptSpace + + italicCorrection + supScriptSize.width; - mReference.x = 0; - mReference.y = aDesiredSize.ascent; + mathMLFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); if (aPlaceOrigin) { nscoord dx, dy; @@ -238,7 +279,7 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); // ... and supscript - dx = baseSize.width + mScriptSpace; + dx = bmBase.width + aScriptSpace + italicCorrection; dy = aDesiredSize.ascent - (supScriptSize.ascent + actualSupScriptShift); FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0); } diff --git a/layout/mathml/base/src/nsMathMLmsupFrame.h b/layout/mathml/base/src/nsMathMLmsupFrame.h index c9170ccd08dc..6815897add58 100644 --- a/layout/mathml/base/src/nsMathMLmsupFrame.h +++ b/layout/mathml/base/src/nsMathMLmsupFrame.h @@ -48,6 +48,15 @@ public: PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize); + static nsresult + PlaceSuperScript (nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aPlaceOrigin, + nsHTMLReflowMetrics& aDesiredSize, + nsIFrame* aForFrame, + nscoord aUserSupScriptShift = 0, + nscoord aScriptSpace = NSFloatPointsToTwips(0.5f)); + NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, @@ -55,7 +64,14 @@ public: { nsresult rv; rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE, PR_FALSE); + // 1. The REC says: + // The element increments scriptlevel by 1, and sets displaystyle to + // "false", within superscript, but leaves both attributes unchanged within base. + // 2. The TeXbook (Ch 17. p.141) says the superscript *inherits* the compression, + // so we don't set the compression flag. Our parent will propagate its own. + UpdatePresentationDataFromChildAt(1, -1, 1, + ~NS_MATHML_DISPLAYSTYLE, + NS_MATHML_DISPLAYSTYLE); // switch the style of the superscript InsertScriptLevelStyleContext(aPresContext); // check whether or not this is an embellished operator diff --git a/layout/mathml/base/src/nsMathMLmunderFrame.cpp b/layout/mathml/base/src/nsMathMLmunderFrame.cpp index 3c8c7013f096..aec4adf17f41 100644 --- a/layout/mathml/base/src/nsMathMLmunderFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderFrame.cpp @@ -40,6 +40,7 @@ #include "nsStyleUtil.h" #include "nsMathMLmunderFrame.h" +#include "nsMathMLmsubFrame.h" // // -- attach an underscript to a base - implementation @@ -184,18 +185,23 @@ XXX The winner is the outermost setting in conflicting settings like these: } } - //The REC says: + /* The REC says: + Within underscript, always sets displaystyle to "false", + but increments scriptlevel by 1 only when accentunder is "false". + */ /* - Within underscript, always sets displaystyle to "false", - but increments scriptlevel by 1 only when accentunder is "false". + The TeXBook treats 'under' like a subscript, so p.141 or Rule 13a + say it should be compressed */ - - PRInt32 incrementScriptLevel; - if (underscriptMathMLFrame) { - incrementScriptLevel = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; - underscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE, PR_FALSE); - underscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE, PR_FALSE); + PRInt32 increment; + increment = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; + underscriptMathMLFrame->UpdatePresentationData(increment, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); + underscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, -1, increment, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); } // switch the style of the underscript @@ -213,13 +219,13 @@ The REC says: the accentunder attribute is ignored. This is often used for limits on symbols such as ∑. -TODO: +i.e.,: if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like subscript } else { - // place like accentunder + // place like underscript } */ @@ -231,6 +237,16 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, { nsresult rv = NS_OK; + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + // place like subscript + return nsMathMLmsubFrame::PlaceSubScript(aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this); + } + //////////////////////////////////// // Get the children's desired sizes @@ -290,7 +306,7 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, nscoord delta2 = 0; // extra space beneath underscript if (!NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)) { // Rule 13a, App. G, TeXbook -// GetItalicCorrectionFromChild (baseFrame, italicCorrection); + GetItalicCorrection (bmBase, italicCorrection); nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy; GetBigOpSpacings (fm, dummy, bigOpSpacing2, @@ -321,9 +337,13 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, nscoord dxUnder = (mBoundingMetrics.width - (bmUnder.width + italicCorrection/2)) / 2; aDesiredSize.ascent = baseSize.ascent; - aDesiredSize.descent = mBoundingMetrics.descent + delta2; + aDesiredSize.descent = + PR_MAX(mBoundingMetrics.descent + delta2, + bmBase.descent + delta1 + bmUnder.ascent + underSize.descent); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.width = mBoundingMetrics.width; + aDesiredSize.width = + PR_MAX(baseSize.width/2,(underSize.width + italicCorrection/2)/2) + + PR_MAX(baseSize.width/2,(underSize.width - italicCorrection/2)/2); mReference.x = 0; mReference.y = aDesiredSize.ascent; diff --git a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp index 1811d9f24171..5c2fbf5325e5 100644 --- a/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp +++ b/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp @@ -40,6 +40,7 @@ #include "nsStyleUtil.h" #include "nsMathMLmunderoverFrame.h" +#include "nsMathMLmsubsupFrame.h" // // -- attach an underscript-overscript pair to a base - implementation @@ -79,6 +80,9 @@ nsMathMLmunderoverFrame::Init(nsIPresContext* aPresContext, mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY; +#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX) + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; +#endif return rv; } @@ -218,21 +222,40 @@ nsMathMLmunderoverFrame::SetInitialChildList(nsIPresContext* aPresContext, but increments scriptlevel by 1 only when accent is "false". */ - PRInt32 incrementScriptLevel; - - if (underscriptMathMLFrame) { - incrementScriptLevel = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; - underscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE, PR_FALSE); - underscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE, PR_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. + */ if (overscriptMathMLFrame) { - incrementScriptLevel = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)? 0 : 1; - overscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE, PR_FALSE); - overscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE, PR_FALSE); + PRInt32 increment = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) + ? 0 : 1; + PRUint32 compress = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags) + ? NS_MATHML_COMPRESSED : 0; + overscriptMathMLFrame->UpdatePresentationData(increment, + ~NS_MATHML_DISPLAYSTYLE | compress, + NS_MATHML_DISPLAYSTYLE | compress); + overscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, -1, 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 + */ + if (underscriptMathMLFrame) { + PRInt32 increment = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; + underscriptMathMLFrame->UpdatePresentationData(increment, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); + underscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, -1, increment, + ~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED, + NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED); + } + // switch the style of the underscript and the overscript InsertScriptLevelStyleContext(aPresContext); @@ -248,16 +271,17 @@ The REC says: the accent and accentunder attributes are ignored. This is often used for limits on symbols such as ∑. -TODO: +i.e.,: if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like subscript-superscript pair } else { - // place like accentunder-accent pair + // place like underscript-overscript pair } */ + NS_IMETHODIMP nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -266,6 +290,16 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, { nsresult rv = NS_OK; + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + // place like sub-superscript pair + return nsMathMLmsubsupFrame::PlaceSubSupScript(aPresContext, + aRenderingContext, + aPlaceOrigin, + aDesiredSize, + this); + } + //////////////////////////////////// // Get the children's desired sizes @@ -298,8 +332,7 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, } count++; } - rv = childFrame->GetNextSibling(&childFrame); - NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); + childFrame->GetNextSibling(&childFrame); } if ((3 != count) || !baseFrame || !underFrame || !overFrame) { #ifdef NS_DEBUG @@ -333,7 +366,7 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, if (!NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)) { // Rule 13a, App. G, TeXbook -// GetItalicCorrectionFromChild (baseFrame, italicCorrection); + GetItalicCorrection (bmBase, italicCorrection); nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy; GetBigOpSpacings (fm, dummy, bigOpSpacing2, @@ -353,13 +386,13 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, // empty under? if (0 == (bmUnder.ascent + bmUnder.descent)) underDelta1 = 0; - nscoord aCorrection = 0; + nscoord correction = 0; nscoord overDelta1 = 0; // gap between base and overscript nscoord overDelta2 = 0; // extra space above overscript if (!NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)) { // Rule 13a, App. G, TeXbook -// GetItalicCorrectionFromChild (baseFrame, aCorrection); + GetItalicCorrection (bmBase, italicCorrection); nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy; GetBigOpSpacings (fm, bigOpSpacing1, dummy, @@ -376,13 +409,11 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, } else { // Rule 13, App. G, TeXbook - GetSkewCorrectionFromChild (aPresContext, baseFrame, aCorrection); -#if 0 - // XXX tune these - overDelta1 = PR_MIN(bmOver.ascent,xHeight); - overDelta2 = 0; -#endif + GetSkewCorrectionFromChild (aPresContext, baseFrame, correction); overDelta1 = ruleThickness; + if (bmBase.ascent < xHeight) { + overDelta1 += xHeight - bmBase.ascent; + } overDelta2 = ruleThickness; } // empty over? @@ -393,17 +424,19 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, mBoundingMetrics.descent = bmBase.descent + underDelta1 + bmUnder.ascent + bmUnder.descent; mBoundingMetrics.width = - PR_MAX(bmBase.width/2,PR_MAX((bmUnder.width + italicCorrection/2)/2,(bmOver.width - aCorrection/2)/2)) + - PR_MAX(bmBase.width/2,PR_MAX((bmUnder.width - italicCorrection/2)/2,(bmOver.width + aCorrection/2)/2)); + PR_MAX(bmBase.width/2,PR_MAX((bmUnder.width + italicCorrection/2)/2,(bmOver.width - correction/2)/2)) + + PR_MAX(bmBase.width/2,PR_MAX((bmUnder.width - italicCorrection/2)/2,(bmOver.width + correction/2)/2)); nscoord dxBase = (mBoundingMetrics.width - bmBase.width) / 2; - nscoord dxOver = (mBoundingMetrics.width - (bmOver.width - aCorrection/2)) / 2; + nscoord dxOver = (mBoundingMetrics.width - (bmOver.width - correction/2)) / 2; nscoord dxUnder = (mBoundingMetrics.width - (bmUnder.width + italicCorrection/2)) / 2; aDesiredSize.ascent = - mBoundingMetrics.ascent + overDelta2; + PR_MAX(mBoundingMetrics.ascent + overDelta2, + overSize.ascent + bmOver.descent + overDelta1 + bmBase.ascent); aDesiredSize.descent = - mBoundingMetrics.descent + underDelta2; + PR_MAX(mBoundingMetrics.descent + underDelta2, + bmBase.descent + underDelta1 + bmUnder.ascent + underSize.descent); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; aDesiredSize.width = mBoundingMetrics.width;