[MATHML] Finally, here goes Shyjan Mahamud's TeX alignment rules. Part I: for superscript/subscript schematta

This commit is contained in:
rbs%maths.uq.edu.au 2000-01-18 04:35:37 +00:00
parent 838f5bcd4f
commit 25576d106c
12 changed files with 620 additions and 258 deletions

View File

@ -333,6 +333,12 @@ struct nsEmbellishData {
// a core <mo>) for which the movablelimits attribute is set to true
#define NS_MATHML_MOVABLELIMITS 0x00000040
// This bit is used for visual debug. When set, the bounding box
// of your frame is painted. You should therefore ensure that you
// have properly filled your mReference and mBoundingMetrics in
// Place().
#define NS_MATHML_SHOW_BOUNDING_METRICS 0x80000000
// Macros that retrieve those bits
#define NS_MATHML_IS_DISPLAYSTYLE(_flags) \
(NS_MATHML_DISPLAYSTYLE == ((_flags) & NS_MATHML_DISPLAYSTYLE))
@ -355,6 +361,9 @@ struct nsEmbellishData {
#define NS_MATHML_IS_MOVABLELIMITS(_flags) \
(NS_MATHML_MOVABLELIMITS == ((_flags) & NS_MATHML_MOVABLELIMITS))
#define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \
(NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS))
// --------------
// Bits used for the embellish flags -- these bits are set
// in their relevant situation as they become available
@ -405,4 +414,3 @@ struct nsEmbellishData {
(NS_MATHML_EMBELLISH_MOVABLELIMITS == ((_flags) & NS_MATHML_EMBELLISH_MOVABLELIMITS))
#endif /* nsIMathMLFrame_h___ */

View File

@ -391,8 +391,8 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
if (aContainerSize.height <= aDesiredStretchSize.height) {
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char later behaves like a normal char
rv = aRenderingContext.GetBoundingMetrics(mData.GetUnicode(),
PRUint32(mData.Length()),
mBoundingMetrics);
PRUint32(mData.Length()),
mBoundingMetrics);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", mData[0], mData[0]&0x00FF); /*getchar();*/ return rv; }
return NS_OK;
}
@ -467,6 +467,19 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
nscoord a, d;
h = w = a = d = 0;
float flex[3] = {0.7f, 0.3f, 0.7f}; // XXX hack!
// get metrics data to be re-used later
nsBoundingMetrics bmdata[4];
for (i = 0; i < 4; i++) {
ch = gMathMLCharGlyph[index+i];
rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm);
if (NS_FAILED(rv)) {
printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/
return rv;
}
bmdata[i] = bm;
}
if (aDirection == NS_STRETCH_DIRECTION_VERTICAL) {
// default is to fill-up the area given to us
width = aDesiredStretchSize.width;
@ -475,9 +488,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
descent = aContainerSize.descent;
for (i = 0; i < 4; i++) {
ch = gMathMLCharGlyph[index+i];
rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; }
bm = bmdata[i];
if (w < bm.width) w = bm.width;
if (i < 3) {
h += nscoord(flex[i]*(bm.ascent+bm.descent)); // sum heights of the parts...
@ -507,9 +518,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
descent = aDesiredStretchSize.descent;
for (i = 0; i < 4; i++) {
ch = gMathMLCharGlyph[index+i];
rv = aRenderingContext.GetBoundingMetrics(&ch, PRUint32(1), bm);
if (NS_FAILED(rv)) { printf("GetBoundingMetrics failed for %04X:%c\n", ch, ch&0x00FF); /*getchar();*/ return rv; }
bm = bmdata[i];
if (0 == i) bm0 = bm;
if (a < bm.ascent) a = bm.ascent;
if (d < bm.descent) d = bm.descent;
@ -527,6 +536,8 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext,
// ascent = a;
// height = a + d;
mBoundingMetrics.width = aContainerSize.width;
mBoundingMetrics.leftBearing = 0;
mBoundingMetrics.rightBearing = aContainerSize.width;
} else { // sum of parts doesn't fit in the space... will use a single glyph
mEnum = eMathMLChar_DONT_STRETCH; // ensure that the char behaves like a normal char
mBoundingMetrics = bm0;

View File

@ -115,7 +115,7 @@ public:
}
void
GetBoundingMetrics(nsBoundingMetrics aBoundingMetrics) {
GetBoundingMetrics(nsBoundingMetrics& aBoundingMetrics) {
aBoundingMetrics = mBoundingMetrics;
}

View File

@ -176,40 +176,46 @@ nsMathMLContainerFrame::SetReference(const nsPoint& aReference)
return NS_OK;
}
// helper methods to facilitate getting/setting the bounding metrics
nsresult
nsMathMLContainerFrame::GetBoundingMetricsFor(nsIFrame* aFrame,
nsBoundingMetrics& aBoundingMetrics)
// helper method to facilitate getting the reflow and bounding metrics
void
nsMathMLContainerFrame::GetReflowAndBoundingMetricsFor(nsIFrame* aFrame,
nsHTMLReflowMetrics& aReflowMetrics,
nsBoundingMetrics& aBoundingMetrics)
{
NS_PRECONDITION(aFrame, "null arg");
// IMPORTANT: This function is only meant to be called in Place() methods
// where it is assumed that the frame's rect is still acting as place holder
// for the frame's ascent and descent information
nsRect aRect;
aFrame->GetRect(aRect);
aReflowMetrics.descent = aRect.x;
aReflowMetrics.ascent = aRect.y;
aReflowMetrics.width = aRect.width;
aReflowMetrics.height = aRect.height;
aBoundingMetrics.Clear();
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
aMathMLFrame->GetBoundingMetrics(aBoundingMetrics);
return NS_OK;
#if 0
nsFrame::ListTag(stdout, aFrame);
printf(" subItalicCorrection:%d supItalicCorrection:%d\n",
aBoundingMetrics.subItalicCorrection, aBoundingMetrics.supItalicCorrection);
#endif
}
// if we reach here, aFrame is not a MathML frame, let the caller know that
printf("GetBoundingMetrics() failed for: "); /* getchar(); */
nsFrame::ListTag(stdout, aFrame);
printf("\n");
// NS_ASSERTION(0, "GetBoundingMetrics() failed!!");
return NS_ERROR_FAILURE;
}
nsresult
nsMathMLContainerFrame::SetBoundingMetricsFor(nsIFrame* aFrame,
nsBoundingMetrics& aBoundingMetrics)
{
nsIMathMLFrame* aMathMLFrame = nsnull;
nsresult rv = aFrame->QueryInterface(nsIMathMLFrame::GetIID(), (void**)&aMathMLFrame);
if (NS_SUCCEEDED(rv) && aMathMLFrame) {
aMathMLFrame->SetBoundingMetrics(aBoundingMetrics);
return NS_OK;
else { // aFrame is not a MathML frame, just return the reflow metrics
aBoundingMetrics.descent = aReflowMetrics.descent;
aBoundingMetrics.ascent = aReflowMetrics.ascent;
aBoundingMetrics.width = aReflowMetrics.width;
#if 0
printf("GetBoundingMetrics() failed for: "); /* getchar(); */
nsFrame::ListTag(stdout, aFrame);
printf("\n");
#endif
}
// if we reach here, aFrame is not a MathML frame, let the caller know that
printf("SetBoundingMetrics() failed!! ...\n"); /* getchar(); */
// NS_ASSERTION(0, "SetBoundingMetrics() failed!!");
return NS_ERROR_FAILURE;
}
/* /////////////
@ -514,6 +520,29 @@ nsMathMLContainerFrame::UpdatePresentationDataFromChildAt(PRInt32 aIndex,
return NS_OK;
}
PRInt32
nsMathMLContainerFrame::FindSmallestFontSizeFor(nsIFrame* aFrame)
{
nsStyleFont aFont;
nsCOMPtr<nsIStyleContext> aStyleContext;
aFrame->GetStyleContext(getter_AddRefs(aStyleContext));
aStyleContext->GetStyle(eStyleStruct_Font, aFont);
// PRInt32 fontSize = NSTwipsToFloorIntPoints(aFont.mFont.size);
PRInt32 fontSize = aFont.mFont.size;
PRInt32 childSize;
nsIFrame* childFrame;
aFrame->FirstChild(nsnull, &childFrame);
while (nsnull != childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
childSize = FindSmallestFontSizeFor(childFrame);
if (fontSize > childSize) fontSize = childSize;
}
childFrame->GetNextSibling(&childFrame);
}
return fontSize;
}
// helper method to alter the style context
// This method is used for switching the font to a subscript/superscript font in
// mfrac, msub, msup, msubsup, munder, mover, munderover, mmultiscripts
@ -544,6 +573,71 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
PRInt32 gap = childData.scriptLevel - mPresentationData.scriptLevel;
if (0 != gap) {
// We are about to change the font-size... We first see if we
// are in the scope of a <mstyle> that tells us what to do.
// This is one of the most obscure part to implement in the spec...
/*
The REC says:
Whenever the scriptlevel is changed, either automatically or by being
explicitly incremented, decremented, or set, the current font size is
multiplied by the value of scriptsizemultiplier to the power of the
change in scriptlevel. For example, if scriptlevel is increased by 2,
the font size is multiplied by scriptsizemultiplier twice in succession;
if scriptlevel is explicitly set to 2 when it had been 3, the font size
is divided by scriptsizemultiplier.
The default value of scriptsizemultiplier is less than one (in fact, it
is approximately the square root of 1/2), resulting in a smaller font size
with increasing scriptlevel. To prevent scripts from becoming unreadably
small, the font size is never allowed to go below the value of
scriptminsize as a result of a change to scriptlevel, though it can be
set to a lower value using the fontsize attribute on <mstyle> or on
token elements. If a change to scriptlevel would cause the font size to
become lower than scriptminsize using the above formula, the font size
is instead set equal to scriptminsize within the subexpression for which
scriptlevel was changed.
In the syntax for scriptminsize, v-unit represents a unit of vertical
length. The most common unit for specifying font sizes in typesetting
is pt (points).
*/
// default scriptsizemultiplier = 0.71
// default scriptminsize = 8pt
// here we only consider scriptminsize, and use the default
// smaller-font-size algorithm of the style system
PRInt32 scriptminsize = NSIntPointsToTwips(8);
// see if the scriptminsize attribute is on <mstyle> that wraps us
nsAutoString value;
nsIFrame* mstyleFrame = mPresentationData.mstyle;
if (mstyleFrame) {
nsCOMPtr<nsIContent> mstyleContent;
mstyleFrame->GetContent(getter_AddRefs(mstyleContent));
if (NS_CONTENT_ATTR_HAS_VALUE == mstyleContent->GetAttribute(kNameSpaceID_None,
nsMathMLAtoms::scriptminsize_, value))
{
PRInt32 errorCode;
PRInt32 userValue = value.ToInteger(&errorCode);
if (NS_SUCCEEDED(errorCode)) {
// assume unit is point
// XXX need consistent, default unit throughout the code
scriptminsize = NSIntPointsToTwips(userValue);
}
else {
// XXX TODO: try to see if it is a h/v-unit like 1ex, 2px, 1em
}
}
}
// get Nav's magic font scaler
PRInt32 scaler;
aPresContext->GetFontScaler(&scaler);
float scaleFactor = nsStyleUtil::GetScalingFactor(scaler);
const nsFont& defaultFont = aPresContext->GetDefaultFontDeprecated();
nsCOMPtr<nsIContent> childContent;
childFrame->GetContent(getter_AddRefs(childContent));
@ -555,13 +649,37 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
nsIStyleContext* lastStyleContext = mStyleContext;
nsCOMPtr<nsIStyleContext> newStyleContext;
// XXX seems not to decrease when the initail font-size is large (100pt)
nsAutoString fontSize = (0 < gap)
? ":-moz-math-font-size-smaller"
: ":-moz-math-font-size-larger";
nsCOMPtr<nsIAtom> fontAtom(getter_AddRefs(NS_NewAtom(fontSize)));
if (0 > gap) gap = -gap; // absolute value
PRBool isSmaller = PR_TRUE;
if (0 > gap) { isSmaller = PR_FALSE; gap = -gap; } // absolute value
PRInt32 smallestFontSize, smallestFontIndex;
if (isSmaller) {
// find the smallest font-size in this subtree
smallestFontSize = FindSmallestFontSizeFor(childFrame);
}
while (0 < gap--) {
if (isSmaller) {
// look ahead for the next smallest font size that will be in the subtree
smallestFontIndex = nsStyleUtil::FindNextSmallerFontSize(smallestFontSize, (PRInt32)defaultFont.size, scaleFactor);
smallestFontSize = nsStyleUtil::CalcFontPointSize(smallestFontIndex, (PRInt32)defaultFont.size, scaleFactor);
//printf("About to move to fontsize:%dpt(%dtwips)\n",
//NSTwipsToFloorIntPoints(smallestFontSize), smallestFontSize);
if (smallestFontSize < scriptminsize) {
// don't bother doing any work
//printf("..... stopping ......\n");
// XXX there should be a mechanism so that we never try this subtree again
break;
}
}
aPresContext->ResolvePseudoStyleContextFor(childContent, fontAtom, lastStyleContext,
PR_FALSE, getter_AddRefs(newStyleContext));
if (newStyleContext && newStyleContext.get() != lastStyleContext) {
@ -620,7 +738,43 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
* Frame construction
* =============================================================================
*/
NS_IMETHODIMP
nsMathMLContainerFrame::Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
nsresult rv = NS_OK;
rv = nsHTMLContainerFrame::Paint(aPresContext,
aRenderingContext,
aDirtyRect,
aWhichLayer);
#ifdef SHOW_BOUNDING_BOX
// for visual debug
// ----------------
// if you want to see your bounding box, make sure to properly fill
// your mBoundingMetrics and mReference point, and set
// mPresentationData.flags |= NS_MATHML_BOUNDING_METRICS
// in the Init() of your sub-class
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer &&
NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags))
{
aRenderingContext.SetColor(NS_RGB(0,0,255));
nscoord x = mReference.x + mBoundingMetrics.leftBearing;
nscoord y = mReference.y;
nscoord w = mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing;
nscoord h = mBoundingMetrics.ascent + mBoundingMetrics.descent;
aRenderingContext.DrawRect(x,y,w,h);
}
#endif
return rv;
}
NS_IMETHODIMP
nsMathMLContainerFrame::Init(nsIPresContext* aPresContext,
nsIContent* aContent,
@ -847,7 +1001,7 @@ nsMathMLContainerFrame::ReflowTokenFor(nsIFrame* aFrame,
// helper function to place token elements
// mBoundingMetrics is computed at the ReflowToken pass, it is
// not computed here because if our children may be text frames that
// not computed here because our children may be text frames that
// do not implement the GetBoundingMetrics() interface.
nsresult
nsMathMLContainerFrame::PlaceTokenFor(nsIFrame* aFrame,
@ -893,6 +1047,11 @@ nsMathMLContainerFrame::PlaceTokenFor(nsIFrame* aFrame,
childFrame->GetNextSibling(&childFrame);
}
}
nsBoundingMetrics bm;
NS_STATIC_CAST(nsMathMLContainerFrame*,
aFrame)->GetBoundingMetrics(bm);
NS_STATIC_CAST(nsMathMLContainerFrame*,
aFrame)->SetReference(nsPoint(0,aDesiredSize.ascent-bm.ascent));
return NS_OK;
}
@ -1087,23 +1246,18 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
aDesiredSize.width = aDesiredSize.height = aDesiredSize.ascent = aDesiredSize.descent = 0;
PRInt32 count = 0;
nsRect rect;
nsBoundingMetrics bm;
nsHTMLReflowMetrics childSize(nsnull);
nsIFrame* childFrame = mFrames.FirstChild();
while (childFrame) {
if (!IsOnlyWhitespace(childFrame)) {
childFrame->GetRect(rect);
GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
aDesiredSize.width += rect.width;
if (aDesiredSize.descent < rect.x) aDesiredSize.descent = rect.x;
if (aDesiredSize.ascent < rect.y) aDesiredSize.ascent = rect.y;
aDesiredSize.width += childSize.width;
if (aDesiredSize.descent < childSize.descent) aDesiredSize.descent = childSize.descent;
if (aDesiredSize.ascent < childSize.ascent) aDesiredSize.ascent = childSize.ascent;
// Compute and cache our bounding metrics
nsBoundingMetrics bm;
if (NS_FAILED(GetBoundingMetricsFor(childFrame, bm))) {
bm.ascent = rect.y;
bm.descent = -rect.x;
bm.width = rect.width;
}
if (0 == count)
mBoundingMetrics = bm;
else
@ -1116,13 +1270,14 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
if (aPlaceOrigin) {
nsRect rect;
nscoord dy;
nscoord dx = 0;
childFrame = mFrames.FirstChild();
while (childFrame) {
childFrame->GetRect(rect);
nsHTMLReflowMetrics childSize(nsnull);
childSize.width = rect.width;
childSize.height = rect.height;
@ -1134,6 +1289,9 @@ nsMathMLContainerFrame::Place(nsIPresContext* aPresContext,
childFrame->GetNextSibling(&childFrame);
}
}
mReference.x = 0;
mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent;
return NS_OK;
}

View File

@ -154,6 +154,12 @@ public:
return nsHTMLContainerFrame::DidReflow(aPresContext, aStatus);
}
NS_IMETHOD
Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
// helper function to reflow token elements
static nsresult
ReflowTokenFor(nsIFrame* aFrame,
@ -223,6 +229,12 @@ public:
NS_IMETHOD
InsertScriptLevelStyleContext(nsIPresContext* aPresContext);
// helper to find the smallest font-size on a tree so that we don't insert
// scriptlevel fonts that lead to unreadable results on deeper nodes below us.
// XXX expensive recursive function, need something better, with cache
static PRInt32
FindSmallestFontSizeFor(nsIFrame* aFrame);
// helper to check if a frame is an embellished container
static PRBool
IsEmbellishOperator(nsIFrame* aFrame);
@ -230,19 +242,19 @@ public:
// helper methods for processing empty MathML frames (with whitespace only)
static PRBool
IsOnlyWhitespace(nsIFrame* aFrame);
static void
ReflowEmptyChild(nsIPresContext* aPresContext,
nsIFrame* aFrame);
// helper methods to facilitate getting/setting the bounding metrics
static nsresult
GetBoundingMetricsFor(nsIFrame* aFrame,
nsBoundingMetrics& aBoundingMetrics);
static nsresult
SetBoundingMetricsFor(nsIFrame* aFrame,
nsBoundingMetrics& aBoundingMetrics);
// helper method to facilitate getting the reflow and bounding metrics
// IMPORTANT: This function is only meant to be called in Place() methods
// where it is assumed that the frame's rect is still acting as place holder
// for the frame's ascent and descent information
static void
GetReflowAndBoundingMetricsFor(nsIFrame* aFrame,
nsHTMLReflowMetrics& aReflowMetrics,
nsBoundingMetrics& aBoundingMetrics);
// helper methods for getting sup/subdrop's from a child
static void
@ -297,6 +309,7 @@ public:
}
// these are TeX specific params not found in ordinary fonts
#if 0
static void
GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop)
{
@ -312,6 +325,124 @@ public:
fm->GetXHeight (xHeight);
aSupDrop = NSToCoordRound(0.3f * xHeight);
}
#endif
static void
GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop)
{
nscoord xHeight;
fm->GetXHeight (xHeight);
aSubDrop = NSToCoordRound(50.000f/430.556f * xHeight);
}
static void
GetSupDrop (nsIFontMetrics *fm, nscoord& aSupDrop)
{
nscoord xHeight;
fm->GetXHeight (xHeight);
aSupDrop = NSToCoordRound(386.108f/430.556f * xHeight);
}
static void
GetSubShifts (nsIFontMetrics *fm,
nscoord& aSubShift1,
nscoord& aSubShift2)
{
nscoord xHeight = 0;
fm->GetXHeight (xHeight);
aSubShift1 = NSToCoordRound (150.000f/430.556f * xHeight);
aSubShift2 = NSToCoordRound (247.217f/430.556f * xHeight);
}
static void
GetSupShifts (nsIFontMetrics *fm,
nscoord& aSupShift1,
nscoord& aSupShift2,
nscoord& aSupShift3)
{
nscoord xHeight = 0;
fm->GetXHeight (xHeight);
aSupShift1 = NSToCoordRound (412.892f/430.556f * xHeight);
aSupShift2 = NSToCoordRound (362.892f/430.556f * xHeight);
aSupShift3 = NSToCoordRound (288.889f/430.556f * xHeight);
}
static void
GetNumShifts (nsIFontMetrics *fm,
nscoord& numShift1,
nscoord& numShift2,
nscoord& numShift3)
{
nscoord xHeight = 0;
fm->GetXHeight (xHeight);
numShift1 = NSToCoordRound (676.508f/430.556f * xHeight);
numShift2 = NSToCoordRound (393.732f/430.556f * xHeight);
numShift3 = NSToCoordRound (443.731f/430.556f * xHeight);
}
static void
GetDenShifts (nsIFontMetrics *fm,
nscoord& denShift1,
nscoord& denShift2)
{
nscoord xHeight = 0;
fm->GetXHeight (xHeight);
denShift1 = NSToCoordRound (685.951f/430.556f * xHeight);
denShift2 = NSToCoordRound (344.841f/430.556f * xHeight);
}
static void
GetAxisHeight (nsIFontMetrics *fm,
nscoord& axisHeight)
{
fm->GetXHeight (axisHeight);
axisHeight = NSToCoordRound (250.000f/430.556f * axisHeight);
}
static void
GetBigOpSpacings (nsIFontMetrics *fm,
nscoord& bigOpSpacing1,
nscoord& bigOpSpacing2,
nscoord& bigOpSpacing3,
nscoord& bigOpSpacing4,
nscoord& bigOpSpacing5)
{
nscoord xHeight = 0;
fm->GetXHeight (xHeight);
bigOpSpacing1 = NSToCoordRound (111.111f/430.556f * xHeight);
bigOpSpacing2 = NSToCoordRound (166.667f/430.556f * xHeight);
bigOpSpacing3 = NSToCoordRound (200.000f/430.556f * xHeight);
bigOpSpacing4 = NSToCoordRound (600.000f/430.556f * xHeight);
bigOpSpacing5 = NSToCoordRound (100.000f/430.556f * xHeight);
}
#if 0
NS_IMETHOD
GetItalicCorrection (nscoord& italicCorrection)
{
italicCorrection = mItalicCorrection;
return NS_OK;
}
NS_IMETHOD
SetItalicCorrection (nscoord italicCorrection)
{
mItalicCorrection = italicCorrection;
return NS_OK;
}
#endif
NS_IMETHOD
GetRuleThickness (nsIFontMetrics *fm, nscoord& ruleThickness)
{
nscoord xHeight;
fm->GetXHeight (xHeight);
ruleThickness = NSToCoordRound (40.000f/430.556f * xHeight);
return NS_OK;
}
protected:

View File

@ -257,9 +257,9 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}

View File

@ -104,6 +104,7 @@ nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext,
}
}
mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
return rv;
}
@ -118,7 +119,6 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
////////////////////////////////////
// Get the children's desired sizes
nscoord italicCorrection = 0;
nscoord minShiftFromXHeight, aSubDrop, aSupDrop;
////////////////////////////////////////
@ -134,9 +134,9 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
nscoord aRuleSize, dummy;
nscoord aRuleSize = 0;
// XXX need to do update this ...
fm->GetStrikeout (dummy, aRuleSize);
GetRuleThickness (fm, aRuleSize);
/////////////////////////////////////
// first the shift for the subscript
@ -201,7 +201,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
// Get the children's sizes
////////////////////////////////////
nscoord width = 0;
nscoord width = 0, prescriptsWidth = 0, rightBearing = 0;
nsIFrame* mprescriptsFrame = nsnull; // frame of <mprescripts/>, if there.
PRBool isSubScript = PR_FALSE;
PRBool isSubScriptPresent = PR_TRUE;
@ -212,7 +212,6 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
nscoord maxSubScriptShift = aSubScriptShift;
nscoord maxSupScriptShift = aSupScriptShift;
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics subScriptSize (nsnull);
nsHTMLReflowMetrics supScriptSize (nsnull);
@ -220,8 +219,14 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
nsIFrame* subScriptFrame;
nsIFrame* supScriptFrame;
PRBool firstPrescriptsPair = PR_FALSE;
nsBoundingMetrics bmBase, bmSubScript, bmSupScript;
// XXX is there an NSPR macro for int_max ???
aDesiredSize.ascent = aDesiredSize.descent = -100000;
mBoundingMetrics.ascent = mBoundingMetrics.descent = -10000000;
mBoundingMetrics.width = 0;
aDesiredSize.ascent = aDesiredSize.descent = -10000000;
aDesiredSize.width = aDesiredSize.height = 0;
nsIFrame* aChildFrame = mFrames.FirstChild();
@ -235,32 +240,36 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
if (childTag.get() == nsMathMLAtoms::mprescripts_) {
mprescriptsFrame = aChildFrame;
firstPrescriptsPair = PR_TRUE;
}
else {
if (childTag.get() == nsMathMLAtoms::none_) {
// we need to record the presence of none tag explicitly
// for correct negotiation between sup/sub shifts later
if (isSubScript) {
isSubScriptPresent = PR_FALSE;
bmSubScript.Clear();
bmSubScript.leftBearing = 10000000;
}
else {
isSupScriptPresent = PR_FALSE;
bmSupScript.Clear();
bmSupScript.leftBearing = 10000000;
}
aRect = nsRect (0, 0, 0, 0);
}
else {
aChildFrame->GetRect(aRect);
}
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width;
baseSize.height = aRect.height;
// we update aDesiredSize.{ascent,descent} with that
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
// we update mBoundingMetrics.{ascent,descent} with that
// of the baseFrame only after processing all the sup/sub pairs
// XXX need italic correction here
aDesiredSize.width = aRect.width + italicCorrection;
// XXX need italic correction only *if* there are postscripts ?
mBoundingMetrics.width = bmBase.width + bmBase.supItalicCorrection;
mBoundingMetrics.rightBearing = bmBase.rightBearing;
mBoundingMetrics.leftBearing = bmBase.leftBearing; // until overwritten
}
else {
// super/subscript block
@ -268,54 +277,66 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
if (isSubScriptPresent) {
// subscript
subScriptFrame = aChildFrame;
subScriptSize.descent = aRect.x;
subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width;
subScriptSize.height = aRect.height;
GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
// get the subdrop from the subscript font
GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop);
// parameter v, Rule 18a, App. G, TeXbook
minSubScriptShift = baseSize.descent + aSubDrop;
minSubScriptShift = bmBase.descent + aSubDrop;
trySubScriptShift = PR_MAX(minSubScriptShift,aSubScriptShift);
mBoundingMetrics.descent =
PR_MAX(mBoundingMetrics.descent,bmSubScript.descent);
aDesiredSize.descent =
PR_MAX(aDesiredSize.descent,subScriptSize.descent);
width = subScriptSize.width + mScriptSpace;
PR_MAX(aDesiredSize.descent,subScriptSize.ascent);
width = bmSubScript.width + mScriptSpace;
rightBearing = bmSubScript.rightBearing + mScriptSpace;
}
}
else {
if (isSupScriptPresent) {
// supscript
supScriptFrame = aChildFrame;
supScriptSize.descent = aRect.x;
supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width;
supScriptSize.height = aRect.height;
GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
// get the supdrop from the supscript font
GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop);
// parameter u, Rule 18a, App. G, TeXbook
minSupScriptShift = baseSize.ascent - aSupDrop;
minSupScriptShift = bmBase.ascent - aSupDrop;
// get min supscript shift limit from x-height
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
minShiftFromXHeight = NSToCoordRound
((supScriptSize.descent + (1.0f/4.0f) * xHeight));
((bmSupScript.descent + (1.0f/4.0f) * xHeight));
trySupScriptShift =
PR_MAX(minSupScriptShift,PR_MAX(minShiftFromXHeight,aSupScriptShift));
mBoundingMetrics.ascent =
PR_MAX(mBoundingMetrics.ascent,bmSupScript.ascent);
aDesiredSize.ascent =
PR_MAX(aDesiredSize.ascent,supScriptSize.ascent);
width = PR_MAX(width, supScriptSize.width + mScriptSpace);
width = PR_MAX(width, bmSupScript.width + mScriptSpace);
rightBearing = PR_MAX(rightBearing, bmSupScript.rightBearing + mScriptSpace);
}
NS_ASSERTION((isSubScriptPresent || isSupScriptPresent),"mmultiscripts : both sup/subscripts are absent");
aDesiredSize.width += width;
width = 0;
if (!mprescriptsFrame) { // we are still looping over base & postscripts
mBoundingMetrics.rightBearing = mBoundingMetrics.width + rightBearing;
mBoundingMetrics.width += width;
}
else {
prescriptsWidth += width;
if (firstPrescriptsPair) {
firstPrescriptsPair = PR_FALSE;
mBoundingMetrics.leftBearing =
PR_MIN(bmSubScript.leftBearing, bmSupScript.leftBearing);
}
}
width = rightBearing = 0;
if (isSubScriptPresent && isSupScriptPresent) {
// negotiate between the various shifts so that
// there is enough gap between the sup and subscripts
// Rule 18e, App. G, TeXbook
nscoord gap =
(trySupScriptShift - supScriptSize.descent) -
(subScriptSize.ascent - trySubScriptShift);
(trySupScriptShift - bmSupScript.descent) -
(bmSubScript.ascent - trySubScriptShift);
if (gap < 4.0f * aRuleSize) {
// adjust trySubScriptShift to get a gap of (4.0 * aRuleSize)
trySubScriptShift += NSToCoordRound ((4.0f * aRuleSize) - gap);
@ -324,7 +345,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
// next we want to ensure that the bottom of the superscript
// will be > (4/5) * x-height above baseline
gap = NSToCoordRound ((4.0f/5.0f) * xHeight -
(trySupScriptShift - supScriptSize.descent));
(trySupScriptShift - bmSupScript.descent));
if (gap > 0.0f) {
trySupScriptShift += gap;
trySubScriptShift -= gap;
@ -348,13 +369,28 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
}
// we left out base during our bounding box updates, so ...
// we left out the width of prescripts, so ...
mBoundingMetrics.rightBearing += prescriptsWidth;
mBoundingMetrics.width += prescriptsWidth;
// we left out the base during our bounding box updates, so ...
mBoundingMetrics.ascent =
PR_MAX(mBoundingMetrics.ascent+maxSupScriptShift,bmBase.ascent);
mBoundingMetrics.descent =
PR_MAX(mBoundingMetrics.descent+maxSubScriptShift,bmBase.descent);
// get the reflow metrics ...
aDesiredSize.ascent =
PR_MAX(aDesiredSize.ascent+maxSupScriptShift,baseSize.ascent);
aDesiredSize.descent =
PR_MAX(aDesiredSize.descent+maxSubScriptShift,baseSize.descent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width = mBoundingMetrics.width;
mReference.x = 0;
mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent;
//////////////////
// Place Children
@ -364,6 +400,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
if (aPlaceOrigin) {
nscoord dx = 0, dy = 0;
nsRect aRect;
count = 0;
aChildFrame = mprescriptsFrame;
@ -371,9 +408,10 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
if (nsnull == aChildFrame) { // end of prescripts,
// place the base ...
aChildFrame = baseFrame;
dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
dx += baseSize.width + italicCorrection;
// dy = mBoundingMetrics.ascent - bmBase.ascent;
dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
dx += baseSize.width + bmBase.supItalicCorrection;
}
else if (mprescriptsFrame != aChildFrame) {
// process each sup/sub pair
@ -386,7 +424,7 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
supScriptFrame = aChildFrame;
count = 0;
// get the bounding boxes of sup/subscripts stored in their rects
// get the ascent/descent of sup/subscripts stored in their rects
// rect.x = descent, rect.y = ascent
subScriptFrame->GetRect (aRect);
subScriptSize.ascent = aRect.y;
@ -401,25 +439,30 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
// XXX should we really center the boxes
// XXX i'm leaving it as left-justified
// XXX which is consistent with what's done for <msubsup>
// reverting to center. It looks much nicer and adds a bit
// of variety to the engine. At least we have two functions
// doing two different things.
width = PR_MAX(subScriptSize.width, supScriptSize.width);
dy = aDesiredSize.ascent -
subScriptSize.ascent +
maxSubScriptShift;
FinishReflowChild (subScriptFrame, aPresContext,
subScriptSize, dx, dy, 0);
FinishReflowChild (subScriptFrame, aPresContext, subScriptSize,
dx + (width-subScriptSize.width)/2, dy, 0);
dy = aDesiredSize.ascent -
supScriptSize.ascent -
maxSupScriptShift;
FinishReflowChild (supScriptFrame, aPresContext,
supScriptSize, dx, dy, 0);
FinishReflowChild (supScriptFrame, aPresContext, supScriptSize,
dx + (width-supScriptSize.width)/2, dy, 0);
width = mScriptSpace +
PR_MAX(subScriptSize.width, supScriptSize.width);
dx += width;
}
dx += mScriptSpace + width;
}
}
}
rv = aChildFrame->GetNextSibling(&aChildFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
} while (mprescriptsFrame != aChildFrame);

View File

@ -119,6 +119,19 @@ nsMathMLmoFrame::Paint(nsIPresContext* aPresContext,
rv = mMathMLChar.Paint(aPresContext,
aRenderingContext,
mStyleContext);
#ifdef SHOW_BOUNDING_BOX
// for visual debug
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer &&
NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags))
{
aRenderingContext.SetColor(NS_RGB(0,0,255));
nscoord x = mReference.x + mBoundingMetrics.leftBearing;
nscoord y = mReference.y;
nscoord w = mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing;
nscoord h = mBoundingMetrics.ascent + mBoundingMetrics.descent;
aRenderingContext.DrawRect(x,y,w,h);
}
#endif
}
else { // let the base class worry about the painting
rv = nsMathMLContainerFrame::Paint(aPresContext,
@ -144,6 +157,7 @@ nsMathMLmoFrame::Init(nsIPresContext* aPresContext,
mLeftSpace = 0.0f; // .27777f;
mRightSpace = 0.0f; // .27777f;
mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
return rv;
}
@ -487,10 +501,6 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
if (old == aDesiredStretchSize) { // hasn't changed !
mFlags &= ~NS_MATHML_OPERATOR_MUTABLE;
}
else {
// update our bounding metrics... it becomes that of our MathML char
mMathMLChar.GetBoundingMetrics(mBoundingMetrics);
}
}
/////////
@ -499,7 +509,9 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) {
// The rendering will be handled by our MathML char
mMathMLChar.SetRect(nsRect(0, 0, aDesiredStretchSize.width,
aDesiredStretchSize.height));
aDesiredStretchSize.height));
// update our bounding metrics... it becomes that of our MathML char
mMathMLChar.GetBoundingMetrics(mBoundingMetrics);
}
else {
nsHTMLReflowMetrics aReflowMetrics(nsnull);
@ -514,6 +526,9 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
aDesiredStretchSize.leftSpace = mLeftSpace;
aDesiredStretchSize.rightSpace = mRightSpace;
mReference.x = 0;
mReference.y = aDesiredStretchSize.ascent - mBoundingMetrics.ascent;
// Before we leave... there is a last item in the check-list:
// If our parent is not embellished, it means we are the outermost embellished
// container and so we put the spacing, otherwise we don't include the spacing,
@ -532,6 +547,8 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
if (0 == dx) return NS_OK;
// adjust the offsets
mReference.x = dx;
nsRect rect;
if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) {
mMathMLChar.GetRect(rect);

View File

@ -268,9 +268,9 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
// XXX Fix me!
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = -aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
mBoundingMetrics.ascent = aDesiredSize.ascent;
mBoundingMetrics.descent = aDesiredSize.descent;
mBoundingMetrics.width = aDesiredSize.width;
return NS_OK;
}

View File

@ -93,6 +93,7 @@ nsMathMLmsubFrame::Init(nsIPresContext* aPresContext,
}
}
mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
return rv;
}
@ -108,7 +109,6 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext,
// Get the children's desired sizes
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics subScriptSize (nsnull);
nsIFrame* baseFrame;
@ -116,39 +116,26 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext,
// parameter v, Rule 18a, Appendix G of the TeXbook
nscoord minSubScriptShift = 0;
nsBoundingMetrics baseBounds, subScriptBounds;
nsBoundingMetrics bmBase, bmSubScript;
nsIFrame* aChildFrame = mFrames.FirstChild();
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace(aChildFrame)) {
aChildFrame->GetRect(aRect);
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width; baseSize.height = aRect.height;
if (NS_FAILED(GetBoundingMetricsFor(baseFrame, baseBounds))) {
baseBounds.descent = baseSize.descent;
baseBounds.ascent = baseSize.ascent;
baseBounds.width = baseSize.width;
}
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
}
else if (1 == count) {
// subscript
subScriptFrame = aChildFrame;
subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width; subScriptSize.height = aRect.height;
if (NS_FAILED(GetBoundingMetricsFor(subScriptFrame, subScriptBounds))) {
subScriptBounds.descent = subScriptSize.descent;
subScriptBounds.ascent = subScriptSize.ascent;
subScriptBounds.width = subScriptSize.width;
}
GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
// get the subdrop from the subscript font
nscoord aSubDrop;
GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop);
// parameter v, Rule 18a, App. G, TeXbook
minSubScriptShift = baseSize.descent + aSubDrop;
minSubScriptShift = bmBase.descent + aSubDrop;
}
else {
NS_ASSERTION((count < 2),"nsMathMLmsubFrame : invalid markup");
@ -167,12 +154,17 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext,
// = h(x) - 4/5 * sigma_5, Rule 18b, App. G, TeXbook
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
// const nsStyleFont* aFont =
// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
const nsStyleFont* aFont;
baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
nscoord minShiftFromXHeight = (nscoord)
(subScriptSize.ascent - (4.0f/5.0f) * xHeight);
(bmSubScript.ascent - (4.0f/5.0f) * xHeight);
// aSubScriptShift
// = minimum amount to shift the subscript down set by user or from the font
@ -181,51 +173,55 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext,
nscoord aSubScriptShift, dummy;
// get aSubScriptShift default from font
GetSubScriptShifts (fm, aSubScriptShift, dummy);
if (mUserSetFlag == PR_TRUE) {
if (mUserSetFlag) {
// the user has set the subscriptshift attribute
aSubScriptShift = NSToCoordRound(mSubScriptShiftFactor * xHeight);
//XXX shouldn't this be
// aSubScriptShift =
// PR_MAX(aSubScriptShift, NSToCoordRound(mSubScriptShiftFactor * xHeight));
}
// get actual subscriptshift to be used
// Rule 18b, App. G, TeXbook
nscoord actualSubScriptShift =
PR_MAX(minSubScriptShift,PR_MAX(aSubScriptShift,minShiftFromXHeight));
#if 0
// get bounding box for base + subscript
aDesiredSize.ascent =
PR_MAX(baseSize.ascent,(subScriptSize.ascent-actualSubScriptShift));
aDesiredSize.descent =
PR_MAX(baseSize.descent,(actualSubScriptShift+subScriptSize.descent));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// add mScriptSpace between base and subscript
aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width;
#endif
mBoundingMetrics.ascent =
PR_MAX(baseBounds.ascent, subScriptBounds.ascent - actualSubScriptShift);
PR_MAX(bmBase.ascent, bmSubScript.ascent - actualSubScriptShift);
mBoundingMetrics.descent =
PR_MAX(baseBounds.descent, subScriptBounds.descent + actualSubScriptShift);
PR_MAX(bmBase.descent, bmSubScript.descent + actualSubScriptShift);
// add mScriptSpace between base and supscript
mBoundingMetrics.width = baseBounds.width + mScriptSpace + subScriptBounds.width;
mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSubScript.width;
// to be simplified
nscoord dyBase = mBoundingMetrics.ascent - bmBase.ascent;
nscoord dySubScript = mBoundingMetrics.ascent - bmSubScript.ascent + actualSubScriptShift;
nscoord baseTop = mBoundingMetrics.ascent - dyBase - bmBase.ascent + baseSize.ascent;
nscoord subScriptTop = mBoundingMetrics.ascent - dySubScript - bmSubScript.ascent + subScriptSize.ascent;
aDesiredSize.ascent = PR_MAX(baseTop, subScriptTop);
aDesiredSize.descent = PR_MAX(baseSize.height-baseTop, subScriptSize.height-subScriptTop);
aDesiredSize.ascent =
PR_MAX(baseSize.ascent, subScriptSize.ascent - actualSubScriptShift);
aDesiredSize.descent =
PR_MAX(baseSize.descent, subScriptSize.descent + actualSubScriptShift);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width = baseSize.width + mScriptSpace + subScriptSize.width;
mReference.x = 0;
mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent;
mBoundingMetrics.leftBearing = bmBase.leftBearing;
mBoundingMetrics.rightBearing = baseSize.width + mScriptSpace + bmSubScript.rightBearing;
if (aPlaceOrigin) {
nscoord dx, dy;
// now place the base ...
dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
dx = 0; dy = aDesiredSize.ascent - baseTop;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
// ... and subscript
dx = baseSize.width;
dy = aDesiredSize.ascent - subScriptSize.ascent + actualSubScriptShift;
dy = aDesiredSize.ascent - subScriptTop;
FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0);
}
return NS_OK;
}

View File

@ -103,6 +103,7 @@ nsMathMLmsubsupFrame::Init(nsIPresContext* aPresContext,
}
}
mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
return rv;
}
@ -118,7 +119,6 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// Get the children's desired sizes
PRInt32 count = 0;
nsRect aRect;
nsHTMLReflowMetrics baseSize (nsnull);
nsHTMLReflowMetrics subScriptSize (nsnull);
nsHTMLReflowMetrics supScriptSize (nsnull);
@ -130,38 +130,36 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// parameter u in Rule 18a, Appendix G of the TeXbook
nscoord minSupScriptShift = 0;
nsBoundingMetrics bmBase, bmSubScript, bmSupScript;
nsIFrame* aChildFrame = mFrames.FirstChild();
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace(aChildFrame)) {
aChildFrame->GetRect(aRect);
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width; baseSize.height = aRect.height;
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
}
else if (1 == count) {
// subscript
subScriptFrame = aChildFrame;
subScriptSize.descent = aRect.x; subScriptSize.ascent = aRect.y;
subScriptSize.width = aRect.width; subScriptSize.height = aRect.height;
GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
// get the subdrop from the subscript font
nscoord aSubDrop;
GetSubDropFromChild (aPresContext, subScriptFrame, aSubDrop);
// parameter v, Rule 18a, App. G, TeXbook
minSubScriptShift = baseSize.descent + aSubDrop;
minSubScriptShift = bmBase.descent + aSubDrop;
}
else if (2 == count) {
// superscript
supScriptFrame = aChildFrame;
supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width; supScriptSize.height = aRect.height;
GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
// get the supdrop from the supscript font
nscoord aSupDrop;
GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop);
// parameter u, Rule 18a, App. G, TeXbook
minSupScriptShift = baseSize.ascent - aSupDrop;
minSupScriptShift = bmBase.ascent - aSupDrop;
}
else {
NS_ASSERTION((count < 2),"nsMathMLmsubFrame : invalid markup");
@ -191,8 +189,13 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// get x-height (an ex)
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
// const nsStyleFont* aFont =
// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
const nsStyleFont* aFont;
baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
@ -219,7 +222,7 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// get min supscript shift limit from x-height
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
nscoord minShiftFromXHeight = (nscoord)
(supScriptSize.descent + (1.0f/4.0f) * xHeight);
(bmSupScript.descent + (1.0f/4.0f) * xHeight);
// aSupScriptShift{1,2,3}
// = minimum amount to shift the supscript up
@ -273,8 +276,8 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// XXX need to do update this ...
fm->GetStrikeout (dummy, aRuleSize);
nscoord gap =
(aSupScriptShift - supScriptSize.descent) -
(subScriptSize.ascent - aSubScriptShift);
(aSupScriptShift - bmSupScript.descent) -
(bmSubScript.ascent - aSubScriptShift);
if (gap < 4.0f * aRuleSize) {
// adjust aSubScriptShift to get a gap of (4.0 * aRuleSize)
aSubScriptShift += NSToCoordRound ((4.0f * aRuleSize) - gap);
@ -283,7 +286,7 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// next we want to ensure that the bottom of the superscript
// will be > (4/5) * x-height above baseline
gap = NSToCoordRound ((4.0f/5.0f) * xHeight -
(aSupScriptShift - supScriptSize.descent));
(aSupScriptShift - bmSupScript.descent));
if (gap > 0.0f) {
aSupScriptShift += gap;
aSubScriptShift -= gap;
@ -292,32 +295,58 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
//////////////////////////////////////////////////
// Do the Placing
//////////////////////////////////////////////////
// get bounding box for base + subscript + superscript
aDesiredSize.ascent =
PR_MAX(baseSize.ascent,(supScriptSize.ascent+aSupScriptShift));
aDesiredSize.descent =
PR_MAX(baseSize.descent,(supScriptSize.descent+aSubScriptShift));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
mBoundingMetrics.ascent =
PR_MAX(bmBase.ascent,(bmSupScript.ascent+aSupScriptShift));
mBoundingMetrics.descent =
PR_MAX(bmBase.descent,(bmSubScript.descent+aSubScriptShift));
// add mScriptSpace to both super/subscript
// add italicCorrection only to superscript
// XXX this will be handled properly later ...
nscoord italicCorrection = 0;
aDesiredSize.width = baseSize.width + mScriptSpace +
PR_MAX((supScriptSize.width + italicCorrection),subScriptSize.width);
mBoundingMetrics.width = bmBase.width + mScriptSpace +
PR_MAX((bmBase.supItalicCorrection + bmSupScript.width),
(bmBase.subItalicCorrection + bmSubScript.width));
// to be simplfied later
nscoord dyBase = mBoundingMetrics.ascent - bmBase.ascent;
nscoord dySubScript = mBoundingMetrics.ascent - bmSubScript.ascent + aSubScriptShift;
nscoord dySupScript = mBoundingMetrics.ascent - bmSupScript.ascent - aSupScriptShift;
nscoord baseTop = mBoundingMetrics.ascent - dyBase - bmBase.ascent + baseSize.ascent;
nscoord subScriptTop = mBoundingMetrics.ascent - dySubScript - bmSubScript.ascent + subScriptSize.ascent;
nscoord supScriptTop = mBoundingMetrics.ascent - dySupScript - bmSupScript.ascent + supScriptSize.ascent;
aDesiredSize.ascent =
PR_MAX(baseTop, PR_MAX(subScriptTop, supScriptTop));
aDesiredSize.descent =
PR_MAX(baseSize.height-baseTop,
PR_MAX(subScriptSize.height-subScriptTop, supScriptSize.height-supScriptTop));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
mReference.x = 0;
mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent;
mBoundingMetrics.leftBearing = bmBase.leftBearing;
mBoundingMetrics.rightBearing = bmBase.width + mScriptSpace +
PR_MAX((bmBase.supItalicCorrection + bmSupScript.rightBearing),
(bmBase.subItalicCorrection + bmSubScript.rightBearing));
aDesiredSize.width = mBoundingMetrics.width;
if (aPlaceOrigin) {
nscoord dx, dy;
// now place the base ...
dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
dx = 0; dy = aDesiredSize.ascent - baseTop;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
// ... and subscript
dx = baseSize.width;
dy = aDesiredSize.ascent - subScriptSize.ascent + aSubScriptShift;
dx = bmBase.width + bmBase.subItalicCorrection;
dy = aDesiredSize.ascent - subScriptTop;
FinishReflowChild (subScriptFrame, aPresContext, subScriptSize, dx, dy, 0);
// ... and the superscript
dx = baseSize.width + italicCorrection;
dy = aDesiredSize.ascent - supScriptSize.ascent - aSupScriptShift;
dx = bmBase.width + bmBase.supItalicCorrection;
dy = aDesiredSize.ascent - supScriptTop;
FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0);
}

View File

@ -92,6 +92,7 @@ nsMathMLmsupFrame::Init(nsIPresContext* aPresContext,
}
}
mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
return rv;
}
@ -121,28 +122,15 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext,
while (nsnull != aChildFrame)
{
if (!IsOnlyWhitespace(aChildFrame)) {
aChildFrame->GetRect(aRect);
if (0 == count) {
// base
baseFrame = aChildFrame;
baseSize.descent = aRect.x; baseSize.ascent = aRect.y;
baseSize.width = aRect.width; baseSize.height = aRect.height;
if (NS_FAILED(GetBoundingMetricsFor(baseFrame, bmBase))) {
bmBase.descent = baseSize.descent;
bmBase.ascent = baseSize.ascent;
bmBase.width = baseSize.width;
}
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
}
else if (1 == count) {
// superscript
supScriptFrame = aChildFrame;
supScriptSize.descent = aRect.x; supScriptSize.ascent = aRect.y;
supScriptSize.width = aRect.width; supScriptSize.height = aRect.height;
if (NS_FAILED(GetBoundingMetricsFor(supScriptFrame, bmSupScript))) {
bmSupScript.descent = supScriptSize.descent;
bmSupScript.ascent = supScriptSize.ascent;
bmSupScript.width = supScriptSize.width;
}
GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
// get the supdrop from the supscript font
nscoord aSupDrop;
GetSupDropFromChild (aPresContext, supScriptFrame, aSupDrop);
@ -165,12 +153,17 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext,
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
nscoord xHeight = 0;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
(const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
// const nsStyleFont* aFont =
// (const nsStyleFont*) mStyleContext->GetStyleData (eStyleStruct_Font);
const nsStyleFont *aFont;
baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)aFont);
aPresContext->GetMetricsFor (aFont->mFont, getter_AddRefs(fm));
fm->GetXHeight (xHeight);
nscoord minShiftFromXHeight = (nscoord)
(supScriptSize.descent + (1.0f/4.0f) * xHeight);
(bmSupScript.descent + (1.0f/4.0f) * xHeight);
// aSupScriptShift{1,2,3}
// = minimum amount to shift the supscript up
@ -187,6 +180,9 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext,
float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1;
float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1;
aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight);
//XXX shouldn't this be
// aSupScriptShift1 =
// PR_MAX(aSupScriptShift1, NSToCoordRound(mSupScriptShiftFactor * xHeight));
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}
@ -214,66 +210,39 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext,
nscoord actualSupScriptShift =
PR_MAX(minSupScriptShift,PR_MAX(aSupScriptShift,minShiftFromXHeight));
// get bounding box for base + supscript
#if 0
const nsStyleFont *font;
baseFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
PRInt32 baseStyle = font->mFont.style;
supScriptFrame->GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)font);
PRInt32 supScriptStyle = font->mFont.style;
if (baseStyle == NS_STYLE_FONT_STYLE_ITALIC &&
supScriptStyle != NS_STYLE_FONT_STYLE_ITALIC) {
// take care of italic correction
...
}
#endif
#if 0
aDesiredSize.ascent =
PR_MAX(baseSize.ascent,(supScriptSize.ascent+actualSupScriptShift));
aDesiredSize.descent =
PR_MAX(baseSize.descent,(supScriptSize.descent-actualSupScriptShift));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
// add mScriptSpace between base and supscript
aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width;
#endif
mBoundingMetrics.ascent =
PR_MAX(bmBase.ascent, bmSupScript.ascent + actualSupScriptShift);
PR_MAX(bmBase.ascent, (bmSupScript.ascent + actualSupScriptShift));
mBoundingMetrics.descent =
PR_MAX(bmBase.descent, bmSupScript.descent - actualSupScriptShift);
PR_MAX(bmBase.descent, (bmSupScript.descent - actualSupScriptShift));
// add mScriptSpace between base and supscript
mBoundingMetrics.width = bmBase.width + mScriptSpace + bmSupScript.width;
#if 0
printf("bmBase.width:%d + mScriptSpace:%d + bmSupScript.width:%d = mBoundingMetrics.width:%d\n",
bmBase.width, mScriptSpace, bmSupScript.width, mBoundingMetrics.width);
#endif
// to be simplified ...
nscoord dyBase = mBoundingMetrics.ascent - bmBase.ascent;
nscoord dySupScript = mBoundingMetrics.ascent - bmSupScript.ascent - actualSupScriptShift;
aDesiredSize.ascent =
PR_MAX(baseSize.ascent, supScriptSize.ascent + actualSupScriptShift);
aDesiredSize.descent =
PR_MAX(baseSize.descent, supScriptSize.descent - actualSupScriptShift);
nscoord baseTop = mBoundingMetrics.ascent - dyBase - bmBase.ascent + baseSize.ascent;
nscoord supScriptTop = mBoundingMetrics.ascent - dySupScript - bmSupScript.ascent + supScriptSize.ascent;
aDesiredSize.ascent = PR_MAX(baseTop, supScriptTop);
aDesiredSize.descent = PR_MAX(baseSize.height-baseTop, supScriptSize.height-supScriptTop);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width = baseSize.width + mScriptSpace + supScriptSize.width;
aDesiredSize.width = mBoundingMetrics.width;
mReference.x = 0;
mReference.y = aDesiredSize.ascent - mBoundingMetrics.ascent;
mBoundingMetrics.leftBearing = bmBase.leftBearing;
mBoundingMetrics.rightBearing = baseSize.width + mScriptSpace + bmSupScript.rightBearing;
if (aPlaceOrigin) {
nscoord dx, dy;
// now place the base ...
dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
dx = 0; dy = aDesiredSize.ascent - baseTop;
FinishReflowChild (baseFrame, aPresContext, baseSize, dx, dy, 0);
// ... and supscript
#if 0
float t2p;
aPresContext->GetTwipsToPixels(&t2p);
PRInt32 scriptspace = NSTwipsToIntPixels(mScriptSpace, t2p);
printf("mScriptSpace in twips:%d pixel:%d\n", mScriptSpace, scriptspace);
#endif
dx = baseSize.width + mScriptSpace;
dy = aDesiredSize.ascent - supScriptSize.ascent - actualSupScriptShift;
dy = aDesiredSize.ascent - supScriptTop;
FinishReflowChild (supScriptFrame, aPresContext, supScriptSize, dx, dy, 0);
}