[not part of default build] Recover from API changes and improve the position of the index in mroot to eliminate the risk of collision with the sqrt symbol

git-svn-id: svn://10.0.0.236/trunk@86069 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rbs%maths.uq.edu.au 2001-02-02 09:39:18 +00:00
parent 18baf8bf80
commit 69af6767db
4 changed files with 112 additions and 62 deletions

View File

@ -57,6 +57,8 @@
// additional style context to be used by our MathMLChar.
#define NS_SQR_CHAR_STYLE_CONTEXT_INDEX 0
static const PRUnichar kSqrChar = PRUnichar(0x221A);
nsresult
NS_NewMathMLmrootFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
@ -95,7 +97,8 @@ nsMathMLmrootFrame::Init(nsIPresContext* aPresContext,
mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
mSqrChar.SetEnum(aPresContext, eMathMLChar_Sqrt);
nsAutoString sqrChar; sqrChar.Assign(kSqrChar);
mSqrChar.SetData(aPresContext, sqrChar);
ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSqrChar);
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
@ -129,8 +132,7 @@ nsMathMLmrootFrame::Paint(nsIPresContext* aPresContext,
nsStyleColor color;
mStyleContext->GetStyle(eStyleStruct_Color, color);
aRenderingContext.SetColor(color.mColor);
aRenderingContext.FillRect(mBarRect.x, mBarRect.y,
mBarRect.width, mBarRect.height);
aRenderingContext.FillRect(mBarRect);
}
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
@ -209,12 +211,11 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
}
count++;
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
childFrame->GetNextSibling(&childFrame);
}
if ((2 != count) || !baseFrame || !indexFrame) {
#ifdef NS_DEBUG
printf("mroot: invalid markup");
printf("mroot: invalid markup\n");
#endif
// report an error, encourage people to get their markups in order
return ReflowError(aPresContext, renderingContext, aDesiredSize);
@ -229,7 +230,7 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
nsCOMPtr<nsIFontMetrics> fm;
renderingContext.GetFontMetrics(*getter_AddRefs(fm));
nscoord ruleThickness;
nscoord ruleThickness, leading;
GetRuleThickness(renderingContext, fm, ruleThickness);
// Rule 11, App. G, TeXbook
@ -246,12 +247,8 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
contSize.descent = bmBase.ascent + bmBase.descent + psi;
contSize.ascent = ruleThickness;
nsBoundingMetrics radicalSize;
radicalSize.Clear(); // this tells Stretch() that we don't know the current size
// height(radical) should be >= height(base) + psi + ruleThickness
// however, nsMathMLChar will only try to meet this condition
// with no guarantee.
nsBoundingMetrics radicalSize;
mSqrChar.Stretch(aPresContext, renderingContext,
NS_STRETCH_DIRECTION_VERTICAL,
contSize, radicalSize,
@ -263,6 +260,16 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
// According to TeX, the ascent of the returned radical should be
// the thickness of the overline
ruleThickness = bmSqr.ascent;
// make sure that the rule appears on on screen
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
if (ruleThickness < onePixel) {
ruleThickness = onePixel;
}
// get the leading to be left at the top of the resulting frame
float em = float(font.mFont.size);
leading = nscoord(0.2f * em);
// adjust clearance psi to absorb any excess difference if any
// in height between radical and content
@ -270,7 +277,7 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
if (bmSqr.descent > (bmBase.ascent + bmBase.descent) + psi)
psi = (psi + bmSqr.descent - (bmBase.ascent + bmBase.descent))/2;
// Update the desired size for the container (like msqrt, index is not yet uncluded)
// Update the desired size for the container (like msqrt, index is not yet included)
// the baseline will be that of the base.
mBoundingMetrics.ascent = bmBase.ascent + psi + ruleThickness;
mBoundingMetrics.descent =
@ -280,7 +287,7 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
mBoundingMetrics.rightBearing = bmSqr.width +
PR_MAX(bmBase.width, bmBase.rightBearing); // take also care of the rule
aDesiredSize.ascent = mBoundingMetrics.ascent + ruleThickness;
aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
aDesiredSize.descent =
PR_MAX(baseSize.descent, (mBoundingMetrics.descent + ruleThickness));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
@ -301,57 +308,68 @@ nsMathMLmrootFrame::Reflow(nsIPresContext* aPresContext,
indexClearance =
indexRaisedAscent - mBoundingMetrics.ascent; // excess gap introduced by a tall index
mBoundingMetrics.ascent = indexRaisedAscent;
aDesiredSize.ascent = mBoundingMetrics.ascent + ruleThickness;
aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
}
// the index is tucked in closer to the radical
// XXX assumes that the kern does not make the content and radical collide.
// the index is tucked in closer to the radical while making sure
// that the kern does not make the index and radical collide
nscoord dxIndex, dxSqr, dx, dy;
nscoord xHeight = 0;
fm->GetXHeight(xHeight);
nscoord indexRadicalKern = NSToCoordRound(1.35f * xHeight);
if (indexRadicalKern < bmIndex.width)
{
mBoundingMetrics.width += (bmIndex.width - indexRadicalKern);
aDesiredSize.width = mBoundingMetrics.width;
if (indexRadicalKern > bmIndex.width) {
dxIndex = indexRadicalKern - bmIndex.width;
dxSqr = 0;
}
else {
dxIndex = 0;
dxSqr = bmIndex.width - indexRadicalKern;
}
// avoid collision by leaving a minimun space between index and radical
nscoord minimumClearance = bmSqr.width/2;
if (dxIndex + bmIndex.width + minimumClearance > dxSqr + bmSqr.width) {
if (bmIndex.width + minimumClearance < bmSqr.width) {
dxIndex = bmSqr.width - (bmIndex.width + minimumClearance);
dxSqr = 0;
}
else {
dxIndex = 0;
dxSqr = (bmIndex.width + minimumClearance) - bmSqr.width;
}
}
mReference.x = 0;
mReference.y = aDesiredSize.ascent;
nscoord dx = 0, dy = 0, lbearing;
// place the index
dx = (indexRadicalKern > bmIndex.width) ? indexRadicalKern - bmIndex.width : 0;
// place the index
dx = dxIndex;
dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
FinishReflowChild(indexFrame, aPresContext, indexSize, dx, dy, 0);
lbearing = dx + bmIndex.leftBearing;
// place the radical symbol
dx = (indexRadicalKern > bmIndex.width) ? 0 : bmIndex.width - indexRadicalKern;
dy = indexClearance + ruleThickness; // leave a kern=ruleThickness at the top
// place the radical symbol and the radical bar
dx = dxSqr;
dy = indexClearance + leading; // leave a leading at the top
mSqrChar.SetRect(nsRect(dx, dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
if (lbearing < dx + bmSqr.leftBearing) {
mBoundingMetrics.leftBearing = lbearing;
mBoundingMetrics.rightBearing += dx;
}
// place the radical bar
dx += bmSqr.width;
dy = indexClearance + ruleThickness; // leave a kern=ruleThickness at the top
mBarRect.SetRect(dx, dy, bmBase.width, ruleThickness);
// place the base
dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild(baseFrame, aPresContext, baseSize, dx, dy, 0);
mReference.x = 0;
mReference.y = aDesiredSize.ascent;
mBoundingMetrics.width = dx + bmBase.width;
mBoundingMetrics.leftBearing =
PR_MIN(dxIndex + bmIndex.leftBearing, dxSqr + bmSqr.leftBearing);
mBoundingMetrics.rightBearing = dx +
PR_MAX(bmBase.width, bmBase.rightBearing);
aDesiredSize.width = mBoundingMetrics.width;
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}

View File

@ -56,7 +56,16 @@ public:
{
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
UpdatePresentationDataFromChildAt(1, 2, PR_FALSE, PR_FALSE);
// 1. The REC says:
// The <mroot> element increments scriptlevel by 2, and sets displaystyle to
// "false", within index, but leaves both attributes unchanged within base.
// 2. The TeXbook (Ch 17. p.141) says \sqrt is compressed
UpdatePresentationDataFromChildAt(1, 1, 2,
~NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED,
NS_MATHML_DISPLAYSTYLE | NS_MATHML_COMPRESSED);
UpdatePresentationDataFromChildAt(0, 0, 0,
NS_MATHML_COMPRESSED, NS_MATHML_COMPRESSED);
// switch the style of the index
InsertScriptLevelStyleContext(aPresContext);
return rv;
}

View File

@ -57,6 +57,8 @@
// additional style context to be used by our MathMLChar.
#define NS_SQR_CHAR_STYLE_CONTEXT_INDEX 0
static const PRUnichar kSqrChar = PRUnichar(0x221A);
nsresult
NS_NewMathMLmsqrtFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
@ -95,7 +97,8 @@ nsMathMLmsqrtFrame::Init(nsIPresContext* aPresContext,
mEmbellishData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
mSqrChar.SetEnum(aPresContext, eMathMLChar_Sqrt);
nsAutoString sqrChar; sqrChar.Assign(kSqrChar);
mSqrChar.SetData(aPresContext, sqrChar);
ResolveMathMLCharStyle(aPresContext, mContent, mStyleContext, &mSqrChar);
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
@ -129,8 +132,7 @@ nsMathMLmsqrtFrame::Paint(nsIPresContext* aPresContext,
nsStyleColor color;
mStyleContext->GetStyle(eStyleStruct_Color, color);
aRenderingContext.SetColor(color.mColor);
aRenderingContext.FillRect(mBarRect.x, mBarRect.y,
mBarRect.width, mBarRect.height);
aRenderingContext.FillRect(mBarRect);
}
#if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
@ -188,9 +190,9 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
nsCOMPtr<nsIFontMetrics> fm;
renderingContext.GetFontMetrics(*getter_AddRefs(fm));
nscoord ruleThickness;
nscoord ruleThickness, leading;
GetRuleThickness(renderingContext, fm, ruleThickness);
// Rule 11, App. G, TeXbook
// psi = clearance between rule and content
nscoord phi = 0, psi = 0;
@ -205,13 +207,10 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
contSize.ascent = ruleThickness;
contSize.descent = bmBase.ascent + bmBase.descent + psi;
nsBoundingMetrics radicalSize;
radicalSize.Clear(); // this tells Stretch() that we don't know the current size
// height(radical) should be >= height(base) + psi + ruleThickness
// however, nsMathMLChar will only try to meet this condition
// with no guarantee.
mSqrChar.SetEnum(aPresContext, eMathMLChar_Sqrt); // XXX hack to reset the enum, bug 45010
nsBoundingMetrics radicalSize;
nsAutoString sqrChar; sqrChar.Assign(kSqrChar);
mSqrChar.SetData(aPresContext, sqrChar); // XXX hack to reset the char, bug 45010
mSqrChar.Stretch(aPresContext, renderingContext,
NS_STRETCH_DIRECTION_VERTICAL,
contSize, radicalSize,
@ -223,6 +222,16 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
// According to TeX, the ascent of the returned radical should be
// the thickness of the overline
ruleThickness = bmSqr.ascent;
// make sure that the rule appears on the screen
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
if (ruleThickness < onePixel) {
ruleThickness = onePixel;
}
// get the leading to be left at the top of the resulting frame
float em = float(font.mFont.size);
leading = nscoord(0.2f * em);
// adjust clearance psi to absorb any excess difference if any
// in height between radical and content
@ -231,13 +240,10 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
psi = (psi + bmSqr.descent - (bmBase.ascent + bmBase.descent))/2;
nscoord dx = 0, dy = 0;
// place the radical symbol
dy = ruleThickness; // leave a kern=ruleThickness at the top
// place the radical symbol and the radical bar
dy = leading; // leave a leading at the top
mSqrChar.SetRect(nsRect(dx, dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
// place the radical bar
dx = bmSqr.width;
dy = ruleThickness; // leave a kern=ruleThickness at the top
mBarRect.SetRect(dx, dy, bmBase.width, ruleThickness);
// Update the desired size for the container.
@ -250,7 +256,7 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
mBoundingMetrics.rightBearing = bmSqr.width +
PR_MAX(bmBase.width, bmBase.rightBearing); // take also care of the rule
aDesiredSize.ascent = bmBase.ascent + psi + 2*ruleThickness;
aDesiredSize.ascent = bmBase.ascent + psi + ruleThickness + leading;
aDesiredSize.descent =
PR_MAX(baseSize.descent, (mBoundingMetrics.descent + ruleThickness));
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
@ -271,8 +277,7 @@ nsMathMLmsqrtFrame::Reflow(nsIPresContext* aPresContext,
childFrame->GetOrigin(origin);
childFrame->MoveTo(aPresContext, origin.x + dx, origin.y + dy);
}
rv = childFrame->GetNextSibling(&childFrame);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to get next child");
childFrame->GetNextSibling(&childFrame);
}
if (nsnull != aDesiredSize.maxElementSize) {

View File

@ -85,6 +85,24 @@ public:
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer);
NS_IMETHOD
SetInitialChildList(nsIPresContext* aPresContext,
nsIAtom* aListName,
nsIFrame* aChildList)
{
nsresult rv;
rv = nsMathMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
// 1. The REC says:
// The <msqrt> element leaves both attributes [displaystyle and scriptlevel]
// unchanged within all its arguments.
// 2. The TeXBook (Ch 17. p.141) says that \sqrt is cramped
UpdatePresentationDataFromChildAt(0, -1, 0,
NS_MATHML_COMPRESSED,
NS_MATHML_COMPRESSED);
InsertScriptLevelStyleContext(aPresContext);
return rv;
}
protected:
nsMathMLmsqrtFrame();
virtual ~nsMathMLmsqrtFrame();