From 4eb2ebeca730f13fd7b9bb583cf0747d8408c69b Mon Sep 17 00:00:00 2001 From: "rbs%maths.uq.edu.au" Date: Tue, 18 Jan 2000 04:35:37 +0000 Subject: [PATCH] [MATHML] Finally, here goes Shyjan Mahamud's TeX alignment rules. Part I: for superscript/subscript schematta git-svn-id: svn://10.0.0.236/trunk@58076 18797224-902f-48f8-a5cc-f745e15eee43 --- .../layout/mathml/base/src/nsIMathMLFrame.h | 10 +- .../layout/mathml/base/src/nsMathMLChar.cpp | 27 +- mozilla/layout/mathml/base/src/nsMathMLChar.h | 2 +- .../base/src/nsMathMLContainerFrame.cpp | 242 +++++++++++++++--- .../mathml/base/src/nsMathMLContainerFrame.h | 149 ++++++++++- .../mathml/base/src/nsMathMLmfracFrame.cpp | 6 +- .../base/src/nsMathMLmmultiscriptsFrame.cpp | 145 +++++++---- .../mathml/base/src/nsMathMLmoFrame.cpp | 27 +- .../mathml/base/src/nsMathMLmrootFrame.cpp | 6 +- .../mathml/base/src/nsMathMLmsubFrame.cpp | 80 +++--- .../mathml/base/src/nsMathMLmsubsupFrame.cpp | 89 ++++--- .../mathml/base/src/nsMathMLmsupFrame.cpp | 95 +++---- 12 files changed, 620 insertions(+), 258 deletions(-) diff --git a/mozilla/layout/mathml/base/src/nsIMathMLFrame.h b/mozilla/layout/mathml/base/src/nsIMathMLFrame.h index 966af76199f..27b64a3813c 100644 --- a/mozilla/layout/mathml/base/src/nsIMathMLFrame.h +++ b/mozilla/layout/mathml/base/src/nsIMathMLFrame.h @@ -333,6 +333,12 @@ struct nsEmbellishData { // a core ) for which the movablelimits attribute is set to true #define NS_MATHML_MOVABLELIMITS 0x00000040 +// This bit is used for visual debug. When set, the bounding box +// of your frame is painted. You should therefore ensure that you +// have properly filled your mReference and mBoundingMetrics in +// Place(). +#define NS_MATHML_SHOW_BOUNDING_METRICS 0x80000000 + // Macros that retrieve those bits #define NS_MATHML_IS_DISPLAYSTYLE(_flags) \ (NS_MATHML_DISPLAYSTYLE == ((_flags) & NS_MATHML_DISPLAYSTYLE)) @@ -355,6 +361,9 @@ struct nsEmbellishData { #define NS_MATHML_IS_MOVABLELIMITS(_flags) \ (NS_MATHML_MOVABLELIMITS == ((_flags) & NS_MATHML_MOVABLELIMITS)) +#define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \ + (NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS)) + // -------------- // Bits used for the embellish flags -- these bits are set // in their relevant situation as they become available @@ -405,4 +414,3 @@ struct nsEmbellishData { (NS_MATHML_EMBELLISH_MOVABLELIMITS == ((_flags) & NS_MATHML_EMBELLISH_MOVABLELIMITS)) #endif /* nsIMathMLFrame_h___ */ - diff --git a/mozilla/layout/mathml/base/src/nsMathMLChar.cpp b/mozilla/layout/mathml/base/src/nsMathMLChar.cpp index c8a6825e62e..57b7726a8dd 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLChar.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLChar.cpp @@ -391,8 +391,8 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, if (aContainerSize.height <= aDesiredStretchSize.height) { mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char later behaves like a normal char rv = aRenderingContext.GetBoundingMetrics(mData.GetUnicode(), - PRUint32(mData.Length()), - mBoundingMetrics); + PRUint32(mData.Length()), + mBoundingMetrics); if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", mData[0], mData[0]&0x00FF); /*getchar();*/ return rv; } return NS_OK; } @@ -467,6 +467,19 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, nscoord a, d; h = w = a = d = 0; float flex[3] = {0.7f, 0.3f, 0.7f}; // XXX hack! + + // get metrics data to be re-used later + nsBoundingMetrics bmdata[4]; + for (i = 0; i < 4; i++) { + ch = gMathMLCharGlyph[index+i]; + rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm); + if (NS_FAILED(rv)) { + printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ + return rv; + } + bmdata[i] = bm; + } + if (aDirection == NS_STRETCH_DIRECTION_VERTICAL) { // default is to fill-up the area given to us width = aDesiredStretchSize.width; @@ -475,9 +488,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, descent = aContainerSize.descent; for (i = 0; i < 4; i++) { - ch = gMathMLCharGlyph[index+i]; - rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm); - if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; } + bm = bmdata[i]; if (w < bm.width) w = bm.width; if (i < 3) { h += nscoord(flex[i]*(bm.ascent+bm.descent)); // sum heights of the parts... @@ -507,9 +518,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, descent = aDesiredStretchSize.descent; for (i = 0; i < 4; i++) { - ch = gMathMLCharGlyph[index+i]; - rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm); - if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; } + bm = bmdata[i]; if (0 == i) bm0 = bm; if (a < bm.ascent) a = bm.ascent; if (d < bm.descent) d = bm.descent; @@ -527,6 +536,8 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, // ascent = a; // height = a + d; mBoundingMetrics.width = aContainerSize.width; + mBoundingMetrics.leftBearing = 0; + mBoundingMetrics.rightBearing = aContainerSize.width; } else { // sum of parts doesn't fit in the space... will use a single glyph mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char behaves like a normal char mBoundingMetrics = bm0; diff --git a/mozilla/layout/mathml/base/src/nsMathMLChar.h b/mozilla/layout/mathml/base/src/nsMathMLChar.h index e3a7218e5e7..c657797dfb9 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLChar.h +++ b/mozilla/layout/mathml/base/src/nsMathMLChar.h @@ -115,7 +115,7 @@ public: } void - GetBoundingMetrics(nsBoundingMetrics aBoundingMetrics) { + GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) { aBoundingMetrics = mBoundingMetrics; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp index c4a47701e01..05e7517c06d 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -176,40 +176,46 @@ nsMathMLContainerFrame::SetReference(const nsPoint& aReference) return NS_OK; } -// helper methods to facilitate getting/setting the bounding metrics -nsresult -nsMathMLContainerFrame::GetBoundingMetricsFor(nsIFrame* aFrame, - nsBoundingMetrics& aBoundingMetrics) +// helper method to facilitate getting the reflow and bounding metrics +void +nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, + nsHTMLReflowMetrics& aReflowMetrics, + nsBoundingMetrics& aBoundingMetrics) { + NS_PRECONDITION(aFrame, "null arg"); + + // IMPORTANT: This function is only meant to be called in Place() methods + // where it is assumed that the frame's rect is still acting as place holder + // for the frame's ascent and descent information + + nsRect aRect; + aFrame->GetRect(aRect); + aReflowMetrics.descent = aRect.x; + aReflowMetrics.ascent = aRect.y; + aReflowMetrics.width = aRect.width; + aReflowMetrics.height = aRect.height; + aBoundingMetrics.Clear(); nsIMathMLFrame* aMathMLFrame = nsnull; nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); - if (NS_SUCCEEDED(rv) && aMathMLFrame) { + if (NS_SUCCEEDED(rv) && aMathMLFrame) { aMathMLFrame->GetBoundingMetrics(aBoundingMetrics); - return NS_OK; +#if 0 + nsFrame::ListTag(stdout, aFrame); + printf(" subItalicCorrection:%d supItalicCorrection:%d\n", + aBoundingMetrics.subItalicCorrection, aBoundingMetrics.supItalicCorrection); +#endif } - // if we reach here, aFrame is not a MathML frame, let the caller know that - printf("GetBoundingMetrics() failed for: "); /* getchar(); */ - nsFrame::ListTag(stdout, aFrame); - printf("\n"); -// NS_ASSERTION(0, "GetBoundingMetrics() failed!!"); - return NS_ERROR_FAILURE; -} - -nsresult -nsMathMLContainerFrame::SetBoundingMetricsFor(nsIFrame* aFrame, - nsBoundingMetrics& aBoundingMetrics) -{ - nsIMathMLFrame* aMathMLFrame = nsnull; - nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); - if (NS_SUCCEEDED(rv) && aMathMLFrame) { - aMathMLFrame->SetBoundingMetrics(aBoundingMetrics); - return NS_OK; + else { // aFrame is not a MathML frame, just return the reflow metrics + aBoundingMetrics.descent = aReflowMetrics.descent; + aBoundingMetrics.ascent = aReflowMetrics.ascent; + aBoundingMetrics.width = aReflowMetrics.width; +#if 0 + printf("GetBoundingMetrics() failed for: "); /* getchar(); */ + nsFrame::ListTag(stdout, aFrame); + printf("\n"); +#endif } - // if we reach here, aFrame is not a MathML frame, let the caller know that - printf("SetBoundingMetrics() failed!! ...\n"); /* getchar(); */ -// NS_ASSERTION(0, "SetBoundingMetrics() failed!!"); - return NS_ERROR_FAILURE; } /* ///////////// @@ -514,6 +520,29 @@ nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(PRInt32 aIndex, return NS_OK; } +PRInt32 +nsMathMLContainerFrame::FindSmallestFontSizeFor(nsIFrame* aFrame) +{ + nsStyleFont aFont; + nsCOMPtr aStyleContext; + aFrame->GetStyleContext(getter_AddRefs(aStyleContext)); + aStyleContext->GetStyle(eStyleStruct_Font, aFont); +// PRInt32 fontSize = NSTwipsToFloorIntPoints(aFont.mFont.size); + PRInt32 fontSize = aFont.mFont.size; + + PRInt32 childSize; + nsIFrame* childFrame; + aFrame->FirstChild(nsnull, &childFrame); + while (nsnull != childFrame) { + if (!IsOnlyWhitespace(childFrame)) { + childSize = FindSmallestFontSizeFor(childFrame); + if (fontSize > childSize) fontSize = childSize; + } + childFrame->GetNextSibling(&childFrame); + } + return fontSize; +} + // helper method to alter the style context // This method is used for switching the font to a subscript/superscript font in // mfrac, msub, msup, msubsup, munder, mover, munderover, mmultiscripts @@ -544,6 +573,71 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte PRInt32 gap = childData.scriptLevel - mPresentationData.scriptLevel; if (0 != gap) { + // We are about to change the font-size... We first see if we + // are in the scope of a that tells us what to do. + // This is one of the most obscure part to implement in the spec... + /* + The REC says: + + Whenever the scriptlevel is changed, either automatically or by being + explicitly incremented, decremented, or set, the current font size is + multiplied by the value of scriptsizemultiplier to the power of the + change in scriptlevel. For example, if scriptlevel is increased by 2, + the font size is multiplied by scriptsizemultiplier twice in succession; + if scriptlevel is explicitly set to 2 when it had been 3, the font size + is divided by scriptsizemultiplier. + + The default value of scriptsizemultiplier is less than one (in fact, it + is approximately the square root of 1/2), resulting in a smaller font size + with increasing scriptlevel. To prevent scripts from becoming unreadably + small, the font size is never allowed to go below the value of + scriptminsize as a result of a change to scriptlevel, though it can be + set to a lower value using the fontsize attribute on or on + token elements. If a change to scriptlevel would cause the font size to + become lower than scriptminsize using the above formula, the font size + is instead set equal to scriptminsize within the subexpression for which + scriptlevel was changed. + + In the syntax for scriptminsize, v-unit represents a unit of vertical + length. The most common unit for specifying font sizes in typesetting + is pt (points). + */ + + // default scriptsizemultiplier = 0.71 + // default scriptminsize = 8pt + + // here we only consider scriptminsize, and use the default + // smaller-font-size algorithm of the style system + PRInt32 scriptminsize = NSIntPointsToTwips(8); + + // see if the scriptminsize attribute is on that wraps us + nsAutoString value; + nsIFrame* mstyleFrame = mPresentationData.mstyle; + if (mstyleFrame) { + nsCOMPtr mstyleContent; + mstyleFrame->GetContent(getter_AddRefs(mstyleContent)); + if (NS_CONTENT_ATTR_HAS_VALUE == mstyleContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::scriptminsize_, value)) + { + PRInt32 errorCode; + PRInt32 userValue = value.ToInteger(&errorCode); + if (NS_SUCCEEDED(errorCode)) { + // assume unit is point + // XXX need consistent, default unit throughout the code + scriptminsize = NSIntPointsToTwips(userValue); + } + else { + // XXX TODO: try to see if it is a h/v-unit like 1ex, 2px, 1em + } + } + } + + // get Nav's magic font scaler + PRInt32 scaler; + aPresContext->GetFontScaler(&scaler); + float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); + const nsFont& defaultFont = aPresContext->GetDefaultFontDeprecated(); + nsCOMPtr childContent; childFrame->GetContent(getter_AddRefs(childContent)); @@ -555,13 +649,37 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte nsIStyleContext* lastStyleContext = mStyleContext; nsCOMPtr newStyleContext; + // XXX seems not to decrease when the initail font-size is large (100pt) nsAutoString fontSize = (0 < gap) ? ":-moz-math-font-size-smaller" : ":-moz-math-font-size-larger"; nsCOMPtr fontAtom(getter_AddRefs(NS_NewAtom(fontSize))); - if (0 > gap) gap = -gap; // absolute value + + PRBool isSmaller = PR_TRUE; + if (0 > gap) { isSmaller = PR_FALSE; gap = -gap; } // absolute value + + PRInt32 smallestFontSize, smallestFontIndex; + if (isSmaller) { + // find the smallest font-size in this subtree + smallestFontSize = FindSmallestFontSizeFor(childFrame); + } + while (0 < gap--) { + if (isSmaller) { + // look ahead for the next smallest font size that will be in the subtree + smallestFontIndex = nsStyleUtil::FindNextSmallerFontSize(smallestFontSize, (PRInt32)defaultFont.size, scaleFactor); + smallestFontSize = nsStyleUtil::CalcFontPointSize(smallestFontIndex, (PRInt32)defaultFont.size, scaleFactor); +//printf("About to move to fontsize:%dpt(%dtwips)\n", +//NSTwipsToFloorIntPoints(smallestFontSize), smallestFontSize); + if (smallestFontSize < scriptminsize) { + // don't bother doing any work +//printf("..... stopping ......\n"); +// XXX there should be a mechanism so that we never try this subtree again + break; + } + } + aPresContext->ResolvePseudoStyleContextFor(childContent, fontAtom, lastStyleContext, PR_FALSE, getter_AddRefs(newStyleContext)); if (newStyleContext && newStyleContext.get() != lastStyleContext) { @@ -620,7 +738,43 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte * Frame construction * ============================================================================= */ - + +NS_IMETHODIMP +nsMathMLContainerFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + nsresult rv = NS_OK; + + rv = nsHTMLContainerFrame::Paint(aPresContext, + aRenderingContext, + aDirtyRect, + aWhichLayer); +#ifdef SHOW_BOUNDING_BOX + // for visual debug + // ---------------- + // if you want to see your bounding box, make sure to properly fill + // your mBoundingMetrics and mReference point, and set + // mPresentationData.flags |= NS_MATHML_BOUNDING_METRICS + // in the Init() of your sub-class + + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && + NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) + { + aRenderingContext.SetColor(NS_RGB(0,0,255)); + + nscoord x = mReference.x + mBoundingMetrics.leftBearing; + nscoord y = mReference.y; + nscoord w = mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing; + nscoord h = mBoundingMetrics.ascent + mBoundingMetrics.descent; + + aRenderingContext.DrawRect(x,y,w,h); + } +#endif + return rv; +} + NS_IMETHODIMP nsMathMLContainerFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -847,7 +1001,7 @@ nsMathMLContainerFrame::ReflowTokenFor(nsIFrame* aFrame, // helper function to place token elements // mBoundingMetrics is computed at the ReflowToken pass, it is -// not computed here because if our children may be text frames that +// not computed here because our children may be text frames that // do not implement the GetBoundingMetrics() interface. nsresult nsMathMLContainerFrame::PlaceTokenFor(nsIFrame* aFrame, @@ -893,6 +1047,11 @@ nsMathMLContainerFrame::PlaceTokenFor(nsIFrame* aFrame, childFrame->GetNextSibling(&childFrame); } } + nsBoundingMetrics bm; + NS_STATIC_CAST(nsMathMLContainerFrame*, + aFrame)->GetBoundingMetrics(bm); + NS_STATIC_CAST(nsMathMLContainerFrame*, + aFrame)->SetReference(nsPoint(0,aDesiredSize.ascent-bm.ascent)); return NS_OK; } @@ -1087,23 +1246,18 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext, aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0; PRInt32 count = 0; - nsRect rect; + nsBoundingMetrics bm; + nsHTMLReflowMetrics childSize(nsnull); nsIFrame* childFrame = mFrames.FirstChild(); while (childFrame) { if (!IsOnlyWhitespace(childFrame)) { - childFrame->GetRect(rect); + GetReflowAndBoundingMetricsFor(childFrame, childSize, bm); - aDesiredSize.width += rect.width; - if (aDesiredSize.descent < rect.x) aDesiredSize.descent = rect.x; - if (aDesiredSize.ascent < rect.y) aDesiredSize.ascent = rect.y; + aDesiredSize.width += childSize.width; + if (aDesiredSize.descent < childSize.descent) aDesiredSize.descent = childSize.descent; + if (aDesiredSize.ascent < childSize.ascent) aDesiredSize.ascent = childSize.ascent; // Compute and cache our bounding metrics - nsBoundingMetrics bm; - if (NS_FAILED(GetBoundingMetricsFor(childFrame, bm))) { - bm.ascent = rect.y; - bm.descent = -rect.x; - bm.width = rect.width; - } if (0 == count) mBoundingMetrics = bm; else @@ -1116,13 +1270,14 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext, aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; if (aPlaceOrigin) { + nsRect rect; + nscoord dy; nscoord dx = 0; childFrame = mFrames.FirstChild(); while (childFrame) { childFrame->GetRect(rect); - nsHTMLReflowMetrics childSize(nsnull); childSize.width = rect.width; childSize.height = rect.height; @@ -1134,6 +1289,9 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext, childFrame->GetNextSibling(&childFrame); } } + + mReference.x = 0; + mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent; return NS_OK; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h index 85271b28c4a..ba5ae202849 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -154,6 +154,12 @@ public: return nsHTMLContainerFrame::DidReflow(aPresContext, aStatus); } + NS_IMETHOD + Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + // helper function to reflow token elements static nsresult ReflowTokenFor(nsIFrame* aFrame, @@ -223,6 +229,12 @@ public: NS_IMETHOD InsertScriptLevelStyleContext(nsIPresContext* aPresContext); + // helper to find the smallest font-size on a tree so that we don't insert + // scriptlevel fonts that lead to unreadable results on deeper nodes below us. + // XXX expensive recursive function, need something better, with cache + static PRInt32 + FindSmallestFontSizeFor(nsIFrame* aFrame); + // helper to check if a frame is an embellished container static PRBool IsEmbellishOperator(nsIFrame* aFrame); @@ -230,19 +242,19 @@ public: // helper methods for processing empty MathML frames (with whitespace only) static PRBool IsOnlyWhitespace(nsIFrame* aFrame); - + static void ReflowEmptyChild(nsIPresContext* aPresContext, nsIFrame* aFrame); - // helper methods to facilitate getting/setting the bounding metrics - static nsresult - GetBoundingMetricsFor(nsIFrame* aFrame, - nsBoundingMetrics& aBoundingMetrics); - - static nsresult - SetBoundingMetricsFor(nsIFrame* aFrame, - nsBoundingMetrics& aBoundingMetrics); + // helper method to facilitate getting the reflow and bounding metrics + // IMPORTANT: This function is only meant to be called in Place() methods + // where it is assumed that the frame's rect is still acting as place holder + // for the frame's ascent and descent information + static void + GetReflowAndBoundingMetricsFor(nsIFrame* aFrame, + nsHTMLReflowMetrics& aReflowMetrics, + nsBoundingMetrics& aBoundingMetrics); // helper methods for getting sup/subdrop's from a child static void @@ -297,6 +309,7 @@ public: } // these are TeX specific params not found in ordinary fonts +#if 0 static void GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop) { @@ -312,6 +325,124 @@ public: fm->GetXHeight (xHeight); aSupDrop = NSToCoordRound(0.3f * xHeight); } +#endif + + static void + GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop) + { + nscoord xHeight; + fm->GetXHeight (xHeight); + aSubDrop = NSToCoordRound(50.000f/430.556f * xHeight); + } + + static void + GetSupDrop (nsIFontMetrics *fm, nscoord& aSupDrop) + { + nscoord xHeight; + fm->GetXHeight (xHeight); + aSupDrop = NSToCoordRound(386.108f/430.556f * xHeight); + } + + static void + GetSubShifts (nsIFontMetrics *fm, + nscoord& aSubShift1, + nscoord& aSubShift2) + { + nscoord xHeight = 0; + fm->GetXHeight (xHeight); + aSubShift1 = NSToCoordRound (150.000f/430.556f * xHeight); + aSubShift2 = NSToCoordRound (247.217f/430.556f * xHeight); + } + + static void + GetSupShifts (nsIFontMetrics *fm, + nscoord& aSupShift1, + nscoord& aSupShift2, + nscoord& aSupShift3) + { + nscoord xHeight = 0; + fm->GetXHeight (xHeight); + aSupShift1 = NSToCoordRound (412.892f/430.556f * xHeight); + aSupShift2 = NSToCoordRound (362.892f/430.556f * xHeight); + aSupShift3 = NSToCoordRound (288.889f/430.556f * xHeight); + } + + static void + GetNumShifts (nsIFontMetrics *fm, + nscoord& numShift1, + nscoord& numShift2, + nscoord& numShift3) + { + nscoord xHeight = 0; + fm->GetXHeight (xHeight); + numShift1 = NSToCoordRound (676.508f/430.556f * xHeight); + numShift2 = NSToCoordRound (393.732f/430.556f * xHeight); + numShift3 = NSToCoordRound (443.731f/430.556f * xHeight); + } + + static void + GetDenShifts (nsIFontMetrics *fm, + nscoord& denShift1, + nscoord& denShift2) + { + nscoord xHeight = 0; + fm->GetXHeight (xHeight); + denShift1 = NSToCoordRound (685.951f/430.556f * xHeight); + denShift2 = NSToCoordRound (344.841f/430.556f * xHeight); + } + + static void + GetAxisHeight (nsIFontMetrics *fm, + nscoord& axisHeight) + { + fm->GetXHeight (axisHeight); + axisHeight = NSToCoordRound (250.000f/430.556f * axisHeight); + } + + static void + GetBigOpSpacings (nsIFontMetrics *fm, + nscoord& bigOpSpacing1, + nscoord& bigOpSpacing2, + nscoord& bigOpSpacing3, + nscoord& bigOpSpacing4, + nscoord& bigOpSpacing5) + { + nscoord xHeight = 0; + fm->GetXHeight (xHeight); + bigOpSpacing1 = NSToCoordRound (111.111f/430.556f * xHeight); + bigOpSpacing2 = NSToCoordRound (166.667f/430.556f * xHeight); + bigOpSpacing3 = NSToCoordRound (200.000f/430.556f * xHeight); + bigOpSpacing4 = NSToCoordRound (600.000f/430.556f * xHeight); + bigOpSpacing5 = NSToCoordRound (100.000f/430.556f * xHeight); + } + +#if 0 + NS_IMETHOD + GetItalicCorrection (nscoord& italicCorrection) + { + italicCorrection = mItalicCorrection; + + return NS_OK; + } + + NS_IMETHOD + SetItalicCorrection (nscoord italicCorrection) + { + mItalicCorrection = italicCorrection; + + return NS_OK; + } +#endif + + NS_IMETHOD + GetRuleThickness (nsIFontMetrics *fm, nscoord& ruleThickness) + { + nscoord xHeight; + fm->GetXHeight (xHeight); + ruleThickness = NSToCoordRound (40.000f/430.556f * xHeight); + + return NS_OK; + } protected: diff --git a/mozilla/layout/mathml/base/src/nsMathMLmfracFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmfracFrame.cpp index f795eb9f7ab..2a408e524b9 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmfracFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmfracFrame.cpp @@ -257,9 +257,9 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; // XXX Fix me! - mBoundingMetrics.ascent = aDesiredSize.ascent; - mBoundingMetrics.descent = -aDesiredSize.descent; - mBoundingMetrics.width = aDesiredSize.width; + mBoundingMetrics.ascent = aDesiredSize.ascent; + mBoundingMetrics.descent = aDesiredSize.descent; + mBoundingMetrics.width = aDesiredSize.width; return NS_OK; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp index 6698a47697f..cae62ff08e9 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp @@ -104,6 +104,7 @@ nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext, } } + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; return rv; } @@ -118,7 +119,6 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, //////////////////////////////////// // Get the children's desired sizes - nscoord italicCorrection = 0; nscoord minShiftFromXHeight, aSubDrop, aSupDrop; //////////////////////////////////////// @@ -134,9 +134,9 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm)); fm->GetXHeight (xHeight); - nscoord aRuleSize, dummy; + nscoord aRuleSize = 0; // XXX need to do update this ... - fm->GetStrikeout (dummy, aRuleSize); + GetRuleThickness (fm, aRuleSize); ///////////////////////////////////// // first the shift for the subscript @@ -201,7 +201,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, // Get the children's sizes //////////////////////////////////// - nscoord width = 0; + nscoord width = 0, prescriptsWidth = 0, rightBearing = 0; nsIFrame* mprescriptsFrame = nsnull; // frame of , if there. PRBool isSubScript = PR_FALSE; PRBool isSubScriptPresent = PR_TRUE; @@ -212,7 +212,6 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, nscoord maxSubScriptShift = aSubScriptShift; nscoord maxSupScriptShift = aSupScriptShift; PRInt32 count = 0; - nsRect aRect; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics subScriptSize (nsnull); nsHTMLReflowMetrics supScriptSize (nsnull); @@ -220,8 +219,14 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, nsIFrame* subScriptFrame; nsIFrame* supScriptFrame; + PRBool firstPrescriptsPair = PR_FALSE; + nsBoundingMetrics bmBase, bmSubScript, bmSupScript; + // XXX is there an NSPR macro for int_max ??? - aDesiredSize.ascent = aDesiredSize.descent = -100000; + mBoundingMetrics.ascent = mBoundingMetrics.descent = -10000000; + mBoundingMetrics.width = 0; + + aDesiredSize.ascent = aDesiredSize.descent = -10000000; aDesiredSize.width = aDesiredSize.height = 0; nsIFrame* aChildFrame = mFrames.FirstChild(); @@ -235,32 +240,36 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, if (childTag.get() == nsMathMLAtoms::mprescripts_) { mprescriptsFrame = aChildFrame; + firstPrescriptsPair = PR_TRUE; } 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; + bmSubScript.Clear(); + bmSubScript.leftBearing = 10000000; } else { isSupScriptPresent = PR_FALSE; + bmSupScript.Clear(); + bmSupScript.leftBearing = 10000000; } - aRect = nsRect (0, 0, 0, 0); - } - else { - aChildFrame->GetRect(aRect); } + if (0 == count) { // base baseFrame = aChildFrame; - baseSize.descent = aRect.x; baseSize.ascent = aRect.y; - baseSize.width = aRect.width; - baseSize.height = aRect.height; - // we update aDesiredSize.{ascent,descent} with that + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); + + // we update mBoundingMetrics.{ascent,descent} with that // of the baseFrame only after processing all the sup/sub pairs - // XXX need italic correction here - aDesiredSize.width = aRect.width + italicCorrection; + // XXX need italic correction only *if* there are postscripts ? + mBoundingMetrics.width = bmBase.width + bmBase.supItalicCorrection; + mBoundingMetrics.rightBearing = bmBase.rightBearing; + mBoundingMetrics.leftBearing = bmBase.leftBearing; // until overwritten } else { // super/subscript block @@ -268,54 +277,66 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, if (isSubScriptPresent) { // subscript subScriptFrame = aChildFrame; - subScriptSize.descent = aRect.x; - subScriptSize.ascent = aRect.y; - subScriptSize.width = aRect.width; - subScriptSize.height = aRect.height; + GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); // get the subdrop from the subscript font GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop); // parameter v, Rule 18a, App. G, TeXbook - minSubScriptShift = baseSize.descent + aSubDrop; + 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 = subScriptSize.width + mScriptSpace; + PR_MAX(aDesiredSize.descent,subScriptSize.ascent); + width = bmSubScript.width + mScriptSpace; + rightBearing = bmSubScript.rightBearing + mScriptSpace; } } else { if (isSupScriptPresent) { // supscript supScriptFrame = aChildFrame; - supScriptSize.descent = aRect.x; - supScriptSize.ascent = aRect.y; - supScriptSize.width = aRect.width; - supScriptSize.height = aRect.height; + GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); // get the supdrop from the supscript font GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); // parameter u, Rule 18a, App. G, TeXbook - minSupScriptShift = baseSize.ascent - aSupDrop; + 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 - ((supScriptSize.descent + (1.0f/4.0f) * xHeight)); + ((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, supScriptSize.width + mScriptSpace); + width = PR_MAX(width, bmSupScript.width + mScriptSpace); + rightBearing = PR_MAX(rightBearing, bmSupScript.rightBearing + mScriptSpace); } NS_ASSERTION((isSubScriptPresent || isSupScriptPresent),"mmultiscripts : both sup/subscripts are absent"); - aDesiredSize.width += width; - width = 0; - + + if (!mprescriptsFrame) { // we are still looping over base & postscripts + mBoundingMetrics.rightBearing = mBoundingMetrics.width + rightBearing; + mBoundingMetrics.width += width; + } + else { + prescriptsWidth += width; + if (firstPrescriptsPair) { + firstPrescriptsPair = PR_FALSE; + mBoundingMetrics.leftBearing = + PR_MIN(bmSubScript.leftBearing, bmSupScript.leftBearing); + } + } + width = rightBearing = 0; + 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 - supScriptSize.descent) - - (subScriptSize.ascent - trySubScriptShift); + (trySupScriptShift - bmSupScript.descent) - + (bmSubScript.ascent - trySubScriptShift); if (gap < 4.0f * aRuleSize) { // adjust trySubScriptShift to get a gap of (4.0 * aRuleSize) trySubScriptShift += NSToCoordRound ((4.0f * aRuleSize) - gap); @@ -324,7 +345,7 @@ nsMathMLmmultiscriptsFrame::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 - - (trySupScriptShift - supScriptSize.descent)); + (trySupScriptShift - bmSupScript.descent)); if (gap > 0.0f) { trySupScriptShift += gap; trySubScriptShift -= gap; @@ -348,13 +369,28 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, rv = aChildFrame->GetNextSibling(&aChildFrame); NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); } - // we left out base during our bounding box updates, so ... + + // we left out the width of prescripts, so ... + mBoundingMetrics.rightBearing += prescriptsWidth; + mBoundingMetrics.width += prescriptsWidth; + + // we left out the base during our bounding box updates, so ... + mBoundingMetrics.ascent = + PR_MAX(mBoundingMetrics.ascent+maxSupScriptShift,bmBase.ascent); + mBoundingMetrics.descent = + PR_MAX(mBoundingMetrics.descent+maxSubScriptShift,bmBase.descent); + + // get the reflow metrics ... aDesiredSize.ascent = PR_MAX(aDesiredSize.ascent+maxSupScriptShift,baseSize.ascent); aDesiredSize.descent = PR_MAX(aDesiredSize.descent+maxSubScriptShift,baseSize.descent); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - + aDesiredSize.width = mBoundingMetrics.width; + + mReference.x = 0; + mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent; + ////////////////// // Place Children @@ -364,6 +400,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, if (aPlaceOrigin) { nscoord dx = 0, dy = 0; + nsRect aRect; count = 0; aChildFrame = mprescriptsFrame; @@ -371,9 +408,10 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, if (nsnull == aChildFrame) { // end of prescripts, // place the base ... aChildFrame = baseFrame; - dy = aDesiredSize.ascent - baseSize.ascent; - FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); - dx += baseSize.width + italicCorrection; +// dy = mBoundingMetrics.ascent - bmBase.ascent; + dy = aDesiredSize.ascent - baseSize.ascent; + FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); + dx += baseSize.width + bmBase.supItalicCorrection; } else if (mprescriptsFrame != aChildFrame) { // process each sup/sub pair @@ -386,7 +424,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, supScriptFrame = aChildFrame; count = 0; - // get the bounding boxes of sup/subscripts stored in their rects + // get the ascent/descent of sup/subscripts stored in their rects // rect.x = descent, rect.y = ascent subScriptFrame->GetRect (aRect); subScriptSize.ascent = aRect.y; @@ -401,25 +439,30 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, // XXX should we really center the boxes // XXX i'm leaving it as left-justified // XXX which is consistent with what's done for + + // reverting to center. It looks much nicer and adds a bit + // of variety to the engine. At least we have two functions + // doing two different things. + + width = PR_MAX(subScriptSize.width, supScriptSize.width); + dy = aDesiredSize.ascent - subScriptSize.ascent + maxSubScriptShift; - FinishReflowChild (subScriptFrame, aPresContext, - subScriptSize, dx, dy, 0); + FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, + dx + (width-subScriptSize.width)/2, dy, 0); dy = aDesiredSize.ascent - supScriptSize.ascent - maxSupScriptShift; - FinishReflowChild (supScriptFrame, aPresContext, - supScriptSize, dx, dy, 0); + FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, + dx + (width-supScriptSize.width)/2, dy, 0); - width = mScriptSpace + - PR_MAX(subScriptSize.width, supScriptSize.width); - dx += width; - } + dx += mScriptSpace + width; + } } } - + rv = aChildFrame->GetNextSibling(&aChildFrame); NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child"); } while (mprescriptsFrame != aChildFrame); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp index d298207afc8..b05b4543508 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp @@ -119,6 +119,19 @@ nsMathMLmoFrame::Paint(nsIPresContext* aPresContext, rv = mMathMLChar.Paint(aPresContext, aRenderingContext, mStyleContext); +#ifdef SHOW_BOUNDING_BOX + // for visual debug + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && + NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags)) + { + aRenderingContext.SetColor(NS_RGB(0,0,255)); + nscoord x = mReference.x + mBoundingMetrics.leftBearing; + nscoord y = mReference.y; + nscoord w = mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing; + nscoord h = mBoundingMetrics.ascent + mBoundingMetrics.descent; + aRenderingContext.DrawRect(x,y,w,h); + } +#endif } else { // let the base class worry about the painting rv = nsMathMLContainerFrame::Paint(aPresContext, @@ -144,6 +157,7 @@ nsMathMLmoFrame::Init(nsIPresContext* aPresContext, mLeftSpace = 0.0f; // .27777f; mRightSpace = 0.0f; // .27777f; + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; return rv; } @@ -487,10 +501,6 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, if (old == aDesiredStretchSize) { // hasn't changed ! mFlags &= ~NS_MATHML_OPERATOR_MUTABLE; } - else { - // update our bounding metrics... it becomes that of our MathML char - mMathMLChar.GetBoundingMetrics(mBoundingMetrics); - } } ///////// @@ -499,7 +509,9 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) { // The rendering will be handled by our MathML char mMathMLChar.SetRect(nsRect(0, 0, aDesiredStretchSize.width, - aDesiredStretchSize.height)); + aDesiredStretchSize.height)); + // update our bounding metrics... it becomes that of our MathML char + mMathMLChar.GetBoundingMetrics(mBoundingMetrics); } else { nsHTMLReflowMetrics aReflowMetrics(nsnull); @@ -514,6 +526,9 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, aDesiredStretchSize.leftSpace = mLeftSpace; aDesiredStretchSize.rightSpace = mRightSpace; + mReference.x = 0; + mReference.y = aDesiredStretchSize.ascent - mBoundingMetrics.ascent; + // Before we leave... there is a last item in the check-list: // If our parent is not embellished, it means we are the outermost embellished // container and so we put the spacing, otherwise we don't include the spacing, @@ -532,6 +547,8 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, if (0 == dx) return NS_OK; // adjust the offsets + mReference.x = dx; + nsRect rect; if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) { mMathMLChar.GetRect(rect); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmrootFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmrootFrame.cpp index 12a9fc0a3ce..9a11657e669 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmrootFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmrootFrame.cpp @@ -268,9 +268,9 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; // XXX Fix me! - mBoundingMetrics.ascent = aDesiredSize.ascent; - mBoundingMetrics.descent = -aDesiredSize.descent; - mBoundingMetrics.width = aDesiredSize.width; + mBoundingMetrics.ascent = aDesiredSize.ascent; + mBoundingMetrics.descent = aDesiredSize.descent; + mBoundingMetrics.width = aDesiredSize.width; return NS_OK; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp index b5d7721f2ef..de113be4a5e 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp @@ -93,6 +93,7 @@ nsMathMLmsubFrame::Init(nsIPresContext* aPresContext, } } + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; return rv; } @@ -108,7 +109,6 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, // Get the children's desired sizes PRInt32 count = 0; - nsRect aRect; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics subScriptSize (nsnull); nsIFrame* baseFrame; @@ -116,39 +116,26 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, // parameter v, Rule 18a, Appendix G of the TeXbook nscoord minSubScriptShift = 0; - nsBoundingMetrics baseBounds, subScriptBounds; + nsBoundingMetrics bmBase, bmSubScript; nsIFrame* aChildFrame = mFrames.FirstChild(); while (nsnull != aChildFrame) { if (!IsOnlyWhitespace(aChildFrame)) { - aChildFrame->GetRect(aRect); if (0 == count) { // base baseFrame = aChildFrame; - baseSize.descent = aRect.x; baseSize.ascent = aRect.y; - baseSize.width = aRect.width; baseSize.height = aRect.height; - if (NS_FAILED(GetBoundingMetricsFor(baseFrame, baseBounds))) { - baseBounds.descent = baseSize.descent; - baseBounds.ascent = baseSize.ascent; - baseBounds.width = baseSize.width; - } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); } else if (1 == count) { // subscript subScriptFrame = aChildFrame; - subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y; - subScriptSize.width = aRect.width; subScriptSize.height = aRect.height; - if (NS_FAILED(GetBoundingMetricsFor(subScriptFrame, subScriptBounds))) { - subScriptBounds.descent = subScriptSize.descent; - subScriptBounds.ascent = subScriptSize.ascent; - subScriptBounds.width = subScriptSize.width; - } + 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 = baseSize.descent + aSubDrop; + minSubScriptShift = bmBase.descent + aSubDrop; } else { NS_ASSERTION((count < 2),"nsMathMLmsubFrame : invalid markup"); @@ -167,12 +154,17 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, // = h(x) - 4/5 * sigma_5, Rule 18b, App. G, TeXbook nscoord xHeight = 0; nsCOMPtr fm; - const nsStyleFont* aFont = - (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); + +// const nsStyleFont* aFont = +// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); + + const nsStyleFont* aFont; + baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont); + aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm)); fm->GetXHeight (xHeight); nscoord minShiftFromXHeight = (nscoord) - (subScriptSize.ascent - (4.0f/5.0f) * xHeight); + (bmSubScript.ascent - (4.0f/5.0f) * xHeight); // aSubScriptShift // = minimum amount to shift the subscript down set by user or from the font @@ -181,51 +173,55 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, nscoord aSubScriptShift, dummy; // get aSubScriptShift default from font GetSubScriptShifts (fm, aSubScriptShift, dummy); - if (mUserSetFlag == PR_TRUE) { + if (mUserSetFlag) { // the user has set the subscriptshift attribute aSubScriptShift = NSToCoordRound(mSubScriptShiftFactor * xHeight); +//XXX shouldn't this be +// aSubScriptShift = +// PR_MAX(aSubScriptShift, NSToCoordRound(mSubScriptShiftFactor * xHeight)); } // get actual subscriptshift to be used // Rule 18b, App. G, TeXbook nscoord actualSubScriptShift = PR_MAX(minSubScriptShift,PR_MAX(aSubScriptShift,minShiftFromXHeight)); -#if 0 // get bounding box for base + subscript - aDesiredSize.ascent = - PR_MAX(baseSize.ascent,(subScriptSize.ascent-actualSubScriptShift)); - aDesiredSize.descent = - PR_MAX(baseSize.descent,(actualSubScriptShift+subScriptSize.descent)); - aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - // add mScriptSpace between base and subscript - aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width; -#endif - mBoundingMetrics.ascent = - PR_MAX(baseBounds.ascent, subScriptBounds.ascent - actualSubScriptShift); + PR_MAX(bmBase.ascent, bmSubScript.ascent - actualSubScriptShift); mBoundingMetrics.descent = - PR_MAX(baseBounds.descent, subScriptBounds.descent + actualSubScriptShift); + PR_MAX(bmBase.descent, bmSubScript.descent + actualSubScriptShift); // add mScriptSpace between base and supscript - mBoundingMetrics.width = baseBounds.width + mScriptSpace + subScriptBounds.width; + mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSubScript.width; + + // to be simplified + nscoord dyBase = mBoundingMetrics.ascent - bmBase.ascent; + nscoord dySubScript = mBoundingMetrics.ascent - bmSubScript.ascent + actualSubScriptShift; + + nscoord baseTop = mBoundingMetrics.ascent - dyBase - bmBase.ascent + baseSize.ascent; + nscoord subScriptTop = mBoundingMetrics.ascent - dySubScript - bmSubScript.ascent + subScriptSize.ascent; + + aDesiredSize.ascent = PR_MAX(baseTop, subScriptTop); + aDesiredSize.descent = PR_MAX(baseSize.height-baseTop, subScriptSize.height-subScriptTop); - aDesiredSize.ascent = - PR_MAX(baseSize.ascent, subScriptSize.ascent - actualSubScriptShift); - aDesiredSize.descent = - PR_MAX(baseSize.descent, subScriptSize.descent + actualSubScriptShift); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width; + mReference.x = 0; + mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent; + mBoundingMetrics.leftBearing = bmBase.leftBearing; + mBoundingMetrics.rightBearing = baseSize.width + mScriptSpace + bmSubScript.rightBearing; + if (aPlaceOrigin) { nscoord dx, dy; // now place the base ... - dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; + dx = 0; dy = aDesiredSize.ascent - baseTop; FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); // ... and subscript dx = baseSize.width; - dy = aDesiredSize.ascent - subScriptSize.ascent + actualSubScriptShift; + dy = aDesiredSize.ascent - subScriptTop; FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0); } return NS_OK; } + diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp index ceab74e30c3..c67e5aa4ccc 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp @@ -103,6 +103,7 @@ nsMathMLmsubsupFrame::Init(nsIPresContext* aPresContext, } } + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; return rv; } @@ -118,7 +119,6 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // Get the children's desired sizes PRInt32 count = 0; - nsRect aRect; nsHTMLReflowMetrics baseSize (nsnull); nsHTMLReflowMetrics subScriptSize (nsnull); nsHTMLReflowMetrics supScriptSize (nsnull); @@ -130,38 +130,36 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // parameter u in Rule 18a, Appendix G of the TeXbook nscoord minSupScriptShift = 0; + nsBoundingMetrics bmBase, bmSubScript, bmSupScript; + nsIFrame* aChildFrame = mFrames.FirstChild(); while (nsnull != aChildFrame) { if (!IsOnlyWhitespace(aChildFrame)) { - aChildFrame->GetRect(aRect); if (0 == count) { // base baseFrame = aChildFrame; - baseSize.descent = aRect.x; baseSize.ascent = aRect.y; - baseSize.width = aRect.width; baseSize.height = aRect.height; + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); } else if (1 == count) { // subscript subScriptFrame = aChildFrame; - subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y; - subScriptSize.width = aRect.width; subScriptSize.height = aRect.height; + 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 = baseSize.descent + aSubDrop; + minSubScriptShift = bmBase.descent + aSubDrop; } else if (2 == count) { // superscript supScriptFrame = aChildFrame; - supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y; - supScriptSize.width = aRect.width; supScriptSize.height = aRect.height; + 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 = baseSize.ascent - aSupDrop; + minSupScriptShift = bmBase.ascent - aSupDrop; } else { NS_ASSERTION((count < 2),"nsMathMLmsubFrame : invalid markup"); @@ -191,8 +189,13 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // get x-height (an ex) nscoord xHeight = 0; nsCOMPtr fm; - const nsStyleFont* aFont = - (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); + +// const nsStyleFont* aFont = +// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); + + const nsStyleFont* aFont; + baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont); + aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm)); fm->GetXHeight (xHeight); @@ -219,7 +222,7 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // get min supscript shift limit from x-height // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook nscoord minShiftFromXHeight = (nscoord) - (supScriptSize.descent + (1.0f/4.0f) * xHeight); + (bmSupScript.descent + (1.0f/4.0f) * xHeight); // aSupScriptShift{1,2,3} // = minimum amount to shift the supscript up @@ -273,8 +276,8 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // XXX need to do update this ... fm->GetStrikeout (dummy, aRuleSize); nscoord gap = - (aSupScriptShift - supScriptSize.descent) - - (subScriptSize.ascent - aSubScriptShift); + (aSupScriptShift - bmSupScript.descent) - + (bmSubScript.ascent - aSubScriptShift); if (gap < 4.0f * aRuleSize) { // adjust aSubScriptShift to get a gap of (4.0 * aRuleSize) aSubScriptShift += NSToCoordRound ((4.0f * aRuleSize) - gap); @@ -283,7 +286,7 @@ 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 - supScriptSize.descent)); + (aSupScriptShift - bmSupScript.descent)); if (gap > 0.0f) { aSupScriptShift += gap; aSubScriptShift -= gap; @@ -292,32 +295,58 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, ////////////////////////////////////////////////// // Do the Placing ////////////////////////////////////////////////// - + // get bounding box for base + subscript + superscript - aDesiredSize.ascent = - PR_MAX(baseSize.ascent,(supScriptSize.ascent+aSupScriptShift)); - aDesiredSize.descent = - PR_MAX(baseSize.descent,(supScriptSize.descent+aSubScriptShift)); - aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; + mBoundingMetrics.ascent = + PR_MAX(bmBase.ascent,(bmSupScript.ascent+aSupScriptShift)); + mBoundingMetrics.descent = + PR_MAX(bmBase.descent,(bmSubScript.descent+aSubScriptShift)); + // add mScriptSpace to both super/subscript // add italicCorrection only to superscript // XXX this will be handled properly later ... nscoord italicCorrection = 0; - aDesiredSize.width = baseSize.width + mScriptSpace + - PR_MAX((supScriptSize.width + italicCorrection),subScriptSize.width); - + mBoundingMetrics.width = bmBase.width + mScriptSpace + + PR_MAX((bmBase.supItalicCorrection + bmSupScript.width), + (bmBase.subItalicCorrection + bmSubScript.width)); + + // to be simplfied 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)); + aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; + + mReference.x = 0; + mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent; + mBoundingMetrics.leftBearing = bmBase.leftBearing; + mBoundingMetrics.rightBearing = bmBase.width + mScriptSpace + + PR_MAX((bmBase.supItalicCorrection + bmSupScript.rightBearing), + (bmBase.subItalicCorrection + bmSubScript.rightBearing)); + + aDesiredSize.width = mBoundingMetrics.width; + if (aPlaceOrigin) { nscoord dx, dy; // now place the base ... - dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; + dx = 0; dy = aDesiredSize.ascent - baseTop; FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); // ... and subscript - dx = baseSize.width; - dy = aDesiredSize.ascent - subScriptSize.ascent + aSubScriptShift; + dx = bmBase.width + bmBase.subItalicCorrection; + dy = aDesiredSize.ascent - subScriptTop; FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0); // ... and the superscript - dx = baseSize.width + italicCorrection; - dy = aDesiredSize.ascent - supScriptSize.ascent - aSupScriptShift; + dx = bmBase.width + bmBase.supItalicCorrection; + dy = aDesiredSize.ascent - supScriptTop; FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0); } diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp index c7cc7ff9a13..2b2d4259a45 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp @@ -92,6 +92,7 @@ nsMathMLmsupFrame::Init(nsIPresContext* aPresContext, } } + mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS; return rv; } @@ -121,28 +122,15 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, while (nsnull != aChildFrame) { if (!IsOnlyWhitespace(aChildFrame)) { - aChildFrame->GetRect(aRect); if (0 == count) { // base baseFrame = aChildFrame; - baseSize.descent = aRect.x; baseSize.ascent = aRect.y; - baseSize.width = aRect.width; baseSize.height = aRect.height; - if (NS_FAILED(GetBoundingMetricsFor(baseFrame, bmBase))) { - bmBase.descent = baseSize.descent; - bmBase.ascent = baseSize.ascent; - bmBase.width = baseSize.width; - } + GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); } else if (1 == count) { // superscript supScriptFrame = aChildFrame; - supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y; - supScriptSize.width = aRect.width; supScriptSize.height = aRect.height; - if (NS_FAILED(GetBoundingMetricsFor(supScriptFrame, bmSupScript))) { - bmSupScript.descent = supScriptSize.descent; - bmSupScript.ascent = supScriptSize.ascent; - bmSupScript.width = supScriptSize.width; - } + GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); // get the supdrop from the supscript font nscoord aSupDrop; GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop); @@ -165,12 +153,17 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook nscoord xHeight = 0; nsCOMPtr fm; - const nsStyleFont* aFont = - (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); + +// const nsStyleFont* aFont = +// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font); + + const nsStyleFont *aFont; + baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont); + aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm)); fm->GetXHeight (xHeight); nscoord minShiftFromXHeight = (nscoord) - (supScriptSize.descent + (1.0f/4.0f) * xHeight); + (bmSupScript.descent + (1.0f/4.0f) * xHeight); // aSupScriptShift{1,2,3} // = minimum amount to shift the supscript up @@ -187,6 +180,9 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1; float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1; aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight); +//XXX shouldn't this be +// aSupScriptShift1 = +// PR_MAX(aSupScriptShift1, NSToCoordRound(mSupScriptShiftFactor * xHeight)); aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1); aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1); } @@ -214,66 +210,39 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, nscoord actualSupScriptShift = PR_MAX(minSupScriptShift,PR_MAX(aSupScriptShift,minShiftFromXHeight)); - // get bounding box for base + supscript -#if 0 - const nsStyleFont *font; - baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); - PRInt32 baseStyle = font->mFont.style; - supScriptFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font); - PRInt32 supScriptStyle = font->mFont.style; - if (baseStyle == NS_STYLE_FONT_STYLE_ITALIC && - supScriptStyle != NS_STYLE_FONT_STYLE_ITALIC) { - // take care of italic correction - ... - } -#endif - -#if 0 - aDesiredSize.ascent = - PR_MAX(baseSize.ascent,(supScriptSize.ascent+actualSupScriptShift)); - aDesiredSize.descent = - PR_MAX(baseSize.descent,(supScriptSize.descent-actualSupScriptShift)); - aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - // add mScriptSpace between base and supscript - aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width; -#endif - mBoundingMetrics.ascent = - PR_MAX(bmBase.ascent, bmSupScript.ascent + actualSupScriptShift); + PR_MAX(bmBase.ascent, (bmSupScript.ascent + actualSupScriptShift)); mBoundingMetrics.descent = - PR_MAX(bmBase.descent, bmSupScript.descent - actualSupScriptShift); + PR_MAX(bmBase.descent, (bmSupScript.descent - actualSupScriptShift)); // add mScriptSpace between base and supscript mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSupScript.width; -#if 0 -printf("bmBase.width:%d + mScriptSpace:%d + bmSupScript.width:%d = mBoundingMetrics.width:%d\n", -bmBase.width, mScriptSpace, bmSupScript.width, mBoundingMetrics.width); -#endif + // to be simplified ... + nscoord dyBase = mBoundingMetrics.ascent - bmBase.ascent; + nscoord dySupScript = mBoundingMetrics.ascent - bmSupScript.ascent - actualSupScriptShift; - aDesiredSize.ascent = - PR_MAX(baseSize.ascent, supScriptSize.ascent + actualSupScriptShift); - aDesiredSize.descent = - PR_MAX(baseSize.descent, supScriptSize.descent - actualSupScriptShift); + nscoord baseTop = mBoundingMetrics.ascent - dyBase - bmBase.ascent + baseSize.ascent; + nscoord supScriptTop = mBoundingMetrics.ascent - dySupScript - bmSupScript.ascent + supScriptSize.ascent; + + aDesiredSize.ascent = PR_MAX(baseTop, supScriptTop); + aDesiredSize.descent = PR_MAX(baseSize.height-baseTop, supScriptSize.height-supScriptTop); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width; + aDesiredSize.width = mBoundingMetrics.width; + + mReference.x = 0; + mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent; + mBoundingMetrics.leftBearing = bmBase.leftBearing; + mBoundingMetrics.rightBearing = baseSize.width + mScriptSpace + bmSupScript.rightBearing; if (aPlaceOrigin) { nscoord dx, dy; // now place the base ... - dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; + dx = 0; dy = aDesiredSize.ascent - baseTop; FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0); // ... and supscript - -#if 0 - float t2p; - aPresContext->GetTwipsToPixels(&t2p); - PRInt32 scriptspace = NSTwipsToIntPixels(mScriptSpace, t2p); - printf("mScriptSpace in twips:%d pixel:%d\n", mScriptSpace, scriptspace); -#endif - dx = baseSize.width + mScriptSpace; - dy = aDesiredSize.ascent - supScriptSize.ascent - actualSupScriptShift; + dy = aDesiredSize.ascent - supScriptTop; FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0); }