From fc2686eba50da09ebca34087501aacbb83fd6769 Mon Sep 17 00:00:00 2001 From: "rbs%maths.uq.edu.au" Date: Fri, 14 Jan 2000 08:38:25 +0000 Subject: [PATCH] [MATHML] *Restructuration to put member data into a mPresentationData struct. *Added support for accent and accentunder, with provision for embellished operators. *Changed usage of GetBoundingMetrics() to the X Windows character coordinate system git-svn-id: svn://10.0.0.236/trunk@57807 18797224-902f-48f8-a5cc-f745e15eee43 --- .../layout/mathml/base/src/nsIMathMLFrame.h | 132 +++++++++++-- .../layout/mathml/base/src/nsMathMLChar.cpp | 24 +-- .../base/src/nsMathMLContainerFrame.cpp | 86 ++++++-- .../mathml/base/src/nsMathMLContainerFrame.h | 60 ++---- .../mathml/base/src/nsMathMLmfencedFrame.cpp | 6 +- .../mathml/base/src/nsMathMLmiFrame.cpp | 41 ++-- .../base/src/nsMathMLmmultiscriptsFrame.cpp | 6 +- .../base/src/nsMathMLmmultiscriptsFrame.h | 5 +- .../mathml/base/src/nsMathMLmoFrame.cpp | 120 ++++++++++-- .../mathml/base/src/nsMathMLmoverFrame.cpp | 143 +++++++++++++- .../mathml/base/src/nsMathMLmoverFrame.h | 12 +- .../mathml/base/src/nsMathMLmsqrtFrame.cpp | 2 +- .../mathml/base/src/nsMathMLmstyleFrame.cpp | 40 ++-- .../mathml/base/src/nsMathMLmstyleFrame.h | 7 +- .../mathml/base/src/nsMathMLmsubFrame.cpp | 12 +- .../mathml/base/src/nsMathMLmsubFrame.h | 4 +- .../mathml/base/src/nsMathMLmsubsupFrame.cpp | 12 +- .../mathml/base/src/nsMathMLmsubsupFrame.h | 4 +- .../mathml/base/src/nsMathMLmsupFrame.cpp | 22 +-- .../mathml/base/src/nsMathMLmsupFrame.h | 4 +- .../mathml/base/src/nsMathMLmunderFrame.cpp | 144 +++++++++++++- .../mathml/base/src/nsMathMLmunderFrame.h | 12 +- .../base/src/nsMathMLmunderoverFrame.cpp | 184 +++++++++++++++++- .../mathml/base/src/nsMathMLmunderoverFrame.h | 12 +- 24 files changed, 879 insertions(+), 215 deletions(-) diff --git a/mozilla/layout/mathml/base/src/nsIMathMLFrame.h b/mozilla/layout/mathml/base/src/nsIMathMLFrame.h index 194ed1fa8eb..966af76199f 100644 --- a/mozilla/layout/mathml/base/src/nsIMathMLFrame.h +++ b/mozilla/layout/mathml/base/src/nsIMathMLFrame.h @@ -22,6 +22,7 @@ #ifndef nsIMathMLFrame_h___ #define nsIMathMLFrame_h___ +struct nsPresentationData; struct nsEmbellishData; struct nsStretchMetrics; typedef PRInt32 nsStretchDirection; @@ -162,7 +163,7 @@ public: EmbellishOperator() = 0; /* GetEmbellishData/SetEmbellishData : - * Get/Set the mEmbellish member data. + * Get/Set the mEmbellishData member variable. */ NS_IMETHOD @@ -175,12 +176,15 @@ public: /* SUPPORT FOR SCRIPTING ELEMENTS: */ /*====================================================================*/ - /* GetPresentationData : - * returns the scriptlevel and displaystyle of the frame + /* GetPresentationData/SetPresentationData : + * Get/Set the mPresentationData member variable. */ + NS_IMETHOD - GetPresentationData(PRInt32* aScriptLevel, - PRBool* aDisplayStyle) = 0; + GetPresentationData(nsPresentationData& aPresentationData) = 0; + + NS_IMETHOD + SetPresentationData(const nsPresentationData& aPresentationData) = 0; /* UpdatePresentationData : * Increments the scriptlevel of the frame, and set its displaystyle. @@ -259,6 +263,20 @@ struct nsStretchMetrics { } }; +// struct used by a frame to modulate its presentation +struct nsPresentationData { + PRUint32 flags; // bits for: displaystyle, compressed, etc + nsIFrame* mstyle; // up-pointer on the mstyle frame, if any, that defines the scope + PRUint32 scriptLevel; // Relevant to nested frames within: msub, msup, msubsup, munder, + // mover, munderover, mmultiscripts, mfrac, mroot, mtable. + nsPresentationData() + { + flags = 0; + mstyle = nsnull; + scriptLevel = 0; + } +}; + // struct used by an embellished container to keep track of its embellished child struct nsEmbellishData { PRUint32 flags; @@ -277,28 +295,114 @@ struct nsEmbellishData { } }; +// ------------- +// Bits used for the presentation flags -- these bits are set +// in their relevant situation as they become available + +// This bit is set if the frame is in the *context* of displaystyle=true. +// Note: This doesn't mean that the frame has displaystyle=true as attribute, +// is the only tag which allows . +// The bit merely tells the context of the frame. In the context of +// displaystyle="false", it is intended to slightly alter how the +// rendering is done in inline mode. +#define NS_MATHML_DISPLAYSTYLE 0x00000001 + +// This bit is used to emulate TeX rendering. +// Internal use only, cannot be set by the user with an attribute. +#define NS_MATHML_COMPRESSED 0x00000002 + +// This bit is set if the frame is actually an frame *and* that +// frame has an explicit attribute scriptlevel="value". +// Note: the flag is not set if the instead has an incremental +/-value. +#define NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL 0x00000004 + +// This bit is set if the frame is actually an *and* that +// has an explicit attribute displaystyle="true" or "false" +#define NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE 0x00000008 + +// This bit is set if the frame is an or with +// an accent frame +#define NS_MATHML_ACCENTOVER 0x00000010 + +// This bit is set if the frame is an or with +// an accentunder frame +#define NS_MATHML_ACCENTUNDER 0x00000020 + +// This bit is set if the frame is , or +// whose base frame is a frame (or an embellished container with +// a core ) for which the movablelimits attribute is set to true +#define NS_MATHML_MOVABLELIMITS 0x00000040 + +// Macros that retrieve those bits +#define NS_MATHML_IS_DISPLAYSTYLE(_flags) \ + (NS_MATHML_DISPLAYSTYLE == ((_flags) & NS_MATHML_DISPLAYSTYLE)) + +#define NS_MATHML_IS_COMPRESSED(_flags) \ + (NS_MATHML_COMPRESSED == ((_flags) & NS_MATHML_COMPRESSED)) + +#define NS_MATHML_IS_MSTYLE_WITH_DISPLAYSTYLE(_flags) \ + (NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE == ((_flags) & NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE)) + +#define NS_MATHML_IS_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL(_flags) \ + (NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL == ((_flags) & NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL)) + +#define NS_MATHML_IS_ACCENTOVER(_flags) \ + (NS_MATHML_ACCENTOVER == ((_flags) & NS_MATHML_ACCENTOVER)) + +#define NS_MATHML_IS_ACCENTUNDER(_flags) \ + (NS_MATHML_ACCENTUNDER == ((_flags) & NS_MATHML_ACCENTUNDER)) + +#define NS_MATHML_IS_MOVABLELIMITS(_flags) \ + (NS_MATHML_MOVABLELIMITS == ((_flags) & NS_MATHML_MOVABLELIMITS)) + // -------------- +// Bits used for the embellish flags -- these bits are set +// in their relevant situation as they become available -#define NS_MATHML_EMBELLISH_OPERATOR 0x1 +// This bit is set if the frame is an embellished operator. +#define NS_MATHML_EMBELLISH_OPERATOR 0x00000001 -#define NS_MATHML_STRETCH_FIRST_CHILD NS_MATHML_EMBELLISH_OPERATOR -#define NS_MATHML_STRETCH_ALL_CHILDREN 0x2 +// This bit is set if the frame is an embellished container that +// will fire a stretch command on its first (non-empty) child. +#define NS_MATHML_STRETCH_FIRST_CHILD NS_MATHML_EMBELLISH_OPERATOR -#define NS_MATHML_STRETCH_DONE 0x4 +// This bit is set if the frame will fire a stretch command on all +// its (non-empty) children. +// Tags like (or an inferred mrow), munderover, etc, +// will fire a stretch command on all their non-empty children +#define NS_MATHML_STRETCH_ALL_CHILDREN 0x00000002 + +// This bit is set if the frame is an frame that should behave +// like an accent +#define NS_MATHML_EMBELLISH_ACCENT 0x00000004 + +// This bit is set if the frame is an frame with the movablelimits +// attribute set to true +#define NS_MATHML_EMBELLISH_MOVABLELIMITS 0x00000008 + +// a bit used for debug +#define NS_MATHML_STRETCH_DONE 0x80000000 + + +// Macros that retrieve those bits #define NS_MATHML_IS_EMBELLISH_OPERATOR(_flags) \ (NS_MATHML_EMBELLISH_OPERATOR == ((_flags) & NS_MATHML_EMBELLISH_OPERATOR)) -#define NS_MATHML_STRETCH_WAS_DONE(_flags) \ - (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE)) - -// an embellished container will fire a stretch command to its first (non-empty) child #define NS_MATHML_WILL_STRETCH_FIRST_CHILD(_flags) \ (NS_MATHML_STRETCH_FIRST_CHILD == ((_flags) & NS_MATHML_STRETCH_FIRST_CHILD)) -// (or an inferred mrow) will fire a stretch command to all its (non-empty) children #define NS_MATHML_WILL_STRETCH_ALL_CHILDREN(_flags) \ (NS_MATHML_STRETCH_ALL_CHILDREN == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN)) +#define NS_MATHML_STRETCH_WAS_DONE(_flags) \ + (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE)) + +#define NS_MATHML_EMBELLISH_IS_ACCENT(_flags) \ + (NS_MATHML_EMBELLISH_ACCENT == ((_flags) & NS_MATHML_EMBELLISH_ACCENT)) + +#define NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(_flags) \ + (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 43314698108..c8a6825e62e 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLChar.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLChar.cpp @@ -438,7 +438,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, // keep track of the default bounding metrics if (index0 == index) bm0 = bm; - h = bm.ascent - bm.descent; + h = bm.ascent + bm.descent; w = bm.rightBearing - bm.leftBearing; // printf("height:%d width:%d ascent:%d descent:%d\n", @@ -448,9 +448,9 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, if ((aDirection == NS_STRETCH_DIRECTION_VERTICAL && h > height) || (aDirection == NS_STRETCH_DIRECTION_HORIZONTAL && w > width)) { sizeOK = PR_TRUE; - descent = -bm.descent; // flip the sign, as expected by Gecko + descent = bm.descent; ascent = bm.ascent; - height = bm.ascent - bm.descent; + height = bm.ascent + bm.descent; width = bm.rightBearing - bm.leftBearing; // cache all this information @@ -480,7 +480,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; } if (w < bm.width) w = bm.width; if (i < 3) { - h += nscoord(flex[i]*(bm.ascent-bm.descent)); // sum heights of the parts... + h += nscoord(flex[i]*(bm.ascent+bm.descent)); // sum heights of the parts... // compute and cache our bounding metrics (vertical stacking!) if (mBoundingMetrics.leftBearing > bm.leftBearing) mBoundingMetrics.leftBearing = bm.leftBearing; @@ -492,7 +492,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, width = w; mBoundingMetrics.width = w; mBoundingMetrics.ascent = aContainerSize.ascent; - mBoundingMetrics.descent = -aContainerSize.descent; + mBoundingMetrics.descent = aContainerSize.descent; } 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; @@ -512,7 +512,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; } if (0 == i) bm0 = bm; if (a < bm.ascent) a = bm.ascent; - if (d > bm.descent) d = bm.descent; + if (d < bm.descent) d = bm.descent; if (i < 3) { w += nscoord(flex[i]*(bm.rightBearing-bm.leftBearing)); // sum widths of the parts... // compute and cache our bounding metrics (horizontal stacking) @@ -525,7 +525,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, if (w <= aContainerSize.width) { // can nicely fit in the available space... //printf("%04X can nicely fit in the available space...\n", ch); // ascent = a; -// height = a - d; +// height = a + d; mBoundingMetrics.width = 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 @@ -663,7 +663,7 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext, // - bmdata[0].ascent - bmdata[2].descent + bm.ascent + bm.descent)/2; // coord for exact fit (i.e., no leading) - dy = aRect.y + (aRect.height - (bm.ascent - bm.descent))/2 + dy = aRect.y + (aRect.height - (bm.ascent + bm.descent))/2 - (fontAscent - bm.ascent); } else if (2 == i) { // bottom @@ -671,7 +671,7 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext, // dy = aRect.y + aRect.height - (fontAscent + fontDescent); // coord for exact fit (i.e., no leading) - dy = aRect.y + aRect.height - (fontAscent - bm.descent); + dy = aRect.y + aRect.height - (fontAscent + bm.descent); } clipRect = nsRect(dx, dy, aRect.width, aRect.height); // abcissa that DrawString used @@ -679,7 +679,7 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext, // *exact* abcissa where the *top-most* pixel of the glyph is painted start[i] = dy + fontAscent - bm.ascent; // *exact* abcissa where the *bottom-most* pixel of the glyph is painted - end[i] = dy + fontAscent - bm.descent; // note: end = start + height + end[i] = dy + fontAscent + bm.descent; // note: end = start + height } ///////////////////////////////////// @@ -718,9 +718,9 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext, aRenderingContext.DrawRect(clipRect); #endif bm = bmdata[i]; - while (dy + fontAscent - bm.descent < start[i+1]) { + while (dy + fontAscent + bm.descent < start[i+1]) { if (2 > count) { - stride = -bm.descent; + stride = bm.descent; bm = bmdata[3]; // glue stride += bm.ascent; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp index 966109415e3..c4a47701e01 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.cpp @@ -176,6 +176,41 @@ nsMathMLContainerFrame::SetReference(const nsPoint& aReference) return NS_OK; } +// helper methods to facilitate getting/setting the bounding metrics +nsresult +nsMathMLContainerFrame::GetBoundingMetricsFor(nsIFrame* aFrame, + nsBoundingMetrics& aBoundingMetrics) +{ + aBoundingMetrics.Clear(); + nsIMathMLFrame* aMathMLFrame = nsnull; + nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetBoundingMetrics(aBoundingMetrics); + return NS_OK; + } + // 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; + } + // 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; +} /* ///////////// * nsIMathMLFrame - support methods for stretchy elements @@ -247,6 +282,7 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext, // the outermost embellished container will take care of it. if (!IsEmbellishOperator(mParent)) { + nsStyleFont font; mStyleContext->GetStyle(eStyleStruct_Font, font); nscoord em = NSToCoordRound(float(font.mFont.size)); @@ -429,12 +465,16 @@ nsMathMLContainerFrame::IsEmbellishOperator(nsIFrame* aFrame) */ NS_IMETHODIMP -nsMathMLContainerFrame::GetPresentationData(PRInt32* aScriptLevel, - PRBool* aDisplayStyle) +nsMathMLContainerFrame::GetPresentationData(nsPresentationData& aPresentationData) { - NS_PRECONDITION(aScriptLevel && aDisplayStyle, "null arg"); - *aScriptLevel = mScriptLevel; - *aDisplayStyle = mDisplayStyle; + aPresentationData = mPresentationData; + return NS_OK; +} + +NS_IMETHODIMP +nsMathMLContainerFrame::SetPresentationData(const nsPresentationData& aPresentationData) +{ + mPresentationData = aPresentationData; return NS_OK; } @@ -442,8 +482,11 @@ NS_IMETHODIMP nsMathMLContainerFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, PRBool aDisplayStyle) { - mScriptLevel += aScriptLevelIncrement; - mDisplayStyle = aDisplayStyle; + mPresentationData.scriptLevel += aScriptLevelIncrement; + if (aDisplayStyle) + mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; + else + mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; return NS_OK; } @@ -491,16 +534,15 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte if (nsnull != aMathMLFrame && NS_SUCCEEDED(rv)) { // get the scriptlevel of the child - PRInt32 childLevel; - PRBool childDisplayStyle; - aMathMLFrame->GetPresentationData(&childLevel, &childDisplayStyle); + nsPresentationData childData; + aMathMLFrame->GetPresentationData(childData); // Iteration to set a style context for the script level font. // Wow, here is what is happening: the style system requires that any style context // *must* be uniquely associated to a frame. So we insert as many frames as needed // to scale-down (or scale-up) the fontsize. - PRInt32 gap = childLevel - mScriptLevel; + PRInt32 gap = childData.scriptLevel - mPresentationData.scriptLevel; if (0 != gap) { nsCOMPtr childContent; childFrame->GetContent(getter_AddRefs(childContent)); @@ -556,7 +598,7 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte aMathMLFrame->GetEmbellishData(embellishData); if (0 != embellishData.flags && nsnull != embellishData.firstChild) { do { // walk the hierarchy in a bottom-up manner - rv= lastFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + rv = lastFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!"); if (NS_FAILED(rv) || !aMathMLFrame) break; embellishData.firstChild = childFrame; @@ -594,10 +636,9 @@ nsMathMLContainerFrame::Init(nsIPresContext* aPresContext, // its scriptlevel and displaystyle. If the parent later wishes to increment // with other values, it will do so in its SetInitialChildList() method. - mScriptLevel = 0; - mDisplayStyle = PR_TRUE; - mCompressed = PR_FALSE; // for compatibility with TeX rendering - mScriptSpace = 0; // = 0.5 pt in plain TeX + mPresentationData.flags = NS_MATHML_DISPLAYSTYLE; + mPresentationData.scriptLevel = 0; + mPresentationData.mstyle = nsnull; mEmbellishData.flags = 0; mEmbellishData.firstChild = nsnull; @@ -605,10 +646,15 @@ nsMathMLContainerFrame::Init(nsIPresContext* aPresContext, nsIMathMLFrame* aMathMLFrame = nsnull; nsresult res = aParent->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); if (NS_SUCCEEDED(res) && nsnull != aMathMLFrame) { - PRInt32 aScriptLevel = 0; - PRBool aDisplayStyle = PR_TRUE; - aMathMLFrame->GetPresentationData(&aScriptLevel, &aDisplayStyle); - UpdatePresentationData(aScriptLevel, aDisplayStyle); + nsPresentationData parentData; + aMathMLFrame->GetPresentationData(parentData); + + mPresentationData.mstyle = parentData.mstyle; + mPresentationData.scriptLevel = parentData.scriptLevel; + if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) + mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; + else + mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; } return rv; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h index 3a2ca85765b..85271b28c4a 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLContainerFrame.h @@ -111,8 +111,10 @@ public: SetEmbellishData(const nsEmbellishData& aEmbellishData); NS_IMETHOD - GetPresentationData(PRInt32* aScriptLevel, - PRBool* aDisplayStyle); + GetPresentationData(nsPresentationData& aPresentationData); + + NS_IMETHOD + SetPresentationData(const nsPresentationData& aPresentationData); NS_IMETHOD UpdatePresentationData(PRInt32 aScriptLevelIncrement, @@ -160,7 +162,7 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); - // helper function to palce token elements + // helper function to place token elements static nsresult PlaceTokenFor(nsIFrame* aFrame, nsIPresContext* aPresContext, @@ -236,34 +238,11 @@ public: // helper methods to facilitate getting/setting the bounding metrics static nsresult GetBoundingMetricsFor(nsIFrame* aFrame, - nsBoundingMetrics& aBoundingMetrics) - { - aBoundingMetrics.Clear(); - nsIMathMLFrame* aMathMLFrame = nsnull; - nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); - if (NS_SUCCEEDED(rv) && aMathMLFrame) { - aMathMLFrame->GetBoundingMetrics(aBoundingMetrics); - return NS_OK; - } - // if we reach here, aFrame is not a MathML frame, let the caller know that - printf("GetBoundingMetrics() failed!! ...\n"); /* getchar(); */ - return NS_ERROR_FAILURE; - } + nsBoundingMetrics& aBoundingMetrics); static nsresult 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; - } - // if we reach here, aFrame is not a MathML frame, let the caller know that - printf("SetBoundingMetrics() failed!! ...\n"); /* getchar(); */ - return NS_ERROR_FAILURE; - } + nsBoundingMetrics& aBoundingMetrics); // helper methods for getting sup/subdrop's from a child static void @@ -336,23 +315,18 @@ public: protected: - PRInt32 mScriptLevel; // Relevant to nested frames within: msub, msup, msubsup, munder, - // mover, munderover, mmultiscripts, mfrac, mroot, mtable. + // information about the presentation policy of the frame + nsPresentationData mPresentationData; - PRBool mDisplayStyle; // displaystyle="false" is intended to slightly alter how the - // rendering is done in inline mode. + // information about a container that is an embellished operator + nsEmbellishData mEmbellishData; + + // Metrics that _exactly_ enclose the text of the frame + nsBoundingMetrics mBoundingMetrics; + + // Reference point of the frame: mReference.y is the baseline + nsPoint mReference; - PRBool mCompressed; // for compatibility with TeX rendering - // for internal use only, cannot be set by the user. - nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript - // = 0.5pt in plain TeX - - nsEmbellishData mEmbellishData; // information about a container that is an embellished operator - - nsBoundingMetrics mBoundingMetrics; // Metrics that _exactly_ enclose the text of the frame - - nsPoint mReference; // Reference point of the frame: mReference.y is the baseline - virtual PRIntn GetSkipSides() const { return 0; } }; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmfencedFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmfencedFrame.cpp index e27f9e83f44..eb9553975c5 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmfencedFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmfencedFrame.cpp @@ -320,7 +320,7 @@ nsMathMLmfencedFrame::Reflow(nsIPresContext* aPresContext, ///////////////// // opening fence ... ReflowChar(aPresContext, renderingContext, mStyleContext, mOpenChar, NS_MATHML_OPERATOR_FORM_PREFIX, - mScriptLevel, fontAscent, fontDescent, em, parentSize, aDesiredSize, dx); + mPresentationData.scriptLevel, fontAscent, fontDescent, em, parentSize, aDesiredSize, dx); ///////////////// // separators ... PRInt32 i = 0; @@ -332,7 +332,7 @@ nsMathMLmfencedFrame::Reflow(nsIPresContext* aPresContext, dx += rect.width; if (i < mSeparatorsCount) { ReflowChar(aPresContext, renderingContext, mStyleContext, &mSeparatorsChar[i], NS_MATHML_OPERATOR_FORM_INFIX, - mScriptLevel, fontAscent, fontDescent, em, parentSize, aDesiredSize, dx); + mPresentationData.scriptLevel, fontAscent, fontDescent, em, parentSize, aDesiredSize, dx); i++; } } @@ -341,7 +341,7 @@ nsMathMLmfencedFrame::Reflow(nsIPresContext* aPresContext, ///////////////// // closing fence ... ReflowChar(aPresContext, renderingContext, mStyleContext, mCloseChar, NS_MATHML_OPERATOR_FORM_POSTFIX, - mScriptLevel, fontAscent, fontDescent, em, parentSize, aDesiredSize, dx); + mPresentationData.scriptLevel, fontAscent, fontDescent, em, parentSize, aDesiredSize, dx); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmiFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmiFrame.cpp index bfe2a37f220..1b11e1f2f2a 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmiFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmiFrame.cpp @@ -20,7 +20,6 @@ * David J. Fiddes */ - #include "nsCOMPtr.h" #include "nsHTMLParts.h" #include "nsIHTMLContent.h" @@ -82,7 +81,6 @@ nsMathMLmiFrame::Init(nsIPresContext* aPresContext, return rv; } -// if our content is a single character, we turn the font to italic // if our content is not a single character, we turn the font to normal // XXX TrimWhitespace / CompressWhitespace? @@ -102,7 +100,7 @@ nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext, PRInt32 aLength = 0; PRInt32 numKids; mContent->ChildCount(numKids); - nsAutoString aData; + //nsAutoString aData; for (PRInt32 kid=0; kid kidContent; mContent->ChildAt(kid, *getter_AddRefs(kidContent)); @@ -112,27 +110,42 @@ nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext, PRUint32 kidLength; kidText->GetLength(&kidLength); aLength += kidLength; - nsAutoString kidData; - kidText->GetData(kidData); - aData += kidData; + //nsAutoString kidData; + //kidText->GetData(kidData); + //aData += kidData; } } } - // Insert a new pseudo frame between our children and us, i.e., the new frame - // becomes our sole child, and our children become children of the new frame. nsIFrame* firstChild = mFrames.FirstChild(); - if (firstChild) { - // Get a pseudo style context for the appropriate style font - // XXX how important is the PseudoStyleContext? - nsAutoString fontStyle = (1 == aLength) - ? ":-moz-math-font-style-italic" - : ":-moz-math-font-style-normal"; + if (firstChild && 1 < aLength) { + + // we are going to switch the font to normal ... + + // we don't switch if we are in the scope of a mstyle frame with an + // explicit fontstyle="italic" ... + nsAutoString fontStyle; + nsIFrame* mstyleFrame = mPresentationData.mstyle; + if (mstyleFrame) { + nsCOMPtr mstyleContent; + mstyleFrame->GetContent(getter_AddRefs(mstyleContent)); + if (NS_CONTENT_ATTR_HAS_VALUE == mstyleContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::fontstyle_, fontStyle)) + { + if (fontStyle == "italic") + return rv; + } + } + + // Get a pseudo style context for the appropriate style font + fontStyle = ":-moz-math-font-style-normal"; nsCOMPtr fontAtom(getter_AddRefs(NS_NewAtom(fontStyle))); nsCOMPtr newStyleContext; aPresContext->ResolvePseudoStyleContextFor(mContent, fontAtom, mStyleContext, PR_FALSE, getter_AddRefs(newStyleContext)); + // Insert a new pseudo frame between our children and us, i.e., the new frame + // becomes our sole child, and our children become children of the new frame. if (newStyleContext && newStyleContext.get() != mStyleContext) { nsCOMPtr shell; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp index 65e6a480cfd..6698a47697f 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.cpp @@ -182,11 +182,13 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext, // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord aSupScriptShift; - if (mScriptLevel == 0 && mDisplayStyle && !mCompressed) { + if ( mPresentationData.scriptLevel == 0 && + NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && + !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style D in TeXbook aSupScriptShift = aSupScriptShift1; } - else if (mCompressed) { + else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' aSupScriptShift = aSupScriptShift3; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h index fe0c6c788b9..4c88d026181 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmmultiscriptsFrame.h @@ -69,10 +69,11 @@ protected: virtual PRIntn GetSkipSides() const { return 0; } - private: +private: + nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript + // = 0.5pt in plain TeX float mSubScriptShiftFactor, mSupScriptShiftFactor; PRBool mSubUserSetFlag, mSupUserSetFlag; - }; #endif /* nsMathMLmmultiscriptsFrame_h___ */ diff --git a/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp index fca27ba3200..d298207afc8 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmoFrame.cpp @@ -180,14 +180,82 @@ nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext, // cache the operator mMathMLChar.SetData(aData); - // for consistency, set the first non-empty child as the embellished child + // fill our mEmbellishData member variable nsIFrame* firstChild = mFrames.FirstChild(); while (firstChild) { if (!IsOnlyWhitespace(firstChild)) { - mEmbellishData.flags = NS_MATHML_EMBELLISH_OPERATOR; - mEmbellishData.firstChild = firstChild; + mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR; mEmbellishData.core = this; mEmbellishData.direction = mMathMLChar.GetStretchDirection(); + + // for consistency, set the first non-empty child as the embellished child + mEmbellishData.firstChild = firstChild; + + // there are two extra things that we need to record so that if our + // parent is , , or , they will treat us properly: + // 1) do we have accent="true" + // 2) do we have movablelimits="true" + + // they need the extra information to decide how to treat their scripts/limits + // (note: , , or need not necessarily be our + // direct parent -- case of embellished operators) + + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; // default is false + mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_MOVABLELIMITS; // default is false + + nsAutoString value; + PRBool accentAttribute = PR_FALSE; + PRBool movablelimitsAttribute = PR_FALSE; + + // see if the accent attribute is there + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::accent_, value)) + { + accentAttribute = PR_TRUE; + if (value == "true") + { + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + } + } + + // see if the movablelimits attribute is there + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::movablelimits_, value)) + { + movablelimitsAttribute = PR_TRUE; + if (value == "true") + { + mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; + } + } + + if (!accentAttribute || !movablelimitsAttribute) { + // If we reach here, it means one or both attributes are missing + // Unfortunately, we have to lookup the dictionary to see who + // we are, i.e., two lookups, counting also the one in Stretch()! + // The lookup in Stretch() assumes that the surrounding frame tree + // is already fully constructed, which is not true at this stage. + + // all accent="true" in the dictionary have form="postfix" + nsOperatorFlags aForm = NS_MATHML_OPERATOR_FORM_POSTFIX; + nsOperatorFlags aFlags = 0; + float aLeftSpace, aRightSpace; + PRBool found = nsMathMLOperators::LookupOperator(aData, aForm, + &aFlags, &aLeftSpace, &aRightSpace); + + if (found && !accentAttribute && NS_MATHML_OPERATOR_IS_ACCENT(aFlags)) + { + mEmbellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + } + + // all movablemits="true" in the dictionary have form="prefix", + // but this doesn't matter here, as the lookup has returned whatever + // is in the dictionary + if (found && !movablelimitsAttribute && NS_MATHML_OPERATOR_IS_MOVABLELIMITS(aFlags)) + { + mEmbellishData.flags |= NS_MATHML_EMBELLISH_MOVABLELIMITS; + } + } break; } firstChild->GetNextSibling(&firstChild); @@ -205,6 +273,7 @@ nsMathMLmoFrame::InitData() nsAutoString value; nsOperatorFlags aForm = NS_MATHML_OPERATOR_FORM_INFIX; nsIMathMLFrame* aMathMLFrame = nsnull; + nsIFrame* embellishAncestor = nsnull; PRBool hasEmbellishAncestor = PR_FALSE; if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsMathMLAtoms::form_, value)) { @@ -214,18 +283,23 @@ nsMathMLmoFrame::InitData() aForm = NS_MATHML_OPERATOR_FORM_POSTFIX; // flag if we have an embellished ancestor - hasEmbellishAncestor = IsEmbellishOperator(mParent); + if (IsEmbellishOperator(mParent)) + { + hasEmbellishAncestor = PR_TRUE; + embellishAncestor = mParent; + } } else { // Get our outermost embellished container and its parent nsIFrame* aParent = this; - nsIFrame* aEmbellishAncestor = this; + nsIFrame* embellishAncestor = this; do { - aEmbellishAncestor = aParent; + embellishAncestor = aParent; aParent->GetParent(&aParent); } while (IsEmbellishOperator(aParent)); // flag if we have an embellished ancestor - if (aEmbellishAncestor != this) { + if (embellishAncestor != this) + { hasEmbellishAncestor = PR_TRUE; } @@ -234,7 +308,7 @@ nsMathMLmoFrame::InitData() ////////////// // WHITESPACE: don't forget that whitespace doesn't count in MathML! // Here is the situation: we may have empty frames between us: - // [space*] [prev] [space*] [aEmbellishAncestor] [space*] [next] + // [space*] [prev] [space*] [embellishAncestor] [space*] [next] // We want to skip them... // The problem looks like a regexp, we ask a little flag to help us. PRInt32 state = 0; @@ -244,7 +318,7 @@ nsMathMLmoFrame::InitData() aParent->FirstChild(nsnull, &aFrame); while (aFrame) { - if (aFrame == aEmbellishAncestor) { // we start looking for next + if (aFrame == embellishAncestor) { // we start looking for next state++; } else if (!IsOnlyWhitespace(aFrame)) { @@ -266,6 +340,17 @@ nsMathMLmoFrame::InitData() aForm = NS_MATHML_OPERATOR_FORM_POSTFIX; } + // Check to see if we are really the 'core' of the ancestor, not just a sibling of the core + if (hasEmbellishAncestor && embellishAncestor) { + hasEmbellishAncestor = PR_FALSE; + rv = embellishAncestor->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + nsEmbellishData embellishData; + aMathMLFrame->GetEmbellishData(embellishData); + if (embellishData.core == this) hasEmbellishAncestor = PR_TRUE; + } + } + // Lookup the operator dictionary nsAutoString aData; mMathMLChar.GetData(aData); @@ -275,7 +360,7 @@ nsMathMLmoFrame::InitData() // All operators are symmetric. But this symmetric flag is *not* stored in // the operator dictionary and operators are treated as non-symmetric... // Uncomment the folllowing line to change this behavior. - // mFlags |= NS_MATHML_OPERATOR_SYMMETRIC; + //mFlags |= NS_MATHML_OPERATOR_SYMMETRIC; // If the operator exists in the dictionary and is stretchy, it is mutable if (found && NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) { @@ -288,7 +373,7 @@ nsMathMLmoFrame::InitData() } // If we don't want too much extra space when we are a script - if (!hasEmbellishAncestor && 0 < mScriptLevel) { + if (!hasEmbellishAncestor && 0 < mPresentationData.scriptLevel) { mLeftSpace /= 2.0f; mRightSpace /= 2.0f; } @@ -342,11 +427,17 @@ nsMathMLmoFrame::InitData() // TODO: add also lspace and rspace, minsize, maxsize, later ... + // If we are an accent without explicit lspace="." or rspace=".", + // ignore our default left/right space + if (NS_MATHML_EMBELLISH_IS_ACCENT(mEmbellishData.flags)) { + mLeftSpace = 0.0f; + mRightSpace = 0.0f; + } + // If the stretchy attribute has been disabled, the operator is not mutable if (!found || !NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) { mFlags &= ~NS_MATHML_OPERATOR_MUTABLE; } - } // NOTE: aDesiredStretchSize is an IN/OUT parameter @@ -397,7 +488,7 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, mFlags &= ~NS_MATHML_OPERATOR_MUTABLE; } else { - // update our bounding metrics... it becomes that our MathML char + // update our bounding metrics... it becomes that of our MathML char mMathMLChar.GetBoundingMetrics(mBoundingMetrics); } } @@ -427,8 +518,9 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext, // If our parent is not embellished, it means we are the outermost embellished // container and so we put the spacing, otherwise we don't include the spacing, // the outermost embellished container will take care of it. - + if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) { + // Get the value of 'em' nsStyleFont font; mStyleContext->GetStyle(eStyleStruct_Font, font); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.cpp index ebfaf774419..83e435c6c20 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.cpp @@ -80,6 +80,126 @@ nsMathMLmoverFrame::Init(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsMathMLmoverFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv; + rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + + // check whether or not this is an embellished operator + EmbellishOperator(); + + // set our accent flag + + /* The REC says: + The default value of accent is false, unless overscript + is an element or an embellished operator. If overscript is + an element, the value of its accent attribute is used as + the default value of accent. If overscript is an embellished + operator, the accent attribute of the element at its + core is used as the default value. As with all attributes, an + explicitly given value overrides the default. + +XXX The winner is the outermost in conflicting settings like these: + + ... + ... + + */ + + PRInt32 count = 0; + nsIFrame* baseFrame = nsnull; + nsIFrame* overscriptFrame = nsnull; + nsIFrame* childFrame = mFrames.FirstChild(); + while (childFrame) { + if (!IsOnlyWhitespace(childFrame)) { + count++; + if (1 == count) baseFrame = childFrame; + if (2 == count) { overscriptFrame = childFrame; break; } + } + childFrame->GetNextSibling(&childFrame); + } + + nsIMathMLFrame* overscriptMathMLFrame = nsnull; + nsIMathMLFrame* aMathMLFrame = nsnull; + nsEmbellishData embellishData; + nsAutoString value; + + mPresentationData.flags &= ~NS_MATHML_MOVABLELIMITS; // default is false + mPresentationData.flags &= ~NS_MATHML_ACCENTOVER; // default of accent is false + + // see if the baseFrame has movablelimits="true" or if it is an + // embellished operator whose movablelimits attribute is set to true + if (baseFrame && NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { + nsCOMPtr baseContent; + baseFrame->GetContent(getter_AddRefs(baseContent)); + if (NS_CONTENT_ATTR_HAS_VALUE == baseContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::movablelimits_, value)) { + if (value == "true") { + mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; + } + } + else { // no attribute, get the value from the core + rv = mEmbellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(embellishData.flags)) { + mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; + } + } + } + } + + // see if the overscriptFrame is or an embellished operator + if (overscriptFrame) { + rv = overscriptFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&overscriptMathMLFrame); + if (NS_SUCCEEDED(rv) && overscriptMathMLFrame) { + overscriptMathMLFrame->GetEmbellishData(embellishData); + // core of the overscriptFrame + if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.core) { + rv = embellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + // if we have the accent attribute, tell the core to behave as + // requested (otherwise leave the core with its default behavior) + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::accent_, value)) + { + if (value == "true") embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + else if (value == "false") embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; + aMathMLFrame->SetEmbellishData(embellishData); + } + + // sync the presentation data: record whether we have an accent + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mPresentationData.flags |= NS_MATHML_ACCENTOVER; + } + } + } + } + + //The REC says: + /* + Within overscript, always sets displaystyle to "false", + but increments scriptlevel by 1 only when accent is "false". + */ + + PRInt32 incrementScriptLevel; + + if (overscriptMathMLFrame) { + incrementScriptLevel = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)? 0 : 1; + overscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE); + overscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE); + } + + // switch the style of the overscript + InsertScriptLevelStyleContext(aPresContext); + + return rv; +} + NS_IMETHODIMP nsMathMLmoverFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -109,6 +229,23 @@ nsMathMLmoverFrame::Reflow(nsIPresContext* aPresContext, return NS_OK; } +/* +The REC says: +* If the base is an operator with movablelimits="true" (or an embellished + operator whose element core has movablelimits="true"), and + displaystyle="false", then overscript is drawn in a superscript + position. In this case, the accent attribute is ignored. This is + often used for limits on symbols such as ∑. + +TODO: + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + // place like superscript + } + else { + // place like accent + } +*/ NS_IMETHODIMP nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, @@ -192,8 +329,8 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext, } // 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/nsMathMLmoverFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.h index 5986a860e42..83ee958bdba 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmoverFrame.h @@ -56,17 +56,7 @@ public: NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, - nsIFrame* aChildList) - { - nsresult rv; - rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE); - // switch the style of the overscript - InsertScriptLevelStyleContext(aPresContext); - // check whether or not this is an embellished operator - EmbellishOperator(); - return rv; - } + nsIFrame* aChildList); protected: nsMathMLmoverFrame(); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp index 35b21430bff..4df076e7147 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsqrtFrame.cpp @@ -156,7 +156,7 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext, // overline bar renderingContext.GetBoundingMetrics(mBarChar.GetUnicode(), PRUint32(1), bmBar); - nscoord thickspace = bmBar.ascent - bmBar.descent; // height of the overline bar + nscoord thickspace = bmBar.ascent + bmBar.descent; // height of the overline bar // Stretch the sqrt symbol to the appropriate height if it is not big enough. nsStretchMetrics contSize(aDesiredSize); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.cpp index 81afe138c90..3a5581d3977 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.cpp @@ -76,7 +76,8 @@ nsMathMLmstyleFrame::Init(nsIPresContext* aPresContext, { nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - mFlags = 0; + mPresentationData.mstyle = this; + mInnerScriptLevelIncrement = 0; // see if the displaystyle attribute is there @@ -84,12 +85,12 @@ nsMathMLmstyleFrame::Init(nsIPresContext* aPresContext, if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsMathMLAtoms::displaystyle_, value)) { if (value == "true") { - mDisplayStyle = PR_TRUE; - mFlags |= NS_MATHML_MSTYLE_DISPLAYSTYLE; + mPresentationData.flags |= NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE; + mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; } else if (value == "false") { - mDisplayStyle = PR_FALSE; - mFlags |= NS_MATHML_MSTYLE_DISPLAYSTYLE; + mPresentationData.flags |= NS_MATHML_MSTYLE_WITH_DISPLAYSTYLE; + mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; } } @@ -100,8 +101,8 @@ nsMathMLmstyleFrame::Init(nsIPresContext* aPresContext, aUserValue = value.ToInteger(&aErrorCode); if (NS_SUCCEEDED(aErrorCode)) { if (value[0] != '+' && value[0] != '-') { // record that it is an explicit value - mFlags |= NS_MATHML_MSTYLE_SCRIPTLEVEL_EXPLICIT; - mScriptLevel = aUserValue; // explicit value... + mPresentationData.flags |= NS_MATHML_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL; + mPresentationData.scriptLevel = aUserValue; } else { // mScriptLevel += aUserValue; // incremental value... @@ -125,12 +126,17 @@ nsMathMLmstyleFrame::UpdatePresentationData(PRInt32 aScriptLevelIncrement, // Since UpdatePresentationData() can be called by a parent frame, the // scriptlevel and displaystyle attributes of mstyle must take precedence. // Update only if attributes are not there - if (!(NS_MATHML_MSTYLE_HAS_DISPLAYSTYLE(mFlags))) { - mDisplayStyle = aDisplayStyle; + + if (!NS_MATHML_IS_MSTYLE_WITH_DISPLAYSTYLE(mPresentationData.flags)) { + if (aDisplayStyle) + mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE; + else + mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE; } - if (!(NS_MATHML_MSTYLE_HAS_SCRIPTLEVEL_EXPLICIT(mFlags))) { - mScriptLevel += aScriptLevelIncrement; + if (!NS_MATHML_IS_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL(mPresentationData.flags)) { + mPresentationData.scriptLevel += aScriptLevelIncrement; } + return NS_OK; } @@ -142,15 +148,17 @@ nsMathMLmstyleFrame::UpdatePresentationDataFromChildAt(PRInt32 aIndex, // mstyle is special... // Since UpdatePresentationDataFromChildAt() can be called by a parent frame, // wee need to ensure that the attributes of mstyle take precedence - if (NS_MATHML_MSTYLE_HAS_DISPLAYSTYLE(mFlags)) { - aDisplayStyle = mDisplayStyle; + + PRBool displayStyle = NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags); + if (NS_MATHML_IS_MSTYLE_WITH_DISPLAYSTYLE(mPresentationData.flags)) { + aDisplayStyle = displayStyle; } - if (NS_MATHML_MSTYLE_HAS_SCRIPTLEVEL_EXPLICIT(mFlags)) { + if (NS_MATHML_IS_MSTYLE_WITH_EXPLICIT_SCRIPTLEVEL(mPresentationData.flags)) { aScriptLevelIncrement = 0; } - if (0 == aScriptLevelIncrement && aDisplayStyle == mDisplayStyle) + if (0 == aScriptLevelIncrement && aDisplayStyle == displayStyle) return NS_OK; - + // let the base class worry about the update return nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(aIndex, aScriptLevelIncrement, aDisplayStyle); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.h index 9ddcc63e719..7c6db0fad9e 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmstyleFrame.h @@ -30,6 +30,8 @@ // -- style change // +#if 0 + #define NS_MATHML_MSTYLE_SCRIPTLEVEL_EXPLICIT (1) #define NS_MATHML_MSTYLE_DISPLAYSTYLE (1<<1) @@ -39,6 +41,7 @@ #define NS_MATHML_MSTYLE_HAS_DISPLAYSTYLE(_flags) \ (NS_MATHML_MSTYLE_DISPLAYSTYLE == ((_flags) & NS_MATHML_MSTYLE_DISPLAYSTYLE)) +#endif class nsMathMLmstyleFrame : public nsMathMLContainerFrame { public: @@ -67,7 +70,7 @@ public: { nsresult rv; rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(0, mInnerScriptLevelIncrement, mDisplayStyle); + UpdatePresentationDataFromChildAt(0, mInnerScriptLevelIncrement, NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)); InsertScriptLevelStyleContext(aPresContext); return rv; } @@ -79,7 +82,7 @@ protected: virtual PRIntn GetSkipSides() const { return 0; } PRInt32 mInnerScriptLevelIncrement; - PRInt32 mFlags; +// PRInt32 mFlags; }; #endif /* nsMathMLmstyleFrame_h___ */ diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp index 303a57df177..b5d7721f2ef 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.cpp @@ -128,9 +128,7 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, baseFrame = aChildFrame; baseSize.descent = aRect.x; baseSize.ascent = aRect.y; baseSize.width = aRect.width; baseSize.height = aRect.height; - if (NS_SUCCEEDED(GetBoundingMetricsFor(baseFrame, baseBounds))) { - baseBounds.descent = -baseBounds.descent; - } else { + if (NS_FAILED(GetBoundingMetricsFor(baseFrame, baseBounds))) { baseBounds.descent = baseSize.descent; baseBounds.ascent = baseSize.ascent; baseBounds.width = baseSize.width; @@ -141,9 +139,7 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, subScriptFrame = aChildFrame; subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y; subScriptSize.width = aRect.width; subScriptSize.height = aRect.height; - if (NS_SUCCEEDED(GetBoundingMetricsFor(subScriptFrame, subScriptBounds))) { - subScriptBounds.descent = -subScriptBounds.descent; - } else { + if (NS_FAILED(GetBoundingMetricsFor(subScriptFrame, subScriptBounds))) { subScriptBounds.descent = subScriptSize.descent; subScriptBounds.ascent = subScriptSize.ascent; subScriptBounds.width = subScriptSize.width; @@ -218,9 +214,7 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext, PR_MAX(baseSize.descent, subScriptSize.descent + actualSubScriptShift); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; -//XXX wrong aDesiredSize.width = mBoundingMetrics.width; - - mBoundingMetrics.descent = -mBoundingMetrics.descent; + aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width; if (aPlaceOrigin) { nscoord dx, dy; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.h index cce1790be7c..fb97b2f73b4 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmsubFrame.h @@ -69,7 +69,9 @@ public: virtual PRIntn GetSkipSides() const { return 0; } - private: +private: + nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript + // = 0.5pt in plain TeX float mSubScriptShiftFactor; PRBool mUserSetFlag; }; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp index ce45e557eee..ceab74e30c3 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.cpp @@ -198,7 +198,7 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // Get aSubScriptShift{1,2} default from font GetSubScriptShifts (fm, aSubScriptShift1, aSubScriptShift2); - if (mSubUserSetFlag == PR_TRUE) { + if (mSubUserSetFlag) { // the user has set the subscriptshift attribute float aFactor = ((float) aSubScriptShift2) / aSubScriptShift1; aSubScriptShift1 = NSToCoordRound(mSubScriptShiftFactor * xHeight); @@ -230,7 +230,7 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3; // Set aSupScriptShift{1,2,3} default from font GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3); - if (mSupUserSetFlag == PR_TRUE) { + if (mSupUserSetFlag) { // the user has set the superscriptshift attribute float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1; float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1; @@ -242,13 +242,13 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext, // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord aSupScriptShift; - if ((mScriptLevel == 0) && - (mDisplayStyle == PR_TRUE) && - (mCompressed == PR_FALSE)) { + if ( mPresentationData.scriptLevel == 0 && + NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && + !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style D in TeXbook aSupScriptShift = aSupScriptShift1; } - else if (mCompressed == PR_TRUE) { + else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' aSupScriptShift = aSupScriptShift3; } diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.h index 96add55b617..0a31848ae40 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmsubsupFrame.h @@ -69,7 +69,9 @@ protected: virtual PRIntn GetSkipSides() const { return 0; } - private: +private: + nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript + // = 0.5pt in plain TeX float mSubScriptShiftFactor, mSupScriptShiftFactor; PRBool mSubUserSetFlag, mSupUserSetFlag; }; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp index 292373f96b5..c7cc7ff9a13 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.cpp @@ -127,9 +127,7 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, baseFrame = aChildFrame; baseSize.descent = aRect.x; baseSize.ascent = aRect.y; baseSize.width = aRect.width; baseSize.height = aRect.height; - if (NS_SUCCEEDED(GetBoundingMetricsFor(baseFrame, bmBase))) { - bmBase.descent = -bmBase.descent; - } else { + if (NS_FAILED(GetBoundingMetricsFor(baseFrame, bmBase))) { bmBase.descent = baseSize.descent; bmBase.ascent = baseSize.ascent; bmBase.width = baseSize.width; @@ -140,9 +138,7 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, supScriptFrame = aChildFrame; supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y; supScriptSize.width = aRect.width; supScriptSize.height = aRect.height; - if (NS_SUCCEEDED(GetBoundingMetricsFor(supScriptFrame, bmSupScript))) { - bmSupScript.descent = -bmSupScript.descent; - } else { + if (NS_FAILED(GetBoundingMetricsFor(supScriptFrame, bmSupScript))) { bmSupScript.descent = supScriptSize.descent; bmSupScript.ascent = supScriptSize.ascent; bmSupScript.width = supScriptSize.width; @@ -198,11 +194,13 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord aSupScriptShift; - if (mScriptLevel == 0 && mDisplayStyle && !mCompressed) { + if ( mPresentationData.scriptLevel == 0 && + NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && + !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style D in TeXbook aSupScriptShift = aSupScriptShift1; } - else if (mCompressed) { + else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' aSupScriptShift = aSupScriptShift3; } @@ -246,17 +244,19 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext, 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 + aDesiredSize.ascent = PR_MAX(baseSize.ascent, supScriptSize.ascent + actualSupScriptShift); aDesiredSize.descent = PR_MAX(baseSize.descent, supScriptSize.descent - actualSupScriptShift); aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent; - aDesiredSize.width = mBoundingMetrics.width; - - mBoundingMetrics.descent = -mBoundingMetrics.descent; + aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width; if (aPlaceOrigin) { nscoord dx, dy; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.h index 89195f76696..d74aeb806ac 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmsupFrame.h @@ -69,7 +69,9 @@ protected: virtual PRIntn GetSkipSides() const { return 0; } - private: +private: + nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript + // = 0.5pt in plain TeX float mSupScriptShiftFactor; PRBool mUserSetFlag; }; diff --git a/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.cpp index d251b994849..ef4d329a4ed 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.cpp @@ -80,6 +80,125 @@ nsMathMLmunderFrame::Init(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsMathMLmunderFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv; + rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + + // check whether or not this is an embellished operator + EmbellishOperator(); + + // set our accentunder flag + /* The REC says: + The default value of accentunder is false, unless underscript + is an element or an embellished operator. If underscript is + an element, the value of its accent attribute is used as the + default value of accentunder. If underscript is an embellished + operator, the accent attribute of the element at its + core is used as the default value. As with all attributes, an + explicitly given value overrides the default. + +XXX The winner is the outermost setting in conflicting settings like these: + + ... + ... + + */ + + PRInt32 count = 0; + nsIFrame* baseFrame = nsnull; + nsIFrame* underscriptFrame = nsnull; + nsIFrame* childFrame = mFrames.FirstChild(); + while (childFrame) { + if (!IsOnlyWhitespace(childFrame)) { + count++; + if (1 == count) baseFrame = childFrame; + if (2 == count) { underscriptFrame = childFrame; break; } + } + childFrame->GetNextSibling(&childFrame); + } + + nsIMathMLFrame* underscriptMathMLFrame = nsnull; + nsIMathMLFrame* aMathMLFrame = nsnull; + nsEmbellishData embellishData; + nsAutoString value; + + mPresentationData.flags &= ~NS_MATHML_MOVABLELIMITS; // default is false + mPresentationData.flags &= ~NS_MATHML_ACCENTUNDER; // default of accentunder is false + + // see if the baseFrame has movablelimits="true" or if it is an + // embellished operator whose movablelimits attribute is set to true + if (baseFrame && NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { + nsCOMPtr baseContent; + baseFrame->GetContent(getter_AddRefs(baseContent)); + if (NS_CONTENT_ATTR_HAS_VALUE == baseContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::movablelimits_, value)) { + if (value == "true") { + mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; + } + } + else { // no attribute, get the value from the core + rv = mEmbellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(embellishData.flags)) { + mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; + } + } + } + } + + // see if the underscriptFrame is or an embellished operator + if (underscriptFrame) { + rv = underscriptFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&underscriptMathMLFrame); + if (NS_SUCCEEDED(rv) && underscriptMathMLFrame) { + underscriptMathMLFrame->GetEmbellishData(embellishData); + // core of the underscriptFrame + if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.core) { + rv = embellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + // if we have the accentunder attribute, tell the core to behave as + // requested (otherwise leave the core with its default behavior) + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::accentunder_, value)) + { + if (value == "true") embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + else if (value == "false") embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; + aMathMLFrame->SetEmbellishData(embellishData); + } + + // sync the presentation data: record whether we have an accentunder + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mPresentationData.flags |= NS_MATHML_ACCENTUNDER; + } + } + } + } + + //The REC says: + /* + Within underscript, always sets displaystyle to "false", + but increments scriptlevel by 1 only when accentunder is "false". + */ + + PRInt32 incrementScriptLevel; + + if (underscriptMathMLFrame) { + incrementScriptLevel = NS_MATHML_IS_ACCENTUNDER(mPresentationData.flags)? 0 : 1; + underscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE); + underscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE); + } + + // switch the style of the underscript + InsertScriptLevelStyleContext(aPresContext); + + return rv; +} + NS_IMETHODIMP nsMathMLmunderFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -111,6 +230,25 @@ nsMathMLmunderFrame::Reflow(nsIPresContext* aPresContext, return NS_OK; } +/* +The REC says: +* If the base is an operator with movablelimits="true" (or + an embellished operator whose element core has + movablelimits="true"), and displaystyle="false", then + underscript is drawn in a subscript position. In this case, + the accentunder attribute is ignored. This is often used + for limits on symbols such as ∑. + +TODO: + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + // place like subscript + } + else { + // place like accentunder + } +*/ + NS_IMETHODIMP nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -170,8 +308,8 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext, } // 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/nsMathMLmunderFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.h index d5756708983..3733102e285 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmunderFrame.h @@ -56,17 +56,7 @@ public: NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, - nsIFrame* aChildList) - { - nsresult rv; - rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE); - // switch the style of the underscript - InsertScriptLevelStyleContext(aPresContext); - // check whether or not this is an embellished operator - EmbellishOperator(); - return rv; - } + nsIFrame* aChildList); protected: nsMathMLmunderFrame(); diff --git a/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp b/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp index 834ad856243..eac65532c2a 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp +++ b/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.cpp @@ -80,6 +80,163 @@ nsMathMLmunderoverFrame::Init(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsMathMLmunderoverFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv; + rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); + + // check whether or not this is an embellished operator + EmbellishOperator(); + + // set our accent and accentunder flags + /* + The REC says: + + The accent and accentunder attributes have the same effect as + the attributes with the same names on and , + respectively. Their default values are also computed in the + same manner as described for those elements, with the default + value of accent depending on overscript and the default value + of accentunder depending on underscript. + */ + + // get our overscript and underscript frames + PRInt32 count = 0; + nsIFrame* baseFrame = nsnull; + nsIFrame* underscriptFrame = nsnull; + nsIFrame* overscriptFrame = nsnull; + nsIFrame* childFrame = mFrames.FirstChild(); + while (childFrame) { + if (!IsOnlyWhitespace(childFrame)) { + count++; + if (1 == count) baseFrame = childFrame; + if (2 == count) underscriptFrame = childFrame; + if (3 == count) { overscriptFrame = childFrame; break; } + } + childFrame->GetNextSibling(&childFrame); + } + + nsIMathMLFrame* underscriptMathMLFrame = nsnull; + nsIMathMLFrame* overscriptMathMLFrame = nsnull; + nsIMathMLFrame* aMathMLFrame = nsnull; + nsEmbellishData embellishData; + nsAutoString value; + + mPresentationData.flags &= ~NS_MATHML_MOVABLELIMITS; // default is false + mPresentationData.flags &= ~NS_MATHML_ACCENTUNDER; // default of accentunder is false + mPresentationData.flags &= ~NS_MATHML_ACCENTOVER; // default of accent is false + + // see if the baseFrame has movablelimits="true" or if it is an + // embellished operator whose movablelimits attribute is set to true + if (baseFrame && NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) { + nsCOMPtr baseContent; + baseFrame->GetContent(getter_AddRefs(baseContent)); + if (NS_CONTENT_ATTR_HAS_VALUE == baseContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::movablelimits_, value)) { + if (value == "true") { + mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; + } + } + else { // no attribute, get the value from the core + rv = mEmbellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + if (NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(embellishData.flags)) { + mPresentationData.flags |= NS_MATHML_MOVABLELIMITS; + } + } + } + } + + // see if the underscriptFrame is or an embellished operator + if (underscriptFrame) { + rv = underscriptFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&underscriptMathMLFrame); + if (NS_SUCCEEDED(rv) && underscriptMathMLFrame) { + underscriptMathMLFrame->GetEmbellishData(embellishData); + // core of the underscriptFrame + if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.core) { + rv = embellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + // if we have the accentunder attribute, tell the core to behave as + // requested (otherwise leave the core with its default behavior) + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::accentunder_, value)) + { + if (value == "true") embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + else if (value == "false") embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; + aMathMLFrame->SetEmbellishData(embellishData); + } + + // sync the presentation data: record whether we have an accentunder + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mPresentationData.flags |= NS_MATHML_ACCENTUNDER; + } + } + } + } + + // see if the overscriptFrame is or an embellished operator + if (overscriptFrame) { + rv = overscriptFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&overscriptMathMLFrame); + if (NS_SUCCEEDED(rv) && overscriptMathMLFrame) { + overscriptMathMLFrame->GetEmbellishData(embellishData); + // core of the overscriptFrame + if (NS_MATHML_IS_EMBELLISH_OPERATOR(embellishData.flags) && embellishData.core) { + rv = embellishData.core->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame); + if (NS_SUCCEEDED(rv) && aMathMLFrame) { + aMathMLFrame->GetEmbellishData(embellishData); + // if we have the accent attribute, tell the core to behave as + // requested (otherwise leave the core with its default behavior) + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, + nsMathMLAtoms::accent_, value)) + { + if (value == "true") embellishData.flags |= NS_MATHML_EMBELLISH_ACCENT; + else if (value == "false") embellishData.flags &= ~NS_MATHML_EMBELLISH_ACCENT; + aMathMLFrame->SetEmbellishData(embellishData); + } + + // sync the presentation data: record whether we have an accent + if (NS_MATHML_EMBELLISH_IS_ACCENT(embellishData.flags)) + mPresentationData.flags |= NS_MATHML_ACCENTOVER; + } + } + } + } + + //The REC says: + /* + Within underscript, always sets displaystyle to "false", + but increments scriptlevel by 1 only when accentunder is "false". + + Within overscript, always sets displaystyle to "false", + 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); + underscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE); + } + + if (overscriptMathMLFrame) + { + incrementScriptLevel = NS_MATHML_IS_ACCENTOVER(mPresentationData.flags)? 0 : 1; + overscriptMathMLFrame->UpdatePresentationData(incrementScriptLevel, PR_FALSE); + overscriptMathMLFrame->UpdatePresentationDataFromChildAt(0, incrementScriptLevel, PR_FALSE); + } + + // switch the style of the underscript and the overscript + InsertScriptLevelStyleContext(aPresContext); + + return rv; +} + NS_IMETHODIMP nsMathMLmunderoverFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -90,7 +247,7 @@ nsMathMLmunderoverFrame::Reflow(nsIPresContext* aPresContext, nsresult rv = NS_OK; ///////////// - // Reflow children to stretch themselves + // Reflow children ReflowChildren(1, aPresContext, aDesiredSize, aReflowState, aStatus); @@ -111,6 +268,25 @@ nsMathMLmunderoverFrame::Reflow(nsIPresContext* aPresContext, return NS_OK; } +/* +The REC says: +* If the base is an operator with movablelimits="true" (or an embellished + operator whose element core has movablelimits="true"), and + displaystyle="false", then underscript and overscript are drawn in + a subscript and superscript position, respectively. In this case, + the accent and accentunder attributes are ignored. This is often + used for limits on symbols such as ∑. + +TODO: + if ( NS_MATHML_IS_MOVABLELIMITS(mPresentationData.flags) && + !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { + // place like subscript-superscript pair + } + else { + // place like accentunder-accent pair + } +*/ + NS_IMETHODIMP nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -173,9 +349,9 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext, } // 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/nsMathMLmunderoverFrame.h b/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.h index 5707b075b22..6973317e5ef 100644 --- a/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.h +++ b/mozilla/layout/mathml/base/src/nsMathMLmunderoverFrame.h @@ -56,17 +56,7 @@ public: NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, - nsIFrame* aChildList) - { - nsresult rv; - rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); - UpdatePresentationDataFromChildAt(1, 1, PR_FALSE); - // switch the style of the underscript and the overscript - InsertScriptLevelStyleContext(aPresContext); - // check whether or not this is an embellished operator - EmbellishOperator(); - return rv; - } + nsIFrame* aChildList); protected: nsMathMLmunderoverFrame();