Rework the positioning functions of <mover>, <munder>, <munderover> to improve their behavior w.r.t italic and non-italics fonts. Also use some fuzzy arithmetic to mitigate roundoff errors that could cause accents to collide with their base, b=135940, r=bzbarsky, sr=roc+moz

This commit is contained in:
rbs%maths.uq.edu.au 2003-01-22 07:42:20 +00:00
Родитель 87c2b9e2b4
Коммит eba1c08907
3 изменённых файлов: 119 добавлений и 72 удалений

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

@ -291,6 +291,10 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver);
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
////////////////////
// Place Children
@ -310,11 +314,12 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
// whether we want an accented overscript or not
nscoord correction = 0;
GetItalicCorrection (bmBase, correction);
nscoord delta1 = 0; // gap between base and overscript
nscoord delta2 = 0; // extra space above overscript
if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {
// Rule 13a, App. G, TeXbook
GetItalicCorrection (bmBase, correction);
nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy;
GetBigOpSpacings (fm,
bigOpSpacing1, dummy,
@ -331,7 +336,6 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
}
else {
// Rule 12, App. G, TeXbook
GetSkewCorrectionFromChild (aPresContext, baseFrame, correction);
// We are going to modify this rule to make it more general.
// The idea behind Rule 12 in the TeXBook is to keep the accent
// as close to the base as possible, while ensuring that the
@ -360,9 +364,9 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
// we try to keep the *bottom* of the accent char atleast x-height
// from the baseline of the base char. we also slap on an extra
// padding between the accent and base chars.
delta1 = ruleThickness; // we have atleast the padding
delta1 = ruleThickness + onePixel/2; // we have at least the padding
if (bmBase.ascent < xHeight) {
// also ensure atleast x-height above the baseline of the base
// also ensure at least x-height above the baseline of the base
delta1 += xHeight - bmBase.ascent;
}
delta2 = ruleThickness;
@ -370,13 +374,7 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
// empty over?
if (!(bmOver.ascent + bmOver.descent)) delta1 = 0;
mBoundingMetrics.ascent =
bmOver.ascent + bmOver.descent + delta1 + bmBase.ascent;
mBoundingMetrics.descent = bmBase.descent;
nscoord dxBase, dxOver = 0;
nscoord dyBase, dyOver;
// Ad-hoc - This is to override fonts which have ready-made _accent_
// glyphs with negative lbearing and rbearing. We want to position
@ -388,13 +386,22 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
}
if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {
mBoundingMetrics.width = PR_MAX(bmBase.width, overWidth);
mBoundingMetrics.width = bmBase.width;
dxOver += correction + (mBoundingMetrics.width - overWidth)/2;
}
else {
mBoundingMetrics.width =
PR_MAX(bmBase.width/2,(overWidth + correction/2)/2) +
PR_MAX(bmBase.width/2,(overWidth - correction/2)/2);
mBoundingMetrics.width = PR_MAX(bmBase.width, overWidth);
dxOver += correction/2 + (mBoundingMetrics.width - overWidth)/2;
}
dxBase = (mBoundingMetrics.width - bmBase.width) / 2;
mBoundingMetrics.ascent =
bmOver.ascent + bmOver.descent + delta1 + bmBase.ascent;
mBoundingMetrics.descent = bmBase.descent;
mBoundingMetrics.leftBearing =
PR_MIN(dxBase + bmBase.leftBearing, dxOver + bmOver.leftBearing);
mBoundingMetrics.rightBearing =
PR_MAX(dxBase + bmBase.rightBearing, dxOver + bmOver.rightBearing);
aDesiredSize.descent = baseSize.descent;
aDesiredSize.ascent =
@ -402,34 +409,19 @@ nsMathMLmoverFrame::Place(nsIPresContext* aPresContext,
overSize.ascent + bmOver.descent + delta1 + bmBase.ascent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width = mBoundingMetrics.width;
dxBase = (mBoundingMetrics.width - bmBase.width) / 2;
dyBase = aDesiredSize.ascent - baseSize.ascent;
if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {
dxOver += correction + (mBoundingMetrics.width - overWidth)/2;
}
else {
dxOver += correction/2 + (mBoundingMetrics.width - overWidth)/2;
}
dyOver = aDesiredSize.ascent -
mBoundingMetrics.ascent + bmOver.ascent - overSize.ascent;
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
mReference.x = 0;
mReference.y = aDesiredSize.ascent;
mBoundingMetrics.leftBearing =
PR_MIN(dxBase + bmBase.leftBearing, dxOver + bmOver.leftBearing);
mBoundingMetrics.rightBearing =
PR_MAX(dxBase + bmBase.rightBearing, dxOver + bmOver.rightBearing);
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
if (aPlaceOrigin) {
// place base
FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dxBase, dyBase, 0);
nscoord dy = aDesiredSize.ascent - baseSize.ascent;
FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dxBase, dy, 0);
// place overscript
FinishReflowChild (overFrame, aPresContext, nsnull, overSize, dxOver, dyOver, 0);
dy = aDesiredSize.ascent -
mBoundingMetrics.ascent + bmOver.ascent - overSize.ascent;
FinishReflowChild (overFrame, aPresContext, nsnull, overSize, dxOver, dy, 0);
}
return NS_OK;
}

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

@ -288,6 +288,10 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext,
GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder);
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
////////////////////
// Place Children
@ -306,12 +310,13 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext,
// there are 2 different types of placement depending on
// whether we want an accented under or not
nscoord italicCorrection = 0;
nscoord correction = 0;
GetItalicCorrection (bmBase, correction);
nscoord delta1 = 0; // gap between base and underscript
nscoord delta2 = 0; // extra space beneath underscript
if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
// Rule 13a, App. G, TeXbook
GetItalicCorrection (bmBase, italicCorrection);
nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy;
GetBigOpSpacings (fm,
dummy, bigOpSpacing2,
@ -325,22 +330,27 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext,
// XXX tune the gap delta between base and underscript
// Should we use Rule 10 like \underline does?
delta1 = ruleThickness;
delta1 = ruleThickness + onePixel/2;
delta2 = ruleThickness;
}
// empty under?
if (!(bmUnder.ascent + bmUnder.descent)) delta1 = 0;
nscoord dxBase, dxUnder;
nscoord maxWidth = PR_MAX(bmBase.width, bmUnder.width);
if (NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
dxUnder = (maxWidth - bmUnder.width)/2;
}
else {
dxUnder = -correction/2 + (maxWidth - bmUnder.width)/2;
}
dxBase = (maxWidth - bmBase.width)/2;
mBoundingMetrics.width =
PR_MAX(dxBase + bmBase.width, dxUnder + bmUnder.width);
mBoundingMetrics.ascent = bmBase.ascent;
mBoundingMetrics.descent =
bmBase.descent + delta1 + bmUnder.ascent + bmUnder.descent;
mBoundingMetrics.width =
PR_MAX(bmBase.width/2,(bmUnder.width + italicCorrection/2)/2) +
PR_MAX(bmBase.width/2,(bmUnder.width - italicCorrection/2)/2);
nscoord dxBase = (mBoundingMetrics.width - bmBase.width) / 2;
nscoord dxUnder = (mBoundingMetrics.width - (bmUnder.width + italicCorrection/2)) / 2;
mBoundingMetrics.leftBearing =
PR_MIN(dxBase + bmBase.leftBearing, dxUnder + bmUnder.leftBearing);
mBoundingMetrics.rightBearing =
@ -351,9 +361,7 @@ nsMathMLmunderFrame::Place(nsIPresContext* aPresContext,
PR_MAX(mBoundingMetrics.descent + delta2,
bmBase.descent + delta1 + bmUnder.ascent + underSize.descent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width =
PR_MAX(baseSize.width/2,(underSize.width + italicCorrection/2)/2) +
PR_MAX(baseSize.width/2,(underSize.width - italicCorrection/2)/2);
aDesiredSize.width = mBoundingMetrics.width;
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
mReference.x = 0;

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

@ -331,6 +331,10 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder);
GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver);
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
////////////////////
// Place Children
@ -346,16 +350,17 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
nscoord ruleThickness;
GetRuleThickness (aRenderingContext, fm, ruleThickness);
nscoord correction = 0;
GetItalicCorrection (bmBase, correction);
// there are 2 different types of placement depending on
// whether we want an accented under or not
nscoord italicCorrection = 0;
nscoord underDelta1 = 0; // gap between base and underscript
nscoord underDelta2 = 0; // extra space beneath underscript
if (!NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
// Rule 13a, App. G, TeXbook
GetItalicCorrection (bmBase, italicCorrection);
nscoord bigOpSpacing2, bigOpSpacing4, bigOpSpacing5, dummy;
GetBigOpSpacings (fm,
dummy, bigOpSpacing2,
@ -369,19 +374,17 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
// XXX tune the gap delta between base and underscript
// Should we use Rule 10 like \underline does?
underDelta1 = ruleThickness;
underDelta1 = ruleThickness + onePixel/2;
underDelta2 = ruleThickness;
}
// empty under?
if (!(bmUnder.ascent + bmUnder.descent)) underDelta1 = 0;
nscoord correction = 0;
nscoord overDelta1 = 0; // gap between base and overscript
nscoord overDelta2 = 0; // extra space above overscript
if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {
// Rule 13a, App. G, TeXbook
GetItalicCorrection (bmBase, italicCorrection);
nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy;
GetBigOpSpacings (fm,
bigOpSpacing1, dummy,
@ -397,9 +400,8 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
overDelta1 = PR_MAX(bigOpSpacing1, (bigOpSpacing3 - (bmOver.ascent + bmOver.descent)));
}
else {
// Rule 13, App. G, TeXbook
GetSkewCorrectionFromChild (aPresContext, baseFrame, correction);
overDelta1 = ruleThickness;
// Rule 12, App. G, TeXbook
overDelta1 = ruleThickness + onePixel/2;
if (bmBase.ascent < xHeight) {
overDelta1 += xHeight - bmBase.ascent;
}
@ -408,33 +410,78 @@ nsMathMLmunderoverFrame::Place(nsIPresContext* aPresContext,
// empty over?
if (!(bmOver.ascent + bmOver.descent)) overDelta1 = 0;
nscoord dxBase, dxOver = 0, dxUnder = 0;
//////////
// pass 1, do what <mover> does: attach the overscript on the base
// Ad-hoc - This is to override fonts which have ready-made _accent_
// glyphs with negative lbearing and rbearing. We want to position
// the overscript ourselves
nscoord overWidth = bmOver.width;
if (!overWidth && (bmOver.rightBearing - bmOver.leftBearing > 0)) {
overWidth = bmOver.rightBearing - bmOver.leftBearing;
dxOver = -bmOver.leftBearing;
}
if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) {
mBoundingMetrics.width = bmBase.width;
dxOver += correction + (mBoundingMetrics.width - overWidth)/2;
}
else {
mBoundingMetrics.width = PR_MAX(bmBase.width, overWidth);
dxOver += correction/2 + (mBoundingMetrics.width - overWidth)/2;
}
dxBase = (mBoundingMetrics.width - bmBase.width)/2;
mBoundingMetrics.ascent =
bmBase.ascent + overDelta1 + bmOver.ascent + bmOver.descent;
mBoundingMetrics.descent =
bmBase.descent + underDelta1 + bmUnder.ascent + bmUnder.descent;
mBoundingMetrics.width =
PR_MAX(bmBase.width/2,PR_MAX((bmUnder.width + italicCorrection/2)/2,(bmOver.width - correction/2)/2)) +
PR_MAX(bmBase.width/2,PR_MAX((bmUnder.width - italicCorrection/2)/2,(bmOver.width + correction/2)/2));
nscoord dxBase = (mBoundingMetrics.width - bmBase.width) / 2;
nscoord dxOver = (mBoundingMetrics.width - (bmOver.width - correction/2)) / 2;
nscoord dxUnder = (mBoundingMetrics.width - (bmUnder.width + italicCorrection/2)) / 2;
mBoundingMetrics.leftBearing =
PR_MIN(dxBase + bmBase.leftBearing, dxUnder + bmUnder.leftBearing);
PR_MIN(dxBase + bmBase.leftBearing, dxOver + bmOver.leftBearing);
mBoundingMetrics.rightBearing =
PR_MAX(dxBase + bmBase.rightBearing, dxUnder + bmUnder.rightBearing);
mBoundingMetrics.leftBearing =
PR_MIN(mBoundingMetrics.leftBearing, dxOver + bmOver.leftBearing);
mBoundingMetrics.rightBearing =
PR_MAX(mBoundingMetrics.rightBearing, dxOver + bmOver.rightBearing);
PR_MAX(dxBase + bmBase.rightBearing, dxOver + bmOver.rightBearing);
aDesiredSize.ascent =
//////////
// pass 2, do what <munder> does: attach the underscript on the previous
// result. We conceptually view the previous result as an "anynomous base"
// from where to attach the underscript. Hence if the underscript is empty,
// we should end up like <mover>. If the overscript is empty, we should
// end up like <munder>.
nsBoundingMetrics bmAnonymousBase = mBoundingMetrics;
nscoord ascentAnonymousBase =
PR_MAX(mBoundingMetrics.ascent + overDelta2,
overSize.ascent + bmOver.descent + overDelta1 + bmBase.ascent);
GetItalicCorrection(bmAnonymousBase, correction);
nscoord maxWidth = PR_MAX(bmAnonymousBase.width, bmUnder.width);
if (NS_MATHML_EMBELLISH_IS_ACCENTUNDER(mEmbellishData.flags)) {
dxUnder = (maxWidth - bmUnder.width)/2;;
}
else {
dxUnder = -correction/2 + (maxWidth - bmUnder.width)/2;
}
nscoord dxAnonymousBase = (maxWidth - bmAnonymousBase.width)/2;
// adjust the offsets of the real base and overscript since their
// final offsets should be relative to us...
dxOver += dxAnonymousBase;
dxBase += dxAnonymousBase;
mBoundingMetrics.width =
PR_MAX(dxAnonymousBase + bmAnonymousBase.width, dxUnder + bmUnder.width);
mBoundingMetrics.leftBearing =
PR_MIN(dxAnonymousBase + bmAnonymousBase.leftBearing, dxUnder + bmUnder.leftBearing);
mBoundingMetrics.rightBearing =
PR_MAX(dxAnonymousBase + bmAnonymousBase.rightBearing, dxUnder + bmUnder.rightBearing);
aDesiredSize.ascent = ascentAnonymousBase;
aDesiredSize.descent =
PR_MAX(mBoundingMetrics.descent + underDelta2,
bmBase.descent + underDelta1 + bmUnder.ascent + underSize.descent);
bmAnonymousBase.descent + underDelta1 + bmUnder.ascent + underSize.descent);
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
aDesiredSize.width = mBoundingMetrics.width;
aDesiredSize.mBoundingMetrics = mBoundingMetrics;