[NOT PART OF THE DEFAULT BUILD]. *Changes to bring the MathML code in sync with layout (this will clear bugs 19398 and 20858). *Postfixed atoms with underscore. *Major revamps to launch the support of embellished operators.

This commit is contained in:
rbs%maths.uq.edu.au 1999-12-10 13:02:23 +00:00
Родитель 26924339a8
Коммит 1231a3e001
42 изменённых файлов: 1898 добавлений и 1048 удалений

Просмотреть файл

@ -22,6 +22,15 @@
#ifndef nsIMathMLFrame_h___
#define nsIMathMLFrame_h___
struct nsEmbellishState;
struct nsStretchMetrics;
typedef PRInt32 nsStretchDirection;
#define NS_STRETCH_DIRECTION_UNSUPPORTED -1
#define NS_STRETCH_DIRECTION_DEFAULT 0
#define NS_STRETCH_DIRECTION_HORIZONTAL 1
#define NS_STRETCH_DIRECTION_VERTICAL 2
// IID for the nsIMathMLFrame interface (the IID was taken from IIDS.h)
/* a6cf9113-15b3-11d2-932e-00805f8add32 */
#define NS_IMATHMLFRAME_IID \
@ -34,20 +43,133 @@ class nsIMathMLFrame : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IMATHMLFRAME_IID; return iid; }
/* SUPPORT FOR PRECISE POSITIONING */
/*====================================================================*/
/* Metrics that _exactly_ enclose the text of the frame.
* The frame *must* have *already* being reflowed, before you can call
* the GetBoundingMetrics() method.
* Note that for a frame with nested children, the bounding metrics
* will exactly enclose its children. For example, the bounding metrics
* of msub is the smallest rectangle that exactly encloses both the
* base and the subscript.
*/
NS_IMETHOD
GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) = 0;
NS_IMETHOD
SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics) = 0;
/*
NS_IMETHOD
GetReference(nsPoint& aReference) = 0;
NS_IMETHOD
SetReference(const nsPoint& aReference) = 0;
*/
/* SUPPORT FOR STRETCHY ELEMENTS: <mo> */
/*====================================================================*/
/* Stretch :
* method used to ask a stretchy MathML frame to stretch
* itself depending on its context
* Called to ask a stretchy MathML frame to stretch itself depending
* on its context.
*
* @param aStretchDirection [in] the direction where to attempt to
* stretch.
* @param aContainerSize [in] struct that suggests the maximumn size for
* the stretched frame. Only member data of the struct that are
* relevant to the direction are used (the rest is ignored).
* @param aDesiredStretchSize [in/out] On input the current size
* size of the frame, on output the size after stretching.
*/
NS_IMETHOD
Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize) = 0;
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize) = 0;
#if 0
NS_IMETHOD
GetDesiredStretchSize(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchMetrics& aDesiredStretchSize) = 0;
#endif
/* Place :
* This method is used before returning from Reflow(), or when a MathML frame
* has just been stretched. It is called to fine-tune the positions of the elements.
*
* IMPORTANT: This method uses the origin of child frames (rect.x and rect.y) as
* placeholders between calls: On invocation, child->GetRect(rect) should give a
* rect such that rect.x holds the child's descent, rect.y holds the child's ascent,
* (rect.width should give the width, and rect.height should give the height).
* The Place() method will use this information to compute the desired size
* of the frame.
*
* @param aPlaceOrigin [in]
* If aPlaceOrigin is false, compute your desired size using the
* information in your children's rectangles. However, upon return,
* the origins of your children should keep their ascent information, i.e.,
* a child rect.x, and rect.y should still act like placeholders for the
* child's descent and ascent.
*
* If aPlaceOrigin is true, reflow is finished. You should position all
* your children, and return your desired size. You should now convert
* the origins of your child frames into the coordinate system
* expected by Gecko (which is relative to the upper-left
* corner of the parent) and use FinishReflowChild() on your children
* to complete post-reflow operations.
*
* @param aDesiredSize [out] parameter where you should return your
* desired size and your ascent/descent info. Compute your desired size
* using the information in your children's rectangles, and include any
* space you want for border/padding in the desired size you return.
*/
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize) = 0;
/* EmbellishOperator :
* Call this method to probe and set a frame as an "embellished operator".
* Calls must be bottom up. The method will set the frame as an
* "embellished operator" if the frame satisfies the definition of
* the MathML REC. Conversely, it will set the frame as
* non-embellished if it is not an "embellished operator".
*
* Note that this method must only be called from tags who *can* be
* embellished operators.
*
* The MathML REC precisely defines an "embellished operator" as:
* - an <mo> element;
* - or one of the elements <msub>, <msup>, <msubsup>, <munder>, <mover>,
* <munderover>, <mmultiscripts>, <mfrac>, or <semantics>, whose first
* argument exists and is an embellished operator;
* - or one of the elements <mstyle>, <mphantom>, or <mpadded>, such that
* an <mrow> containing the same arguments would be an embellished
* operator;
* - or an <maction> element whose selected subexpression exists and is an
* embellished operator;
* - or an <mrow> whose arguments consist (in any order) of one embellished
* operator and zero or more spacelike elements.
*
* When an embellished frame receives a Stretch() command, it passes the
* command to its first child and the stretched size is bubbled up from the
* inner-most <mo> frame.
*/
NS_IMETHOD
EmbellishOperator() = 0;
/* GetEmbellishState/SetEmbellishState :
* Get/Set the mEmbellish member data.
*/
NS_IMETHOD
GetEmbellishState(nsEmbellishState& aEmbellishState) = 0;
NS_IMETHOD
SetEmbellishState(const nsEmbellishState& aEmbellishState) = 0;
/* SUPPORT FOR SCRIPTING ELEMENTS: */
@ -64,6 +186,7 @@ public:
* Increments the scriptlevel of the frame, and set its displaystyle.
* Note that <mstyle> is the only tag which allows to set
* <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
* to reset or increment the scriptlevel in a manual way.
* Therefore <mstyle> has its peculiar version of this method.
*/
NS_IMETHOD
@ -86,5 +209,94 @@ public:
PRBool aDisplayStyle) = 0;
};
/* Structure used for stretching a frame. */
struct nsStretchMetrics {
// nscoord leading;
nscoord descent, ascent;
nscoord width, height;
float leftSpace, rightSpace;
nsStretchMetrics(nscoord aDescent = 0,
nscoord aAscent = 0,
nscoord aWidth = 0,
nscoord aHeight = 0,
float aLeftSpace = 0.0f,
float aRightSpace = 0.0f) {
width = aWidth;
height = aHeight;
ascent = aAscent;
descent = aDescent;
leftSpace = aLeftSpace;
rightSpace = aRightSpace;
}
nsStretchMetrics(const nsStretchMetrics& aStretchMetrics) {
width = aStretchMetrics.width;
height = aStretchMetrics.height;
ascent = aStretchMetrics.ascent;
descent = aStretchMetrics.descent;
leftSpace = aStretchMetrics.leftSpace;
rightSpace = aStretchMetrics.rightSpace;
}
nsStretchMetrics(const nsHTMLReflowMetrics& aReflowMetrics) {
width = aReflowMetrics.width;
height = aReflowMetrics.height;
ascent = aReflowMetrics.ascent;
descent = aReflowMetrics.descent;
leftSpace = 0.0f;
rightSpace = 0.0f;
}
PRBool
operator == (const nsStretchMetrics& aStretchMetrics) {
return (width == aStretchMetrics.width &&
height == aStretchMetrics.height &&
ascent == aStretchMetrics.ascent &&
descent == aStretchMetrics.descent &&
leftSpace == aStretchMetrics.leftSpace &&
rightSpace == aStretchMetrics.rightSpace);
}
};
#define NS_MATHML_EMBELLISH_OPERATOR 0x1
#define NS_MATHML_STRETCH_FIRST_CHILD NS_MATHML_EMBELLISH_OPERATOR
#define NS_MATHML_STRETCH_ALL_CHILDREN 0x2
#define NS_MATHML_STRETCH_DONE 0x4
#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))
// <mrow> (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))
// struct used by an embellished container to keep track of its embellished child
struct nsEmbellishState {
PRUint32 flags;
nsIFrame* firstChild; // handy pointer on our embellished child
nsIFrame* core; // pointer on the mo frame at the core of the embellished hierarchy
nsStretchDirection direction;
nscoord leftSpace, rightSpace;
nsEmbellishState()
{
flags = 0;
firstChild = nsnull;
core = nsnull;
direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
leftSpace = rightSpace = 0;
}
};
#endif /* nsIMathMLFrame_h___ */

Просмотреть файл

@ -48,6 +48,7 @@
// XXX Error-prone stuff. See how it can be automated.
/* Structure of the table gMathMLCharGlyph[]:
------------------------------------------
The table is divided into sections, each corresponding to a
stretchy symbol. Each section itself is divided into two blocks
that are separated with the special null code 0x0000.
@ -58,8 +59,8 @@
Another separate table, gMathMLCharIndex[], is used to store
pointers to the beginning of each section.
3 steps are needed to extend the table:
---------------------------------------
Three steps are needed to extend the table:
---------------------------------------=---
1. Append your new section in gMathMLCharGlyph[].
2. Append your new enum in nsMathMLCharEnum, and kMathMLChar
3. Append a new pointer in gMathMLCharIndex[], so that
@ -222,17 +223,29 @@ static PRUnichar gMathMLCharGlyph[] = {
//------------
//index = 66
//Section for: square-root bar
0xF8E5, // RADICAL EXTENDER # radicalex (CUS)
0x00AF, // RADICAL EXTENDER # radicalex (CUS) -- formerly 0xF8E5
0x0000, // That's all folks ...
//Block of partial glyphs in the order top/left, middle, bottom/right, glue
0xF8E5, // RADICAL EXTENDER # radicalex (CUS)
0xF8E5, // RADICAL EXTENDER # radicalex (CUS)
0xF8E5, // RADICAL EXTENDER # radicalex (CUS)
0xF8E5, // RADICAL EXTENDER # radicalex (CUS)
0x00AF, // RADICAL EXTENDER # radicalex (CUS)
0x00AF, // RADICAL EXTENDER # radicalex (CUS)
0x00AF, // RADICAL EXTENDER # radicalex (CUS)
0x00AF, // RADICAL EXTENDER # radicalex (CUS)
//------------
//index = 72
//Section for: vertical bar (0x2223)
'|',
0x0000, // That's all folks ...
//Block of partial glyphs in the order top/left, middle, bottom/right, glue
'|',
'|',
'|',
'|',
//------------
//index = 78
//end of table ...
0x0000,
};
@ -251,47 +264,84 @@ static PRInt32 gMathMLCharIndex[] = {
54, // eMathMLChar_LeftArrow,
60, // eMathMLChar_RightArrow,
66, // eMathMLChar_RadicalBar,
72, // safeguard, *must* always point at the *end* of gMathMLCharGlyph[]
72, // eMathMLChar_Radical, -- placeholder for now
72, // eMathMLChar_VerticalBar,
78, // safeguard, *must* always point at the *end* of gMathMLCharGlyph[]
};
// data to enable a clean architecture and extensibility
#define STRETCH_UNSUPPORTED NS_STRETCH_DIRECTION_UNSUPPORTED
#define STRETCH_HORIZONTAL NS_STRETCH_DIRECTION_HORIZONTAL
#define STRETCH_VERTICAL NS_STRETCH_DIRECTION_VERTICAL
static const PRInt32 kMathMLChar[] = {
eMathMLChar_LeftParenthesis , '(',
eMathMLChar_RightParenthesis , ')',
eMathMLChar_Integral , 0x222B,
eMathMLChar_LeftSquareBracket, '[',
eMathMLChar_RightSquareBracket, ']',
eMathMLChar_LeftCurlyBracket, '{',
eMathMLChar_RightCurlyBracket, '}',
eMathMLChar_DownArrow, 0x2193,
eMathMLChar_UpArrow, 0x2191,
eMathMLChar_LeftArrow, 0x2190,
eMathMLChar_RightArrow, 0x2192,
eMathMLChar_RadicalBar, 0xF8E5,
// eMathMLChar_Radical, 0x221A,
eMathMLChar_LeftParenthesis , '(', STRETCH_VERTICAL,
eMathMLChar_RightParenthesis , ')', STRETCH_VERTICAL,
eMathMLChar_Integral , 0x222B, STRETCH_VERTICAL,
eMathMLChar_LeftSquareBracket, '[', STRETCH_VERTICAL,
eMathMLChar_RightSquareBracket, ']', STRETCH_VERTICAL,
eMathMLChar_LeftCurlyBracket, '{', STRETCH_VERTICAL,
eMathMLChar_RightCurlyBracket, '}', STRETCH_VERTICAL,
eMathMLChar_DownArrow, 0x2193, STRETCH_VERTICAL,
eMathMLChar_UpArrow, 0x2191, STRETCH_VERTICAL,
eMathMLChar_LeftArrow, 0x2190, STRETCH_HORIZONTAL,
eMathMLChar_RightArrow, 0x2192, STRETCH_HORIZONTAL,
eMathMLChar_RadicalBar, 0x00AF, STRETCH_HORIZONTAL,
eMathMLChar_Radical, 0x221A, STRETCH_UNSUPPORTED,
eMathMLChar_VerticalBar, '|', STRETCH_VERTICAL,
};
#undef STRETCH_UNSUPPORTED
#undef STRETCH_HORIZONTAL
#undef STRETCH_VERTICAL
//---------------------------------------------
// Helper method that detects a new enum and cache it for you.
// You do not have to call this method. SetData() will call it
// for you whenever mData changes.
// If you call SetData(), it will lookup the enum
// of the char and set it for you.
void
nsMathMLChar::SetEnum() {
nsMathMLChar::SetData(nsString& aData) {
mData = aData;
// some assumptions until proven otherwise!
mEnum = eMathMLChar_DONT_STRETCH;
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
// lookup the enum ...
if (1 == mData.Length()) {
PRUnichar ch = mData[0];
PRInt32 count = sizeof(kMathMLChar) / sizeof(kMathMLChar[0]);
for (PRInt32 i = 0; i < count; i += 2) {
for (PRInt32 i = 0; i < count; i += 3) {
if (ch == kMathMLChar[i+1]) {
mEnum = nsMathMLCharEnum(kMathMLChar[i]);
mDirection = kMathMLChar[i+2];
break;
}
}
}
}
// If you call SetEnum(), it will lookup the actual value
// of the char and set it for you.
void
nsMathMLChar::SetEnum(nsMathMLCharEnum aEnum) {
mEnum = aEnum;
// some assumptions until proven otherwise!
mData = "";
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
// lookup the data ...
if (mEnum != eMathMLChar_DONT_STRETCH) {
PRInt32 count = sizeof(kMathMLChar) / sizeof(kMathMLChar[0]);
for (PRInt32 i = 0; i < count; i += 3) {
if (mEnum == kMathMLChar[i]) {
mData = PRUnichar(kMathMLChar[i+1]);
mDirection = kMathMLChar[i+2];
break;
}
}
}
NS_ASSERTION(mData.Length(), "Something is wrong somewhere");
}
/*
The Stretch:
@param aContainerSize - suggested size for the stretched char
@ -328,46 +378,47 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIStyleContext* aStyleContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize)
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize)
{
nsresult rv = NS_OK;
nsStretchDirection aDirection = aStretchDirection;
if (aDirection == NS_STRETCH_DIRECTION_DEFAULT) {
aDirection = mDirection;
}
// quick return if there is nothing special about this char
if (eMathMLChar_DONT_STRETCH == mEnum) {
if (eMathMLChar_DONT_STRETCH == mEnum || aDirection != mDirection) {
return NS_OK;
}
// check the common situations where stretching is not actually needed
// XXX need better criteria
if (aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) {
if (aDirection == NS_STRETCH_DIRECTION_VERTICAL) {
if (aContainerSize.height <= aDesiredStretchSize.height) {
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char behaves like a normal char
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char later behaves like a normal char
return NS_OK;
}
}
else if (aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL) {
else if (aDirection == NS_STRETCH_DIRECTION_HORIZONTAL) {
if (aContainerSize.width <= aDesiredStretchSize.width) {
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char behaves like a normal char
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char later behaves like a normal char
return NS_OK;
}
}
// printf("Container height:%d ascent:%d descent:%d\n contains height:%d ascent:%d descent:%d\n",
// aContainerSize.height, aContainerSize.ascent, aContainerSize.descent,
// aDesiredStretchSize.height, aDesiredStretchSize.ascent,
// printf("Container height:%d width:%d ascent:%d descent:%d\n contains height:%d width:%d ascent:%d descent:%d\n",
// aContainerSize.height, aContainerSize.width, aContainerSize.ascent, aContainerSize.descent,
// aDesiredStretchSize.height, aDesiredStretchSize.width, aDesiredStretchSize.ascent,
// aDesiredStretchSize.descent);
// XXX Note: there are other symbols that just need to slightly
// increase their size, like \Sum
// Set font
nsStyleFont font;
nsStyleColor color;
aStyleContext->GetStyle(eStyleStruct_Font, font);
aStyleContext->GetStyle(eStyleStruct_Color, color);
// Set color and font
aRenderingContext.SetColor(color.mColor);
aRenderingContext.SetFont(font.mFont);
nscoord height = aDesiredStretchSize.height;
@ -383,24 +434,25 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
PRBool sizeOK = PR_FALSE;
PRUnichar ch = gMathMLCharGlyph[index++];
nsBoundingMetrics bm;
while (ch && index <= limit) {
// printf("Checking size of:%c index:%d\n", ch & 0x00FF, index);
rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; }
h = bm.ascent - bm.descent;
w = bm.width;
w = bm.rightBearing - bm.leftBearing;
// printf("height:%d width:%d ascent:%d descent:%d\n",
// height, bm.width, bm.ascent, bm.descent);
// XXX temp hack -- need better criteria
if ((aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL && h > height) ||
(aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL && w > width)) {
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
ascent = bm.ascent;
height = bm.ascent - bm.descent;
width = bm.width;
width = bm.rightBearing - bm.leftBearing;
mGlyph = ch;
break;
}
@ -413,7 +465,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
nscoord a, d;
h = w = a = d = 0;
float flex[3] = {0.7f, 0.3f, 0.7f}; // XXX hack!
if (aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) {
if (aDirection == NS_STRETCH_DIRECTION_VERTICAL) {
// default is to fill-up the area given to us
width = aDesiredStretchSize.width;
height = aContainerSize.height;
@ -434,7 +486,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
return NS_OK;
}
}
else if (aStretchDirection == NS_STRETCH_DIRECTION_HORIZONTAL) {
else if (aDirection == NS_STRETCH_DIRECTION_HORIZONTAL) {
// default is to fill-up the area given to us
width = aContainerSize.width;
height = aDesiredStretchSize.height;
@ -450,6 +502,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
if (i < 3) w += nscoord(flex[i]*(bm.rightBearing-bm.leftBearing)); // sum widths of the parts...
}
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;
} else { // sum of parts doesn't fit in the space... will use a single glyph
@ -459,9 +512,6 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
}
}
// cache the stretch direction to be used later at the painting stage
mDirection = aStretchDirection;
aDesiredStretchSize.width = width;
aDesiredStretchSize.height = height;
aDesiredStretchSize.ascent = ascent;
@ -486,13 +536,13 @@ nsMathMLChar::Paint(nsIPresContext* aPresContext,
aRenderingContext.SetColor(color.mColor);
aRenderingContext.SetFont(font.mFont);
// quick return if there is nothing special about this char ...
if (eMathMLChar_DONT_STRETCH == mEnum) {
if (eMathMLChar_DONT_STRETCH == mEnum || NS_STRETCH_DIRECTION_UNSUPPORTED == mDirection) {
// normal drawing if there is nothing special about this char ...
aRenderingContext.DrawString(mData.GetUnicode(), PRUint32(mData.Length()), mRect.x, mRect.y);
return NS_OK;
//printf("Painting %04X like a normal char\n", mData[0]);
}
if (0 < mGlyph) { // wow, there is a glyph of appropriate size!
else if (0 < mGlyph) { // wow, there is a glyph of appropriate size!
//printf("Painting %04X with a glyph of appropriate size\n", mData[0]);
aRenderingContext.DrawString(&mGlyph, PRUint32(1), mRect.x, mRect.y);
}
else { // paint by parts
@ -503,10 +553,10 @@ nsMathMLChar::Paint(nsIPresContext* aPresContext,
fm->GetMaxAscent(fontAscent);
fm->GetMaxDescent(fontDescent);
// do the painting ...
if (mDirection == NS_STRETCH_DIRECTION_VERTICAL)
if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
return PaintVertically(aPresContext, aRenderingContext, aStyleContext,
fontAscent, fontDescent, mEnum, mRect);
else if (mDirection == NS_STRETCH_DIRECTION_HORIZONTAL)
else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
return PaintHorizontally(aPresContext, aRenderingContext, aStyleContext,
fontAscent, fontDescent, mEnum, mRect);
}
@ -519,16 +569,16 @@ nsMathMLChar::Paint(nsIPresContext* aPresContext,
// draw a glyph in a clipped area so that we don't have hairy chars pending outside
void
nsMathMLChar::DrawChar(nsIRenderingContext& aRenderingContext,
PRUnichar aChar,
nscoord aX,
nscoord aY,
nsRect& aClipRect)
nsMathMLChar::DrawGlyph(nsIRenderingContext& aRenderingContext,
PRUnichar aGlyph,
nscoord aX,
nscoord aY,
nsRect& aClipRect)
{
PRBool clipState;
aRenderingContext.PushState();
aRenderingContext.SetClipRect(aClipRect, nsClipCombine_kIntersect, clipState);
aRenderingContext.DrawString(&aChar, PRUint32(1), aX, aY);
aRenderingContext.DrawString(&aGlyph, PRUint32(1), aX, aY);
aRenderingContext.PopState(clipState);
}
@ -548,10 +598,10 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext,
// jump past the glyphs of various size...
PRUnichar ch = gMathMLCharGlyph[index++];
while (ch && index <= limit) {
ch = gMathMLCharGlyph[index++];
ch = gMathMLCharGlyph[index++];
}
// return if there are no partial glyphs (an erroneous table!)
if (!gMathMLCharGlyph[index]) return NS_OK;
if (!gMathMLCharGlyph[index]) { printf("Erroneous gMathMLCharGlyph table!\n"); return NS_OK; }
nscoord dx = aRect.x;
nscoord dy = aRect.y;
@ -628,7 +678,7 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext,
if (!clipRect.IsEmpty()) {
clipRect.Inflate(onePixel, onePixel);
DrawChar(aRenderingContext, ch, dx, dy, clipRect);
DrawGlyph(aRenderingContext, ch, dx, dy, clipRect);
}
}
@ -653,7 +703,7 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext,
}
count++;
dy += stride;
DrawChar(aRenderingContext, ch, dx, dy, clipRect);
DrawGlyph(aRenderingContext, ch, dx, dy, clipRect);
// NS_ASSERTION(5000 == count, "Error - gMathMLCharGlyph is incorrectly set");
if (1000 == count) return NS_ERROR_UNEXPECTED;
}
@ -686,7 +736,7 @@ nsMathMLChar::PaintHorizontally(nsIPresContext* aPresContext,
ch = gMathMLCharGlyph[index++];
}
// return if there are no partial glyphs (an erroneous table!)
if (!gMathMLCharGlyph[index]) return NS_OK;
if (!gMathMLCharGlyph[index]) { printf("Erroneous gMathMLCharGlyph table!\n"); return NS_OK; }
nscoord dx = aRect.x;
nscoord dy = aRect.y;
@ -757,7 +807,7 @@ nsMathMLChar::PaintHorizontally(nsIPresContext* aPresContext,
// getchar();
if (!clipRect.IsEmpty()) {
clipRect.Inflate(onePixel, onePixel);
DrawChar(aRenderingContext, ch, dx, dy, clipRect);
DrawGlyph(aRenderingContext, ch, dx, dy, clipRect);
}
}
@ -784,7 +834,7 @@ nsMathMLChar::PaintHorizontally(nsIPresContext* aPresContext,
}
count++;
dx += stride;
DrawChar(aRenderingContext, ch, dx, dy, clipRect);
DrawGlyph(aRenderingContext, ch, dx, dy, clipRect);
// NS_ASSERTION(5000 == count, "Error - gMathMLCharGlyph is incorrectly set");
if (1000 == count) return NS_ERROR_UNEXPECTED;
// printf("Drawing %04X ascent:%d descent:%d at position dx:%d dy:%d\n",

Просмотреть файл

@ -23,13 +23,9 @@
#define nsMathMLChar_h___
#include "nsMathMLOperators.h"
#include "nsIMathMLFrame.h"
typedef PRUint32 nsStretchDirection;
#define NS_STRETCH_DIRECTION_HORIZONTAL 0
#define NS_STRETCH_DIRECTION_VERTICAL 1
// chars that we know how to stretch
// chars that we know how something about
enum nsMathMLCharEnum {
eMathMLChar_DONT_STRETCH = -1,
eMathMLChar_LeftParenthesis,
@ -44,57 +40,12 @@ enum nsMathMLCharEnum {
eMathMLChar_LeftArrow,
eMathMLChar_RightArrow,
eMathMLChar_RadicalBar,
eMathMLChar_Radical,
eMathMLChar_VerticalBar,
eMathMLChar_COUNT
};
// Structure used for a char's size and alignment information.
struct nsCharMetrics {
// nscoord leading;
nscoord descent, ascent;
nscoord width, height;
nsCharMetrics(nscoord aDescent=0, nscoord aAscent=0,
nscoord aWidth=0, nscoord aHeight=0) {
width = aWidth;
height = aHeight;
ascent = aAscent;
descent = aDescent;
}
nsCharMetrics(const nsCharMetrics& aCharMetrics) {
width = aCharMetrics.width;
height = aCharMetrics.height;
ascent = aCharMetrics.ascent;
descent = aCharMetrics.descent;
}
nsCharMetrics(const nsHTMLReflowMetrics& aReflowMetrics) {
width = aReflowMetrics.width;
height = aReflowMetrics.height;
ascent = aReflowMetrics.ascent;
descent = aReflowMetrics.descent;
}
#if 0
void
operator=(const nsCharMetrics& aCharMetrics) {
width = aCharMetrics.width;
height = aCharMetrics.height;
ascent = aCharMetrics.ascent;
descent = aCharMetrics.descent;
}
#endif
PRBool
operator==(const nsCharMetrics& aCharMetrics) {
return (width == aCharMetrics.width &&
height == aCharMetrics.height &&
ascent == aCharMetrics.ascent &&
descent == aCharMetrics.descent);
}
};
// class used to handle stretchy symbols (accent and boundary symbols)
// class used to handle stretchy symbols (accent and boundary symbol)
class nsMathMLChar
{
public:
@ -103,49 +54,59 @@ public:
{
}
/*
nsMathMLChar() : mData(),
mGlyph(0)
{
nsStr::Initialize(mData, eTwoByte); // with MathML, we are two-byte by default
}
*/
virtual ~nsMathMLChar()
{
}
NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIStyleContext* aStyleContext);
NS_IMETHOD
Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIStyleContext* aStyleContext);
// This is the method called to ask the char to stretch itself.
// aDesiredStretchSize is an IN/OUT parameter.
// On input - it contains our current size.
// On output - the same size or the new size that the char wants.
NS_IMETHOD Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIStyleContext* aStyleContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize);
NS_IMETHOD
Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsIStyleContext* aStyleContext,
nsStretchDirection aStretchDirection,
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize);
// If you call SetData(), it will lookup the enum of the data
// and set mEnum for you. If the data is an arbitrary string for
// which no enum is defined, mEnum is set to eMathMLChar_DONT_STRETCH
// and the data is interpreted as a normal string.
void
SetData(nsString& aData);
void
SetData(nsString& aData) {
mData = aData;
SetEnum();
}
void
GetData(nsString& aData) {
aData = mData;
}
// If you call SetEnum(), it will lookup the actual value of the data and
// set it for you. All the enums listed above have their corresponding data.
void
SetEnum(nsMathMLCharEnum aEnum);
nsMathMLCharEnum
Enum() {
return mEnum;
}
PRInt32
Length() {
return mData.Length();
}
nsStretchDirection
GetStretchDirection() {
return mDirection;
}
// Sometimes we only want to pass the data to another routine,
// this function helps to avoid copying
const PRUnichar*
@ -164,22 +125,20 @@ public:
}
private:
nsString mData;
PRUnichar mGlyph;
nsRect mRect;
PRInt32 mDirection;
nsMathMLCharEnum mEnum;
nsString mData;
PRUnichar mGlyph;
nsRect mRect;
nsStretchDirection mDirection;
nsMathMLCharEnum mEnum;
// helper methods
void
SetEnum();
static void
DrawChar(nsIRenderingContext& aRenderingContext,
PRUnichar aChar,
nscoord aX,
nscoord aY,
nsRect& aClipRect);
DrawGlyph(nsIRenderingContext& aRenderingContext,
PRUnichar aChar,
nscoord aX,
nscoord aY,
nsRect& aClipRect);
static nsresult
PaintVertically(nsIPresContext* aPresContext,

Просмотреть файл

@ -111,8 +111,7 @@ nsMathMLContainerFrame::IsOnlyWhitespace(nsIFrame* aFrame)
// by empty frame we mean a leaf frame whose text content is empty...
nsCOMPtr<nsIContent> aContent;
aFrame->GetContent(getter_AddRefs(aContent));
if (nsnull == aContent)
return PR_TRUE;
if (!aContent) return PR_TRUE;
PRInt32 numKids;
aContent->ChildCount(numKids);
if (0 == numKids) {
@ -144,9 +143,39 @@ nsMathMLContainerFrame::ReflowEmptyChild(nsIPresContext* aPresContext,
}
/* /////////////
* nsIMathMLFrame - support methods for stretchy elements and scripting
* elements (nested frames within msub, msup, msubsup, munder, mover,
* munderover, mmultiscripts, mfrac, mroot, mtable).
* nsIMathMLFrame - support methods for precise positioning
* =============================================================================
*/
NS_IMETHODIMP
nsMathMLContainerFrame::GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics)
{
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics)
{
return NS_OK;
}
/*
NS_IMETHOD
GetReference(nsPoint& aReference)
{
return NS_OK;
}
NS_IMETHOD
SetReference(const nsPoint& aReference);
{
return NS_OK;
}
*/
/* /////////////
* nsIMathMLFrame - support methods for stretchy elements
* =============================================================================
*/
@ -154,12 +183,246 @@ NS_IMETHODIMP
nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize)
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize)
{
return NS_OK; // the Stretch() is only implemented by <mo> and its nsMathMLChar
nsresult rv = NS_OK;
if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellish.flags)) {
if (NS_MATHML_STRETCH_WAS_DONE(mEmbellish.flags)) {
printf("WARNING *** it is wrong to fire stretch more than once on a frame...\n");
// NS_ASSERTION(PR_FALSE,"Stretch() was fired more than once on a frame!");
return NS_OK;
}
mEmbellish.flags |= NS_MATHML_STRETCH_DONE;
// Pass the stretch to the first non-empty child ...
nsIFrame* childFrame = mEmbellish.firstChild;
NS_ASSERTION(childFrame, "Something is wrong somewhere");
if (childFrame) {
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Something is wrong somewhere");
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsHTMLReflowMetrics aReflowMetrics(nsnull);
nsRect rect;
childFrame->GetRect(rect);
// And the trick is that rect.x is still holding the descent, and rect.y
// is still holding the ascent ...
nsStretchMetrics childSize(rect.x, rect.y, rect.width, rect.height);
nsStretchMetrics container(aContainerSize);
if (aStretchDirection != NS_STRETCH_DIRECTION_DEFAULT && aStretchDirection != mEmbellish.direction) {
// change the direction and confine the stretch to us
#if 0
GetDesiredStretchSize(aPresContext, aRenderingContext, container);
#endif
GetRect(rect);
container = nsStretchMetrics(rect.x, rect.y, rect.width, rect.height);
}
aMathMLFrame->Stretch(aPresContext, aRenderingContext, mEmbellish.direction,
container, childSize);
childFrame->SetRect(aPresContext,
nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height));
// We now have one child that may have changed, re-position all our children
Place(aPresContext, aRenderingContext, PR_TRUE, aReflowMetrics);
// Prepare the metrics to be returned
aDesiredStretchSize = nsStretchMetrics(aReflowMetrics);
aDesiredStretchSize.leftSpace = childSize.leftSpace;
aDesiredStretchSize.rightSpace = childSize.rightSpace;
// 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 (!IsEmbellishOperator(mParent)) {
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
nscoord em = NSToCoordRound(float(font.mFont.size));
// cache these values
mEmbellish.leftSpace = nscoord( em * aDesiredStretchSize.leftSpace );
mEmbellish.rightSpace = nscoord( em * aDesiredStretchSize.rightSpace );
aDesiredStretchSize.width += nscoord( (aDesiredStretchSize.leftSpace + aDesiredStretchSize.rightSpace) * em );
nscoord dx = nscoord( aDesiredStretchSize.leftSpace * em );
if (0 == dx) return NS_OK;
nsPoint origin;
childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->GetOrigin(origin);
childFrame->MoveTo(aPresContext, origin.x + dx, origin.y);
childFrame->GetNextSibling(&childFrame);
}
}
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::FinalizeReflow(PRInt32 aDirection,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsHTMLReflowMetrics& aDesiredSize)
{
// During reflow, we use rect.x and rect.y as placeholders for the child's ascent
// and descent in expectation of a stretch command. Hence we need to ensure that
// a stretch command will actually be fired later on, after exiting from our
// reflow. If the stretch is not fired, the rect.x, and rect.y will remain
// with inappropriate data causing children to be improperly positioned.
// This helper method checks to see if our parent will fire a stretch command
// targeted at us. If not, we go ahead and fire an involutive stretch on
// ourselves. This will clear all the rect.x and rect.y, and return our
// desired size.
// First, complete the post-reflow hook.
// We use the information in our children rectangles to position them.
// If placeOrigin==false, then Place() will not touch rect.x, and rect.y.
// They will still be holding the ascent and descent for each child.
PRBool placeOrigin = !NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellish.flags);
Place(aPresContext, aRenderingContext, placeOrigin, aDesiredSize);
if (!placeOrigin) {
// This means the rect.x and rect.y of our children were not set!!
// Don't go without checking to see if our parent will later fire a Stretch() command
// targeted at us. The Stretch() will cause the rect.x and rect.y to clear...
PRBool parentWillFireStretch = PR_FALSE;
nsEmbellishState parentState;
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = mParent->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
aMathMLFrame->GetEmbellishState(parentState);
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(parentState.flags) ||
(NS_MATHML_WILL_STRETCH_FIRST_CHILD(parentState.flags) &&
parentState.firstChild == this)) {
parentWillFireStretch = PR_TRUE;
}
}
if (!parentWillFireStretch) {
// There is nobody who will fire the stretch for us, we do it ourselves!
// BEGIN of GETTING THE STRETCH SIZE
// What is the size that we should use to stretch our stretchy children ????
// 1) With this code, vertical stretching works. But horizontal stretching
// does not work when the firstChild happens to be the core embellished mo...
// nsRect rect;
// nsIFrame* childFrame = mEmbellish.firstChild;
// NS_ASSERTION(childFrame, "Something is wrong somewhere");
// childFrame->GetRect(rect);
// nsStretchMetrics curSize(rect.x, rect.y, rect.width, rect.height);
// 2) With this code, horizontal stretching works. But vertical stretching
// is done in some cases where frames could have simply been kept as is.
nsStretchMetrics curSize(aDesiredSize);
// 3) With this code, we should get appropriate size when it is done !!
// GetDesiredSize(aDirection, aPresContext, aRenderingContext, curSize);
// XXX It is not clear if a direction should be imposed.
// With the default direction, the MathMLChar will attempt to stretch
// in its preferred direction.
nsStretchMetrics newSize(curSize);
Stretch(aPresContext, aRenderingContext, NS_STRETCH_DIRECTION_DEFAULT,
curSize, newSize);
aDesiredSize.width = newSize.width;
aDesiredSize.height = newSize.height;
aDesiredSize.ascent = newSize.ascent;
aDesiredSize.descent = newSize.descent;
}
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
return NS_OK;
}
// This is the method used to set the frame as an embellished container.
// It checks if the first (non-empty) child is embellished. Hence, calls
// must be bottom-up. The method must only be called from within frames who are
// entitled to be potential embellished operators as per the MathML REC.
NS_IMETHODIMP
nsMathMLContainerFrame::EmbellishOperator()
{
// Get the first non-empty child
nsIFrame* firstChild = mFrames.FirstChild();
while (firstChild) {
if (!IsOnlyWhitespace(firstChild)) break;
firstChild->GetNextSibling(&firstChild);
}
if (firstChild && IsEmbellishOperator(firstChild)) {
// Cache the first child
mEmbellish.flags |= NS_MATHML_EMBELLISH_OPERATOR;
mEmbellish.firstChild = firstChild;
// Cache also the inner-most embellished frame at the core of the hierarchy
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = firstChild->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
nsEmbellishState embellishState;
aMathMLFrame->GetEmbellishState(embellishState);
mEmbellish.core = embellishState.core;
mEmbellish.direction = embellishState.direction;
}
else {
mEmbellish.flags &= ~NS_MATHML_EMBELLISH_OPERATOR;
mEmbellish.firstChild = nsnull;
mEmbellish.core = nsnull;
mEmbellish.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
}
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::GetEmbellishState(nsEmbellishState& aEmbellishState)
{
aEmbellishState = mEmbellish;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::SetEmbellishState(const nsEmbellishState& aEmbellishState)
{
mEmbellish = aEmbellishState;
return NS_OK;
}
PRBool
nsMathMLContainerFrame::IsEmbellishOperator(nsIFrame* aFrame)
{
NS_PRECONDITION(aFrame, "null arg");
if (!aFrame) return PR_FALSE;
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_FAILED(rv) || !aMathMLFrame) return PR_FALSE;
nsEmbellishState aEmbellishState;
aMathMLFrame->GetEmbellishState(aEmbellishState);
return NS_MATHML_IS_EMBELLISH_OPERATOR(aEmbellishState.flags);
}
/* /////////////
* nsIMathMLFrame - support methods for scripting elements (nested frames
* within msub, msup, msubsup, munder, mover, munderover, mmultiscripts,
* mfrac, mroot, mtable).
* =============================================================================
*/
NS_IMETHODIMP
nsMathMLContainerFrame::GetPresentationData(PRInt32* aScriptLevel,
PRBool* aDisplayStyle)
@ -184,7 +447,7 @@ nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(PRInt32 aIndex,
PRInt32 aScriptLevelIncrement,
PRBool aDisplayStyle)
{
nsIFrame* childFrame = mFrames.FirstChild();
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
if (0 >= aIndex--) {
@ -218,7 +481,7 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
if (!IsOnlyWhitespace(childFrame) && NS_SUCCEEDED(rv)) {
// see if the child frame implements the nsIMathMLFrame interface
nsIMathMLFrame* aMathMLFrame;
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (nsnull != aMathMLFrame && NS_SUCCEEDED(rv)) {
@ -237,6 +500,9 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
nsCOMPtr<nsIContent> childContent;
childFrame->GetContent(getter_AddRefs(childContent));
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* firstFrame = nsnull;
nsIFrame* lastFrame = this;
nsIStyleContext* lastStyleContext = mStyleContext;
@ -250,11 +516,11 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
while (0 < gap--) {
aPresContext->ResolvePseudoStyleContextFor(childContent, fontAtom, lastStyleContext,
PR_FALSE, getter_AddRefs(newStyleContext));
PR_FALSE, getter_AddRefs(newStyleContext));
if (newStyleContext && newStyleContext.get() != lastStyleContext) {
// create a new frame and append it as sole child of the last created frame
// create a new wrapper frame and append it as sole child of the last created frame
nsIFrame* newFrame = nsnull;
NS_NewMathMLWrapperFrame(&newFrame);
NS_NewMathMLWrapperFrame(shell, &newFrame);
NS_ASSERTION(newFrame, "Failed to create new frame");
newFrame->Init(aPresContext, childContent, lastFrame, newStyleContext, nsnull);
@ -278,6 +544,22 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
childFrame->SetNextSibling(nsnull);
aPresContext->ReParentStyleContext(childFrame, lastStyleContext);
lastFrame->SetInitialChildList(aPresContext, nsnull, childFrame);
// if the child was an embellished operator,
// make the whole list embellished as well
nsEmbellishState embellishState;
aMathMLFrame->GetEmbellishState(embellishState);
if (0 != embellishState.flags && nsnull != embellishState.firstChild) {
do { // walk the hierarchy in a bottom-up manner
rv= lastFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
if (NS_FAILED(rv) || !aMathMLFrame) break;
embellishState.firstChild = childFrame;
aMathMLFrame->SetEmbellishState(embellishState);
childFrame = lastFrame;
lastFrame->GetParent(&lastFrame);
} while (lastFrame != this);
}
}
}
}
@ -309,6 +591,9 @@ nsMathMLContainerFrame::Init(nsIPresContext* aPresContext,
mScriptLevel = 0;
mDisplayStyle = PR_TRUE;
mEmbellish.flags = 0;
mEmbellish.firstChild = nsnull;
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult res = aParent->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
@ -353,20 +638,21 @@ nsMathMLContainerFrame::SetInitialChildList(nsIPresContext* aPresContext,
if (!IsOnlyWhitespace(child)) {
nsInlineFrame* inlineFrame = nsnull;
rv = child->QueryInterface(nsInlineFrame::kInlineFrameCID, (void**)&inlineFrame);
if (inlineFrame) {
if (NS_SUCCEEDED(rv) && inlineFrame) {
// create a new anonymous block frame to wrap this child...
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* anonymous;
rv = NS_NewBlockFrame(&anonymous);
rv = NS_NewBlockFrame(shell, &anonymous);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIStyleContext> newStyleContext;
aPresContext->ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::mozAnonymousBlock,
mStyleContext, PR_FALSE,
getter_AddRefs(newStyleContext));
mStyleContext, PR_FALSE,
getter_AddRefs(newStyleContext));
rv = anonymous->Init(aPresContext, mContent, this, newStyleContext, nsnull);
if (NS_FAILED(rv)) {
anonymous->Destroy(aPresContext);
delete anonymous;
return rv;
}
mFrames.ReplaceFrame(this, child, anonymous);
@ -381,6 +667,217 @@ nsMathMLContainerFrame::SetInitialChildList(nsIPresContext* aPresContext,
return rv;
}
#if 0
// helper method to compute the desired size of a frame
NS_IMETHODIMP
nsMathMLContainerFrame::GetDesiredStretchSize(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv = NS_OK;
nsRect rect;
nscoord count = 0;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
childFrame->GetRect(rect);
if (IsEmbellishOperator(childFrame)) {
// We have encountered an embellished operator...
// It is treated as if the embellishments were not there!
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsEmbellishState embellishState;
aMathMLFrame->GetEmbellishState(embellishState);
embellishState.core->GetRect(rect);
}
}
if (0 == aDirection) { // for horizontal positioning of child frames like in mrow
aDesiredSize.width += rect.width;
if (aDesiredSize.ascent < rect.y) aDesiredSize.ascent = rect.y;
if (aDesiredSize.descent < rect.x) aDesiredSize.descent = rect.x;
}
else if (1 == aDirection) { // for vertical positioning of child frames like in mfrac, munder
if (0 == count) { // it is the ascent and descent of the 'base' that is returned by defaul
aDesiredSize.ascent = rect.y;
aDesiredSize.descent = rect.x;
}
if (aDesiredSize.width < rect.width) aDesiredSize.width = rect.width;
}
count++;
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// Check if embellished operators didn't have (non-empty) sibblings...
if (0 < count && 0 == aDirection && 0 == aDesiredSize.height) {
// Return the font ascent and font descent
nsCOMPtr<nsIFontMetrics> fm;
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
aPresContext->GetMetricsFor(font.mFont, getter_AddRefs(fm));
fm->GetMaxAscent(aDesiredSize.ascent);
fm->GetMaxDescent(aDesiredSize.descent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
}
if (0 < count && 1 == aDirection && 0 == aDesiredSize.width) {
// Return em
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
aDesiredSize.width = NSToCoordRound(float(font.mFont.size));
}
return NS_OK;
}
#endif
// helper function to reflow all children
NS_IMETHODIMP
nsMathMLContainerFrame::ReflowChildren(PRInt32 aDirection,
nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
NS_PRECONDITION(aDirection==0 || aDirection==1, "Unknown direction");
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nscoord count = 0;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) return rv;
// At this stage, the origin points of the children have no use, so we will use the
// origins as placeholders to store the child's ascent and descent. Later on,
// we should set the origins so as to overwrite what we are storing there now.
childFrame->SetRect(aPresContext,
nsRect(childDesiredSize.descent, childDesiredSize.ascent,
childDesiredSize.width, childDesiredSize.height));
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(mEmbellish.flags) &&
IsEmbellishOperator(childFrame)) {
// We have encountered an embellished operator...
// It is treated as if the embellishments were not there!
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsEmbellishState embellishState;
aMathMLFrame->GetEmbellishState(embellishState);
nsRect rect;
embellishState.core->GetRect(rect);
childDesiredSize.descent = rect.x;
childDesiredSize.ascent = rect.y;
childDesiredSize.width = rect.width;
childDesiredSize.height = rect.height;
#if 0
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
nsStretchMetrics stretchSize;
aMathMLFrame->GetDesiredStretchSize(aPresContext, renderingContext, stretchSize);
childDesiredSize.descent = stretchSize.descent;
childDesiredSize.ascent = stretchSize.ascent;
childDesiredSize.width = stretchSize.width;
childDesiredSize.height = stretchSize.height;
#endif
}
}
if (0 == aDirection) { // for horizontal positioning of child frames like in mrow
aDesiredSize.width += childDesiredSize.width;
if (aDesiredSize.ascent < childDesiredSize.ascent) aDesiredSize.ascent = childDesiredSize.ascent;
if (aDesiredSize.descent < childDesiredSize.descent) aDesiredSize.descent = childDesiredSize.descent;
}
else if (1 == aDirection) { // for vertical positioning of child frames like in mfrac, munder
if (0 == count) { // it is the ascent and descent of the 'base' that is returned by defaul
aDesiredSize.ascent = childDesiredSize.ascent;
aDesiredSize.descent = childDesiredSize.descent;
}
if (aDesiredSize.width < childDesiredSize.width) aDesiredSize.width = childDesiredSize.width;
}
count++;
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// Check if embellished operators didn't have (non-empty) sibblings...
if (0 < count && 0 == aDirection && 0 == aDesiredSize.height) {
// Return the font ascent and font descent
nsCOMPtr<nsIFontMetrics> fm;
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
aPresContext->GetMetricsFor(font.mFont, getter_AddRefs(fm));
fm->GetMaxAscent(aDesiredSize.ascent);
fm->GetMaxDescent(aDesiredSize.descent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
}
if (0 < count && 1 == aDirection && 0 == aDesiredSize.width) {
// Return em
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
aDesiredSize.width = NSToCoordRound(float(font.mFont.size));
}
return NS_OK;
}
// helper function to stretch all children
NS_IMETHODIMP
nsMathMLContainerFrame::StretchChildren(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsStretchMetrics& aContainerSize)
{
nsRect rect;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (mEmbellish.firstChild == childFrame) {
// Skip this child... because:
// If we are here it means we are an embellished container and
// for now, we don't touch our embellished child frame.
// Its stretch will be handled separatedly when we receive
// stretch command fired by our parent frame.
}
else {
nsIMathMLFrame* aMathMLFrame;
nsresult rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
// retrieve the metrics that was stored at the ReflowChildren pass
childFrame->GetRect(rect);
nsStretchMetrics childSize(rect.x, rect.y, rect.width, rect.height);
aMathMLFrame->Stretch(aPresContext, aRenderingContext,
aStretchDirection, aContainerSize, childSize);
// store the updated metrics
childFrame->SetRect(aPresContext,
nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height));
}
}
childFrame->GetNextSibling(&childFrame);
}
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -389,127 +886,99 @@ nsMathMLContainerFrame::Reflow(nsIPresContext* aPresContext,
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
nsRect rect;
aStatus = NS_FRAME_NOT_COMPLETE;
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
//////////////////
// Reflow Children
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame) {
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else {
nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
// At this stage, the origin points of the children have no use, so we will use the
// origins as placeholders to store the child's ascent and descent. Before return,
// we should set the origins so as to overwrite what we are storing there now.
childFrame->SetRect(aPresContext,
nsRect(childDesiredSize.descent, childDesiredSize.ascent,
childDesiredSize.width, childDesiredSize.height));
aDesiredSize.width += childDesiredSize.width;
if (aDesiredSize.ascent < childDesiredSize.ascent) {
aDesiredSize.ascent = childDesiredSize.ascent;
}
if (aDesiredSize.descent < childDesiredSize.descent) {
aDesiredSize.descent = childDesiredSize.descent;
}
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
ReflowChildren(0, aPresContext, aDesiredSize, aReflowState, aStatus);
/////////////
// Ask stretchy children to stretch themselves
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
nsCharMetrics parentSize(aDesiredSize);
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
childFrame = mFrames.FirstChild();
while (nsnull != childFrame) {
// retrieve the metrics that was stored at the previous pass
childFrame->GetRect(rect);
nsCharMetrics childSize(rect.x, rect.y, rect.width, rect.height);
// If we are a container which is entitled to stretch its children, then we
// ask our stretchy children to stretch themselves
//////////
// Stretch ...
// Only directed at frames that implement the nsIMathMLFrame interface
nsIMathMLFrame* aMathMLFrame;
rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && nsnull != aMathMLFrame) {
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
aMathMLFrame->Stretch(aPresContext, renderingContext,
stretchDir, parentSize, childSize);
// store the updated metrics
childFrame->SetRect(aPresContext,
nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height));
}
aDesiredSize.width += childSize.width;
if (aDesiredSize.ascent < childSize.ascent) {
aDesiredSize.ascent = childSize.ascent;
}
if (aDesiredSize.descent < childSize.descent) {
aDesiredSize.descent = childSize.descent;
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(mEmbellish.flags)) {
nsStretchMetrics containerSize(aDesiredSize);
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
StretchChildren(aPresContext, renderingContext, stretchDir, containerSize);
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
/////////////
// Place Children now by re-adjusting the origins to align the baselines
nsPoint offset(0,0);
childFrame = mFrames.FirstChild();
while (nsnull != childFrame) {
childFrame->GetRect(rect);
offset.y = aDesiredSize.ascent - rect.y;
childFrame->MoveTo(aPresContext, offset.x,offset.y);
offset.x += rect.width;
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
// Place children now by re-adjusting the origins to align the baselines
FinalizeReflow(0, aPresContext, renderingContext, aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nsRect rect;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->GetRect(rect);
aDesiredSize.width += rect.width;
if (aDesiredSize.descent < rect.x) aDesiredSize.descent = rect.x;
if (aDesiredSize.ascent < rect.y) aDesiredSize.ascent = rect.y;
childFrame->GetNextSibling(&childFrame);
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
if (aPlaceOrigin) {
nscoord dy;
nscoord dx = 0;
childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->GetRect(rect);
dy = aDesiredSize.ascent - rect.y;
nsHTMLReflowMetrics childSize(nsnull);
childSize.width = rect.width;
childSize.height = rect.height;
// childSize.descent = rect.x;
// childSize.ascent = rect.y;
// Place and size the child
// childFrame->MoveTo(aPresContext, dx, dy);
FinishReflowChild(childFrame, aPresContext, childSize, dx, dy, 0);
dx += rect.width;
childFrame->GetNextSibling(&childFrame);
}
}
return NS_OK;
}
//==========================
// *BEWARE* of the wrapper frame!
// This is the frame that is inserted to alter the style context of
// scripting elements. What this means is that looking for your parent
// or your sibblings with (possible several) wrapper frames around you
// can make you wonder what is going on. For example, the direct parent
// of the subscript within <msub> is not <msub>, but instead the wrapper
// frame that was insterted to alter the style context of the subscript!
// You will seldom need to find out who is exactly your parent. You should
// first rethink your code to see if you can avoid finding who is your parent.
// Be careful, there are wrapper frames all over the place, and probably
// one or many are wrapping you if you are in a position where the
// scriptlevel is non zero.
nsresult
NS_NewMathMLWrapperFrame(nsIFrame** aNewFrame)
NS_NewMathMLWrapperFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLWrapperFrame* it = new nsMathMLWrapperFrame;
nsMathMLWrapperFrame* it = new (aPresShell) nsMathMLWrapperFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -525,26 +994,6 @@ nsMathMLWrapperFrame::~nsMathMLWrapperFrame()
{
}
NS_IMETHODIMP
nsMathMLWrapperFrame::Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize)
{
nsIFrame* childFrame = mFrames.FirstChild();
if (childFrame) {
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
aMathMLFrame->Stretch(aPresContext, aRenderingContext, aStretchDirection,
aContainerSize, aDesiredStretchSize);
childFrame->SetRect(aPresContext, nsRect(0,0,aDesiredStretchSize.width,aDesiredStretchSize.height));
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMathMLWrapperFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -561,13 +1010,43 @@ nsMathMLWrapperFrame::Reflow(nsIPresContext* aPresContext,
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus);
childFrame->SetRect(aPresContext, nsRect(0,0,childDesiredSize.width,childDesiredSize.height));
childFrame->SetRect(aPresContext,
nsRect(childDesiredSize.descent,childDesiredSize.ascent,
childDesiredSize.width,childDesiredSize.height));
aDesiredSize = childDesiredSize;
aStatus = childStatus;
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
FinalizeReflow(0, aPresContext, renderingContext, aDesiredSize);
}
return rv;
}
NS_IMETHODIMP
nsMathMLWrapperFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nsIFrame* childFrame = mFrames.FirstChild();
if (childFrame) {
nsRect rect;
childFrame->GetRect(rect);
aDesiredSize.descent = rect.x;
aDesiredSize.ascent = rect.y;
aDesiredSize.width = rect.width;
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
if (aPlaceOrigin) {
nsHTMLReflowMetrics childSize(nsnull);
childSize.width = rect.width;
childSize.height = rect.height;
// childFrame->SetRect(aPresContext, nsRect(0,0,rect.width,rect.height));
FinishReflowChild(childFrame, aPresContext, childSize, 0, 0, 0);
}
}
return NS_OK;
}

Просмотреть файл

@ -38,6 +38,9 @@
* Base class for MathML container frames. It acts like an inferred
* mrow. By default, this frame uses its Reflow() method to lay its
* children horizontally and ensure that their baselines are aligned.
* The Reflow() method relies upon Place() to position children.
* By overloading Place() in derived classes, it is therefore possible
* to position children in various customized ways.
*
* This frame is a *math-aware frame* in the sense that given the markup
* <tag>base arguments</tag>, the method InsertScriptLevelStyleContext()
@ -46,9 +49,9 @@
* msubsup, mover, munder, munderover, mmultiscripts. All are derived
* from this base class. They use SetInitialChildList() to trigger
* InsertScriptLevelStyleContext() for the very first time as soon as all
* their children are known. However, each of these tags has its own Reflow()
* method to lay its children as appropriate, thus overriding the default
* Reflow() method in this base class.
* their children are known. However, each of these tags has its own
* Reflow() and/or Place() methods to lay its children as appropriate,
* thus overriding the default behavior in this base class.
*
* Other tags like mi that do not have 'arguments' can be derived from
* this base class as well. The class caters for empty arguments.
@ -61,17 +64,51 @@
class nsMathMLContainerFrame : public nsHTMLContainerFrame, public nsIMathMLFrame {
public:
// nsIMathMLFrame methods
// nsIMathMLFrame methods -- see documentation in nsIMathMLFrame.h
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_IMETHOD Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize);
NS_IMETHOD
GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics);
NS_IMETHOD
SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics);
/*
NS_IMETHOD
GetReference(nsPoint& aReference);
NS_IMETHOD
SetReference(const nsPoint& aReference);
*/
NS_IMETHOD
Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize);
#if 0
NS_IMETHOD
GetDesiredStretchSize(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchMetrics& aDesiredStretchSize);
#endif
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
EmbellishOperator();
NS_IMETHOD
GetEmbellishState(nsEmbellishState& aEmbellishState);
NS_IMETHOD
SetEmbellishState(const nsEmbellishState& aEmbellishState);
NS_IMETHOD
GetPresentationData(PRInt32* aScriptLevel,
PRBool* aDisplayStyle);
@ -105,7 +142,16 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
// helper to reflow our children. We are inline frames, and we don't
NS_IMETHOD
DidReflow(nsIPresContext* aPresContext,
nsDidReflowStatus aStatus)
{
mEmbellish.flags &= ~NS_MATHML_STRETCH_DONE;
return nsHTMLContainerFrame::DidReflow(aPresContext, aStatus);
}
// helper method to reflow a child frame. We are inline frames, and we don't
// know our positions until reflow is finished. That's why we ask the
// base method not to worry about our position.
nsresult
@ -115,20 +161,54 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
return nsHTMLContainerFrame::ReflowChild(aKidFrame, aPresContext, aDesiredSize, aReflowState,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
return nsHTMLContainerFrame::ReflowChild(aKidFrame, aPresContext, aDesiredSize, aReflowState,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
}
// helper method for altering the style contexts of subscript/superscript elements
// helper function to reflow all children before placing them.
// With MathML, we have to reflow all children and use their desired size
// information in order to figure out how to lay them.
// aDirection = 0 means children will later be laid horizontally
// aDirection = 1 means children will later be laid vertically
NS_IMETHOD
ReflowChildren(PRInt32 aDirection,
nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
// helper function to fire a Stretch command on all children,
// Note that if the container is embellished, the stretch is not fired
// on its embellished child. It is the responsibility of the parent
// of the embellished container to fire a stretch that is then passed
// onto the embellished child.
// If an embellished container doesn't have a parent that will fire
// a stretch, it will do it itself (see FinalizeReflow).
NS_IMETHOD
StretchChildren(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsStretchMetrics& aContainerSize);
// helper method to complete the post-reflow hook and ensure that embellish
// operators don't terminate their Reflow without receiving a Stretch command.
NS_IMETHOD
FinalizeReflow(PRInt32 aDirection,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsHTMLReflowMetrics& aDesiredSize);
// helper method to alter the style contexts of subscript/superscript elements
// XXX this is pretty much a hack until the content model caters for MathML and
// the style system has some provisions for MathML
NS_IMETHOD
InsertScriptLevelStyleContext(nsIPresContext* aPresContext);
// helper methods for processing empty MathML frames (with whitespace only)
// helper to check if a frame is an embellished container
static PRBool
IsEmbellishOperator(nsIFrame* aFrame);
// helper methods for processing empty MathML frames (with whitespace only)
static PRBool
IsOnlyWhitespace(nsIFrame* aFrame);
@ -144,6 +224,12 @@ protected:
PRBool mDisplayStyle; // displaystyle="false" is intended to slightly alter how the
// rendering is done in inline mode.
nsEmbellishState mEmbellish; // 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.x is the baseline
*/
virtual PRIntn GetSkipSides() const { return 0; }
};
@ -151,13 +237,7 @@ protected:
// has some provisions for MathML
class nsMathMLWrapperFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLWrapperFrame(nsIFrame** aNewFrame);
NS_IMETHOD Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize);
friend nsresult NS_NewMathMLWrapperFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
@ -165,6 +245,12 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
protected:
nsMathMLWrapperFrame();
virtual ~nsMathMLWrapperFrame();

Просмотреть файл

@ -26,23 +26,23 @@
#include "nsISupports.h"
// Factory methods for creating MathML objects
extern nsresult NS_NewMathMLmrowFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmiFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmoFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmphantomFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmpaddedFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmfencedFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmfracFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsubFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsupFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsubsupFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmunderFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmoverFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmunderoverFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmmultiscriptsFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmstyleFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmtdFrame ( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsqrtFrame( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmrootFrame( nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmrowFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmiFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmoFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmphantomFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmpaddedFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmfencedFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmfracFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsubFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsubsupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmunderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmoverFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmunderoverFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmmultiscriptsFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmstyleFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmtdFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmsqrtFrame( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmrootFrame( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
#endif /* nsMathMLParts_h___ */

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmfencedFrame(nsIFrame** aNewFrame)
NS_NewMathMLmfencedFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmfencedFrame* it = new nsMathMLmfencedFrame;
nsMathMLmfencedFrame* it = new (aPresShell) nsMathMLmfencedFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -126,7 +126,7 @@ nsMathMLmfencedFrame::ReCreateFencesAndSeparators()
// see if the opening fence is there ...
data = '('; // default as per the MathML REC
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::open, value)) {
nsMathMLAtoms::open_, value)) {
value.Trim(" ");
data = value;
}
@ -139,7 +139,7 @@ nsMathMLmfencedFrame::ReCreateFencesAndSeparators()
// see if the closing fence is there ...
data = ')'; // default as per the MathML REC
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::close, value)) {
nsMathMLAtoms::close_, value)) {
value.Trim(" ");
data = value;
}
@ -152,7 +152,7 @@ nsMathMLmfencedFrame::ReCreateFencesAndSeparators()
// see if separators are there ...
data = ','; // default as per the MathML REC
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::separators, value)) {
nsMathMLAtoms::separators_, value)) {
value.Trim(" ");
data = value;
}
@ -263,14 +263,14 @@ nsMathMLmfencedFrame::Reflow(nsIPresContext* aPresContext,
// Ask stretchy children to stretch themselves
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
nsCharMetrics parentSize(aDesiredSize);
nsStretchMetrics parentSize(aDesiredSize);
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
childFrame = mFrames.FirstChild();
while (childFrame) {
// retrieve the metrics that was stored at the previous pass
childFrame->GetRect(rect);
nsCharMetrics childSize(rect.x, rect.y, rect.width, rect.height);
nsStretchMetrics childSize(rect.x, rect.y, rect.width, rect.height);
//////////
// Stretch ...
// Only directed at frames that implement the nsIMathMLFrame interface
@ -312,7 +312,7 @@ nsMathMLmfencedFrame::Reflow(nsIPresContext* aPresContext,
fm->GetMaxAscent(fontAscent);
fm->GetMaxDescent(fontDescent);
em = NSToCoordRound(float(font.mFont.size));
parentSize = nsCharMetrics(aDesiredSize);
parentSize = nsStretchMetrics(aDesiredSize);
nscoord dx = 0; // running x-origin of children ...
@ -351,7 +351,12 @@ nsMathMLmfencedFrame::Reflow(nsIPresContext* aPresContext,
while (childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
childFrame->GetRect(rect);
childFrame->MoveTo(aPresContext, rect.x, aDesiredSize.ascent - rect.y);
// childFrame->MoveTo(aPresContext, rect.x, aDesiredSize.ascent - rect.y);
nsHTMLReflowMetrics childSize(nsnull);
childSize.width = rect.width;
childSize.height = rect.height;
FinishReflowChild(childFrame, aPresContext, childSize, rect.x, aDesiredSize.ascent - rect.y, 0);
}
childFrame->GetNextSibling(&childFrame);
}
@ -387,12 +392,12 @@ nsMathMLmfencedFrame::ReflowChar(nsIPresContext* aPresContext,
nscoord fontAscent,
nscoord fontDescent,
nscoord em,
nsCharMetrics& aContainerSize,
nsStretchMetrics& aContainerSize,
nsHTMLReflowMetrics& aDesiredSize,
nscoord& aX)
{
if (aMathMLChar && 0 < aMathMLChar->Length()) {
nsCharMetrics aCharSize(fontDescent, fontAscent, 0, fontDescent + fontAscent);
nsStretchMetrics aCharSize(fontDescent, fontAscent, 0, fontDescent + fontAscent);
aRenderingContext.GetWidth(aMathMLChar->GetUnicode(),
PRUint32(aMathMLChar->Length()),
aCharSize.width);

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmfencedFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmfencedFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmfencedFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
@ -80,7 +80,7 @@ protected:
nscoord fontAscent,
nscoord fontDescent,
nscoord em,
nsCharMetrics& aContainerSize,
nsStretchMetrics& aContainerSize,
nsHTMLReflowMetrics& aDesiredSize,
nscoord& aX);

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmfracFrame(nsIFrame** aNewFrame)
NS_NewMathMLmfracFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmfracFrame* it = new nsMathMLmfracFrame;
nsMathMLmfracFrame* it = new (aPresShell) nsMathMLmfracFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -85,7 +85,7 @@ nsMathMLmfracFrame::Init(nsIPresContext* aPresContext,
// see if the linethickness attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::linethickness, value))
nsMathMLAtoms::linethickness_, value))
{
if (value == "thin")
aLineThickness = THIN_FRACTION_LINE_THICKNESS;
@ -237,9 +237,15 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
rect[1].x = (aDesiredSize.width - rect[1].width) / 2;
rect[0].y = 0;
rect[1].y = aDesiredSize.height - rect[1].height;
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
SetLineOrigin(nsPoint(0,rect[0].height)); // position the fraction bar
if (nsnull != aDesiredSize.maxElementSize) {

Просмотреть файл

@ -96,7 +96,7 @@ pc picas (1 pica = 12 points)
class nsMathMLmfracFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmfracFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmfracFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -48,13 +48,13 @@
//
nsresult
NS_NewMathMLmiFrame(nsIFrame** aNewFrame)
NS_NewMathMLmiFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmiFrame* it = new nsMathMLmiFrame;
nsMathMLmiFrame* it = new (aPresShell) nsMathMLmiFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -137,8 +137,11 @@ nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext,
if (newStyleContext && newStyleContext.get() != mStyleContext) {
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame* newFrame = nsnull;
NS_NewMathMLWrapperFrame(&newFrame);
NS_NewMathMLWrapperFrame(shell, &newFrame);
NS_ASSERTION(newFrame, "Failed to create new frame");
newFrame->Init(aPresContext, mContent, this, newStyleContext, nsnull);

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmiFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmiFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmiFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmmultiscriptsFrame(nsIFrame** aNewFrame)
NS_NewMathMLmmultiscriptsFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmmultiscriptsFrame* it = new nsMathMLmmultiscriptsFrame;
nsMathMLmmultiscriptsFrame* it = new (aPresShell) nsMathMLmmultiscriptsFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -67,19 +67,12 @@ nsMathMLmmultiscriptsFrame::~nsMathMLmmultiscriptsFrame()
}
NS_IMETHODIMP
nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
// Reflow Children
nsresult rv;
nsIFrame* mprescriptsFrame = nsnull; // frame of <mprescripts/>, if there.
PRBool isSubscript = PR_FALSE;
nscoord ascent, descent, width, height;
@ -88,71 +81,44 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
nsIFrame* baseFrame = nsnull;
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else {
nsRect childRect;
while (childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
nsCOMPtr<nsIContent> childContent;
nsCOMPtr<nsIAtom> childTag;
childFrame->GetContent(getter_AddRefs(childContent));
childContent->GetTag(*getter_AddRefs(childTag));
if (childTag.get() == nsMathMLAtoms::mprescripts) {
// NS_ASSERTION(mprescriptsFrame == nsnull,"duplicate <mprescripts/>");
//printf("mprescripts Found ...\n"); // should ignore?
if (childTag.get() == nsMathMLAtoms::mprescripts_) {
mprescriptsFrame = childFrame;
}
else if (childTag.get() == nsMathMLAtoms::none) {
childDesiredSize.height = 0;
childDesiredSize.width = 0;
childDesiredSize.ascent = 0;
childDesiredSize.descent = 0;
}
else {
//printf("child count: %d...\n", count);
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
else if (childTag.get() != nsMathMLAtoms::none_) {
childFrame->GetRect(childRect);
if (0 == count) {
baseFrame = childFrame;
ascent = childDesiredSize.ascent;
descent = childDesiredSize.descent;
height = childDesiredSize.height;
subsupWidth = childDesiredSize.width;
descent = childRect.x;
ascent = childRect.y;
height = childRect.height;
subsupWidth = childRect.width;
subHeight = supHeight = height;
supAscent = ascent;
subDescent = descent;
}
else {
if (isSubscript) {
subDescent = PR_MAX(subDescent, childDesiredSize.descent);
subHeight = PR_MAX(subHeight, childDesiredSize.height);
width = childDesiredSize.width;
subDescent = PR_MAX(subDescent, childRect.x);
subHeight = PR_MAX(subHeight, childRect.height);
width = childRect.width;
}
else {
supAscent = PR_MAX(supAscent, childDesiredSize.ascent);
supHeight = PR_MAX(supHeight, childDesiredSize.height);
width = PR_MAX(width, childDesiredSize.width);
supAscent = PR_MAX(supAscent, childRect.y);
supHeight = PR_MAX(supHeight, childRect.height);
width = PR_MAX(width, childRect.width);
subsupWidth += width;
}
}
// At this stage, the origin points of the children have no use, so we will use the
// origins to store the child's ascent and descent. At the next pass, we should
// set the origins so as to overwrite what we are storing there now
childFrame->SetRect(aPresContext,
nsRect(childDesiredSize.descent, childDesiredSize.ascent,
childDesiredSize.width, childDesiredSize.height));
isSubscript = !isSubscript;
count++;
}
@ -161,9 +127,6 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
//////////////////
// Place Children
// Get the subscript and superscript offsets
nscoord subscriptOffset, superscriptOffset, leading;
nsCOMPtr<nsIFontMetrics> fm;
@ -182,15 +145,12 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.height = aDesiredSize.descent + aDesiredSize.ascent;
aDesiredSize.width = subsupWidth;
// Place prescripts, followed by base, and then postscripts.
// The list of frames is in the order: {base} {postscripts} {prescripts}
// We go over the list in a circular manner, starting at <prescripts/>
nscoord offset = 0;
nsIFrame* child[2];
nsRect rect[2];
count = 0;
nsHTMLReflowMetrics childSize(nsnull);
childFrame = mprescriptsFrame;
do {
if (nsnull == childFrame) { // end of prescripts,
@ -199,7 +159,12 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
childFrame->GetRect(rect[0]);
rect[0].x = offset;
rect[0].y = aDesiredSize.height - subHeight;
childFrame->SetRect(aPresContext, rect[0]);
if (aPlaceOrigin) {
// childFrame->SetRect(aPresContext, rect[0]);
childSize.width = rect[0].width;
childSize.height = rect[0].height;
FinishReflowChild(child[0], aPresContext, childSize, rect[0].x, rect[0].y, 0);
}
offset += rect[0].width;
}
else if (mprescriptsFrame != childFrame) {
@ -208,7 +173,6 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
if (!IsOnlyWhitespace(childFrame)) {
child[count++] = childFrame;
if (2 == count) { // place a sub-sup pair
count = 0;
//printf("Placing the sub-sup pair...\n");
child[0]->GetRect(rect[0]);
@ -220,9 +184,18 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
rect[0].x = offset + (width - rect[0].width) / 2; // centering
rect[1].x = offset + (width - rect[1].width) / 2;
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
offset += width;
count = 0;
}
}
}
@ -234,6 +207,6 @@ nsMathMLmmultiscriptsFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
return rv;
}

Просмотреть файл

@ -32,13 +32,13 @@
class nsMathMLmmultiscriptsFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmmultiscriptsFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmmultiscriptsFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
@ -48,7 +48,10 @@ public:
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
UpdatePresentationDataFromChildAt(1, 1, PR_FALSE);
// switch the style of the postscripts and prescripts
InsertScriptLevelStyleContext(aPresContext);
// check whether or not this is an embellished operator
EmbellishOperator();
return rv;
}

Просмотреть файл

@ -3,19 +3,19 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* The Original Code is Mozilla MathML Project.
*
* The Initial Developer of the Original Code is The University Of
*
* The Initial Developer of the Original Code is The University Of
* Queensland. Portions created by The University Of Queensland are
* Copyright (C) 1999 The University Of Queensland. All Rights Reserved.
*
* Contributor(s):
*
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
*/
@ -44,23 +44,23 @@
// <mo> -- operator, fence, or separator - implementation
//
// TODO:
// TODO:
// * Handle embellished operators
// See the section "Exception for embellished operators"
// in http://www.w3.org/TR/REC-MathML/chap3_2.html
//
// * For a markup <mo>content</mo>, if "content" is not found in
// the operator dictionary, the REC sets default attributes :
// fence = false
// separator = false
// lspace = .27777em
// rspace = .27777em
// stretchy = false
// fence = false
// separator = false
// lspace = .27777em
// rspace = .27777em
// stretchy = false
// symmetric = true
// maxsize = infinity
// minsize = 1
// largeop = false
// movablelimits = false
// movablelimits = false
// accent = false
//
// We only have to handle *lspace* and *rspace*, perhaps via a CSS padding rule
@ -69,32 +69,32 @@
// * The spacing is wrong in certain situations, e.g.// <mrow> <mo>&ForAll;</mo> <mo>+</mo></mrow>
//
// The REC tells more about lspace and rspace attributes:
// The REC tells more about lspace and rspace attributes:
//
// The values for lspace and rspace given here range from 0 to 6/18 em in
// The values for lspace and rspace given here range from 0 to 6/18 em in
// units of 1/18 em. For the invisible operators whose content is
// "&InvisibleTimes;" or "&ApplyFunction;", it is suggested that MathML
// "&InvisibleTimes;" or "&ApplyFunction;", it is suggested that MathML
// renderers choose spacing in a context-sensitive way (which is an exception to
// the static values given in the following table). For <mo>&ApplyFunction;</mo>,
// the static values given in the following table). For <mo>&ApplyFunction;</mo>,
// the total spacing (lspace + rspace) in expressions such as "sin x"
// (where the right operand doesn't start with a fence) should be greater
// (where the right operand doesn't start with a fence) should be greater
// than 0; for <mo>&InvisibleTimes;</mo>, the total spacing should be greater
// than 0 when both operands (or the nearest tokens on either side, if on
// the baseline) are identifiers displayed in a non-slanted font (i.e., under
// the suggested rules, when both operands are multi-character identifiers).
// than 0 when both operands (or the nearest tokens on either side, if on
// the baseline) are identifiers displayed in a non-slanted font (i.e., under
// the suggested rules, when both operands are multi-character identifiers).
nsresult
NS_NewMathMLmoFrame(nsIFrame** aNewFrame)
NS_NewMathMLmoFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmoFrame* it = new nsMathMLmoFrame;
nsMathMLmoFrame* it = new (aPresShell) nsMathMLmoFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aNewFrame = it;
*aNewFrame = it;
return NS_OK;
}
@ -116,14 +116,14 @@ nsMathMLmoFrame::Paint(nsIPresContext* aPresContext,
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer &&
NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) {
rv = mMathMLChar.Paint(aPresContext,
rv = mMathMLChar.Paint(aPresContext,
aRenderingContext,
mStyleContext);
}
else { // let the base class worry about the painting
rv = nsMathMLContainerFrame::Paint(aPresContext,
rv = nsMathMLContainerFrame::Paint(aPresContext,
aRenderingContext,
aDirtyRect,
aDirtyRect,
aWhichLayer);
}
return rv;
@ -147,9 +147,13 @@ nsMathMLmoFrame::Init(nsIPresContext* aPresContext,
return rv;
}
void
nsMathMLmoFrame::InitData()
NS_IMETHODIMP
nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
// get the text that we enclose. // XXX aData.CompressWhitespace() ?
nsAutoString aData;
@ -161,52 +165,91 @@ nsMathMLmoFrame::InitData()
for (PRInt32 kid=0; kid<numKids; kid++) {
nsCOMPtr<nsIContent> kidContent;
mContent->ChildAt(kid, *getter_AddRefs(kidContent));
if (kidContent.get()) {
if (kidContent.get()) {
nsCOMPtr<nsIDOMText> kidText(do_QueryInterface(kidContent));
if (kidText.get()) {
// PRUint32 kidLength;
// kidText->GetLength(&kidLength);
// aLength += kidLength;
// aLength += kidLength;
nsAutoString kidData;
kidText->GetData(kidData);
aData += kidData;
}
}
}
// cache the operator
mMathMLChar.SetData(aData);
// find our form
// for consistency, set the first non-empty child as the embellished child
nsIFrame* firstChild = mFrames.FirstChild();
while (firstChild) {
if (!IsOnlyWhitespace(firstChild)) {
mEmbellish.flags = NS_MATHML_EMBELLISH_OPERATOR;
mEmbellish.firstChild = firstChild;
mEmbellish.core = this;
mEmbellish.direction = mMathMLChar.GetStretchDirection();
break;
}
firstChild->GetNextSibling(&firstChild);
}
return rv;
}
void
nsMathMLmoFrame::InitData()
{
nsresult rv = NS_OK;
mFlags = 0;
// find our form
nsAutoString value;
nsOperatorFlags aForm = NS_MATHML_OPERATOR_FORM_INFIX;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::form, value)) {
if (value == "prefix")
nsIMathMLFrame* aMathMLFrame = nsnull;
PRBool hasEmbellishAncestor = PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::form_, value)) {
if (value == "prefix")
aForm = NS_MATHML_OPERATOR_FORM_PREFIX;
else if (value == "postfix")
else if (value == "postfix")
aForm = NS_MATHML_OPERATOR_FORM_POSTFIX;
}
else { // look at our position from our parent (frames are singly-linked together).
// flag if we have an embellished ancestor
hasEmbellishAncestor = IsEmbellishOperator(mParent);
}
else {
// Get our outermost embellished container and its parent
nsIFrame* aParent = this;
nsIFrame* aEmbellish = this;
do {
aEmbellish = aParent;
aParent->GetParent(&aParent);
} while (IsEmbellishOperator(aParent));
// flag if we have an embellished ancestor
if (aEmbellish != this) {
hasEmbellishAncestor = PR_TRUE;
}
// Find the position of our outermost embellished container w.r.t
// its sibblings (frames are singly-linked together).
//////////////
// 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*] [this] [space*] [next]
// We want to skip them...
// [space*] [prev] [space*] [aEmbellish] [space*] [next]
// We want to skip them...
// The problem looks like a regexp, we ask a little flag to help us.
PRInt32 state = 0;
nsIFrame* prev = nsnull;
nsIFrame* next = nsnull;
nsIFrame* aFrame;
mParent->FirstChild(nsnull, &aFrame);
while (nsnull != aFrame) {
if (aFrame == this) { // we start looking for next
aParent->FirstChild(nsnull, &aFrame);
while (aFrame) {
if (aFrame == aEmbellish) { // we start looking for next
state++;
}
else if (!IsOnlyWhitespace(aFrame)) {
if (0 == state) { // we are still looking for prev
prev = aFrame;
prev = aFrame;
}
else if (1 == state) { // we got next
next = aFrame;
@ -215,86 +258,95 @@ nsMathMLmoFrame::InitData()
}
aFrame->GetNextSibling(&aFrame);
}
// set our form flag depending on our position
if (nsnull == prev && nsnull != next)
// set our form flag depending on the position
if (!prev && next)
aForm = NS_MATHML_OPERATOR_FORM_PREFIX;
else if (nsnull != prev && nsnull == next)
else if (prev && !next)
aForm = NS_MATHML_OPERATOR_FORM_POSTFIX;
}
// cache our form
mFlags |= aForm;
// Lookup the operator dictionary
nsAutoString aData;
mMathMLChar.GetData(aData);
PRBool found = nsMathMLOperators::LookupOperator(aData, aForm,
&mFlags, &mLeftSpace, &mRightSpace);
// Now that we know our text an our form, we can lookup the operator dictionary
PRBool found;
found = nsMathMLOperators::LookupOperator(aData, aForm,
&mFlags, &mLeftSpace, &mRightSpace);
// All operators are symmetric. But this symmetric flag is *not* stored in the
// operator dictionary and operaptors are treated as non-symmetric...
// Uncomment the folllowing line to change this behavior.
// 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)) {
mFlags |= NS_MATHML_OPERATOR_MUTABLE;
}
// If we don't want extra space when we are a script
if (mScriptLevel > 0) {
// Set the flag if the operator has an embellished ancestor
if (hasEmbellishAncestor) {
mFlags |= NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR;
}
// If we don't want too much extra space when we are a script
if (!hasEmbellishAncestor && 0 < mScriptLevel) {
mLeftSpace /= 2.0f;
mRightSpace /= 2.0f;
}
// XXX Factor all this in nsMathMLAttributes.cpp
// Now see if there are user-defined attributes that override the dictionary.
// XXX If an attribute can be forced to be true when it is false in the
// Now see if there are user-defined attributes that override the dictionary.
// XXX If an attribute can be forced to be true when it is false in the
// dictionary, then the following code has to change...
// For each attribute disabled by the user, turn off its bit flag.
// movablelimits|separator|largeop|accent|fence|stretchy|form
nsAutoString kfalse("false");
nsAutoString kfalse("false"), ktrue("true");
if (NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::stretchy, value) && value == kfalse)
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::stretchy_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_STRETCHY;
}
if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::fence, value) && value == kfalse)
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::fence_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_FENCE;
}
if (NS_MATHML_OPERATOR_IS_ACCENT(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::accent, value) && value == kfalse)
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::accent_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_ACCENT;
}
if (NS_MATHML_OPERATOR_IS_LARGEOP(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::largeop, value) && value == kfalse)
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::largeop_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_LARGEOP;
}
if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::separator, value) && value == kfalse)
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::separator_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR;
}
if (NS_MATHML_OPERATOR_IS_MOVABLELIMITS(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::movablelimits, value) && value == kfalse)
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::movablelimits_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_MOVABLELIMITS;
}
// TODO: add also lspace and rspace, minsize, maxsize later ...
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::symmetric_, value)) {
if (value == ktrue) mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
if (value == kfalse) mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC;
}
// TODO: add also lspace and rspace, minsize, maxsize, later ...
// 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;
return;
}
// cache the operator
mMathMLChar.SetData(aData);
return;
}
// NOTE: aDesiredStretchSize is an IN/OUT parameter
@ -304,62 +356,100 @@ NS_IMETHODIMP
nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize)
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize)
{
if (0 == mFlags) { // first time...
InitData();
if (NS_MATHML_STRETCH_WAS_DONE(mEmbellish.flags)) {
printf("WARNING *** it is wrong to fire stretch more than once on a frame...\n");
return NS_OK;
}
mEmbellish.flags |= NS_MATHML_STRETCH_DONE;
// get the value of 'em';
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
nscoord em = NSToCoordRound(float(aFont->mFont.size));
// if (0 == mFlags) { // first time...
InitData();
// }
nscoord dx = nscoord( mLeftSpace * em );
nscoord dy = 0;
// see if it is okay to stretch
/////////
// See if it is okay to stretch
if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) {
nsCharMetrics old(aDesiredStretchSize);
nsStretchMetrics container(aContainerSize);
// little adjustments if the operator is symmetric
// XXX Also use maxsize and minsize to find what size we should
// really suggest to our MathMLChar.
if (NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags) &&
((aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) ||
(aStretchDirection == NS_STRETCH_DIRECTION_DEFAULT &&
mMathMLChar.GetStretchDirection() == NS_STRETCH_DIRECTION_VERTICAL)))
{
container.ascent = PR_MAX(container.ascent, container.descent);
container.descent = container.ascent;
container.height = container.ascent + container.descent;
}
// let the MathMLChar stretch itself...
nsStretchMetrics old(aDesiredStretchSize);
mMathMLChar.Stretch(aPresContext, aRenderingContext,
mStyleContext, aStretchDirection,
aContainerSize, aDesiredStretchSize);
container, aDesiredStretchSize);
if (old == aDesiredStretchSize) { // hasn't changed !
mFlags &= ~NS_MATHML_OPERATOR_MUTABLE;
}
else {
nscoord gap;
if (aDesiredStretchSize == NS_STRETCH_DIRECTION_VERTICAL) {
gap = aContainerSize.ascent - aDesiredStretchSize.ascent;
if (0 < gap) dy += gap;
} else if (aDesiredStretchSize == NS_STRETCH_DIRECTION_HORIZONTAL) {
gap = (aContainerSize.width - aDesiredStretchSize.width)/2;
if (0 < gap) dx += gap;
}
mMathMLChar.SetRect(nsRect(dx, dy, aDesiredStretchSize.width,
aDesiredStretchSize.height));
}
}
// adjust our children's offsets to leave the spacing
if (0 < dx || 0 < dy) {
/////////
// Place our children and adjust our children's offsets to leave the spacing.
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));
}
else {
nsHTMLReflowMetrics aReflowMetrics(nsnull);
Place(aPresContext, aRenderingContext, PR_TRUE, aReflowMetrics);
// Prepare the metrics to be returned
aDesiredStretchSize.width = aReflowMetrics.width;
aDesiredStretchSize.height = aReflowMetrics.height;
aDesiredStretchSize.ascent = aReflowMetrics.ascent;
aDesiredStretchSize.descent = aReflowMetrics.descent;
}
aDesiredStretchSize.leftSpace = mLeftSpace;
aDesiredStretchSize.rightSpace = mRightSpace;
// Before we leave... there is a last item in the check-list:
// If our parent is not embellished, it means we are the outermost embellished
// container and so we put the spacing, otherwise we don't include the spacing,
// the outermost embellished container will take care of it.
if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) {
// Get the value of 'em'
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
nscoord em = NSToCoordRound(float(font.mFont.size));
// Account the spacing
aDesiredStretchSize.width += nscoord( (aDesiredStretchSize.leftSpace + aDesiredStretchSize.rightSpace) * em );
nscoord dx = nscoord( mLeftSpace * em );
if (0 == dx) return NS_OK;
// adjust the offsets
nsRect rect;
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) {
mMathMLChar.GetRect(rect);
mMathMLChar.SetRect(nsRect(rect.x + dx, rect.y, rect.width, rect.height));
}
else {
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->GetRect(rect);
childFrame->MoveTo(aPresContext, rect.x + dx, rect.y + dy);
dx += rect.width;
childFrame->MoveTo(aPresContext, rect.x + dx, rect.y);
childFrame->GetNextSibling(&childFrame);
}
childFrame->GetNextSibling(&childFrame);
}
}
// account the spacing
aDesiredStretchSize.width += nscoord( (mLeftSpace + mRightSpace) * em );
return NS_OK;
}

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmoFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmoFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmoFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
@ -41,6 +41,11 @@ public:
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD
Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -53,12 +58,12 @@ public:
Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsCharMetrics& aContainerSize,
nsCharMetrics& aDesiredStretchSize);
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize);
// helper method to lookup the operator dictionary and initialize our member data
void InitData();
protected:
nsMathMLmoFrame();
virtual ~nsMathMLmoFrame();

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmoverFrame(nsIFrame** aNewFrame)
NS_NewMathMLmoverFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmoverFrame* it = new nsMathMLmoverFrame;
nsMathMLmoverFrame* it = new (aPresShell) nsMathMLmoverFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -66,91 +66,104 @@ nsMathMLmoverFrame::~nsMathMLmoverFrame()
{
}
NS_IMETHODIMP
nsMathMLmoverFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
return rv;
}
NS_IMETHODIMP
nsMathMLmoverFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
// Reflow Children
nsresult rv = NS_OK;
/////////////
// Reflow children
ReflowChildren(1, aPresContext, aDesiredSize, aReflowState, aStatus);
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
/////////////
// Ask stretchy children to stretch themselves
nsStretchMetrics containerSize(aDesiredSize);
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_HORIZONTAL;
StretchChildren(aPresContext, renderingContext, stretchDir, containerSize);
/////////////
// Place children now by re-adjusting the origins to align the baselines
FinalizeReflow(1, aPresContext, renderingContext, aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nscoord count = 0;
nsRect rect[2];
nsIFrame* child[2];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else if (2 > count) {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
nscoord width[2];
nscoord maxWidth = 0;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 2 > count) {
childFrame->GetRect(rect[count]);
child[count] = childFrame;
if (aPlaceOrigin) {
width[count] = rect[count].width;
if (IsEmbellishOperator(childFrame)) {
// treated as if embellishments were not there...
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsRect rect;
nsEmbellishState embellishState;
aMathMLFrame->GetEmbellishState(embellishState);
embellishState.core->GetRect(rect);
width[count] = rect.width + embellishState.leftSpace + embellishState.rightSpace;
}
}
maxWidth = PR_MAX(maxWidth, width[count]); // clean up and use "if" later
}
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
if (0 == count) {
aDesiredSize.ascent = childDesiredSize.ascent;
aDesiredSize.descent = childDesiredSize.descent;
}
count++;
}
// else { invalid markup... }
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
childFrame->GetNextSibling(&childFrame);
}
aDesiredSize.ascent = rect[0].y;
aDesiredSize.descent = rect[0].x;
aDesiredSize.width = PR_MAX(rect[0].width, rect[1].width);
/////////////
// Ask stretchy children to stretch themselves
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_HORIZONTAL;
nsCharMetrics parentSize(aDesiredSize);
for (PRInt32 i = 0; i < count; i++) {
//////////
// Stretch ...
// Only directed at frames that implement the nsIMathMLFrame interface
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = child[i]->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsCharMetrics childSize(rect[i].x, rect[i].y, rect[i].width, rect[i].height);
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
aMathMLFrame->Stretch(aPresContext, renderingContext,
stretchDir, parentSize, childSize);
// store the updated metrics
rect[i] = nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height);
}
}
//////////////////
// Place Children
aDesiredSize.ascent += rect[1].height;
aDesiredSize.width = PR_MAX(rect[0].width, rect[1].width);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
rect[0].x = (aDesiredSize.width - rect[0].width) / 2; // center w.r.t largest width
rect[1].x = (aDesiredSize.width - rect[1].width) / 2;
rect[1].y = 0;
rect[0].y = rect[1].height;
if (aPlaceOrigin) {
rect[0].x = (maxWidth - width[0]) / 2; // center w.r.t largest width
rect[1].x = (maxWidth - width[1]) / 2;
rect[1].y = 0;
rect[0].y = rect[1].height;
}
//ignore the leading (line spacing) that is attached to the text
nscoord leading;
nsCOMPtr<nsIFontMetrics> fm;
@ -162,14 +175,20 @@ nsMathMLmoverFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.height -= leading;
aDesiredSize.ascent -= leading;
rect[0].y -= leading;
//
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
//
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}

Просмотреть файл

@ -32,7 +32,14 @@
class nsMathMLmoverFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmoverFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmoverFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
@ -40,6 +47,12 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
@ -48,7 +61,10 @@ public:
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;
}

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmpaddedFrame(nsIFrame** aNewFrame)
NS_NewMathMLmpaddedFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmpaddedFrame* it = new nsMathMLmpaddedFrame;
nsMathMLmpaddedFrame* it = new (aPresShell) nsMathMLmpaddedFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmpaddedFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmpaddedFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmpaddedFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmphantomFrame(nsIFrame** aNewFrame)
NS_NewMathMLmphantomFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmphantomFrame* it = new nsMathMLmphantomFrame;
nsMathMLmphantomFrame* it = new (aPresShell) nsMathMLmphantomFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmphantomFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmphantomFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmphantomFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Paint(nsIPresContext* aPresContext,

Просмотреть файл

@ -45,13 +45,13 @@
//
nsresult
NS_NewMathMLmrootFrame(nsIFrame** aNewFrame)
NS_NewMathMLmrootFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmrootFrame* it = new nsMathMLmrootFrame;
nsMathMLmrootFrame* it = new (aPresShell) nsMathMLmrootFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -63,10 +63,8 @@ nsMathMLmrootFrame::nsMathMLmrootFrame() :
mSqrChar(),
mBarChar()
{
nsAutoString sqr(PRUnichar(0x221A)),
bar(PRUnichar(0xF8E5));
mSqrChar.SetData(sqr);
mBarChar.SetData(bar);
mSqrChar.SetEnum(eMathMLChar_Radical);
mBarChar.SetEnum(eMathMLChar_RadicalBar);
}
nsMathMLmrootFrame::~nsMathMLmrootFrame()
@ -190,10 +188,10 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
nscoord heightBar = bmBar.ascent - bmBar.descent; // height of the overline bar
// Stretch the sqrt symbol to the appropriate height if it is not big enough.
nsCharMetrics contSize(aDesiredSize);
nsCharMetrics desSize(fontDescent, fontAscent, widthSqr, fontAscent + fontDescent);
nsStretchMetrics contSize(aDesiredSize);
nsStretchMetrics desSize(fontDescent, fontAscent, widthSqr, fontAscent + fontDescent);
mSqrChar.Stretch(aPresContext, renderingContext, mStyleContext,
NS_STRETCH_DIRECTION_VERTICAL, contSize, desSize);
NS_STRETCH_DIRECTION_VERTICAL, contSize, desSize);
widthSqr = desSize.width;
if (aDesiredSize.ascent < desSize.ascent) {
aDesiredSize.ascent = desSize.ascent;
@ -209,9 +207,9 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
dx = bmSqr.rightBearing;
// Stretch the overline bar to the appropriate width if it is not big enough.
contSize = nsCharMetrics(aDesiredSize);
desSize = nsCharMetrics(fontDescent, fontAscent, bmBar.rightBearing-bmBar.leftBearing, fontAscent + fontDescent);
nsCharMetrics oldSize = desSize;
contSize = nsStretchMetrics(aDesiredSize);
desSize = nsStretchMetrics(fontDescent, fontAscent, bmBar.rightBearing-bmBar.leftBearing, fontAscent + fontDescent);
nsStretchMetrics oldSize = desSize;
mBarChar.Stretch(aPresContext, renderingContext, mStyleContext,
NS_STRETCH_DIRECTION_HORIZONTAL, contSize, desSize);
@ -250,8 +248,14 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
rect[3].x += dx; // x-origin of bar
}
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
mSqrChar.SetRect(rect[2]);
mBarChar.SetRect(rect[3]);

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmrootFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmrootFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmrootFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmrowFrame(nsIFrame** aNewFrame)
NS_NewMathMLmrowFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmrowFrame* it = new nsMathMLmrowFrame;
nsMathMLmrowFrame* it = new (aPresShell) nsMathMLmrowFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -75,6 +75,8 @@ nsMathMLmrowFrame::Init(nsIPresContext* aPresContext,
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
// XXX Attributes?
return rv;
}

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmrowFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmrowFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmrowFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -45,13 +45,13 @@
//
nsresult
NS_NewMathMLmsqrtFrame(nsIFrame** aNewFrame)
NS_NewMathMLmsqrtFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmsqrtFrame* it = new nsMathMLmsqrtFrame;
nsMathMLmsqrtFrame* it = new (aPresShell) nsMathMLmsqrtFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -63,10 +63,8 @@ nsMathMLmsqrtFrame::nsMathMLmsqrtFrame() :
mSqrChar(),
mBarChar()
{
nsAutoString sqr(PRUnichar(0x221A)),
bar(PRUnichar(0xF8E5));
mSqrChar.SetData(sqr);
mBarChar.SetData(bar);
mSqrChar.SetEnum(eMathMLChar_Radical);
mBarChar.SetEnum(eMathMLChar_RadicalBar);
}
nsMathMLmsqrtFrame::~nsMathMLmsqrtFrame()
@ -83,9 +81,8 @@ nsMathMLmsqrtFrame::Init(nsIPresContext* aPresContext,
nsresult rv = NS_OK;
rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent,
aContext, aPrevInFlow);
if (NS_FAILED(rv)) {
return rv;
}
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
// TODO: other attributes...
return rv;
@ -146,6 +143,10 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
fm->GetMaxAscent(fontAscent);
fm->GetMaxDescent(fontDescent);
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nsBoundingMetrics bmSqr, bmBar;
nscoord dx, dy;
@ -158,10 +159,10 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
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.
nsCharMetrics contSize(aDesiredSize);
nsCharMetrics desSize(fontDescent, fontAscent, charWidth, fontAscent + fontDescent);
nsStretchMetrics contSize(aDesiredSize);
nsStretchMetrics desSize(fontDescent, fontAscent, charWidth, fontAscent + fontDescent);
mSqrChar.Stretch(aPresContext, renderingContext, mStyleContext,
NS_STRETCH_DIRECTION_VERTICAL, contSize, desSize);
NS_STRETCH_DIRECTION_VERTICAL, contSize, desSize);
charWidth = desSize.width;
if (aDesiredSize.ascent < desSize.ascent) {
aDesiredSize.ascent = desSize.ascent;
@ -172,31 +173,32 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
dx = 0;
dy = bmSqr.ascent - fontAscent;
dy = 2*onePixel + (bmSqr.ascent - fontAscent);
mSqrChar.SetRect(nsRect(dx, dy, desSize.width, aDesiredSize.height));
dx = bmSqr.rightBearing;
// Stretch the overline bar to the appropriate width if it is not big enough.
contSize = nsCharMetrics(aDesiredSize);
desSize = nsCharMetrics(fontDescent, fontAscent, bmBar.rightBearing-bmBar.leftBearing, fontAscent + fontDescent);
nsCharMetrics oldSize = desSize;
contSize = nsStretchMetrics(aDesiredSize);
desSize = nsStretchMetrics(fontDescent, fontAscent, bmBar.rightBearing-bmBar.leftBearing, fontAscent + fontDescent);
nsStretchMetrics oldSize = desSize;
mBarChar.Stretch(aPresContext, renderingContext, mStyleContext,
NS_STRETCH_DIRECTION_HORIZONTAL, contSize, desSize);
dy = bmBar.ascent - fontAscent;
dy = 2*onePixel + (bmBar.ascent - fontAscent);
if (oldSize == desSize) { // hasn't changed size! Char will be painted as a normal char
dx -= bmBar.leftBearing; // adjust so that it coincides with the sqrt char
}
dy = bmBar.ascent - fontAscent;
mBarChar.SetRect(nsRect(dx, dy, desSize.width, thickspace));
// XXX need also to check when a single glyph wil be used
}
mBarChar.SetRect(nsRect(dx, dy, desSize.width, 2*onePixel + thickspace));
// Update the size of the container
aDesiredSize.width += charWidth;
aDesiredSize.ascent += thickspace;
aDesiredSize.ascent += 2*onePixel + thickspace;
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
//////////////////
// Place Children now by setting the origin of each child.
// Adjust the origins to leave room for the sqrt char and the overline bar
nsRect rect;
dx = charWidth;

Просмотреть файл

@ -56,7 +56,7 @@ TODO:
class nsMathMLmsqrtFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsqrtFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmsqrtFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmstyleFrame(nsIFrame** aNewFrame)
NS_NewMathMLmstyleFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmstyleFrame* it = new nsMathMLmstyleFrame;
nsMathMLmstyleFrame* it = new (aPresShell) nsMathMLmstyleFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -82,7 +82,7 @@ nsMathMLmstyleFrame::Init(nsIPresContext* aPresContext,
// see if the displaystyle attribute is there
nsAutoString value;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::displaystyle, value)) {
nsMathMLAtoms::displaystyle_, value)) {
if (value == "true") {
mDisplayStyle = PR_TRUE;
mFlags |= NS_MATHML_MSTYLE_DISPLAYSTYLE;
@ -95,7 +95,7 @@ nsMathMLmstyleFrame::Init(nsIPresContext* aPresContext,
// see if the scriptlevel attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::scriptlevel, value)) {
nsMathMLAtoms::scriptlevel_, value)) {
PRInt32 aErrorCode, aUserValue;
aUserValue = value.ToInteger(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {

Просмотреть файл

@ -42,7 +42,7 @@
class nsMathMLmstyleFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmstyleFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmstyleFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmsubFrame(nsIFrame** aNewFrame)
NS_NewMathMLmsubFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmsubFrame* it = new nsMathMLmsubFrame;
nsMathMLmsubFrame* it = new (aPresShell) nsMathMLmsubFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -67,56 +67,24 @@ nsMathMLmsubFrame::~nsMathMLmsubFrame()
}
NS_IMETHODIMP
nsMathMLmsubFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsMathMLmsubFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
// Reflow Children
nscoord count = 0;
nsRect rect[2];
nsIFrame* child[2];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else if (2 > count) {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
while (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 2 > count) {
childFrame->GetRect(rect[count]);
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
if (0 == count) {
aDesiredSize.ascent = childDesiredSize.ascent;
}
count++;
}
// else { invalid markup... }
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
childFrame->GetNextSibling(&childFrame);
}
//////////////////
// Place Children
aDesiredSize.ascent = rect[0].y;
// Get the subscript offset
nscoord subscriptOffset, leading;
@ -151,13 +119,15 @@ subscriptOffset = PR_MAX(subscriptOffset,fmAscent-(xHeight*4)/5);
rect[1].y = aDesiredSize.height - rect[1].height;
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}

Просмотреть файл

@ -32,13 +32,13 @@
class nsMathMLmsubFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsubFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmsubFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
@ -48,7 +48,10 @@ public:
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
UpdatePresentationDataFromChildAt(1, 1, PR_FALSE);
// switch the style of the subscript
InsertScriptLevelStyleContext(aPresContext);
// check whether or not this is an embellished operator
EmbellishOperator();
return rv;
}

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmsubsupFrame(nsIFrame** aNewFrame)
NS_NewMathMLmsubsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmsubsupFrame* it = new nsMathMLmsubsupFrame;
nsMathMLmsubsupFrame* it = new (aPresShell) nsMathMLmsubsupFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -67,59 +67,30 @@ nsMathMLmsubsupFrame::~nsMathMLmsubsupFrame()
}
NS_IMETHODIMP
nsMathMLmsubsupFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
// Reflow Children
nsresult rv;
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nscoord ascent, descent;
nscoord count = 0;
nsRect rect[3];
nsIFrame* child[3];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else if (3 > count) {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
while (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 3 > count) {
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
if (0 == count) {
ascent = childDesiredSize.ascent;
descent = childDesiredSize.descent;
}
childFrame->GetRect(rect[count]);
count++;
}
// else { invalid markup... }
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
descent = rect[0].x;
ascent = rect[0].y;
//////////////////
// Place Children
// Get the subscript and superscript offsets
nscoord subscriptOffset, superscriptOffset, leading;
nsCOMPtr<nsIFontMetrics> fm;
@ -158,15 +129,21 @@ subscriptOffset = PR_MAX(subscriptOffset,fmAscent-(xHeight*4)/5);
rect[2].y = 0;
rect[1].y = aDesiredSize.height - rect[1].height;
rect[0].y = aDesiredSize.height - subHeight;
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
child[2]->SetRect(aPresContext, rect[2]);
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
// child[2]->SetRect(aPresContext, rect[2]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}

Просмотреть файл

@ -32,13 +32,13 @@
class nsMathMLmsubsupFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsubsupFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmsubsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
@ -48,7 +48,10 @@ public:
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
UpdatePresentationDataFromChildAt(1, 1, PR_FALSE);
// switch the style of the subscript and superscript
InsertScriptLevelStyleContext(aPresContext);
// check whether or not this is an embellished operator
EmbellishOperator();
return rv;
}

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmsupFrame(nsIFrame** aNewFrame)
NS_NewMathMLmsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmsupFrame* it = new nsMathMLmsupFrame;
nsMathMLmsupFrame* it = new (aPresShell) nsMathMLmsupFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -67,58 +67,25 @@ nsMathMLmsupFrame::~nsMathMLmsupFrame()
}
NS_IMETHODIMP
nsMathMLmsupFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsMathMLmsupFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
// Reflow Children
nscoord count = 0;
nsRect rect[2];
nsIFrame* child[2];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else if (2 > count) {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
if (0 == count) {
aDesiredSize.descent = childDesiredSize.descent;
}
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 2 > count) {
childFrame->GetRect(rect[count]);
child[count] = childFrame;
count++;
}
// else { invalid markup... }
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
childFrame->GetNextSibling(&childFrame);
}
aDesiredSize.descent = rect[0].x;
//////////////////
// Place Children
// Get the superscript offset
nscoord superscriptOffset, leading;
nsCOMPtr<nsIFontMetrics> fm;
@ -137,14 +104,20 @@ nsMathMLmsupFrame::Reflow(nsIPresContext* aPresContext,
rect[1].y = 0;
rect[0].y = aDesiredSize.height - rect[0].height;
aDesiredSize.ascent = aDesiredSize.height - aDesiredSize.descent;
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}

Просмотреть файл

@ -32,13 +32,13 @@
class nsMathMLmsupFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsupFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
@ -48,7 +48,10 @@ public:
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
UpdatePresentationDataFromChildAt(1, 1, PR_FALSE);
// switch the style of the superscript
InsertScriptLevelStyleContext(aPresContext);
// check whether or not this is an embellished operator
EmbellishOperator();
return rv;
}

Просмотреть файл

@ -45,13 +45,13 @@
//
nsresult
NS_NewMathMLmtdFrame(nsIFrame** aNewFrame)
NS_NewMathMLmtdFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmtdFrame* it = new nsMathMLmtdFrame;
nsMathMLmtdFrame* it = new (aPresShell) nsMathMLmtdFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -32,7 +32,7 @@
class nsMathMLmtdFrame : public nsAreaFrame {
public:
friend nsresult NS_NewMathMLmtdFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmtdFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,

Просмотреть файл

@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmunderFrame(nsIFrame** aNewFrame)
NS_NewMathMLmunderFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmunderFrame* it = new nsMathMLmunderFrame;
nsMathMLmunderFrame* it = new (aPresShell) nsMathMLmunderFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -66,93 +66,73 @@ nsMathMLmunderFrame::~nsMathMLmunderFrame()
{
}
NS_IMETHODIMP
nsMathMLmunderFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
return rv;
}
NS_IMETHODIMP
nsMathMLmunderFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
// Reflow Children
nscoord count = 0;
nsRect rect[2];
nsIFrame* child[2];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else if (2 > count) {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
/////////////
// Reflow children
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
if (0 == count) {
aDesiredSize.ascent = childDesiredSize.ascent;
aDesiredSize.descent = childDesiredSize.descent;
}
count++;
}
// else { invalid markup... }
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
aDesiredSize.width = PR_MAX(rect[0].width, rect[1].width);
ReflowChildren(1, aPresContext, aDesiredSize, aReflowState, aStatus);
/////////////
// Ask stretchy children to stretch themselves
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
nsStretchMetrics containerSize(aDesiredSize);
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_HORIZONTAL;
nsCharMetrics parentSize(aDesiredSize);
for (PRInt32 i = 0; i < count; i++) {
//////////
// Stretch ...
// Only directed at frames that implement the nsIMathMLFrame interface
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = child[i]->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsCharMetrics childSize(rect[i].x, rect[i].y, rect[i].width, rect[i].height);
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
aMathMLFrame->Stretch(aPresContext, renderingContext,
stretchDir, parentSize, childSize);
// store the updated metrics
rect[i] = nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height);
StretchChildren(aPresContext, renderingContext, stretchDir, containerSize);
/////////////
// Place children now by re-adjusting the origins to align the baselines
FinalizeReflow(1, aPresContext, renderingContext, aDesiredSize);
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLmunderFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nscoord count = 0;
nsRect rect[2];
nsIFrame* child[2];
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 2 > count) {
childFrame->GetRect(rect[count]);
child[count] = childFrame;
count++;
}
childFrame->GetNextSibling(&childFrame);
}
//////////////////
// Place Children
aDesiredSize.descent = rect[0].x;
aDesiredSize.ascent = rect[0].y;
#if 0
// Get the underline offset and align the top of the under-element with it
nscoord underOffset, underThickness;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
aPresContext->GetMetricsFor(aFont->mFont, getter_AddRefs(fm));
fm->GetUnderline(underOffset, underThickness);
#endif
aDesiredSize.descent += rect[1].height;
aDesiredSize.width = PR_MAX(rect[0].width, rect[1].width);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
@ -174,13 +154,19 @@ nsMathMLmunderFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.descent -= leading;
rect[1].y -= leading;
//
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
}

Просмотреть файл

@ -32,7 +32,14 @@
class nsMathMLmunderFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmunderFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmunderFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
@ -40,6 +47,12 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
@ -48,7 +61,10 @@ public:
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;
}

Просмотреть файл

@ -3,19 +3,19 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* The Original Code is Mozilla MathML Project.
*
* The Initial Developer of the Original Code is The University Of
*
* The Initial Developer of the Original Code is The University Of
* Queensland. Portions created by The University Of Queensland are
* Copyright (C) 1999 The University Of Queensland. All Rights Reserved.
*
* Contributor(s):
*
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
*/
@ -44,13 +44,13 @@
//
nsresult
NS_NewMathMLmunderoverFrame(nsIFrame** aNewFrame)
NS_NewMathMLmunderoverFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aNewFrame, "null OUT ptr");
if (nsnull == aNewFrame) {
return NS_ERROR_NULL_POINTER;
}
nsMathMLmunderoverFrame* it = new nsMathMLmunderoverFrame;
nsMathMLmunderoverFrame* it = new (aPresShell) nsMathMLmunderoverFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -66,121 +66,110 @@ nsMathMLmunderoverFrame::~nsMathMLmunderoverFrame()
{
}
NS_IMETHODIMP
nsMathMLmunderoverFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
return rv;
}
NS_IMETHODIMP
nsMathMLmunderoverFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
aDesiredSize.width = 0;
/////////////
// Reflow children to stretch themselves
//////////////////
// Reflow Children
nscoord count = 0;
nsRect rect[3];
nsIFrame* child[3];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else if (3 > count) {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
childReflowState, childStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
if (NS_FAILED(rv)) {
return rv;
}
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
if (aDesiredSize.width < childDesiredSize.width) {
aDesiredSize.width = childDesiredSize.width;
}
if (0 == count) {
aDesiredSize.ascent = childDesiredSize.ascent;
aDesiredSize.descent = childDesiredSize.descent;
}
count++;
}
// else { invalid markup... }
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
ReflowChildren(1, aPresContext, aDesiredSize, aReflowState, aStatus);
/////////////
// Ask stretchy children to stretch themselves
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
nsStretchMetrics containerSize(aDesiredSize);
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_HORIZONTAL;
nsCharMetrics parentSize(aDesiredSize);
for (PRInt32 i = 0; i < count; i++) {
//////////
// Stretch ...
// Only directed at frames that implement the nsIMathMLFrame interface
nsIMathMLFrame* aMathMLFrame = nsnull;
rv = child[i]->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsCharMetrics childSize(rect[i].x, rect[i].y, rect[i].width, rect[i].height);
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
aMathMLFrame->Stretch(aPresContext, renderingContext,
stretchDir, parentSize, childSize);
// store the updated metrics
rect[i] = nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height);
}
}
//////////////////
// Place Children
aDesiredSize.ascent += rect[1].height;
aDesiredSize.descent += rect[2].height;
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
StretchChildren(aPresContext, renderingContext, stretchDir, containerSize);
rect[0].x = (aDesiredSize.width - rect[0].width) / 2; // center w.r.t largest width
rect[1].x = (aDesiredSize.width - rect[1].width) / 2;
rect[2].x = (aDesiredSize.width - rect[2].width) / 2;
rect[0].y = rect[1].height;
rect[1].y = aDesiredSize.height - rect[1].height;
rect[2].y = 0;
//ignore the leading (line spacing) that is attached to the text
nscoord leading;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
aPresContext->GetMetricsFor(aFont->mFont, getter_AddRefs(fm));
fm->GetLeading(leading);
aDesiredSize.height -= 2*leading;
aDesiredSize.ascent -= leading;
aDesiredSize.descent -= leading;
rect[0].y -= leading;
rect[1].y -= 2*leading;
//
child[0]->SetRect(aPresContext, rect[0]);
child[1]->SetRect(aPresContext, rect[1]);
child[2]->SetRect(aPresContext, rect[2]);
/////////////
// Place children now by re-adjusting the origins to align the baselines
FinalizeReflow(1, aPresContext, renderingContext, aDesiredSize);
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nscoord count = 0;
nsRect rect[3];
nsIFrame* child[3];
aDesiredSize.width = 0;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 3 > count) {
child[count] = childFrame;
childFrame->GetRect(rect[count]);
if (aDesiredSize.width < rect[count].width) aDesiredSize.width = rect[count].width;
count++;
}
childFrame->GetNextSibling(&childFrame);
}
aDesiredSize.descent = rect[0].x;
aDesiredSize.ascent = rect[0].y;
aDesiredSize.ascent += rect[2].height;
aDesiredSize.descent += rect[1].height;
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
rect[0].x = (aDesiredSize.width - rect[0].width) / 2; // center w.r.t largest width
rect[1].x = (aDesiredSize.width - rect[1].width) / 2;
rect[2].x = (aDesiredSize.width - rect[2].width) / 2;
rect[0].y = rect[2].height;
rect[1].y = aDesiredSize.height - rect[1].height;
rect[2].y = 0;
//ignore the leading (line spacing) that is attached to the text
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
nsCOMPtr<nsIFontMetrics> fm;
aPresContext->GetMetricsFor(font.mFont, getter_AddRefs(fm));
nscoord leading;
fm->GetLeading(leading);
aDesiredSize.height -= 2*leading;
aDesiredSize.ascent -= leading;
aDesiredSize.descent -= leading;
rect[0].y -= leading;
rect[1].y -= 2*leading;
//
if (aPlaceOrigin) {
// child[0]->SetRect(aPresContext, rect[0]);
// child[1]->SetRect(aPresContext, rect[1]);
// child[2]->SetRect(aPresContext, rect[2]);
nsHTMLReflowMetrics childSize(nsnull);
for (PRInt32 i=0; i<count; i++) {
childSize.width = rect[i].width;
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
return NS_OK;
}

Просмотреть файл

@ -32,7 +32,14 @@
class nsMathMLmunderoverFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmunderoverFrame(nsIFrame** aNewFrame);
friend nsresult NS_NewMathMLmunderoverFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
@ -40,6 +47,12 @@ public:
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
@ -48,7 +61,10 @@ public:
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;
}