[MATHML]. Laying some groundwork to pave the way for the future landing of Shyjan Mahamud's TeX alignment code.

This commit is contained in:
rbs%maths.uq.edu.au 2000-01-07 14:49:46 +00:00
Родитель 8fb2624d02
Коммит 423260e01b
28 изменённых файлов: 1554 добавлений и 506 удалений

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

@ -50,6 +50,7 @@ CPPSRCS = nsMathMLChar.cpp \
nsMathMLmsubsupFrame.cpp \
nsMathMLmmultiscriptsFrame.cpp \
nsMathMLmiFrame.cpp \
nsMathMLmnFrame.cpp \
nsMathMLmtdFrame.cpp \
nsMathMLmoFrame.cpp \
nsMathMLmunderFrame.cpp \

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

@ -36,6 +36,7 @@ CPPSRCS= nsMathMLChar.cpp \
nsMathMLmfracFrame.cpp \
nsMathMLmsubFrame.cpp \
nsMathMLmiFrame.cpp \
nsMathMLmnFrame.cpp \
nsMathMLmsubsupFrame.cpp \
nsMathMLmmultiscriptsFrame.cpp \
nsMathMLmsupFrame.cpp \
@ -58,6 +59,7 @@ CPP_OBJS= .\$(OBJDIR)\nsMathMLChar.obj \
.\$(OBJDIR)\nsMathMLmfracFrame.obj \
.\$(OBJDIR)\nsMathMLmsubFrame.obj \
.\$(OBJDIR)\nsMathMLmiFrame.obj \
.\$(OBJDIR)\nsMathMLmnFrame.obj \
.\$(OBJDIR)\nsMathMLmsubsupFrame.obj \
.\$(OBJDIR)\nsMathMLmmultiscriptsFrame.obj \
.\$(OBJDIR)\nsMathMLmsupFrame.obj \

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

@ -22,7 +22,7 @@
#ifndef nsIMathMLFrame_h___
#define nsIMathMLFrame_h___
struct nsEmbellishState;
struct nsEmbellishData;
struct nsStretchMetrics;
typedef PRInt32 nsStretchDirection;
@ -59,13 +59,13 @@ public:
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> */
/*====================================================================*/
@ -161,15 +161,15 @@ public:
NS_IMETHOD
EmbellishOperator() = 0;
/* GetEmbellishState/SetEmbellishState :
/* GetEmbellishData/SetEmbellishData :
* Get/Set the mEmbellish member data.
*/
NS_IMETHOD
GetEmbellishState(nsEmbellishState& aEmbellishState) = 0;
GetEmbellishData(nsEmbellishData& aEmbellishData) = 0;
NS_IMETHOD
SetEmbellishState(const nsEmbellishState& aEmbellishState) = 0;
SetEmbellishData(const nsEmbellishData& aEmbellishData) = 0;
/* SUPPORT FOR SCRIPTING ELEMENTS: */
@ -199,7 +199,7 @@ public:
* their mDisplayStyle to aDisplayStyle and increment their mScriptLevel
* with aScriptLevelIncrement. The increment is propagated down to the
* subtrees of each of these child frames. Note that <mstyle> is the only
* tag which allows <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
* tag which allows <mstyle displaystyle="true|false" scriptlevel="[+|-]number">
* to reset or increment the scriptlevel in a manual way. Therefore <mstyle>
* has its own peculiar version of this method.
*/
@ -259,6 +259,26 @@ struct nsStretchMetrics {
}
};
// struct used by an embellished container to keep track of its embellished child
struct nsEmbellishData {
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;
nsEmbellishData()
{
flags = 0;
firstChild = nsnull;
core = nsnull;
direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
leftSpace = rightSpace = 0;
}
};
// --------------
#define NS_MATHML_EMBELLISH_OPERATOR 0x1
#define NS_MATHML_STRETCH_FIRST_CHILD NS_MATHML_EMBELLISH_OPERATOR
@ -280,23 +300,5 @@ struct nsStretchMetrics {
#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___ */

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

@ -61,8 +61,8 @@
Three steps are needed to extend the table:
---------------------------------------=---
1. Append your new section in gMathMLCharGlyph[].
2. Append your new enum in nsMathMLCharEnum, and kMathMLChar
1. Append your new enum in nsMathMLCharList.h
2. Append your new section in gMathMLCharGlyph[].
3. Append a new pointer in gMathMLCharIndex[], so that
gMathMLCharIndex[your_enum] points to the begining of
your new section in gMathMLCharGlyph[]. That is,
@ -263,38 +263,18 @@ static PRInt32 gMathMLCharIndex[] = {
48, // eMathMLChar_UpArrow,
54, // eMathMLChar_LeftArrow,
60, // eMathMLChar_RightArrow,
66, // eMathMLChar_RadicalBar,
72, // eMathMLChar_Radical, -- placeholder for now
66, // eMathMLChar_OverBar,
72, // eMathMLChar_VerticalBar,
78, // eMathMLChar_Sqrt, -- placeholder for now
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 , '(', 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,
#define MATHML_CHAR(_name, _value, _direction) eMathMLChar_##_name, _value, _direction,
#include "nsMathMLCharList.h"
#undef MATHML_CHAR
};
#undef STRETCH_UNSUPPORTED
#undef STRETCH_HORIZONTAL
#undef STRETCH_VERTICAL
//---------------------------------------------
@ -306,6 +286,7 @@ nsMathMLChar::SetData(nsString& aData) {
// some assumptions until proven otherwise!
mEnum = eMathMLChar_DONT_STRETCH;
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
mBoundingMetrics.Clear();
// lookup the enum ...
if (1 == mData.Length()) {
PRUnichar ch = mData[0];
@ -328,6 +309,7 @@ nsMathMLChar::SetEnum(nsMathMLCharEnum aEnum) {
// some assumptions until proven otherwise!
mData = "";
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
mBoundingMetrics.Clear();
// lookup the data ...
if (mEnum != eMathMLChar_DONT_STRETCH) {
PRInt32 count = sizeof(kMathMLChar) / sizeof(kMathMLChar[0]);
@ -388,8 +370,18 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
aDirection = mDirection;
}
// quick return if there is nothing special about this char
// Set font
nsStyleFont font;
aStyleContext->GetStyle(eStyleStruct_Font, font);
aRenderingContext.SetFont(font.mFont);
// cache our bounding metrics and quickly return if there is nothing
// special about this char
if (eMathMLChar_DONT_STRETCH == mEnum || aDirection != mDirection) {
rv = aRenderingContext.GetBoundingMetrics(mData.GetUnicode(),
PRUint32(mData.Length()),
mBoundingMetrics);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", mData[0], mData[0]&0x00FF); /*getchar();*/ return rv; }
return NS_OK;
}
@ -398,12 +390,20 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
if (aDirection == NS_STRETCH_DIRECTION_VERTICAL) {
if (aContainerSize.height <= aDesiredStretchSize.height) {
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char later behaves like a normal char
rv = aRenderingContext.GetBoundingMetrics(mData.GetUnicode(),
PRUint32(mData.Length()),
mBoundingMetrics);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", mData[0], mData[0]&0x00FF); /*getchar();*/ return rv; }
return NS_OK;
}
}
else if (aDirection == NS_STRETCH_DIRECTION_HORIZONTAL) {
if (aContainerSize.width <= aDesiredStretchSize.width) {
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char later behaves like a normal char
rv = aRenderingContext.GetBoundingMetrics(mData.GetUnicode(),
PRUint32(mData.Length()),
mBoundingMetrics);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", mData[0], mData[0]&0x00FF); /*getchar();*/ return rv; }
return NS_OK;
}
}
@ -416,11 +416,6 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
// XXX Note: there are other symbols that just need to slightly
// increase their size, like \Sum
// Set font
nsStyleFont font;
aStyleContext->GetStyle(eStyleStruct_Font, font);
aRenderingContext.SetFont(font.mFont);
nscoord height = aDesiredStretchSize.height;
nscoord width = aDesiredStretchSize.width;
nscoord ascent = aDesiredStretchSize.ascent;
@ -433,12 +428,16 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
// try first to see if there is a glyph of appropriate size ...
PRBool sizeOK = PR_FALSE;
PRUnichar ch = gMathMLCharGlyph[index++];
nsBoundingMetrics bm;
nsBoundingMetrics bm, bm0;
PRInt32 index0 = index;
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; }
// keep track of the default bounding metrics
if (index0 == index) bm0 = bm;
h = bm.ascent - bm.descent;
w = bm.rightBearing - bm.leftBearing;
@ -453,7 +452,10 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
ascent = bm.ascent;
height = bm.ascent - bm.descent;
width = bm.rightBearing - bm.leftBearing;
// cache all this information
mGlyph = ch;
mBoundingMetrics = bm;
break;
}
ch = gMathMLCharGlyph[index++];
@ -477,12 +479,23 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; }
if (w < bm.width) w = bm.width;
if (i < 3) h += nscoord(flex[i]*(bm.ascent-bm.descent)); // sum heights of the parts...
if (i < 3) {
h += nscoord(flex[i]*(bm.ascent-bm.descent)); // sum heights of the parts...
// compute and cache our bounding metrics (vertical stacking!)
if (mBoundingMetrics.leftBearing > bm.leftBearing)
mBoundingMetrics.leftBearing = bm.leftBearing;
if (mBoundingMetrics.rightBearing < bm.rightBearing)
mBoundingMetrics.rightBearing = bm.rightBearing;
}
}
if (h <= aContainerSize.height) { // can nicely fit in the available space...
width = w;
mBoundingMetrics.width = w;
mBoundingMetrics.ascent = aContainerSize.ascent;
mBoundingMetrics.descent = -aContainerSize.descent;
} else { // sum of parts doesn't fit in the space... will use a single glyph
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char behaves like a normal char
mBoundingMetrics = bm0;
return NS_OK;
}
}
@ -497,16 +510,26 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
ch = gMathMLCharGlyph[index+i];
rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; }
if (0 == i) bm0 = bm;
if (a < bm.ascent) a = bm.ascent;
if (d > bm.descent) d = bm.descent;
if (i < 3) w += nscoord(flex[i]*(bm.rightBearing-bm.leftBearing)); // sum widths of the parts...
if (i < 3) {
w += nscoord(flex[i]*(bm.rightBearing-bm.leftBearing)); // sum widths of the parts...
// compute and cache our bounding metrics (horizontal stacking)
if (0 == i)
mBoundingMetrics = bm;
else
mBoundingMetrics += bm;
}
}
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;
mBoundingMetrics.width = aContainerSize.width;
} else { // sum of parts doesn't fit in the space... will use a single glyph
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char behaves like a normal char
mBoundingMetrics = bm0;
return NS_OK;
}
}

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

@ -25,26 +25,16 @@
#include "nsMathMLOperators.h"
#include "nsIMathMLFrame.h"
// chars that we know how something about
// enum of chars that we know something about
enum nsMathMLCharEnum {
eMathMLChar_DONT_STRETCH = -1,
eMathMLChar_LeftParenthesis,
eMathMLChar_RightParenthesis,
eMathMLChar_Integral ,
eMathMLChar_LeftSquareBracket,
eMathMLChar_RightSquareBracket,
eMathMLChar_LeftCurlyBracket,
eMathMLChar_RightCurlyBracket,
eMathMLChar_DownArrow,
eMathMLChar_UpArrow,
eMathMLChar_LeftArrow,
eMathMLChar_RightArrow,
eMathMLChar_RadicalBar,
eMathMLChar_Radical,
eMathMLChar_VerticalBar,
#define MATHML_CHAR(_name, _value, _direction) eMathMLChar_##_name,
#include "nsMathMLCharList.h"
#undef MATHML_CHAR
eMathMLChar_COUNT
};
// class used to handle stretchy symbols (accent and boundary symbol)
class nsMathMLChar
{
@ -124,12 +114,18 @@ public:
mRect = aRect;
}
void
GetBoundingMetrics(nsBoundingMetrics aBoundingMetrics) {
aBoundingMetrics = mBoundingMetrics;
}
private:
nsString mData;
PRUnichar mGlyph;
nsRect mRect;
nsStretchDirection mDirection;
nsMathMLCharEnum mEnum;
nsBoundingMetrics mBoundingMetrics;
// helper methods

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

@ -27,6 +27,7 @@
#include "nsLineLayout.h"
#include "nsHTMLIIDs.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsHTMLAtoms.h"
#include "nsUnitConversion.h"
#include "nsIStyleContext.h"
@ -150,28 +151,30 @@ nsMathMLContainerFrame::ReflowEmptyChild(nsIPresContext* aPresContext,
NS_IMETHODIMP
nsMathMLContainerFrame::GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics)
{
aBoundingMetrics = mBoundingMetrics;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics)
{
mBoundingMetrics = aBoundingMetrics;
return NS_OK;
}
/*
NS_IMETHOD
GetReference(nsPoint& aReference)
NS_IMETHODIMP
nsMathMLContainerFrame::GetReference(nsPoint& aReference)
{
aReference = mReference;
return NS_OK;
}
NS_IMETHOD
SetReference(const nsPoint& aReference);
NS_IMETHODIMP
nsMathMLContainerFrame::SetReference(const nsPoint& aReference)
{
mReference = aReference;
return NS_OK;
}
*/
/* /////////////
@ -187,19 +190,19 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext,
nsStretchMetrics& aDesiredStretchSize)
{
nsresult rv = NS_OK;
if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellish.flags)) {
if (NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags)) {
if (NS_MATHML_STRETCH_WAS_DONE(mEmbellish.flags)) {
if (NS_MATHML_STRETCH_WAS_DONE(mEmbellishData.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;
mEmbellishData.flags |= NS_MATHML_STRETCH_DONE;
// Pass the stretch to the first non-empty child ...
nsIFrame* childFrame = mEmbellish.firstChild;
nsIFrame* childFrame = mEmbellishData.firstChild;
NS_ASSERTION(childFrame, "Something is wrong somewhere");
if (childFrame) {
@ -209,24 +212,24 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext,
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsHTMLReflowMetrics aReflowMetrics(nsnull);
nsRect rect;
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) {
if (aStretchDirection != NS_STRETCH_DIRECTION_DEFAULT && aStretchDirection != mEmbellishData.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);
aMathMLFrame->Stretch(aPresContext, aRenderingContext,
mEmbellishData.direction, container, childSize);
childFrame->SetRect(aPresContext,
nsRect(childSize.descent, childSize.ascent,
childSize.width, childSize.height));
@ -249,8 +252,8 @@ nsMathMLContainerFrame::Stretch(nsIPresContext* aPresContext,
nscoord em = NSToCoordRound(float(font.mFont.size));
// cache these values
mEmbellish.leftSpace = nscoord( em * aDesiredStretchSize.leftSpace );
mEmbellish.rightSpace = nscoord( em * aDesiredStretchSize.rightSpace );
mEmbellishData.leftSpace = nscoord( em * aDesiredStretchSize.leftSpace );
mEmbellishData.rightSpace = nscoord( em * aDesiredStretchSize.rightSpace );
aDesiredStretchSize.width += nscoord( (aDesiredStretchSize.leftSpace + aDesiredStretchSize.rightSpace) * em );
nscoord dx = nscoord( aDesiredStretchSize.leftSpace * em );
@ -291,7 +294,7 @@ nsMathMLContainerFrame::FinalizeReflow(PRInt32 aDirection,
// 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);
PRBool placeOrigin = !NS_MATHML_IS_EMBELLISH_OPERATOR(mEmbellishData.flags);
Place(aPresContext, aRenderingContext, placeOrigin, aDesiredSize);
if (!placeOrigin) {
@ -299,14 +302,14 @@ nsMathMLContainerFrame::FinalizeReflow(PRInt32 aDirection,
// 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;
nsEmbellishData parentData;
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)) {
aMathMLFrame->GetEmbellishData(parentData);
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(parentData.flags) ||
(NS_MATHML_WILL_STRETCH_FIRST_CHILD(parentData.flags) &&
parentData.firstChild == this)) {
parentWillFireStretch = PR_TRUE;
}
}
@ -319,7 +322,7 @@ nsMathMLContainerFrame::FinalizeReflow(PRInt32 aDirection,
// 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;
// nsIFrame* childFrame = mEmbellishData.firstChild;
// NS_ASSERTION(childFrame, "Something is wrong somewhere");
// childFrame->GetRect(rect);
// nsStretchMetrics curSize(rect.x, rect.y, rect.width, rect.height);
@ -351,6 +354,8 @@ nsMathMLContainerFrame::FinalizeReflow(PRInt32 aDirection,
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
// Also return our bounding metrics
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
return NS_OK;
}
@ -369,37 +374,37 @@ nsMathMLContainerFrame::EmbellishOperator()
}
if (firstChild && IsEmbellishOperator(firstChild)) {
// Cache the first child
mEmbellish.flags |= NS_MATHML_EMBELLISH_OPERATOR;
mEmbellish.firstChild = firstChild;
mEmbellishData.flags |= NS_MATHML_EMBELLISH_OPERATOR;
mEmbellishData.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;
nsEmbellishData embellishData;
aMathMLFrame->GetEmbellishData(embellishData);
mEmbellishData.core = embellishData.core;
mEmbellishData.direction = embellishData.direction;
}
else {
mEmbellish.flags &= ~NS_MATHML_EMBELLISH_OPERATOR;
mEmbellish.firstChild = nsnull;
mEmbellish.core = nsnull;
mEmbellish.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
mEmbellishData.flags &= ~NS_MATHML_EMBELLISH_OPERATOR;
mEmbellishData.firstChild = nsnull;
mEmbellishData.core = nsnull;
mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
}
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::GetEmbellishState(nsEmbellishState& aEmbellishState)
nsMathMLContainerFrame::GetEmbellishData(nsEmbellishData& aEmbellishData)
{
aEmbellishState = mEmbellish;
aEmbellishData = mEmbellishData;
return NS_OK;
}
NS_IMETHODIMP
nsMathMLContainerFrame::SetEmbellishState(const nsEmbellishState& aEmbellishState)
nsMathMLContainerFrame::SetEmbellishData(const nsEmbellishData& aEmbellishData)
{
mEmbellish = aEmbellishState;
mEmbellishData = aEmbellishData;
return NS_OK;
}
@ -411,9 +416,9 @@ nsMathMLContainerFrame::IsEmbellishOperator(nsIFrame* aFrame)
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);
nsEmbellishData aEmbellishData;
aMathMLFrame->GetEmbellishData(aEmbellishData);
return NS_MATHML_IS_EMBELLISH_OPERATOR(aEmbellishData.flags);
}
/* /////////////
@ -451,7 +456,7 @@ nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(PRInt32 aIndex,
while (nsnull != childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
if (0 >= aIndex--) {
nsIMathMLFrame* aMathMLFrame = nsnull;
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = childFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && nsnull != aMathMLFrame) {
// update
@ -522,7 +527,7 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
nsIFrame* newFrame = nsnull;
NS_NewMathMLWrapperFrame(shell, &newFrame);
NS_ASSERTION(newFrame, "Failed to create new frame");
if (!newFrame) break;
newFrame->Init(aPresContext, childContent, lastFrame, newStyleContext, nsnull);
if (nsnull == firstFrame) {
@ -547,15 +552,15 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
// 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) {
nsEmbellishData embellishData;
aMathMLFrame->GetEmbellishData(embellishData);
if (0 != embellishData.flags && nsnull != embellishData.firstChild) {
do { // walk the hierarchy in a bottom-up manner
rv= lastFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
if (NS_FAILED(rv) || !aMathMLFrame) break;
embellishState.firstChild = childFrame;
aMathMLFrame->SetEmbellishState(embellishState);
embellishData.firstChild = childFrame;
aMathMLFrame->SetEmbellishData(embellishData);
childFrame = lastFrame;
lastFrame->GetParent(&lastFrame);
} while (lastFrame != this);
@ -591,10 +596,12 @@ nsMathMLContainerFrame::Init(nsIPresContext* aPresContext,
mScriptLevel = 0;
mDisplayStyle = PR_TRUE;
mCompressed = PR_FALSE; // for compatibility with TeX rendering
mScriptSpace = 0; // = 0.5 pt in plain TeX
mEmbellishData.flags = 0;
mEmbellishData.firstChild = nsnull;
mEmbellish.flags = 0;
mEmbellish.firstChild = nsnull;
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult res = aParent->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(res) && nsnull != aMathMLFrame) {
@ -688,9 +695,9 @@ nsMathMLContainerFrame::GetDesiredStretchSize(nsIPresContext* aPresContext,
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);
nsEmbellishData embellishData;
aMathMLFrame->GetEmbellishData(embellishData);
embellishData.core->GetRect(rect);
}
}
if (0 == aDirection) { // for horizontal positioning of child frames like in mrow
@ -712,7 +719,7 @@ nsMathMLContainerFrame::GetDesiredStretchSize(nsIPresContext* aPresContext,
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// Check if embellished operators didn't have (non-empty) sibblings...
// Check if embellished operators didn't have (non-empty) siblings...
if (0 < count && 0 == aDirection && 0 == aDesiredSize.height) {
// Return the font ascent and font descent
nsCOMPtr<nsIFontMetrics> fm;
@ -733,6 +740,116 @@ nsMathMLContainerFrame::GetDesiredStretchSize(nsIPresContext* aPresContext,
}
#endif
// helper function to reflow token elements
// note that mBoundingMetrics is computed here
nsresult
nsMathMLContainerFrame::ReflowTokenFor(nsIFrame* aFrame,
nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
NS_PRECONDITION(aFrame, "null arg");
nsresult rv = NS_OK;
// ask our children to compute their bounding metrics
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize,
aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
nsBoundingMetrics bm;
PRInt32 count = 0;
nsIFrame* childFrame;
aFrame->FirstChild(nsnull, &childFrame);
while (childFrame) {
if (IsOnlyWhitespace(childFrame)) {
ReflowEmptyChild(aPresContext, childFrame);
}
else {
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
childFrame, availSize);
rv = NS_STATIC_CAST(nsMathMLContainerFrame*,
aFrame)->ReflowChild(childFrame,
aPresContext, childDesiredSize,
childReflowState, aStatus);
NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
if (NS_FAILED(rv)) return rv;
// origins are used as placeholders to store the child's ascent and descent.
childFrame->SetRect(aPresContext,
nsRect(childDesiredSize.descent, childDesiredSize.ascent,
childDesiredSize.width, childDesiredSize.height));
// compute and cache the bounding metrics
if (0 == count)
bm = childDesiredSize.mBoundingMetrics;
else
bm += childDesiredSize.mBoundingMetrics;
count++;
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
NS_STATIC_CAST(nsMathMLContainerFrame*, aFrame)->SetBoundingMetrics(bm);
// Place and size children
NS_STATIC_CAST(nsMathMLContainerFrame*,
aFrame)->FinalizeReflow(0, aPresContext, *aReflowState.rendContext,
aDesiredSize);
return NS_OK;
}
// helper function to place token elements
// mBoundingMetrics is computed at the ReflowToken pass, it is
// not computed here because if our children may be text frames that
// do not implement the GetBoundingMetrics() interface.
nsresult
nsMathMLContainerFrame::PlaceTokenFor(nsIFrame* aFrame,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nsRect rect;
nsIFrame* childFrame;
aFrame->FirstChild(nsnull, &childFrame);
while (childFrame) {
if (!IsOnlyWhitespace(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;
aFrame->FirstChild(nsnull, &childFrame);
while (childFrame) {
childFrame->GetRect(rect);
nsHTMLReflowMetrics childSize(nsnull);
childSize.width = rect.width;
childSize.height = rect.height;
// Place and size the child
dy = aDesiredSize.ascent - rect.y;
NS_STATIC_CAST(nsMathMLContainerFrame*,
aFrame)->FinishReflowChild(childFrame, aPresContext,
childSize, dx, dy, 0);
dx += rect.width;
childFrame->GetNextSibling(&childFrame);
}
}
return NS_OK;
}
// helper function to reflow all children
NS_IMETHODIMP
nsMathMLContainerFrame::ReflowChildren(PRInt32 aDirection,
@ -742,11 +859,15 @@ nsMathMLContainerFrame::ReflowChildren(PRInt32 aDirection,
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);
// Asks the child to cache its bounding metrics
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize,
aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS);
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nscoord count = 0;
@ -772,7 +893,7 @@ nsMathMLContainerFrame::ReflowChildren(PRInt32 aDirection,
nsRect(childDesiredSize.descent, childDesiredSize.ascent,
childDesiredSize.width, childDesiredSize.height));
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(mEmbellish.flags) &&
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(mEmbellishData.flags) &&
IsEmbellishOperator(childFrame)) {
// We have encountered an embellished operator...
// It is treated as if the embellishments were not there!
@ -781,10 +902,10 @@ nsMathMLContainerFrame::ReflowChildren(PRInt32 aDirection,
NS_ASSERTION(NS_SUCCEEDED(rv) && aMathMLFrame, "Mystery!");
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
nsEmbellishState embellishState;
aMathMLFrame->GetEmbellishState(embellishState);
nsEmbellishData embellishData;
aMathMLFrame->GetEmbellishData(embellishData);
nsRect rect;
embellishState.core->GetRect(rect);
embellishData.core->GetRect(rect);
childDesiredSize.descent = rect.x;
childDesiredSize.ascent = rect.y;
childDesiredSize.width = rect.width;
@ -820,7 +941,7 @@ nsMathMLContainerFrame::ReflowChildren(PRInt32 aDirection,
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// Check if embellished operators didn't have (non-empty) sibblings...
// Check if embellished operators didn't have (non-empty) siblings...
if (0 < count && 0 == aDirection && 0 == aDesiredSize.height) {
// Return the font ascent and font descent
nsCOMPtr<nsIFontMetrics> fm;
@ -851,7 +972,7 @@ nsMathMLContainerFrame::StretchChildren(nsIPresContext* aPresContext,
nsRect rect;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (mEmbellish.firstChild == childFrame) {
if (mEmbellishData.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.
@ -886,6 +1007,8 @@ nsMathMLContainerFrame::Reflow(nsIPresContext* aPresContext,
{
nsresult rv = NS_OK;
/////////////
// Reflow children
ReflowChildren(0, aPresContext, aDesiredSize, aReflowState, aStatus);
/////////////
@ -894,7 +1017,7 @@ nsMathMLContainerFrame::Reflow(nsIPresContext* aPresContext,
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(mEmbellish.flags)) {
if (NS_MATHML_WILL_STRETCH_ALL_CHILDREN(mEmbellishData.flags)) {
nsStretchMetrics containerSize(aDesiredSize);
nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL;
@ -917,19 +1040,35 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
{
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
PRInt32 count = 0;
nsRect rect;
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->GetRect(rect);
if (!IsOnlyWhitespace(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;
aDesiredSize.width += rect.width;
if (aDesiredSize.descent < rect.x) aDesiredSize.descent = rect.x;
if (aDesiredSize.ascent < rect.y) aDesiredSize.ascent = rect.y;
// Compute and cache our bounding metrics
nsBoundingMetrics bm;
if (NS_FAILED(GetBoundingMetricsFor(childFrame, bm))) {
bm.ascent = rect.y;
bm.descent = -rect.x;
bm.width = rect.width;
}
if (0 == count)
mBoundingMetrics = bm;
else
mBoundingMetrics += bm;
count++;
}
childFrame->GetNextSibling(&childFrame);
}
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
if (aPlaceOrigin) {
nscoord dy;
nscoord dx = 0;
@ -937,16 +1076,12 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
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);
dy = aDesiredSize.ascent - rect.y;
FinishReflowChild(childFrame, aPresContext, childSize, dx, dy, 0);
dx += rect.width;
@ -961,7 +1096,7 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
// *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
// or your siblings 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!
@ -994,32 +1129,15 @@ nsMathMLWrapperFrame::~nsMathMLWrapperFrame()
{
}
// For Reflow() and Place(), pretend we are a token to re-use code
NS_IMETHODIMP
nsMathMLWrapperFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsresult rv = NS_OK;
aStatus = NS_FRAME_COMPLETE;
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
nsIFrame* childFrame = mFrames.FirstChild();
if (childFrame) {
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize);
rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus);
childFrame->SetRect(aPresContext,
nsRect(childDesiredSize.descent,childDesiredSize.ascent,
childDesiredSize.width,childDesiredSize.height));
aDesiredSize = childDesiredSize;
aStatus = childStatus;
nsIRenderingContext& renderingContext = *aReflowState.rendContext;
FinalizeReflow(0, aPresContext, renderingContext, aDesiredSize);
}
return rv;
return ReflowTokenFor(this, aPresContext, aDesiredSize,
aReflowState, aStatus);
}
NS_IMETHODIMP
@ -1028,25 +1146,6 @@ nsMathMLWrapperFrame::Place(nsIPresContext* aPresContext,
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;
return PlaceTokenFor(this, aPresContext, aRenderingContext,
aPlaceOrigin, aDesiredSize);
}

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
#ifndef nsMathMLContainerFrame_h___
@ -75,13 +76,13 @@ public:
NS_IMETHOD
SetBoundingMetrics(const nsBoundingMetrics& aBoundingMetrics);
/*
NS_IMETHOD
GetReference(nsPoint& aReference);
NS_IMETHOD
SetReference(const nsPoint& aReference);
*/
NS_IMETHOD
Stretch(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -104,10 +105,10 @@ public:
EmbellishOperator();
NS_IMETHOD
GetEmbellishState(nsEmbellishState& aEmbellishState);
GetEmbellishData(nsEmbellishData& aEmbellishData);
NS_IMETHOD
SetEmbellishState(const nsEmbellishState& aEmbellishState);
SetEmbellishData(const nsEmbellishData& aEmbellishData);
NS_IMETHOD
GetPresentationData(PRInt32* aScriptLevel,
@ -147,10 +148,26 @@ public:
nsDidReflowStatus aStatus)
{
mEmbellish.flags &= ~NS_MATHML_STRETCH_DONE;
mEmbellishData.flags &= ~NS_MATHML_STRETCH_DONE;
return nsHTMLContainerFrame::DidReflow(aPresContext, aStatus);
}
// helper function to reflow token elements
static nsresult
ReflowTokenFor(nsIFrame* aFrame,
nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
// helper function to palce token elements
static nsresult
PlaceTokenFor(nsIFrame* aFrame,
nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
// 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.
@ -190,7 +207,7 @@ public:
nsStretchDirection aStretchDirection,
nsStretchMetrics& aContainerSize);
// helper method to complete the post-reflow hook and ensure that embellish
// helper method to complete the post-reflow hook and ensure that embellished
// operators don't terminate their Reflow without receiving a Stretch command.
NS_IMETHOD
FinalizeReflow(PRInt32 aDirection,
@ -216,6 +233,107 @@ public:
ReflowEmptyChild(nsIPresContext* aPresContext,
nsIFrame* aFrame);
// helper methods to facilitate getting/setting the bounding metrics
static nsresult
GetBoundingMetricsFor(nsIFrame* aFrame,
nsBoundingMetrics& aBoundingMetrics)
{
aBoundingMetrics.Clear();
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
aMathMLFrame->GetBoundingMetrics(aBoundingMetrics);
return NS_OK;
}
// if we reach here, aFrame is not a MathML frame, let the caller know that
printf("GetBoundingMetrics() failed!! ...\n"); /* getchar(); */
return NS_ERROR_FAILURE;
}
static nsresult
SetBoundingMetricsFor(nsIFrame* aFrame,
nsBoundingMetrics& aBoundingMetrics)
{
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
aMathMLFrame->SetBoundingMetrics(aBoundingMetrics);
return NS_OK;
}
// if we reach here, aFrame is not a MathML frame, let the caller know that
printf("SetBoundingMetrics() failed!! ...\n"); /* getchar(); */
return NS_ERROR_FAILURE;
}
// helper methods for getting sup/subdrop's from a child
static void
GetSubDropFromChild (nsIPresContext* aPresContext,
nsIFrame* aChild,
nscoord& aSubDrop)
{
const nsStyleFont *font;
aChild->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
nsCOMPtr<nsIFontMetrics> fm;
aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm));
GetSubDrop (fm, aSubDrop);
}
static void
GetSupDropFromChild (nsIPresContext* aPresContext,
nsIFrame* aChild,
nscoord& aSupDrop)
{
const nsStyleFont *font;
aChild->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
nsCOMPtr<nsIFontMetrics> fm;
aPresContext->GetMetricsFor(font->mFont, getter_AddRefs(fm));
GetSupDrop (fm, aSupDrop);
}
// 2 levels of subscript shifts
static void
GetSubScriptShifts (nsIFontMetrics *fm,
nscoord& aSubScriptShift1,
nscoord& aSubScriptShift2)
{
// XXX for now an alias for GetSubscriptOffset
fm->GetSubscriptOffset (aSubScriptShift1);
aSubScriptShift2 = aSubScriptShift1
= NSToCoordRound(0.5f * aSubScriptShift1);
}
// 3 levels of superscript shifts
static void
GetSupScriptShifts (nsIFontMetrics *fm,
nscoord& aSupScriptShift1,
nscoord& aSupScriptShift2,
nscoord& aSupScriptShift3)
{
// XXX for now an alias for GetSupscriptOffset
fm->GetSuperscriptOffset (aSupScriptShift1);
aSupScriptShift2 = aSupScriptShift3 = aSupScriptShift1
= NSToCoordRound(0.75f * aSupScriptShift1);
}
// these are TeX specific params not found in ordinary fonts
static void
GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop)
{
nscoord xHeight;
fm->GetXHeight (xHeight);
aSubDrop = NSToCoordRound(0.3f * xHeight);
}
static void
GetSupDrop (nsIFontMetrics *fm, nscoord& aSupDrop)
{
nscoord xHeight;
fm->GetXHeight (xHeight);
aSupDrop = NSToCoordRound(0.3f * xHeight);
}
protected:
PRInt32 mScriptLevel; // Relevant to nested frames within: msub, msup, msubsup, munder,
@ -223,13 +341,18 @@ protected:
PRBool mDisplayStyle; // displaystyle="false" is intended to slightly alter how the
// rendering is done in inline mode.
PRBool mCompressed; // for compatibility with TeX rendering
// for internal use only, cannot be set by the user.
nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript
// = 0.5pt in plain TeX
nsEmbellishState mEmbellish; // information about a container that is an embellished operator
nsEmbellishData mEmbellishData; // information about a container that is an embellished operator
nsBoundingMetrics mBoundingMetrics; // Metrics that _exactly_ enclose the text of the frame
/*
nsPoint mReference; // Reference point of the frame: mReference.x is the baseline
*/
nsPoint mReference; // Reference point of the frame: mReference.y is the baseline
virtual PRIntn GetSkipSides() const { return 0; }
};

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

@ -28,6 +28,7 @@
// Factory methods for creating MathML objects
extern nsresult NS_NewMathMLmrowFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmiFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
extern nsresult NS_NewMathMLmnFrame ( 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 );

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

@ -75,12 +75,13 @@ nsMathMLmfencedFrame::Init(nsIPresContext* aPresContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
return rv;
mOpenChar = nsnull;
mCloseChar = nsnull;
mSeparatorsChar = nsnull;
mSeparatorsCount = 0;
return rv;
}

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

@ -167,7 +167,9 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
// ask our children to compute their bounding metrics
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize,
aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
@ -253,6 +255,12 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}

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

@ -42,6 +42,7 @@
#include "nsITextContent.h"
#include "nsMathMLmiFrame.h"
#include "nsMathMLTextFrame.h"
//
// <mi> -- identifier - implementation
@ -70,7 +71,6 @@ nsMathMLmiFrame::~nsMathMLmiFrame()
{
}
NS_IMETHODIMP
nsMathMLmiFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
@ -97,14 +97,13 @@ nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext,
// First, let the base class do its work
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
// Get the length of the text content that we enclose
// our content can include comment-nodes, attribute-nodes, text-nodes...
// we use the DOM to make sure that we are only looking at text-nodes...
PRInt32 aLength = 0;
PRInt32 numKids;
mContent->ChildCount(numKids);
// nsAutoString aData;
nsAutoString aData;
for (PRInt32 kid=0; kid<numKids; kid++) {
nsCOMPtr<nsIContent> kidContent;
mContent->ChildAt(kid, *getter_AddRefs(kidContent));
@ -114,9 +113,9 @@ nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext,
PRUint32 kidLength;
kidText->GetLength(&kidLength);
aLength += kidLength;
// nsAutoString kidData;
// kidText->GetData(kidData);
// aData += kidData;
nsAutoString kidData;
kidText->GetData(kidData);
aData += kidData;
}
}
}
@ -143,21 +142,40 @@ nsMathMLmiFrame::SetInitialChildList(nsIPresContext* aPresContext,
nsIFrame* newFrame = nsnull;
NS_NewMathMLWrapperFrame(shell, &newFrame);
NS_ASSERTION(newFrame, "Failed to create new frame");
newFrame->Init(aPresContext, mContent, this, newStyleContext, nsnull);
// our children become children of the new frame
nsIFrame* childFrame = firstChild;
while (childFrame) {
childFrame->SetParent(newFrame);
aPresContext->ReParentStyleContext(childFrame, newStyleContext);
childFrame->GetNextSibling(&childFrame);
if (newFrame) {
newFrame->Init(aPresContext, mContent, this, newStyleContext, nsnull);
// our children become children of the new frame
nsIFrame* childFrame = firstChild;
while (childFrame) {
childFrame->SetParent(newFrame);
aPresContext->ReParentStyleContext(childFrame, newStyleContext);
childFrame->GetNextSibling(&childFrame);
}
newFrame->SetInitialChildList(aPresContext, nsnull, firstChild);
// the new frame becomes our sole child
mFrames.SetFrames(newFrame);
}
newFrame->SetInitialChildList(aPresContext, nsnull, firstChild);
// the new frame becomes our sole child
mFrames.SetFrames(newFrame);
}
}
return rv;
}
NS_IMETHODIMP
nsMathMLmiFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
return ReflowTokenFor(this, aPresContext, aDesiredSize,
aReflowState, aStatus);
}
NS_IMETHODIMP
nsMathMLmiFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
return PlaceTokenFor(this, aPresContext, aRenderingContext,
aPlaceOrigin, aDesiredSize);
}

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

@ -45,6 +45,19 @@ public:
SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
protected:
nsMathMLmiFrame();
virtual ~nsMathMLmiFrame();

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
@ -66,147 +67,361 @@ nsMathMLmmultiscriptsFrame::~nsMathMLmmultiscriptsFrame()
{
}
NS_IMETHODIMP
nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSubScriptShiftFactor = 0.0f;
mSupScriptShiftFactor = 0.0f;
mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX
// check for subscriptshift and superscriptshift attribute in ex units
nsAutoString value;
mSubUserSetFlag = mSupUserSetFlag = PR_FALSE;
mSubScriptShiftFactor = mSubScriptShiftFactor = 0.0f;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute
(kNameSpaceID_None, nsMathMLAtoms::subscriptshift_, value)) {
PRInt32 aErrorCode;
float aUserValue = value.ToFloat(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {
mSubUserSetFlag = PR_TRUE;
mSubScriptShiftFactor = aUserValue;
}
}
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute
(kNameSpaceID_None, nsMathMLAtoms::superscriptshift_, value)) {
PRInt32 aErrorCode;
float aUserValue = value.ToFloat(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {
mSupUserSetFlag = PR_TRUE;
mSupScriptShiftFactor = aUserValue;
}
}
return rv;
}
NS_IMETHODIMP
nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
nsresult rv;
nsresult rv = NS_OK;
////////////////////////////////////
// Get the children's desired sizes
nscoord italicCorrection = 0;
nscoord minShiftFromXHeight, aSubDrop, aSupDrop;
////////////////////////////////////////
// Initialize super/sub shifts that
// depend only on the current font
////////////////////////////////////////
// get x-height (an ex)
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
nscoord aRuleSize, dummy;
// XXX need to do update this ...
fm->GetStrikeout (dummy, aRuleSize);
/////////////////////////////////////
// first the shift for the subscript
// aSubScriptShift{1,2}
// = minimum amount to shift the subscript down
// = sub{1,2} in TeXbook
// aSubScriptShift1 = subscriptshift attribute * x-height
nscoord aSubScriptShift1, aSubScriptShift2;
// Get aSubScriptShift{1,2} default from font
GetSubScriptShifts (fm, aSubScriptShift1, aSubScriptShift2);
if (mSubUserSetFlag) {
// the user has set the subscriptshift attribute
float aFactor = ((float) aSubScriptShift2) / aSubScriptShift1;
aSubScriptShift1 = NSToCoordRound(mSubScriptShiftFactor * xHeight);
aSubScriptShift2 = NSToCoordRound(aFactor * aSubScriptShift1);
}
// the font dependent shift
nscoord aSubScriptShift = PR_MAX(aSubScriptShift1,aSubScriptShift2);
/////////////////////////////////////
// next the shift for the superscript
// aSupScriptShift{1,2,3}
// = minimum amount to shift the supscript up
// = sup{1,2,3} in TeX
// aSupScriptShift1 = superscriptshift attribute * x-height
// Note that there are THREE values for supscript shifts depending
// on the current style
nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3;
// Set aSupScriptShift{1,2,3} default from font
GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3);
if (mSupUserSetFlag) {
// the user has set the superscriptshift attribute
float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1;
float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1;
aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight);
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}
// get sup script shift depending on current script level and display style
// Rule 18c, App. G, TeXbook
nscoord aSupScriptShift;
if (mScriptLevel == 0 && mDisplayStyle && !mCompressed) {
// Style D in TeXbook
aSupScriptShift = aSupScriptShift1;
}
else if (mCompressed) {
// Style C' in TeXbook = D',T',S',SS'
aSupScriptShift = aSupScriptShift3;
}
else {
// everything else = T,S,SS
aSupScriptShift = aSupScriptShift2;
}
////////////////////////////////////
// Get the children's sizes
////////////////////////////////////
nscoord width = 0;
nsIFrame* mprescriptsFrame = nsnull; // frame of <mprescripts/>, if there.
PRBool isSubscript = PR_FALSE;
nscoord ascent, descent, width, height;
nscoord subsupWidth, subHeight, supHeight, subDescent, supAscent;
nscoord count = 0;
PRBool isSubScript = PR_FALSE;
PRBool isSubScriptPresent = PR_TRUE;
PRBool isSupScriptPresent = PR_TRUE;
nscoord minSubScriptShift = 0, minSupScriptShift = 0;
nscoord trySubScriptShift = aSubScriptShift;
nscoord trySupScriptShift = aSupScriptShift;
nscoord maxSubScriptShift = aSubScriptShift;
nscoord maxSupScriptShift = aSupScriptShift;
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics subScriptSize (nsnull);
nsHTMLReflowMetrics supScriptSize (nsnull);
nsIFrame* baseFrame;
nsIFrame* subScriptFrame;
nsIFrame* supScriptFrame;
nsIFrame* baseFrame = nsnull;
nsIFrame* childFrame = mFrames.FirstChild();
nsRect childRect;
while (childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
// XXX is there an NSPR macro for int_max ???
aDesiredSize.ascent = aDesiredSize.descent = -100000;
aDesiredSize.width = aDesiredSize.height = 0;
nsIFrame* aChildFrame = mFrames.FirstChild();
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace (aChildFrame)) {
nsCOMPtr<nsIContent> childContent;
nsCOMPtr<nsIAtom> childTag;
childFrame->GetContent(getter_AddRefs(childContent));
aChildFrame->GetContent(getter_AddRefs(childContent));
childContent->GetTag(*getter_AddRefs(childTag));
if (childTag.get() == nsMathMLAtoms::mprescripts_) {
mprescriptsFrame = childFrame;
mprescriptsFrame = aChildFrame;
}
else if (childTag.get() != nsMathMLAtoms::none_) {
childFrame->GetRect(childRect);
else {
if (childTag.get() == nsMathMLAtoms::none_) {
// we need to record the presence of none tag explicitly
// for correct negotiation between sup/sub shifts later
if (isSubScript) {
isSubScriptPresent = PR_FALSE;
}
else {
isSupScriptPresent = PR_FALSE;
}
aRect = nsRect (0, 0, 0, 0);
}
else {
aChildFrame->GetRect(aRect);
}
if (0 == count) {
baseFrame = childFrame;
descent = childRect.x;
ascent = childRect.y;
height = childRect.height;
subsupWidth = childRect.width;
subHeight = supHeight = height;
supAscent = ascent;
subDescent = descent;
}
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width;
baseSize.height = aRect.height;
// we update aDesiredSize.{ascent,descent} with that
// of the baseFrame only after processing all the sup/sub pairs
// XXX need italic correction here
aDesiredSize.width = aRect.width + italicCorrection;
}
else {
if (isSubscript) {
subDescent = PR_MAX(subDescent, childRect.x);
subHeight = PR_MAX(subHeight, childRect.height);
width = childRect.width;
}
else {
supAscent = PR_MAX(supAscent, childRect.y);
supHeight = PR_MAX(supHeight, childRect.height);
width = PR_MAX(width, childRect.width);
subsupWidth += width;
// super/subscript block
if (isSubScript) {
if (isSubScriptPresent) {
// subscript
subScriptFrame = aChildFrame;
subScriptSize.descent = aRect.x;
subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width;
subScriptSize.height = aRect.height;
// get the subdrop from the subscript font
GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop);
// parameter v, Rule 18a, App. G, TeXbook
minSubScriptShift = baseSize.descent + aSubDrop;
trySubScriptShift = PR_MAX(minSubScriptShift,aSubScriptShift);
aDesiredSize.descent =
PR_MAX(aDesiredSize.descent,subScriptSize.descent);
width = subScriptSize.width + mScriptSpace;
}
}
else {
if (isSupScriptPresent) {
// supscript
supScriptFrame = aChildFrame;
supScriptSize.descent = aRect.x;
supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width;
supScriptSize.height = aRect.height;
// get the supdrop from the supscript font
GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop);
// parameter u, Rule 18a, App. G, TeXbook
minSupScriptShift = baseSize.ascent - aSupDrop;
// get min supscript shift limit from x-height
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
minShiftFromXHeight = NSToCoordRound
((supScriptSize.descent + (1.0f/4.0f) * xHeight));
trySupScriptShift =
PR_MAX(minSupScriptShift,PR_MAX(minShiftFromXHeight,aSupScriptShift));
aDesiredSize.ascent =
PR_MAX(aDesiredSize.ascent,supScriptSize.ascent);
width = PR_MAX(width, supScriptSize.width + mScriptSpace);
}
NS_ASSERTION((isSubScriptPresent || isSupScriptPresent),"mmultiscripts : both sup/subscripts are absent");
aDesiredSize.width += width;
width = 0;
if (isSubScriptPresent && isSupScriptPresent) {
// negotiate between the various shifts so that
// there is enough gap between the sup and subscripts
// Rule 18e, App. G, TeXbook
nscoord gap =
(trySupScriptShift - supScriptSize.descent) -
(subScriptSize.ascent - trySubScriptShift);
if (gap < 4.0f * aRuleSize) {
// adjust trySubScriptShift to get a gap of (4.0 * aRuleSize)
trySubScriptShift += NSToCoordRound ((4.0f * aRuleSize) - gap);
}
// next we want to ensure that the bottom of the superscript
// will be > (4/5) * x-height above baseline
gap = NSToCoordRound ((4.0f/5.0f) * xHeight -
(trySupScriptShift - supScriptSize.descent));
if (gap > 0.0f) {
trySupScriptShift += gap;
trySubScriptShift -= gap;
}
}
maxSubScriptShift = PR_MAX(maxSubScriptShift, trySubScriptShift);
maxSupScriptShift = PR_MAX(maxSupScriptShift, trySupScriptShift);
trySubScriptShift = aSubScriptShift;
trySupScriptShift = aSupScriptShift;
isSubScriptPresent = PR_TRUE;
isSupScriptPresent = PR_TRUE;
}
}
isSubscript = !isSubscript;
isSubScript = !isSubScript;
count++;
}
}
rv = childFrame->GetNextSibling(&childFrame);
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
// we left out base during our bounding box updates, so ...
aDesiredSize.ascent =
PR_MAX(aDesiredSize.ascent+maxSupScriptShift,baseSize.ascent);
aDesiredSize.descent =
PR_MAX(aDesiredSize.descent+maxSubScriptShift,baseSize.descent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
//////////////////
// Place Children
// Get the subscript and superscript offsets
nscoord subscriptOffset, superscriptOffset, leading;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
aPresContext->GetMetricsFor(aFont->mFont, getter_AddRefs(fm));
fm->GetSubscriptOffset(subscriptOffset);
fm->GetSuperscriptOffset(superscriptOffset);
fm->GetLeading(leading);
// 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/>
subHeight = PR_MAX(height, subHeight) + subscriptOffset + leading;
supHeight = PR_MAX(height, supHeight) + superscriptOffset;
aDesiredSize.descent = subHeight - ascent;
aDesiredSize.ascent = supHeight - descent;
aDesiredSize.height = aDesiredSize.descent + aDesiredSize.ascent;
aDesiredSize.width = subsupWidth;
nscoord offset = 0;
nsIFrame* child[2];
nsRect rect[2];
if (aPlaceOrigin) {
nscoord dx = 0, dy = 0;
count = 0;
nsHTMLReflowMetrics childSize(nsnull);
childFrame = mprescriptsFrame;
do {
if (nsnull == childFrame) { // end of prescripts,
//printf("Placing the base ...\n");
childFrame = baseFrame; // place the base
childFrame->GetRect(rect[0]);
rect[0].x = offset;
rect[0].y = aDesiredSize.height - subHeight;
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);
count = 0;
aChildFrame = mprescriptsFrame;
do {
if (nsnull == aChildFrame) { // end of prescripts,
// place the base ...
aChildFrame = baseFrame;
dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
dx += baseSize.width + italicCorrection;
}
offset += rect[0].width;
}
else if (mprescriptsFrame != childFrame) {
//////////////
// WHITESPACE: whitespace doesn't count. Iteration over non empty frames
if (!IsOnlyWhitespace(childFrame)) {
child[count++] = childFrame;
if (2 == count) { // place a sub-sup pair
//printf("Placing the sub-sup pair...\n");
else if (mprescriptsFrame != aChildFrame) {
// process each sup/sub pair
if (!IsOnlyWhitespace (aChildFrame)) {
if (0 == count) {
subScriptFrame = aChildFrame;
count++;
}
else if (1 == count) {
supScriptFrame = aChildFrame;
count = 0;
// get the bounding boxes of sup/subscripts stored in their rects
// rect.x = descent, rect.y = ascent
subScriptFrame->GetRect (aRect);
subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width;
subScriptSize.height = aRect.height;
child[0]->GetRect(rect[0]);
child[1]->GetRect(rect[1]);
rect[0].y = aDesiredSize.height - (subDescent + rect[0].y);
rect[1].y = supAscent - rect[1].y;
supScriptFrame->GetRect (aRect);
supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width;
supScriptSize.height = aRect.height;
width = PR_MAX(rect[0].width, rect[1].width);
rect[0].x = offset + (width - rect[0].width) / 2; // centering
rect[1].x = offset + (width - rect[1].width) / 2;
// XXX should we really center the boxes
// XXX i'm leaving it as left-justified
// XXX which is consistent with what's done for <msubsup>
dy = aDesiredSize.ascent -
subScriptSize.ascent +
maxSubScriptShift;
FinishReflowChild (subScriptFrame, aPresContext,
subScriptSize, dx, dy, 0);
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;
}
dy = aDesiredSize.ascent -
supScriptSize.ascent -
maxSupScriptShift;
FinishReflowChild (supScriptFrame, aPresContext,
supScriptSize, dx, dy, 0);
width = mScriptSpace +
PR_MAX(subScriptSize.width, supScriptSize.width);
dx += width;
}
}
}
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
} while (mprescriptsFrame != childFrame);
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
} while (mprescriptsFrame != aChildFrame);
}
return rv;
}

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
#ifndef nsMathMLmmultiscriptsFrame_h___
@ -34,6 +35,13 @@ class nsMathMLmmultiscriptsFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmmultiscriptsFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -60,6 +68,11 @@ protected:
virtual ~nsMathMLmmultiscriptsFrame();
virtual PRIntn GetSkipSides() const { return 0; }
private:
float mSubScriptShiftFactor, mSupScriptShiftFactor;
PRBool mSubUserSetFlag, mSupUserSetFlag;
};
#endif /* nsMathMLmmultiscriptsFrame_h___ */

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

@ -184,10 +184,10 @@ nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext,
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();
mEmbellishData.flags = NS_MATHML_EMBELLISH_OPERATOR;
mEmbellishData.firstChild = firstChild;
mEmbellishData.core = this;
mEmbellishData.direction = mMathMLChar.GetStretchDirection();
break;
}
firstChild->GetNextSibling(&firstChild);
@ -219,22 +219,22 @@ nsMathMLmoFrame::InitData()
else {
// Get our outermost embellished container and its parent
nsIFrame* aParent = this;
nsIFrame* aEmbellish = this;
nsIFrame* aEmbellishAncestor = this;
do {
aEmbellish = aParent;
aEmbellishAncestor = aParent;
aParent->GetParent(&aParent);
} while (IsEmbellishOperator(aParent));
// flag if we have an embellished ancestor
if (aEmbellish != this) {
if (aEmbellishAncestor != this) {
hasEmbellishAncestor = PR_TRUE;
}
// Find the position of our outermost embellished container w.r.t
// its sibblings (frames are singly-linked together).
// its siblings (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*] [aEmbellish] [space*] [next]
// [space*] [prev] [space*] [aEmbellishAncestor] [space*] [next]
// We want to skip them...
// The problem looks like a regexp, we ask a little flag to help us.
PRInt32 state = 0;
@ -244,7 +244,7 @@ nsMathMLmoFrame::InitData()
aParent->FirstChild(nsnull, &aFrame);
while (aFrame) {
if (aFrame == aEmbellish) { // we start looking for next
if (aFrame == aEmbellishAncestor) { // we start looking for next
state++;
}
else if (!IsOnlyWhitespace(aFrame)) {
@ -272,8 +272,8 @@ nsMathMLmoFrame::InitData()
PRBool 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...
// All operators are symmetric. But this symmetric flag is *not* stored in
// the operator dictionary and operators are treated as non-symmetric...
// Uncomment the folllowing line to change this behavior.
// mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
@ -359,11 +359,11 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
nsStretchMetrics& aContainerSize,
nsStretchMetrics& aDesiredStretchSize)
{
if (NS_MATHML_STRETCH_WAS_DONE(mEmbellish.flags)) {
if (NS_MATHML_STRETCH_WAS_DONE(mEmbellishData.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;
mEmbellishData.flags |= NS_MATHML_STRETCH_DONE;
// if (0 == mFlags) { // first time...
InitData();
@ -396,6 +396,10 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
if (old == aDesiredStretchSize) { // hasn't changed !
mFlags &= ~NS_MATHML_OPERATOR_MUTABLE;
}
else {
// update our bounding metrics... it becomes that our MathML char
mMathMLChar.GetBoundingMetrics(mBoundingMetrics);
}
}
/////////
@ -405,7 +409,7 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
// 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);
@ -453,3 +457,22 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
return NS_OK;
}
NS_IMETHODIMP
nsMathMLmoFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
return ReflowTokenFor(this, aPresContext, aDesiredSize,
aReflowState, aStatus);
}
NS_IMETHODIMP
nsMathMLmoFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
return PlaceTokenFor(this, aPresContext, aRenderingContext,
aPlaceOrigin, aDesiredSize);
}

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

@ -52,6 +52,18 @@ public:
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD
Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize);
// This method is called by the parent frame to ask <mo>
// to stretch itself.
NS_IMETHOD

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

@ -75,7 +75,7 @@ nsMathMLmoverFrame::Init(nsIPresContext* aPresContext,
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
mEmbellishData.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
return rv;
}
@ -136,10 +136,10 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
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;
nsEmbellishData embellishData;
aMathMLFrame->GetEmbellishData(embellishData);
embellishData.core->GetRect(rect);
width[count] = rect.width + embellishData.leftSpace + embellishData.rightSpace;
}
}
maxWidth = PR_MAX(maxWidth, width[count]); // clean up and use "if" later
@ -190,5 +190,10 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}

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

@ -63,8 +63,8 @@ nsMathMLmrootFrame::nsMathMLmrootFrame() :
mSqrChar(),
mBarChar()
{
mSqrChar.SetEnum(eMathMLChar_Radical);
mBarChar.SetEnum(eMathMLChar_RadicalBar);
mSqrChar.SetEnum(eMathMLChar_Sqrt);
mBarChar.SetEnum(eMathMLChar_OverBar);
}
nsMathMLmrootFrame::~nsMathMLmrootFrame()
@ -113,7 +113,9 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize);
// ask our children to compute their bounding metrics
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.maxElementSize,
aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS);
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
//////////////////
@ -264,5 +266,11 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aStatus = NS_FRAME_COMPLETE;
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}

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

@ -75,7 +75,7 @@ nsMathMLmrowFrame::Init(nsIPresContext* aPresContext,
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
mEmbellishData.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
// XXX Attributes?
return rv;

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

@ -63,8 +63,8 @@ nsMathMLmsqrtFrame::nsMathMLmsqrtFrame() :
mSqrChar(),
mBarChar()
{
mSqrChar.SetEnum(eMathMLChar_Radical);
mBarChar.SetEnum(eMathMLChar_RadicalBar);
mSqrChar.SetEnum(eMathMLChar_Sqrt);
mBarChar.SetEnum(eMathMLChar_OverBar);
}
nsMathMLmsqrtFrame::~nsMathMLmsqrtFrame()
@ -82,7 +82,7 @@ nsMathMLmsqrtFrame::Init(nsIPresContext* aPresContext,
rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent,
aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
mEmbellishData.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
// TODO: other attributes...
return rv;

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
@ -66,68 +67,171 @@ nsMathMLmsubFrame::~nsMathMLmsubFrame()
{
}
NS_IMETHODIMP
nsMathMLmsubFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSubScriptShiftFactor = 0.0;
mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX
// check for subscriptshift attribute in ex units
nsAutoString value;
mUserSetFlag = PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute
(kNameSpaceID_None, nsMathMLAtoms::subscriptshift_, value)) {
PRInt32 aErrorCode;
float aUserValue = value.ToFloat(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {
mUserSetFlag = PR_TRUE;
mSubScriptShiftFactor = aUserValue;
}
}
return rv;
}
NS_IMETHODIMP
nsMathMLmsubFrame::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;
nsresult rv = NS_OK;
////////////////////////////////////
// Get the children's desired sizes
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics subScriptSize (nsnull);
nsIFrame* baseFrame;
nsIFrame* subScriptFrame;
// parameter v, Rule 18a, Appendix G of the TeXbook
nscoord minSubScriptShift = 0;
nsBoundingMetrics baseBounds, subScriptBounds;
nsIFrame* aChildFrame = mFrames.FirstChild();
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace(aChildFrame)) {
aChildFrame->GetRect(aRect);
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width; baseSize.height = aRect.height;
if (NS_SUCCEEDED(GetBoundingMetricsFor(baseFrame, baseBounds))) {
baseBounds.descent = -baseBounds.descent;
} else {
baseBounds.descent = baseSize.descent;
baseBounds.ascent = baseSize.ascent;
baseBounds.width = baseSize.width;
}
}
else if (1 == count) {
// subscript
subScriptFrame = aChildFrame;
subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width; subScriptSize.height = aRect.height;
if (NS_SUCCEEDED(GetBoundingMetricsFor(subScriptFrame, subScriptBounds))) {
subScriptBounds.descent = -subScriptBounds.descent;
} else {
subScriptBounds.descent = subScriptSize.descent;
subScriptBounds.ascent = subScriptSize.ascent;
subScriptBounds.width = subScriptSize.width;
}
// get the subdrop from the subscript font
nscoord aSubDrop;
GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop);
// parameter v, Rule 18a, App. G, TeXbook
minSubScriptShift = baseSize.descent + aSubDrop;
}
else {
NS_ASSERTION((count < 2),"nsMathMLmsubFrame : invalid markup");
}
count++;
}
childFrame->GetNextSibling(&childFrame);
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
aDesiredSize.ascent = rect[0].y;
// Get the subscript offset
nscoord subscriptOffset, leading;
//////////////////
// Place Children
// get min subscript shift limit from x-height
// = h(x) - 4/5 * sigma_5, Rule 18b, App. G, TeXbook
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
aPresContext->GetMetricsFor(aFont->mFont, getter_AddRefs(fm));
fm->GetSubscriptOffset(subscriptOffset);
fm->GetLeading(leading);
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
nscoord minShiftFromXHeight = (nscoord)
(subScriptSize.ascent - (4.0f/5.0f) * xHeight);
// XXX temporary hack pending bug http://bugzilla.mozilla.org/show_bug.cgi?id=9640
//#if 0
nscoord fmAscent, xHeight;
fm->GetMaxAscent(fmAscent);
fm->GetXHeight(xHeight);
subscriptOffset = PR_MAX(subscriptOffset,fmAscent-(xHeight*4)/5);
//#endif
// aSubScriptShift
// = minimum amount to shift the subscript down set by user or from the font
// = sub1 in TeX
// = subscriptshift attribute * x-height
nscoord aSubScriptShift, dummy;
// get aSubScriptShift default from font
GetSubScriptShifts (fm, aSubScriptShift, dummy);
if (mUserSetFlag == PR_TRUE) {
// the user has set the subscriptshift attribute
aSubScriptShift = NSToCoordRound(mSubScriptShiftFactor * xHeight);
}
//for (int i=0; i<100; i++) {
//printf("Ascent:%d xHeight:%d subscriptOffset:%d leading: %d ",
//fmAscent, xHeight, subscriptOffset, leading);
//}
// get actual subscriptshift to be used
// Rule 18b, App. G, TeXbook
nscoord actualSubScriptShift =
PR_MAX(minSubScriptShift,PR_MAX(aSubScriptShift,minShiftFromXHeight));
#if 0
// get bounding box for base + subscript
aDesiredSize.ascent =
PR_MAX(baseSize.ascent,(subScriptSize.ascent-actualSubScriptShift));
aDesiredSize.descent =
PR_MAX(baseSize.descent,(actualSubScriptShift+subScriptSize.descent));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// add mScriptSpace between base and subscript
aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width;
#endif
subscriptOffset += leading;
mBoundingMetrics.ascent =
PR_MAX(baseBounds.ascent, subScriptBounds.ascent - actualSubScriptShift);
mBoundingMetrics.descent =
PR_MAX(baseBounds.descent, subScriptBounds.descent + actualSubScriptShift);
// add mScriptSpace between base and supscript
mBoundingMetrics.width = baseBounds.width + mScriptSpace + subScriptBounds.width;
// logic derived after examining the boxes on three cases: h0==h1, h0>h1, h0<h1
aDesiredSize.height = rect[0].height + rect[1].height - subscriptOffset;
aDesiredSize.width = rect[0].width + rect[1].width;
rect[0].x = 0;
rect[0].y = 0;
rect[1].x = rect[0].width;
rect[1].y = aDesiredSize.height - rect[1].height;
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
aDesiredSize.ascent =
PR_MAX(baseSize.ascent, subScriptSize.ascent - actualSubScriptShift);
aDesiredSize.descent =
PR_MAX(baseSize.descent, subScriptSize.descent + actualSubScriptShift);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
//XXX wrong aDesiredSize.width = mBoundingMetrics.width;
mBoundingMetrics.descent = -mBoundingMetrics.descent;
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);
}
nscoord dx, dy;
// now place the base ...
dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
// ... and subscript
dx = baseSize.width;
dy = aDesiredSize.ascent - subScriptSize.ascent + actualSubScriptShift;
FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0);
}
return NS_OK;
}

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
#ifndef nsMathMLmsubFrame_h___
@ -34,6 +35,13 @@ class nsMathMLmsubFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsubFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -55,11 +63,15 @@ public:
return rv;
}
protected:
protected:
nsMathMLmsubFrame();
virtual ~nsMathMLmsubFrame();
virtual PRIntn GetSkipSides() const { return 0; }
private:
float mSubScriptShiftFactor;
PRBool mUserSetFlag;
};
#endif /* nsMathMLmsubFrame_h___ */

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
@ -66,84 +67,259 @@ nsMathMLmsubsupFrame::~nsMathMLmsubsupFrame()
{
}
NS_IMETHODIMP
nsMathMLmsubsupFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSubScriptShiftFactor = 0.0f;
mSupScriptShiftFactor = 0.0f;
mScriptSpace = 0;
// check for subscriptshift and superscriptshift attribute in ex units
nsAutoString value;
mSubUserSetFlag = mSupUserSetFlag = PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute
(kNameSpaceID_None, nsMathMLAtoms::subscriptshift_, value)) {
PRInt32 aErrorCode;
float aUserValue = value.ToFloat(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {
mSubUserSetFlag = PR_TRUE;
mSubScriptShiftFactor = aUserValue;
}
}
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute
(kNameSpaceID_None, nsMathMLAtoms::superscriptshift_, value)) {
PRInt32 aErrorCode;
float aUserValue = value.ToFloat(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {
mSupUserSetFlag = PR_TRUE;
mSupScriptShiftFactor = aUserValue;
}
}
return rv;
}
NS_IMETHODIMP
nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRBool aPlaceOrigin,
nsHTMLReflowMetrics& aDesiredSize)
{
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 (childFrame) {
if (!IsOnlyWhitespace(childFrame) && 3 > count) {
child[count] = childFrame;
childFrame->GetRect(rect[count]);
nsresult rv = NS_OK;
////////////////////////////////////
// Get the children's desired sizes
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics subScriptSize (nsnull);
nsHTMLReflowMetrics supScriptSize (nsnull);
nsIFrame* baseFrame;
nsIFrame* subScriptFrame;
nsIFrame* supScriptFrame;
// parameter v, Rule 18a, Appendix G of the TeXbook
nscoord minSubScriptShift = 0;
// parameter u in Rule 18a, Appendix G of the TeXbook
nscoord minSupScriptShift = 0;
nsIFrame* aChildFrame = mFrames.FirstChild();
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace(aChildFrame)) {
aChildFrame->GetRect(aRect);
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width; baseSize.height = aRect.height;
}
else if (1 == count) {
// subscript
subScriptFrame = aChildFrame;
subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width; subScriptSize.height = aRect.height;
// get the subdrop from the subscript font
nscoord aSubDrop;
GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop);
// parameter v, Rule 18a, App. G, TeXbook
minSubScriptShift = baseSize.descent + aSubDrop;
}
else if (2 == count) {
// superscript
supScriptFrame = aChildFrame;
supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width; supScriptSize.height = aRect.height;
// get the supdrop from the supscript font
nscoord aSupDrop;
GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop);
// parameter u, Rule 18a, App. G, TeXbook
minSupScriptShift = baseSize.ascent - aSupDrop;
}
else {
NS_ASSERTION((count < 2),"nsMathMLmsubFrame : invalid markup");
}
count++;
}
rv = childFrame->GetNextSibling(&childFrame);
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
descent = rect[0].x;
ascent = rect[0].y;
// Get the subscript and superscript offsets
nscoord subscriptOffset, superscriptOffset, leading;
//////////////////
// Place Children
//////////////////
//////////////////////////////////////////////////
// Get subscript shift
// slightly different from nsMathMLmsubFrame.cpp
//////////////////////////////////////////////////
// aSubScriptShift{1,2}
// = minimum amount to shift the subscript down
// = sub{1,2} in TeXbook
// aSubScriptShift1 = subscriptshift attribute * x-height
nscoord aSubScriptShift1, aSubScriptShift2;
// get x-height (an ex)
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
aPresContext->GetMetricsFor(aFont->mFont, getter_AddRefs(fm));
fm->GetSubscriptOffset(subscriptOffset);
fm->GetSuperscriptOffset(superscriptOffset);
fm->GetLeading(leading);
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
//#if 0
// XXX temporary hack pending bug http://bugzilla.mozilla.org/show_bug.cgi?id=9640
nscoord fmAscent, xHeight;
fm->GetMaxAscent(fmAscent);
fm->GetXHeight(xHeight);
subscriptOffset = PR_MAX(subscriptOffset,fmAscent-(xHeight*4)/5);
//#endif
subscriptOffset += leading;
superscriptOffset += leading;
// logic of superimposing a box with sub and the same box with sup
rect[0].x = 0;
rect[1].x = rect[0].width;
rect[2].x = rect[0].width;
nscoord subHeight = rect[0].height + rect[1].height - subscriptOffset;
nscoord supHeight = rect[0].height + rect[2].height - superscriptOffset;
aDesiredSize.descent = subHeight - ascent;
aDesiredSize.ascent = supHeight - descent;
aDesiredSize.height = aDesiredSize.descent + aDesiredSize.ascent;
aDesiredSize.width = rect[0].width + PR_MAX(rect[1].width, rect[2].width);
rect[2].y = 0;
rect[1].y = aDesiredSize.height - rect[1].height;
rect[0].y = aDesiredSize.height - subHeight;
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);
}
// Get aSubScriptShift{1,2} default from font
GetSubScriptShifts (fm, aSubScriptShift1, aSubScriptShift2);
if (mSubUserSetFlag == PR_TRUE) {
// the user has set the subscriptshift attribute
float aFactor = ((float) aSubScriptShift2) / aSubScriptShift1;
aSubScriptShift1 = NSToCoordRound(mSubScriptShiftFactor * xHeight);
aSubScriptShift2 = NSToCoordRound(aFactor * aSubScriptShift1);
}
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
// get a tentative value for subscriptshift
// Rule 18d, App. G, TeXbook
nscoord aSubScriptShift =
PR_MAX(minSubScriptShift,PR_MAX(aSubScriptShift1,aSubScriptShift2));
//////////////////////////////////////////////////
// Get supscript shift
// same code from nsMathMLmsupFrame.cpp
//////////////////////////////////////////////////
// get min supscript shift limit from x-height
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
nscoord minShiftFromXHeight = (nscoord)
(supScriptSize.descent + (1.0f/4.0f) * xHeight);
// aSupScriptShift{1,2,3}
// = minimum amount to shift the supscript up
// = sup{1,2,3} in TeX
// aSupScriptShift1 = superscriptshift attribute * x-height
// Note that there are THREE values for supscript shifts depending
// on the current style
nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3;
// Set aSupScriptShift{1,2,3} default from font
GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3);
if (mSupUserSetFlag == PR_TRUE) {
// the user has set the superscriptshift attribute
float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1;
float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1;
aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight);
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}
// get sup script shift depending on current script level and display style
// Rule 18c, App. G, TeXbook
nscoord aSupScriptShift;
if ((mScriptLevel == 0) &&
(mDisplayStyle == PR_TRUE) &&
(mCompressed == PR_FALSE)) {
// Style D in TeXbook
aSupScriptShift = aSupScriptShift1;
}
else if (mCompressed == PR_TRUE) {
// Style C' in TeXbook = D',T',S',SS'
aSupScriptShift = aSupScriptShift3;
}
else {
// everything else = T,S,SS
aSupScriptShift = aSupScriptShift2;
}
// get tentative value for superscriptshift
// Rule 18c, App. G, TeXbook
aSupScriptShift =
PR_MAX(minSupScriptShift,PR_MAX(aSupScriptShift,minShiftFromXHeight));
//////////////////////////////////////////////////
// Negotiate between aSupScriptShift and aSubScriptShift
// so that there will be enough gap between them
// Rule 18e, App. G, TeXbook
//////////////////////////////////////////////////
nscoord aRuleSize, dummy;
// XXX need to do update this ...
fm->GetStrikeout (dummy, aRuleSize);
nscoord gap =
(aSupScriptShift - supScriptSize.descent) -
(subScriptSize.ascent - aSubScriptShift);
if (gap < 4.0f * aRuleSize) {
// adjust aSubScriptShift to get a gap of (4.0 * aRuleSize)
aSubScriptShift += NSToCoordRound ((4.0f * aRuleSize) - gap);
}
// next we want to ensure that the bottom of the superscript
// will be > (4/5) * x-height above baseline
gap = NSToCoordRound ((4.0f/5.0f) * xHeight -
(aSupScriptShift - supScriptSize.descent));
if (gap > 0.0f) {
aSupScriptShift += gap;
aSubScriptShift -= gap;
}
//////////////////////////////////////////////////
// Do the Placing
//////////////////////////////////////////////////
// get bounding box for base + subscript + superscript
aDesiredSize.ascent =
PR_MAX(baseSize.ascent,(supScriptSize.ascent+aSupScriptShift));
aDesiredSize.descent =
PR_MAX(baseSize.descent,(supScriptSize.descent+aSubScriptShift));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// add mScriptSpace to both super/subscript
// add italicCorrection only to superscript
// XXX this will be handled properly later ...
nscoord italicCorrection = 0;
aDesiredSize.width = baseSize.width + mScriptSpace +
PR_MAX((supScriptSize.width + italicCorrection),subScriptSize.width);
if (aPlaceOrigin) {
nscoord dx, dy;
// now place the base ...
dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
// ... and subscript
dx = baseSize.width;
dy = aDesiredSize.ascent - subScriptSize.ascent + aSubScriptShift;
FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0);
// ... and the superscript
dx = baseSize.width + italicCorrection;
dy = aDesiredSize.ascent - supScriptSize.ascent - aSupScriptShift;
FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0);
}
return NS_OK;
}

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
#ifndef nsMathMLmsubsupFrame_h___
@ -34,6 +35,13 @@ class nsMathMLmsubsupFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsubsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -60,6 +68,10 @@ protected:
virtual ~nsMathMLmsubsupFrame();
virtual PRIntn GetSkipSides() const { return 0; }
private:
float mSubScriptShiftFactor, mSupScriptShiftFactor;
PRBool mSubUserSetFlag, mSupUserSetFlag;
};
#endif /* nsMathMLmsubsupFrame_h___ */

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

@ -18,9 +18,9 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
#include "nsCOMPtr.h"
#include "nsHTMLParts.h"
#include "nsIHTMLContent.h"
@ -66,58 +66,216 @@ nsMathMLmsupFrame::~nsMathMLmsupFrame()
{
}
NS_IMETHODIMP
nsMathMLmsupFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow)
{
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSupScriptShiftFactor = 0.0f;
mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX
// check for superscriptshift attribute in ex units
nsAutoString value;
mUserSetFlag = PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute
(kNameSpaceID_None, nsMathMLAtoms::superscriptshift_, value)) {
PRInt32 aErrorCode;
float aUserValue = value.ToFloat(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode)) {
mUserSetFlag = PR_TRUE;
mSupScriptShiftFactor = aUserValue;
}
}
return rv;
}
NS_IMETHODIMP
nsMathMLmsupFrame::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;
nsresult rv = NS_OK;
////////////////////////////////////
// Get the children's desired sizes
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics supScriptSize (nsnull);
nsIFrame* baseFrame;
nsIFrame* supScriptFrame;
// parameter u in Rule 18a, Appendix G of the TeXbook
nscoord minSupScriptShift = 0;
nsBoundingMetrics bmBase, bmSupScript;
nsIFrame* aChildFrame = mFrames.FirstChild();
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace(aChildFrame)) {
aChildFrame->GetRect(aRect);
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width; baseSize.height = aRect.height;
if (NS_SUCCEEDED(GetBoundingMetricsFor(baseFrame, bmBase))) {
bmBase.descent = -bmBase.descent;
} else {
bmBase.descent = baseSize.descent;
bmBase.ascent = baseSize.ascent;
bmBase.width = baseSize.width;
}
}
else if (1 == count) {
// superscript
supScriptFrame = aChildFrame;
supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width; supScriptSize.height = aRect.height;
if (NS_SUCCEEDED(GetBoundingMetricsFor(supScriptFrame, bmSupScript))) {
bmSupScript.descent = -bmSupScript.descent;
} else {
bmSupScript.descent = supScriptSize.descent;
bmSupScript.ascent = supScriptSize.ascent;
bmSupScript.width = supScriptSize.width;
}
// get the supdrop from the supscript font
nscoord aSupDrop;
GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop);
// parameter u, Rule 18a, App. G, TeXbook
minSupScriptShift = bmBase.ascent - aSupDrop;
}
else {
NS_ASSERTION((count < 2),"nsMathMLmsupFrame : invalid markup");
}
count++;
}
childFrame->GetNextSibling(&childFrame);
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
aDesiredSize.descent = rect[0].x;
// Get the superscript offset
nscoord superscriptOffset, leading;
//////////////////
// Place Children
// get min supscript shift limit from x-height
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font);
aPresContext->GetMetricsFor(aFont->mFont, getter_AddRefs(fm));
fm->GetSuperscriptOffset(superscriptOffset);
fm->GetLeading(leading);
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
nscoord minShiftFromXHeight = (nscoord)
(supScriptSize.descent + (1.0f/4.0f) * xHeight);
superscriptOffset += leading;
// aSupScriptShift{1,2,3}
// = minimum amount to shift the supscript up
// = sup{1,2,3} in TeX
// aSupScriptShift1 = superscriptshift attribute * x-height
// Note that there are THREE values for supscript shifts depending
// on the current style
nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3;
// Set aSupScriptShift{1,2,3} default from font
GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3);
aDesiredSize.height = rect[0].height + rect[1].height - superscriptOffset;
aDesiredSize.width = rect[0].width + rect[1].width;
rect[0].x = 0;
rect[1].x = rect[0].width;
rect[1].y = 0;
rect[0].y = aDesiredSize.height - rect[0].height;
aDesiredSize.ascent = aDesiredSize.height - aDesiredSize.descent;
if (mUserSetFlag) {
// the user has set the supscriptshift attribute
float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1;
float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1;
aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight);
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}
// get sup script shift depending on current script level and display style
// Rule 18c, App. G, TeXbook
nscoord aSupScriptShift;
if (mScriptLevel == 0 && mDisplayStyle && !mCompressed) {
// Style D in TeXbook
aSupScriptShift = aSupScriptShift1;
}
else if (mCompressed) {
// Style C' in TeXbook = D',T',S',SS'
aSupScriptShift = aSupScriptShift3;
}
else {
// everything else = T,S,SS
aSupScriptShift = aSupScriptShift2;
}
// get actual supscriptshift to be used
// Rule 18c, App. G, TeXbook
nscoord actualSupScriptShift =
PR_MAX(minSupScriptShift,PR_MAX(aSupScriptShift,minShiftFromXHeight));
// get bounding box for base + supscript
#if 0
const nsStyleFont *font;
baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
PRInt32 baseStyle = font->mFont.style;
supScriptFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
PRInt32 supScriptStyle = font->mFont.style;
if (baseStyle == NS_STYLE_FONT_STYLE_ITALIC &&
supScriptStyle != NS_STYLE_FONT_STYLE_ITALIC) {
// take care of italic correction
...
}
#endif
#if 0
aDesiredSize.ascent =
PR_MAX(baseSize.ascent,(supScriptSize.ascent+actualSupScriptShift));
aDesiredSize.descent =
PR_MAX(baseSize.descent,(supScriptSize.descent-actualSupScriptShift));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// add mScriptSpace between base and supscript
aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width;
#endif
mBoundingMetrics.ascent =
PR_MAX(bmBase.ascent, bmSupScript.ascent + actualSupScriptShift);
mBoundingMetrics.descent =
PR_MAX(bmBase.descent, bmSupScript.descent - actualSupScriptShift);
// add mScriptSpace between base and supscript
mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSupScript.width;
printf("bmBase.width:%d + mScriptSpace:%d + bmSupScript.width:%d = mBoundingMetrics.width:%d\n",
bmBase.width, mScriptSpace, bmSupScript.width, mBoundingMetrics.width);
aDesiredSize.ascent =
PR_MAX(baseSize.ascent, supScriptSize.ascent + actualSupScriptShift);
aDesiredSize.descent =
PR_MAX(baseSize.descent, supScriptSize.descent - actualSupScriptShift);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width = mBoundingMetrics.width;
mBoundingMetrics.descent = -mBoundingMetrics.descent;
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;
nscoord dx, dy;
// now place the base ...
dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
// ... and supscript
#if 0
float t2p;
aPresContext->GetTwipsToPixels(&t2p);
PRInt32 scriptspace = NSTwipsToIntPixels(mScriptSpace, t2p);
printf("mScriptSpace in twips:%d pixel:%d\n", mScriptSpace, scriptspace);
#endif
dx = baseSize.width + mScriptSpace;
dy = aDesiredSize.ascent - supScriptSize.ascent - actualSupScriptShift;
FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0);
}
return NS_OK;
}

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

@ -18,6 +18,7 @@
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
* Shyjan Mahamud <mahamud@cs.cmu.edu> (added TeX rendering rules)
*/
#ifndef nsMathMLmsupFrame_h___
@ -34,6 +35,13 @@ class nsMathMLmsupFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmsupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
NS_IMETHOD
Init(nsIPresContext* aPresContext,
nsIContent* aContent,
nsIFrame* aParent,
nsIStyleContext* aContext,
nsIFrame* aPrevInFlow);
NS_IMETHOD
Place(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -60,6 +68,10 @@ protected:
virtual ~nsMathMLmsupFrame();
virtual PRIntn GetSkipSides() const { return 0; }
private:
float mSupScriptShiftFactor;
PRBool mUserSetFlag;
};
#endif /* nsMathMLmsupFrame_h___ */

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

@ -75,7 +75,7 @@ nsMathMLmunderFrame::Init(nsIPresContext* aPresContext,
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
mEmbellishData.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
return rv;
}
@ -168,5 +168,10 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext,
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}

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

@ -75,7 +75,7 @@ nsMathMLmunderoverFrame::Init(nsIPresContext* aPresContext,
{
nsresult rv = nsMathMLContainerFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mEmbellish.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
mEmbellishData.flags = NS_MATHML_STRETCH_ALL_CHILDREN;
return rv;
}
@ -171,5 +171,11 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
}
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}