зеркало из https://github.com/mozilla/gecko-dev.git
[MATHML]. Laying some groundwork to pave the way for the future landing of Shyjan Mahamud's TeX alignment code.
This commit is contained in:
Родитель
8fb2624d02
Коммит
423260e01b
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче