[MathML] Added support for CSS units on numeric attributes and updated code to make use of the support

This commit is contained in:
rbs%maths.uq.edu.au 2000-01-26 06:49:38 +00:00
Родитель cc0d62ff60
Коммит bdab93b4ec
13 изменённых файлов: 474 добавлений и 223 удалений

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

@ -122,6 +122,164 @@ nsMathMLContainerFrame::IsOnlyWhitespace(nsIFrame* aFrame)
return rv;
}
// helper to get an attribute from the content or the surrounding <mstyle>
nsresult
nsMathMLContainerFrame::GetAttribute(nsIContent* aContent,
nsIFrame* aMathMLmstyleFrame,
nsIAtom* aAttributeAtom,
nsString& aValue)
{
// see if we can get the attribute from the content
if (aContent) {
if (NS_CONTENT_ATTR_HAS_VALUE ==
aContent->GetAttribute(kNameSpaceID_None, aAttributeAtom, aValue))
return NS_CONTENT_ATTR_HAS_VALUE;
}
// see if we can get the attribute from the mstyle frame
if (aMathMLmstyleFrame) {
nsCOMPtr<nsIContent> mstyleContent;
aMathMLmstyleFrame->GetContent(getter_AddRefs(mstyleContent));
if (NS_CONTENT_ATTR_HAS_VALUE ==
mstyleContent->GetAttribute(kNameSpaceID_None, aAttributeAtom, aValue))
return NS_CONTENT_ATTR_HAS_VALUE;
}
return NS_CONTENT_ATTR_NOT_THERE;
}
// ================
// Utilities for parsing and retrieving numeric values
// All returned values are in twips.
/*
The REC says:
An explicit plus sign ('+') is not allowed as part of a numeric value
except when it is specifically listed in the syntax (as a quoted '+' or "+"),
Units allowed
ID Description
em ems (font-relative unit traditionally used for horizontal lengths)
ex exs (font-relative unit traditionally used for vertical lengths)
px pixels, or pixel size of a "typical computer display"
in inches (1 inch = 2.54 centimeters)
cm centimeters
mm millimeters
pt points (1 point = 1/72 inch)
pc picas (1 pica = 12 points)
% percentage of default value
Implementation here:
The numeric value is valid only if it is of the form nnn.nnn [h/v-unit]
*/
// Adapted from nsCSSScanner.cpp & CSSParser.cpp
PRBool
nsMathMLContainerFrame::ParseNumericValue(const nsString& aString,
nsCSSValue& aCSSValue)
{
PRInt32 stringLength = aString.Length();
if (!stringLength) return PR_FALSE;
nsAutoString number = aString;
number.SetLength(0);
nsAutoString unit = aString;
unit.SetLength(0);
// Gather up characters that make up the number
PRBool gotDot = PR_FALSE;
PRUnichar c;
for (PRInt32 i = 0; i < stringLength; i++) {
c = aString[i];
if (gotDot && c == '.')
return PR_FALSE; // two dots encountered
else if (c == '.')
gotDot = PR_TRUE;
else if (!nsString::IsDigit(c)) {
aString.Right(unit, stringLength - i);
break;
}
number.Append(PRUnichar(c));
}
#if 0
char s1[50], s2[50], s3[50];
aString.ToCString(s1, 50);
number.ToCString(s2, 50);
unit.ToCString(s3, 50);
printf("String:%s, Number:%s, Unit:%s\n", s1, s2, s3);
#endif
// Convert number to floating point
PRInt32 errorCode;
float floatValue = number.ToFloat(&errorCode);
if (NS_FAILED(errorCode)) return PR_FALSE;
nsCSSUnit cssUnit;
if (0 == unit.Length()) {
cssUnit = eCSSUnit_Number; // no explicit unit, this is a number that will act as a multiplier
}
else if (unit == "%") {
floatValue = floatValue / 100.0f;
aCSSValue.SetPercentValue(floatValue);
return PR_TRUE;
}
else if (unit == "em") cssUnit = eCSSUnit_EM;
else if (unit == "ex") cssUnit = eCSSUnit_XHeight;
else if (unit == "px") cssUnit = eCSSUnit_Pixel;
else if (unit == "in") cssUnit = eCSSUnit_Inch;
else if (unit == "cm") cssUnit = eCSSUnit_Centimeter;
else if (unit == "mm") cssUnit = eCSSUnit_Millimeter;
else if (unit == "pt") cssUnit = eCSSUnit_Point;
else if (unit == "pc") cssUnit = eCSSUnit_Pica;
else // unexpected unit
return PR_FALSE;
aCSSValue.SetFloatValue(floatValue, cssUnit);
return PR_TRUE;
}
// Adapted from nsCSSStyleRule.cpp
nscoord
nsMathMLContainerFrame::CalcLength(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
const nsCSSValue& aValue)
{
NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit");
if (aValue.IsFixedLengthUnit()) {
return aValue.GetLengthTwips();
}
nsCSSUnit unit = aValue.GetUnit();
if (eCSSUnit_Pixel == unit) {
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
return NSFloatPixelsToTwips(aValue.GetFloatValue(), p2t);
}
else if (eCSSUnit_EM == unit) {
nsStyleFont font;
aStyleContext->GetStyle(eStyleStruct_Font, font);
return NSToCoordRound(aValue.GetFloatValue() * (float)font.mFont.size);
}
else if (eCSSUnit_XHeight == unit) {
nscoord xHeight;
nsStyleFont font;
aStyleContext->GetStyle(eStyleStruct_Font, font);
nsCOMPtr<nsIFontMetrics> fm;
aPresContext->GetMetricsFor(font.mFont, getter_AddRefs(fm));
fm->GetXHeight(xHeight);
return NSToCoordRound(aValue.GetFloatValue() * (float)xHeight);
}
return 0;
}
// -------------------------
void
nsMathMLContainerFrame::ReflowEmptyChild(nsIPresContext* aPresContext,
nsIFrame* aFrame)
@ -610,26 +768,29 @@ nsMathMLContainerFrame::InsertScriptLevelStyleContext(nsIPresContext* aPresConte
// smaller-font-size algorithm of the style system
PRInt32 scriptminsize = NSIntPointsToTwips(8);
// see if the scriptminsize attribute is on <mstyle> that wraps us
// see if there is a scriptminsize attribute on a <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
}
if (NS_CONTENT_ATTR_HAS_VALUE ==
GetAttribute(nsnull, mPresentationData.mstyle,
nsMathMLAtoms::scriptminsize_, value))
{
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue)) {
nsCSSUnit unit = cssValue.GetUnit();
if (eCSSUnit_Number == unit)
scriptminsize = nscoord(float(scriptminsize) * cssValue.GetFloatValue());
else if (eCSSUnit_Percent == unit)
scriptminsize = nscoord(float(scriptminsize) * cssValue.GetPercentValue());
else if (eCSSUnit_Null != unit)
scriptminsize = CalcLength(aPresContext, mStyleContext, cssValue);
}
#ifdef NS_DEBUG
else {
char str[50];
value.ToCString(str, 50);
printf("Invalid attribute scriptminsize=%s\n", str);
}
#endif
}
// get Nav's magic font scaler

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

@ -35,6 +35,8 @@
#include "nsIMathMLFrame.h"
#include "nsMathMLParts.h"
#include "nsCSSValue.h"
/*
* Base class for MathML container frames. It acts like an inferred
* mrow. By default, this frame uses its Reflow() method to lay its
@ -256,6 +258,27 @@ public:
nsHTMLReflowMetrics& aReflowMetrics,
nsBoundingMetrics& aBoundingMetrics);
// helper to check if a content has an attribute. If content is nsnull or if
// the attribute is not there, check if the attribute is on the mstyle frame.
// @return NS_CONTENT_ATTR_HAS_VALUE --if attribute is there
// NS_CONTENT_ATTR_NOT_THERE --if attribute is not there
static nsresult
GetAttribute(nsIContent* aContent,
nsIFrame* aMathMLmstyleFrame,
nsIAtom* aAttributeAtom,
nsString& aValue);
// utilities to parse and retrieve numeric values in CSS units
// All values are stored in twips.
static PRBool
ParseNumericValue(const nsString& aString,
nsCSSValue& aCSSValue);
static nscoord
CalcLength(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
const nsCSSValue& aValue);
// helper methods for getting sup/subdrop's from a child
static void
GetSubDropFromChild (nsIPresContext* aPresContext,
@ -309,23 +332,6 @@ public:
}
// these are TeX specific params not found in ordinary fonts
#if 0
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);
}
#endif
static void
GetSubDrop (nsIFontMetrics *fm, nscoord& aSubDrop)

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

@ -3,19 +3,19 @@
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* The Original Code is Mozilla MathML Project.
*
* The Initial Developer of the Original Code is The University Of
*
* The Initial Developer of the Original Code is The University Of
* Queensland. Portions created by The University Of Queensland are
* Copyright (C) 1999 The University Of Queensland. All Rights Reserved.
*
* Contributor(s):
*
* Contributor(s):
* Roger B. Sidje <rbs@maths.uq.edu.au>
* David J. Fiddes <D.J.Fiddes@hw.ac.uk>
*/
@ -80,39 +80,51 @@ nsMathMLmfracFrame::Init(nsIPresContext* aPresContext,
return rv;
}
nscoord aLineThickness = DEFAULT_FRACTION_LINE_THICKNESS;
nsAutoString value;
// see if the linethickness attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
nscoord defaultThickness = onePixel * DEFAULT_FRACTION_LINE_THICKNESS;
mLineThickness = defaultThickness;
// see if the linethickness attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE ==
GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::linethickness_, value))
{
if (value == "thin")
aLineThickness = THIN_FRACTION_LINE_THICKNESS;
mLineThickness = onePixel * THIN_FRACTION_LINE_THICKNESS;
else if (value == "medium")
aLineThickness = MEDIUM_FRACTION_LINE_THICKNESS;
mLineThickness = onePixel * MEDIUM_FRACTION_LINE_THICKNESS;
else if (value == "thick")
aLineThickness = THICK_FRACTION_LINE_THICKNESS;
else {
PRInt32 aErrorCode;
PRInt32 aMultiplier = value.ToInteger(&aErrorCode);
if (NS_SUCCEEDED(aErrorCode))
aLineThickness = aMultiplier * DEFAULT_FRACTION_LINE_THICKNESS;
else {
// XXX TODO: try to see if it is a h/v-unit like 1ex, 2px, 1em
// see also nsUnitConversion.h
mLineThickness = onePixel * THICK_FRACTION_LINE_THICKNESS;
else { // see if it is a plain number, or a percentage, or a h/v-unit like 1ex, 2px, 1em
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue)) {
nsCSSUnit unit = cssValue.GetUnit();
if (eCSSUnit_Number == unit)
mLineThickness = nscoord(float(defaultThickness) * cssValue.GetFloatValue());
else if (eCSSUnit_Percent == unit)
mLineThickness = nscoord(float(defaultThickness) * cssValue.GetPercentValue());
else if (eCSSUnit_Null != unit)
mLineThickness = CalcLength(aPresContext, mStyleContext, cssValue);
}
#ifdef NS_DEBUG
else {
char str[50];
value.ToCString(str, 50);
printf("Invalid attribute linethickness=%s\n", str);
}
#endif
}
}
// mLineThickness = (aLineThickness > MAX_FRACTION_LINE_THICKNESS) ?
// MAX_FRACTION_LINE_THICKNESS : aLineThickness;
mLineThickness = aLineThickness;
mLineOrigin.x = 0;
mLineOrigin.y = 0;
mLineOrigin.y = 0;
// TODO: other attributes...
return rv;
}
@ -123,10 +135,10 @@ nsMathMLmfracFrame::Paint(nsIPresContext* aPresContext,
nsFramePaintLayer aWhichLayer)
{
nsresult rv = NS_OK;
/////////////
// paint the numerator and denominator
rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext,
rv = nsMathMLContainerFrame::Paint(aPresContext, aRenderingContext,
aDirtyRect, aWhichLayer);
if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
@ -136,24 +148,22 @@ nsMathMLmfracFrame::Paint(nsIPresContext* aPresContext,
////////////
// paint the fraction line
if (NS_SUCCEEDED(rv) && 0 < mLineThickness) {
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord thickness = NSIntPixelsToTwips(mLineThickness, p2t);
/*
// line looking like <hr noshade>
const nsStyleColor* color;
nscolor colors[2];
color = nsStyleUtil::FindNonTransparentBackground(mStyleContext);
NS_Get3DColors(colors, color->mBackgroundColor);
aRenderingContext.SetColor(colors[0]);
nscolor colors[2];
color = nsStyleUtil::FindNonTransparentBackground(mStyleContext);
NS_Get3DColors(colors, color->mBackgroundColor);
aRenderingContext.SetColor(colors[0]);
*/
// solid line with the current text color
const nsStyleColor* color =
(const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
aRenderingContext.SetColor(color->mColor);
// draw the line
aRenderingContext.FillRect(mLineOrigin.x, mLineOrigin.y, mRect.width, thickness);
// draw the line
aRenderingContext.FillRect(mLineOrigin.x, mLineOrigin.y, mRect.width, mLineThickness);
}
return rv;
@ -167,19 +177,19 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
{
nsresult rv = NS_OK;
nsReflowStatus childStatus;
// ask our children to compute their bounding metrics
// 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);
//////////////////
// Reflow Children
nscoord count = 0;
nsRect rect[2];
nsIFrame* child[2];
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
nsIFrame* childFrame = mFrames.FirstChild();
while (nsnull != childFrame)
{
//////////////
// WHITESPACE: don't forget that whitespace doesn't count in MathML!
@ -195,10 +205,10 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
return rv;
}
child[count] = childFrame;
child[count] = childFrame;
rect[count].width = childDesiredSize.width;
rect[count].height = childDesiredSize.height;
count++;
count++;
}
// else { invalid markup... }
@ -207,9 +217,9 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
}
//////////////////
// Place Children
// Get the <strike> line and center the fraction bar with the <strike> line.
// Place Children
// Get the <strike> line and center the fraction bar with the <strike> line.
nscoord strikeOffset, strikeThickness;
nsCOMPtr<nsIFontMetrics> fm;
const nsStyleFont* aFont =
@ -219,16 +229,12 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
// Take care of mLineThickness
float p2t;
nscoord Thickspace, halfThickspace;
nscoord halfThickspace;
aPresContext->GetScaledPixelsToTwips(&p2t);
if (mLineThickness <= 1) {
Thickspace = 0;
halfThickspace = 0;
}
else {
Thickspace = NSIntPixelsToTwips(mLineThickness-1, p2t);
halfThickspace = Thickspace/2; // distance from the middle of the axis
}
nscoord onePixel = NSIntPixelsToTwips(1, p2t);
// distance from the middle of the axis
halfThickspace = (mLineThickness > onePixel)? mLineThickness/2 : 0;
aDesiredSize.width = PR_MAX(rect[0].width, rect[1].width);
aDesiredSize.ascent = rect[0].height + strikeOffset + halfThickspace;
@ -248,7 +254,7 @@ nsMathMLmfracFrame::Reflow(nsIPresContext* aPresContext,
childSize.height = rect[i].height;
FinishReflowChild(child[i], aPresContext, childSize, rect[i].x, rect[i].y, 0);
}
SetLineOrigin(nsPoint(0,rect[0].height)); // position the fraction bar
SetLineOrigin(nsPoint(0,rect[0].height)); // position the fraction bar
if (nsnull != aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = aDesiredSize.width;

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

@ -50,7 +50,7 @@ The linethickness attribute indicates the thickness of the horizontal
"fraction bar", or "rule", typically used to render fractions. A fraction
with linethickness="0" renders without the bar, and might be used within
binomial coefficients. A linethickness greater than one might be used with
nested fractions. These cases are shown below:
nested fractions.
In general, the value of linethickness can be a number, as a multiplier
of the default thickness of the fraction bar (the default thickness is
@ -63,26 +63,9 @@ The <mfrac> element sets displaystyle to "false", or if it was already
false increments scriptlevel by 1, within numerator and denominator.
These attributes are inherited by every element from its rendering
environment, but can be set explicitly only on the <mstyle>
element. (See Section 3.3.4.)
element.
*/
/*
TODO:
Units...
- CalcLength(..) in nsCSSStyleRule.cpp is where CSS units are implemented.
How to use that for linethickness and, in general, how to factor the use
of units in the MathML world?
ID Description
em ems (font-relative unit traditionally used for horizontal lengths)
ex exs (font-relative unit traditionally used for vertical lengths)
px pixels, or pixel size of a "typical computer display"
in inches (1 inch = 2.54 centimeters)
cm centimeters
mm millimeters
pt points (1 point = 1/72 inch)
pc picas (1 pica = 12 points)
% percentage of default value
*/
// default fraction line thickness in pixels
#define DEFAULT_FRACTION_LINE_THICKNESS 1
@ -91,9 +74,6 @@ pc picas (1 pica = 12 points)
#define MEDIUM_FRACTION_LINE_THICKNESS 2
#define THICK_FRACTION_LINE_THICKNESS 4
// use an upper bound just in case someone set a too high value? why bother?
// #define MAX_FRACTION_LINE_THICKNESS 5
class nsMathMLmfracFrame : public nsMathMLContainerFrame {
public:
friend nsresult NS_NewMathMLmfracFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);

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

@ -77,30 +77,25 @@ nsMathMLmmultiscriptsFrame::Init(nsIPresContext* aPresContext,
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSubScriptShiftFactor = 0.0f;
mSupScriptShiftFactor = 0.0f;
mSubScriptShift = 0;
mSupScriptShift = 0;
mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX
// check for subscriptshift and superscriptshift attribute in ex units
// check if the subscriptshift attribute is there
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 == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::subscriptshift_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mSubScriptShift = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
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;
// check if the superscriptshift attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::superscriptshift_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mSupScriptShift = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
@ -149,10 +144,10 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
// Get aSubScriptShift{1,2} default from font
GetSubScriptShifts (fm, aSubScriptShift1, aSubScriptShift2);
if (mSubUserSetFlag) {
if (0 < mSubScriptShift) {
// the user has set the subscriptshift attribute
float aFactor = ((float) aSubScriptShift2) / aSubScriptShift1;
aSubScriptShift1 = NSToCoordRound(mSubScriptShiftFactor * xHeight);
aSubScriptShift1 = PR_MAX(aSubScriptShift1, mSubScriptShift);
aSubScriptShift2 = NSToCoordRound(aFactor * aSubScriptShift1);
}
// the font dependent shift
@ -170,11 +165,11 @@ nsMathMLmmultiscriptsFrame::Place(nsIPresContext* aPresContext,
nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3;
// Set aSupScriptShift{1,2,3} default from font
GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3);
if (mSupUserSetFlag) {
if (0 < mSupScriptShift) {
// the user has set the superscriptshift attribute
float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1;
float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1;
aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight);
aSupScriptShift1 = PR_MAX(aSupScriptShift1, mSupScriptShift);
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}

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

@ -72,8 +72,8 @@ protected:
private:
nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript
// = 0.5pt in plain TeX
float mSubScriptShiftFactor, mSupScriptShiftFactor;
PRBool mSubUserSetFlag, mSupUserSetFlag;
nscoord mSubScriptShift;
nscoord mSupScriptShift;
};
#endif /* nsMathMLmmultiscriptsFrame_h___ */

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

@ -156,6 +156,8 @@ nsMathMLmoFrame::Init(nsIPresContext* aPresContext,
mFlags = 0;
mLeftSpace = 0.0f; // .27777f;
mRightSpace = 0.0f; // .27777f;
mMinSize = float(NS_UNCONSTRAINEDSIZE);
mMaxSize = float(NS_UNCONSTRAINEDSIZE);
mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
return rv;
@ -222,7 +224,7 @@ nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext,
PRBool movablelimitsAttribute = PR_FALSE;
// see if the accent attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::accent_, value))
{
accentAttribute = PR_TRUE;
@ -233,7 +235,7 @@ nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext,
}
// see if the movablelimits attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::movablelimits_, value))
{
movablelimitsAttribute = PR_TRUE;
@ -278,7 +280,7 @@ nsMathMLmoFrame::SetInitialChildList(nsIPresContext* aPresContext,
}
void
nsMathMLmoFrame::InitData()
nsMathMLmoFrame::InitData(nsIPresContext* aPresContext)
{
nsresult rv = NS_OK;
mFlags = 0;
@ -289,7 +291,7 @@ nsMathMLmoFrame::InitData()
nsIMathMLFrame* aMathMLFrame = nsnull;
nsIFrame* embellishAncestor = nsnull;
PRBool hasEmbellishAncestor = PR_FALSE;
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::form_, value)) {
if (value == "prefix")
aForm = NS_MATHML_OPERATOR_FORM_PREFIX;
@ -392,8 +394,6 @@ nsMathMLmoFrame::InitData()
mRightSpace /= 2.0f;
}
// XXX Factor all this in nsMathMLAttributes.cpp
// Now see if there are user-defined attributes that override the dictionary.
// XXX If an attribute can be forced to be true when it is false in the
// dictionary, then the following code has to change...
@ -403,51 +403,108 @@ nsMathMLmoFrame::InitData()
nsAutoString kfalse("false"), ktrue("true");
if (NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::stretchy_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_STRETCHY;
}
if (NS_MATHML_OPERATOR_IS_FENCE(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::fence_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_FENCE;
}
if (NS_MATHML_OPERATOR_IS_ACCENT(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::accent_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_ACCENT;
}
if (NS_MATHML_OPERATOR_IS_LARGEOP(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::largeop_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_LARGEOP;
}
if (NS_MATHML_OPERATOR_IS_SEPARATOR(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::separator_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_SEPARATOR;
}
if (NS_MATHML_OPERATOR_IS_MOVABLELIMITS(mFlags)) {
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::movablelimits_, value) && value == kfalse)
mFlags &= ~NS_MATHML_OPERATOR_MOVABLELIMITS;
}
if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None,
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::symmetric_, value)) {
if (value == ktrue) mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
if (value == kfalse) mFlags &= ~NS_MATHML_OPERATOR_SYMMETRIC;
}
// TODO: add also lspace and rspace, minsize, maxsize, later ...
// If we are an accent without explicit lspace="." or rspace=".",
// ignore our default left/right space
if (NS_MATHML_EMBELLISH_IS_ACCENT(mEmbellishData.flags)) {
// Get the value of 'em'
nsStyleFont font;
mStyleContext->GetStyle(eStyleStruct_Font, font);
float em = float(font.mFont.size);
// lspace = number h-unit
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::lspace_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mLeftSpace = float(CalcLength(aPresContext, mStyleContext, cssValue)) / em;
}
}
else if (NS_MATHML_EMBELLISH_IS_ACCENT(mEmbellishData.flags)) {
mLeftSpace = 0.0f;
}
// rspace = number h-unit
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::rspace_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mRightSpace = float(CalcLength(aPresContext, mStyleContext, cssValue)) / em;
}
}
else if (NS_MATHML_EMBELLISH_IS_ACCENT(mEmbellishData.flags)) {
mRightSpace = 0.0f;
}
// minsize = number [ v-unit | h-unit ]
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::minsize_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue)) {
nsCSSUnit unit = cssValue.GetUnit();
if (eCSSUnit_Number == unit)
mMinSize = cssValue.GetFloatValue();
else if (eCSSUnit_Percent == unit)
mMinSize = cssValue.GetPercentValue();
else if (eCSSUnit_Null != unit) {
mMinSize = float(CalcLength(aPresContext, mStyleContext, cssValue));
mFlags |= NS_MATHML_OPERATOR_MINSIZE_EXPLICIT;
}
}
}
// maxsize = number [ v-unit | h-unit ] | infinity
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::maxsize_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue)) {
nsCSSUnit unit = cssValue.GetUnit();
if (eCSSUnit_Number == unit)
mMaxSize = cssValue.GetFloatValue();
else if (eCSSUnit_Percent == unit)
mMaxSize = cssValue.GetPercentValue();
else if (eCSSUnit_Null != unit) {
mMaxSize = float(CalcLength(aPresContext, mStyleContext, cssValue));
mFlags |= NS_MATHML_OPERATOR_MAXSIZE_EXPLICIT;
}
}
}
// If the stretchy attribute has been disabled, the operator is not mutable
if (!found || !NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) {
mFlags &= ~NS_MATHML_OPERATOR_MUTABLE;
@ -471,7 +528,7 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
mEmbellishData.flags |= NS_MATHML_STRETCH_DONE;
// if (0 == mFlags) { // first time...
InitData();
InitData(aPresContext);
// }
@ -479,10 +536,12 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
// See if it is okay to stretch
if (NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) {
nsStretchMetrics initialSize(aDesiredStretchSize);
nsStretchMetrics container(aContainerSize);
// little adjustments if the operator is symmetric
// XXX Also use maxsize and minsize to find what size we should
// really suggest to our MathMLChar.
if (NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags) &&
((aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) ||
(aStretchDirection == NS_STRETCH_DIRECTION_DEFAULT &&
@ -490,15 +549,72 @@ nsMathMLmoFrame::Stretch(nsIPresContext* aPresContext,
{
container.ascent = PR_MAX(container.ascent, container.descent);
container.descent = container.ascent;
container.height = container.ascent + container.descent;
container.height = container.ascent + container.descent;
// get ready in case we encounter user-desired min-max
initialSize.ascent = PR_MAX(initialSize.ascent, initialSize.descent);
initialSize.descent = initialSize.ascent;
initialSize.height = initialSize.ascent + initialSize.descent;
}
// check for user-desired min-max size
if (mMaxSize != float(NS_UNCONSTRAINEDSIZE) && mMaxSize > 0.0f) {
// if we are here, there is a user defined maxsize ...
if (NS_MATHML_OPERATOR_MAXSIZE_IS_EXPLICIT(mFlags)) {
// there is an explicit value like maxsize="20pt"
// try to maintain the aspect ratio of the char
float aspect = mMaxSize / float(initialSize.ascent + initialSize.descent);
container.ascent =
PR_MIN(container.ascent, nscoord(initialSize.ascent * aspect));
container.descent =
PR_MIN(container.descent, nscoord(initialSize.descent * aspect));
// below we use a type cast instead of a conversion to avoid a VC++ bug
// see http://support.microsoft.com/support/kb/articles/Q115/7/05.ASP
container.width =
PR_MIN(container.width, (nscoord)mMaxSize);
}
else { // multiplicative value
container.ascent =
PR_MIN(container.ascent, nscoord(initialSize.ascent * mMaxSize));
container.descent =
PR_MIN(container.descent, nscoord(initialSize.descent * mMaxSize));
container.width =
PR_MIN(container.width, nscoord(initialSize.width * mMaxSize));
}
}
if (mMinSize != float(NS_UNCONSTRAINEDSIZE) && mMinSize > 0.0f) {
// if we are here, there is a user defined minsize ...
if (NS_MATHML_OPERATOR_MINSIZE_IS_EXPLICIT(mFlags)) {
// there is an explicit value like minsize="20pt"
// try to maintain the aspect ratio of the char
float aspect = mMinSize / float(initialSize.ascent + initialSize.descent);
container.ascent =
PR_MAX(container.ascent, nscoord(initialSize.ascent * aspect));
container.descent =
PR_MAX(container.descent, nscoord(initialSize.descent * aspect));
container.width =
PR_MAX(container.width, (nscoord)mMinSize);
}
else { // multiplicative value
container.ascent =
PR_MAX(container.ascent, nscoord(initialSize.ascent * mMinSize));
container.descent =
PR_MAX(container.descent, nscoord(initialSize.descent * mMinSize));
container.width =
PR_MAX(container.width, nscoord(initialSize.width * mMinSize));
}
}
// things may have changed
container.height = container.ascent + container.descent;
// let the MathMLChar stretch itself...
nsStretchMetrics old(aDesiredStretchSize);
mMathMLChar.Stretch(aPresContext, aRenderingContext,
mStyleContext, aStretchDirection,
container, aDesiredStretchSize);
if (old == aDesiredStretchSize) { // hasn't changed !
if (initialSize == aDesiredStretchSize) { // hasn't changed !
mFlags &= ~NS_MATHML_OPERATOR_MUTABLE;
}
}

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

@ -74,7 +74,8 @@ public:
nsStretchMetrics& aDesiredStretchSize);
// helper method to lookup the operator dictionary and initialize our member data
void InitData();
void
InitData(nsIPresContext* aPresContext);
protected:
nsMathMLmoFrame();
@ -82,10 +83,12 @@ protected:
virtual PRIntn GetSkipSides() const { return 0; }
nsMathMLChar mMathMLChar; // Here is the MathChar that will deal with the operator.
nsMathMLChar mMathMLChar; // Here is the MathMLChar that will deal with the operator.
nsOperatorFlags mFlags;
float mLeftSpace;
float mRightSpace;
float mMinSize;
float mMaxSize;
};
#endif /* nsMathMLmoFrame_h___ */

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

@ -77,19 +77,16 @@ nsMathMLmsubFrame::Init(nsIPresContext* aPresContext,
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSubScriptShiftFactor = 0.0;
mSubScriptShift = 0;
mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX
// check for subscriptshift attribute in ex units
// check if the subscriptshift attribute is there
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;
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::subscriptshift_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mSubScriptShift = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
@ -173,13 +170,9 @@ nsMathMLmsubFrame::Place(nsIPresContext* aPresContext,
nscoord aSubScriptShift, dummy;
// get aSubScriptShift default from font
GetSubScriptShifts (fm, aSubScriptShift, dummy);
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));
}
aSubScriptShift =
PR_MAX(aSubScriptShift, mSubScriptShift);
// get actual subscriptshift to be used
// Rule 18b, App. G, TeXbook

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

@ -72,8 +72,7 @@ public:
private:
nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript
// = 0.5pt in plain TeX
float mSubScriptShiftFactor;
PRBool mUserSetFlag;
nscoord mSubScriptShift;
};
#endif /* nsMathMLmsubFrame_h___ */

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

@ -77,29 +77,25 @@ nsMathMLmsubsupFrame::Init(nsIPresContext* aPresContext,
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSubScriptShiftFactor = 0.0f;
mSupScriptShiftFactor = 0.0f;
mSubScriptShift = 0;
mSupScriptShift = 0;
mScriptSpace = 0;
// check for subscriptshift and superscriptshift attribute in ex units
// check if the subscriptshift attribute is there
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 == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::subscriptshift_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mSubScriptShift = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
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;
// check if the superscriptshift attribute is there
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::superscriptshift_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mSupScriptShift = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
@ -201,10 +197,11 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// Get aSubScriptShift{1,2} default from font
GetSubScriptShifts (fm, aSubScriptShift1, aSubScriptShift2);
if (mSubUserSetFlag) {
if (0 < mSubScriptShift) {
// the user has set the subscriptshift attribute
float aFactor = ((float) aSubScriptShift2) / aSubScriptShift1;
aSubScriptShift1 = NSToCoordRound(mSubScriptShiftFactor * xHeight);
aSubScriptShift1 = PR_MAX(aSubScriptShift1, mSubScriptShift);
aSubScriptShift2 = NSToCoordRound(aFactor * aSubScriptShift1);
}
@ -233,11 +230,11 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
nscoord aSupScriptShift1, aSupScriptShift2, aSupScriptShift3;
// Set aSupScriptShift{1,2,3} default from font
GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3);
if (mSupUserSetFlag) {
if (0 < mSupScriptShift) {
// the user has set the superscriptshift attribute
float aFactor2 = ((float) aSupScriptShift2) / aSupScriptShift1;
float aFactor3 = ((float) aSupScriptShift3) / aSupScriptShift1;
aSupScriptShift1 = NSToCoordRound(mSupScriptShiftFactor * xHeight);
aSupScriptShift1 = PR_MAX(aSupScriptShift1, mSupScriptShift);
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}
@ -272,7 +269,7 @@ nsMathMLmsubsupFrame::Place(nsIPresContext* aPresContext,
// Rule 18e, App. G, TeXbook
//////////////////////////////////////////////////
nscoord aRuleSize, dummy;
nscoord aRuleSize;
// XXX need to do update this ...
GetRuleThickness (fm, aRuleSize);
// aRuleSize /= 2;

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

@ -72,8 +72,8 @@ protected:
private:
nscoord mScriptSpace; // scriptspace from TeX for extra spacing after sup/subscript
// = 0.5pt in plain TeX
float mSubScriptShiftFactor, mSupScriptShiftFactor;
PRBool mSubUserSetFlag, mSupUserSetFlag;
nscoord mSubScriptShift;
nscoord mSupScriptShift;
};
#endif /* nsMathMLmsubsupFrame_h___ */

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

@ -76,19 +76,16 @@ nsMathMLmsupFrame::Init(nsIPresContext* aPresContext,
nsresult rv = nsMathMLContainerFrame::Init
(aPresContext, aContent, aParent, aContext, aPrevInFlow);
mSupScriptShiftFactor = 0.0f;
mSupScriptShift = 0;
mScriptSpace = NSFloatPointsToTwips(0.5f); // 0.5pt as in plain TeX
// check for superscriptshift attribute in ex units
// check if the superscriptshift attribute is there
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;
if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(mContent, mPresentationData.mstyle,
nsMathMLAtoms::superscriptshift_, value)) {
nsCSSValue cssValue;
if (ParseNumericValue(value, cssValue) && cssValue.IsLengthUnit()) {
mSupScriptShift = CalcLength(aPresContext, mStyleContext, cssValue);
}
}
@ -175,14 +172,12 @@ nsMathMLmsupFrame::Place(nsIPresContext* aPresContext,
// Set aSupScriptShift{1,2,3} default from font
GetSupScriptShifts (fm, aSupScriptShift1, aSupScriptShift2, aSupScriptShift3);
if (mUserSetFlag) {
// the user has set the supscriptshift attribute
if (0 < mSupScriptShift) {
// the user has set the superscriptshift attribute
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));
aSupScriptShift1 =
PR_MAX(aSupScriptShift1, mSupScriptShift);
aSupScriptShift2 = NSToCoordRound(aFactor2 * aSupScriptShift1);
aSupScriptShift3 = NSToCoordRound(aFactor3 * aSupScriptShift1);
}