nsMathMLChar::GetMaxWidth and stretchy <mo> GetIntrinsicWidth implementations. Rename MAXSIZE_IS_EXPLICIT to MAXSIZE_IS_ABSOLUTE. Avoid unsigned/signed warnings with 1<<31. b=363240, r+sr=roc

This commit is contained in:
karlt+@karlt.net 2008-03-13 21:05:43 -07:00
parent a5b6672d1f
commit 2071d69173
5 changed files with 482 additions and 309 deletions

View File

@ -1170,25 +1170,74 @@ SetFontFamily(nsIRenderingContext& aRenderingContext,
}
}
class nsMathMLChar::StretchEnumContext {
public:
StretchEnumContext(nsMathMLChar* aChar,
nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nscoord aTargetSize,
PRUint32 aStretchHint,
nsBoundingMetrics& aStretchedMetrics,
const nsAString& aFamilies)
: mChar(aChar),
mPresContext(aPresContext),
mRenderingContext(aRenderingContext),
mDirection(aStretchDirection),
mTargetSize(aTargetSize),
mStretchHint(aStretchHint),
mBoundingMetrics(aStretchedMetrics),
mFamilies(aFamilies),
mTryVariants(PR_TRUE),
mTryParts(PR_TRUE) {}
static PRBool
EnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData);
private:
static PRBool
ResolverCallback (const nsAString& aFamily, void *aData);
PRBool TryVariants(nsGlyphTable* aGlyphTable, const nsAString& aFamily);
PRBool TryParts(nsGlyphTable* aGlyphTable, const nsAString& aFamily);
nsMathMLChar* mChar;
nsPresContext* mPresContext;
nsIRenderingContext& mRenderingContext;
const nsStretchDirection mDirection;
const nscoord mTargetSize;
const PRUint32 mStretchHint;
nsBoundingMetrics& mBoundingMetrics;
// Font families to search
const nsAString& mFamilies;
public:
PRPackedBool mTryVariants;
PRPackedBool mTryParts;
private:
nsAutoTArray<nsGlyphTable*,16> mTablesTried;
nsGlyphTable* mGlyphTable; // for this callback
};
// 2. See if there are any glyphs of the appropriate size.
// Returns PR_TRUE if the size is OK, PR_FALSE to keep searching.
// Always updates the char if a better match is found.
PRBool
nsMathMLChar::TryVariants(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsGlyphTable* aGlyphTable,
nscoord aTargetSize,
PRUint32 aStretchHint,
const nsAString& aFamily)
nsMathMLChar::StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
const nsAString& aFamily)
{
// Use our stretchy style context now that stretching is in progress
nsFont font = mStyleContext->GetStyleFont()->mFont;
// Ensure aRenderingContext.SetFont will be called:
nsFont font = mChar->mStyleContext->GetStyleFont()->mFont;
// Ensure mRenderingContext.SetFont will be called:
font.name.Truncate();
PRBool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL);
PRBool largeop = (NS_STRETCH_LARGEOP & aStretchHint) != 0;
PRBool largeopOnly = (NS_STRETCH_LARGEOP == aStretchHint); // (==, not mask!)
PRBool largeop = (NS_STRETCH_LARGEOP & mStretchHint) != 0;
PRBool largeopOnly =
largeop && (NS_STRETCH_VARIABLE_MASK & mStretchHint) == 0;
PRBool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0;
nscoord bestSize =
isVertical ? mBoundingMetrics.ascent + mBoundingMetrics.descent
@ -1197,7 +1246,7 @@ nsMathMLChar::TryVariants(nsPresContext* aPresContext,
// figure out the starting size : if this is a largeop, start at 2 else 1
PRInt32 size = 1; // size=0 is the char at its normal size
if (largeop && aGlyphTable->BigOf(aPresContext, this, 2).Exists()) {
if (largeop && aGlyphTable->BigOf(mPresContext, mChar, 2).Exists()) {
size = 2;
}
#ifdef NOISY_SEARCH
@ -1206,28 +1255,43 @@ nsMathMLChar::TryVariants(nsPresContext* aPresContext,
#endif
nsGlyphCode ch;
while ((ch = aGlyphTable->BigOf(aPresContext, this, size)).Exists()) {
while ((ch = aGlyphTable->BigOf(mPresContext, mChar, size)).Exists()) {
SetFontFamily(aRenderingContext, font, aGlyphTable, ch, aFamily);
SetFontFamily(mRenderingContext, font, aGlyphTable, ch, aFamily);
NS_ASSERTION(ch.code != mGlyph.code || ! font.name.Equals(mFamily),
NS_ASSERTION(maxWidth || ch.code != mChar->mGlyph.code ||
!font.name.Equals(mChar->mFamily),
"glyph table incorrectly set -- duplicate found");
nsBoundingMetrics bm;
nsresult rv = aRenderingContext.GetBoundingMetrics(&ch.code, 1, bm);
nsresult rv = mRenderingContext.GetBoundingMetrics(&ch.code, 1, bm);
if (NS_SUCCEEDED(rv)) {
nscoord charSize =
isVertical ? bm.ascent + bm.descent
: bm.rightBearing - bm.leftBearing;
if (largeopOnly ||
IsSizeBetter(charSize, bestSize, aTargetSize, aStretchHint)) {
haveBetter = PR_TRUE;
bestSize = charSize;
mGlyphTable = aGlyphTable;
mGlyph = ch;
mBoundingMetrics = bm;
mFamily = font.name;
IsSizeBetter(charSize, bestSize, mTargetSize, mStretchHint)) {
if (maxWidth) {
// IsSizeBetter() checked that charSize < maxsize;
// Leave ascent, descent, and bestsize as these contain maxsize.
if (mBoundingMetrics.width < bm.width)
mBoundingMetrics.width = bm.width;
if (mBoundingMetrics.leftBearing > bm.leftBearing)
mBoundingMetrics.leftBearing = bm.leftBearing;
if (mBoundingMetrics.rightBearing < bm.rightBearing)
mBoundingMetrics.rightBearing = bm.rightBearing;
// Continue to check other sizes unless largeopOnly
haveBetter = largeopOnly;
}
else {
mBoundingMetrics = bm;
haveBetter = PR_TRUE;
bestSize = charSize;
mChar->mGlyphTable = aGlyphTable;
mChar->mGlyph = ch;
mChar->mFamily = font.name;
}
#ifdef NOISY_SEARCH
printf(" size:%d Current best\n", size);
#endif
@ -1247,32 +1311,29 @@ nsMathMLChar::TryVariants(nsPresContext* aPresContext,
}
return haveBetter &&
(largeopOnly || IsSizeOK(aPresContext, bestSize, aTargetSize, aStretchHint));
(largeopOnly || IsSizeOK(mPresContext, bestSize, mTargetSize, mStretchHint));
}
// 3. Build by parts.
// Returns PR_TRUE if the size is OK, PR_FALSE to keep searching.
// Always updates the char if a better match is found.
PRBool
nsMathMLChar::TryParts(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsGlyphTable* aGlyphTable,
nscoord aTargetSize,
PRUint32 aStretchHint,
const nsAString& aFamily)
nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable,
const nsAString& aFamily)
{
if (!aGlyphTable->HasPartsOf(aPresContext, this))
if (!aGlyphTable->HasPartsOf(mPresContext, mChar))
return PR_FALSE; // to next table
// See if this is a composite character /////////////////////////////////////
if (aGlyphTable->IsComposite(aPresContext, this)) {
if (aGlyphTable->IsComposite(mPresContext, mChar)) {
// let the child chars do the job
nsBoundingMetrics compositeSize;
nsresult rv = ComposeChildren(aPresContext, aRenderingContext, aGlyphTable,
aTargetSize, compositeSize, aStretchHint);
nsresult rv =
mChar->ComposeChildren(mPresContext, mRenderingContext, aGlyphTable,
mTargetSize, compositeSize, mStretchHint);
#ifdef NOISY_SEARCH
printf(" Composing %d chars in font %s %s!\n",
aGlyphTable->ChildCountOf(aPresContext, this),
aGlyphTable->ChildCountOf(mPresContext, mChar),
NS_LossyConvertUTF16toASCII(fontName).get(),
NS_SUCCEEDED(rv)? "OK" : "Rejected");
#endif
@ -1280,8 +1341,8 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
return PR_FALSE; // to next table
// all went well, painting will be delegated from now on to children
mGlyph = kNullGlyph; // this will tell paint to build by parts
mGlyphTable = aGlyphTable;
mChar->mGlyph = kNullGlyph; // this will tell paint to build by parts
mChar->mGlyphTable = aGlyphTable;
mBoundingMetrics = compositeSize;
return PR_TRUE; // no more searching
}
@ -1289,26 +1350,26 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
// See if the parts of this table fit in the desired space //////////////////
// Use our stretchy style context now that stretching is in progress
nsFont font = mStyleContext->GetStyleFont()->mFont;
// Ensure aRenderingContext.SetFont will be called:
nsFont font = mChar->mStyleContext->GetStyleFont()->mFont;
// Ensure mRenderingContext.SetFont will be called:
font.name.Truncate();
// Compute the bounding metrics of all partial glyphs
PRInt32 i;
nsGlyphCode chdata[4];
nsBoundingMetrics bmdata[4];
nscoord sizedata[4];
nsGlyphCode glue = aGlyphTable->GlueOf(aPresContext, this);
nsGlyphCode glue = aGlyphTable->GlueOf(mPresContext, mChar);
PRBool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL);
PRBool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0;
for (i = 0; i < 4; i++) {
for (PRInt32 i = 0; i < 4; i++) {
nsGlyphCode ch;
switch (i) {
case 0: ch = aGlyphTable->TopOf(aPresContext, this); break;
case 1: ch = aGlyphTable->MiddleOf(aPresContext, this); break;
case 2: ch = aGlyphTable->BottomOf(aPresContext, this); break;
case 3: ch = glue; break;
case 0: ch = aGlyphTable->TopOf(mPresContext, mChar); break;
case 1: ch = aGlyphTable->MiddleOf(mPresContext, mChar); break;
case 2: ch = aGlyphTable->BottomOf(mPresContext, mChar); break;
case 3: ch = glue; break;
}
// empty slots are filled with the glue if it is not null
if (!ch.Exists()) ch = glue;
@ -1317,11 +1378,11 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
if (!ch.Exists()) {
// Null glue indicates that a rule will be drawn, which can stretch to
// fill any space. Leave bounding metrics at 0.
sizedata[i] = aTargetSize;
sizedata[i] = mTargetSize;
}
else {
SetFontFamily(aRenderingContext, font, aGlyphTable, ch, aFamily);
nsresult rv = aRenderingContext.GetBoundingMetrics(&ch.code, 1, bm);
SetFontFamily(mRenderingContext, font, aGlyphTable, ch, aFamily);
nsresult rv = mRenderingContext.GetBoundingMetrics(&ch.code, 1, bm);
if (NS_FAILED(rv)) {
// stop if we failed to compute the bounding metrics of a part.
NS_WARNING("GetBoundingMetrics failed");
@ -1339,14 +1400,14 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
// Build by parts if we have successfully computed the
// bounding metrics of all parts.
nscoord computedSize = ComputeSizeFromParts(aPresContext, chdata, sizedata,
aTargetSize, aStretchHint);
nscoord computedSize = ComputeSizeFromParts(mPresContext, chdata, sizedata,
mTargetSize, mStretchHint);
nscoord currentSize =
isVertical ? mBoundingMetrics.ascent + mBoundingMetrics.descent
: mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing;
if (!IsSizeBetter(computedSize, currentSize, aTargetSize, aStretchHint)) {
if (!IsSizeBetter(computedSize, currentSize, mTargetSize, mStretchHint)) {
#ifdef NOISY_SEARCH
printf(" Font %s Rejected!\n",
NS_LossyConvertUTF16toASCII(fontName).get());
@ -1362,16 +1423,32 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
// The computed size is the best we have found so far...
// now is the time to compute and cache our bounding metrics
if (isVertical) {
nscoord lbearing = bmdata[0].leftBearing;
nscoord rbearing = bmdata[0].rightBearing;
nscoord width = bmdata[0].width;
for (i = 1; i < 4; i++) {
PRInt32 i;
nscoord lbearing;
nscoord rbearing;
nscoord width;
if (maxWidth) {
lbearing = mBoundingMetrics.leftBearing;
rbearing = mBoundingMetrics.rightBearing;
width = mBoundingMetrics.width;
i = 0;
}
else {
lbearing = bmdata[0].leftBearing;
rbearing = bmdata[0].rightBearing;
width = bmdata[0].width;
i = 1;
}
for (; i < 4; i++) {
const nsBoundingMetrics& bm = bmdata[i];
if (width < bm.width) width = bm.width;
if (lbearing > bm.leftBearing) lbearing = bm.leftBearing;
if (rbearing < bm.rightBearing) rbearing = bm.rightBearing;
}
mBoundingMetrics.width = width;
// When maxWidth, updating ascent and descent indicates that no characters
// larger than this character's minimum size need to be checked as they
// will not be used.
mBoundingMetrics.ascent = bmdata[0].ascent; // not used except with descent for height
mBoundingMetrics.descent = computedSize - mBoundingMetrics.ascent;
mBoundingMetrics.leftBearing = lbearing;
@ -1380,7 +1457,7 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
else {
nscoord ascent = bmdata[0].ascent;
nscoord descent = bmdata[0].descent;
for (i = 1; i < 4; i++) {
for (PRInt32 i = 1; i < 4; i++) {
const nsBoundingMetrics& bm = bmdata[i];
if (ascent < bm.ascent) ascent = bm.ascent;
if (descent < bm.descent) descent = bm.descent;
@ -1391,52 +1468,22 @@ nsMathMLChar::TryParts(nsPresContext* aPresContext,
mBoundingMetrics.leftBearing = 0;
mBoundingMetrics.rightBearing = computedSize;
}
if (maxWidth)
return PR_FALSE; // Continue to check other sizes
// reset
mGlyph = kNullGlyph; // this will tell paint to build by parts
mGlyphTable = aGlyphTable;
mFamily = aFamily;
mChar->mGlyph = kNullGlyph; // this will tell paint to build by parts
mChar->mGlyphTable = aGlyphTable;
mChar->mFamily = aFamily;
return IsSizeOK(aPresContext, computedSize, aTargetSize, aStretchHint);
return IsSizeOK(mPresContext, computedSize, mTargetSize, mStretchHint);
}
struct StretchEnumContext {
StretchEnumContext(nsMathMLChar* aChar,
nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nscoord aTargetSize,
PRUint32 aStretchHint,
const nsAString& aFamilies) :
mChar(aChar),
mPresContext(aPresContext),
mRenderingContext(aRenderingContext),
mTargetSize(aTargetSize),
mStretchHint(aStretchHint),
mFamilies(aFamilies),
mTryVariants(PR_TRUE),
mTryParts(PR_TRUE)
{
}
nsMathMLChar* mChar;
nsPresContext* mPresContext;
nsIRenderingContext& mRenderingContext;
const nscoord mTargetSize;
const PRUint32 mStretchHint;
// Font families to search
const nsAString& mFamilies;
PRBool mTryVariants;
PRBool mTryParts;
nsAutoTArray<nsGlyphTable*,16> mTablesTried;
nsGlyphTable* mGlyphTable; // for this callback
};
// This is only called for glyph table corresponding to a family that exists.
// See if the table has a glyph that matches the container
PRBool
nsMathMLChar::StretchResolverCallback (const nsAString& aFamily, void *aData)
nsMathMLChar::StretchEnumContext::ResolverCallback (const nsAString& aFamily,
void *aData)
{
StretchEnumContext* context = static_cast<StretchEnumContext*>(aData);
nsGlyphTable* glyphTable = context->mGlyphTable;
@ -1451,19 +1498,13 @@ nsMathMLChar::StretchResolverCallback (const nsAString& aFamily, void *aData)
context->mFamilies : aFamily;
if(context->mTryVariants) {
PRBool isOK = context->mChar->
TryVariants(context->mPresContext, context->mRenderingContext,
glyphTable, context->mTargetSize, context->mStretchHint,
family);
PRBool isOK = context->TryVariants(glyphTable, family);
if (isOK)
return PR_FALSE; // no need to continue
}
if(context->mTryParts) {
PRBool isOK = context->mChar->
TryParts(context->mPresContext, context->mRenderingContext,
glyphTable, context->mTargetSize, context->mStretchHint,
family);
PRBool isOK = context->TryParts(glyphTable, family);
if (isOK)
return PR_FALSE; // no need to continue
}
@ -1472,8 +1513,8 @@ nsMathMLChar::StretchResolverCallback (const nsAString& aFamily, void *aData)
// This is called for each family, whether it exists or not
PRBool
nsMathMLChar::StretchEnumCallback(const nsString& aFamily, PRBool aGeneric,
void *aData)
nsMathMLChar::StretchEnumContext::EnumCallback(const nsString& aFamily,
PRBool aGeneric, void *aData)
{
StretchEnumContext* context = static_cast<StretchEnumContext*>(aData);
@ -1488,37 +1529,34 @@ nsMathMLChar::StretchEnumCallback(const nsString& aFamily, PRBool aGeneric,
context->mGlyphTable = glyphTable;
if (aGeneric)
return StretchResolverCallback(aFamily, aData);
return ResolverCallback(aFamily, aData);
PRBool aborted;
gfxPlatform *pf = gfxPlatform::GetPlatform();
nsresult rv =
pf->ResolveFontName(aFamily, StretchResolverCallback, aData, aborted);
pf->ResolveFontName(aFamily, ResolverCallback, aData, aborted);
return NS_SUCCEEDED(rv) && !aborted; // true means continue
}
nsresult
nsMathMLChar::Stretch(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsBoundingMetrics& aContainerSize,
nsBoundingMetrics& aDesiredStretchSize,
PRUint32 aStretchHint)
nsMathMLChar::StretchInternal(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection& aStretchDirection,
const nsBoundingMetrics& aContainerSize,
nsBoundingMetrics& aDesiredStretchSize,
PRUint32 aStretchHint,
// These are currently only used when
// aStretchHint & NS_STRETCH_MAXWIDTH:
float aMaxSize,
PRBool aMaxSizeIsAbsolute)
{
nsresult rv = NS_OK;
nsStretchDirection direction = aStretchDirection;
// if we have been called before, and we didn't actually stretch, our
// direction may have been set to NS_STRETCH_DIRECTION_UNSUPPORTED.
// So first set our direction back to its instrinsic value
nsStretchDirection direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
if (mOperator >= 0) {
// mOperator is initialized in SetData() and remains unchanged
mDirection = nsMathMLOperators::GetStretchyDirectionAt(mOperator);
}
// if no specified direction, attempt to stretch in our preferred direction
if (direction == NS_STRETCH_DIRECTION_DEFAULT) {
direction = mDirection;
direction = nsMathMLOperators::GetStretchyDirectionAt(mOperator);
}
// Set default font and get the default bounding metrics
@ -1530,68 +1568,106 @@ nsMathMLChar::Stretch(nsPresContext* aPresContext,
// Override with specific fonts if applicable for this character
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
nsAutoString families;
if (GetFontExtensionPref(prefBranch, mData[0], eExtension_base,
families)) {
if (GetFontExtensionPref(prefBranch, mData[0], eExtension_base, families)) {
font.name = families;
}
// Don't modify this nsMathMLChar when doing GetMaxWidth()
PRBool maxWidth = (NS_STRETCH_MAXWIDTH & aStretchHint) != 0;
if (!maxWidth) {
// Record the families in case there is no stretch. But don't bother
// storing families when they are just those from the StyleContext.
mFamily = families;
}
else {
// Don't bother storing families when they are just those from the
// StyleContext.
mFamily.Truncate();
}
}
aRenderingContext.SetFont(font, nsnull);
rv = aRenderingContext.GetBoundingMetrics(mData.get(),
PRUint32(mData.Length()),
mBoundingMetrics);
nsresult rv =
aRenderingContext.GetBoundingMetrics(mData.get(), PRUint32(mData.Length()),
aDesiredStretchSize);
if (NS_FAILED(rv)) {
NS_WARNING("GetBoundingMetrics failed");
// ensure that the char later behaves like a normal char
// (will be reset back to its intrinsic value in case of dynamic updates)
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
return rv;
}
// set the default desired metrics in case stretching doesn't happen
aDesiredStretchSize = mBoundingMetrics;
// quick return if there is nothing special about this char
if (!mGlyphTable || (mDirection != direction)) {
// ensure that the char later behaves like a normal char
// (will be reset back to its intrinsic value in case of dynamic updates)
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
return NS_OK;
}
// see if this is a particular largeop or largeopOnly request
PRBool largeop = (NS_STRETCH_LARGEOP & aStretchHint) != 0;
PRBool largeopOnly = (NS_STRETCH_LARGEOP == aStretchHint); // (==, not mask!)
////////////////////////////////////////////////////////////////////////////////////
// 1. Check the common situations where stretching is not actually needed
////////////////////////////////////////////////////////////////////////////////////
nscoord targetSize, charSize;
PRBool isVertical = (direction == NS_STRETCH_DIRECTION_VERTICAL);
if (isVertical) {
charSize = aDesiredStretchSize.ascent + aDesiredStretchSize.descent;
targetSize = aContainerSize.ascent + aContainerSize.descent;
}
else {
charSize = aDesiredStretchSize.width;
targetSize = aContainerSize.width;
}
// if we are not a largeop in display mode, return if size fits
if ((targetSize <= 0) ||
(!largeop && ((isVertical && charSize >= targetSize) ||
IsSizeOK(aPresContext, charSize, targetSize, aStretchHint)))) {
// ensure that the char later behaves like a normal char
// (will be reset back to its intrinsic value in case of dynamic updates)
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
// quick return if there is nothing special about this char
if (!mGlyphTable ||
(aStretchDirection != direction &&
aStretchDirection != NS_STRETCH_DIRECTION_DEFAULT) ||
(aStretchHint & ~NS_STRETCH_MAXWIDTH) == NS_STRETCH_NONE) {
return NS_OK;
}
// if no specified direction, attempt to stretch in our preferred direction
if (aStretchDirection == NS_STRETCH_DIRECTION_DEFAULT) {
aStretchDirection = direction;
}
// see if this is a particular largeop or largeopOnly request
PRBool largeop = (NS_STRETCH_LARGEOP & aStretchHint) != 0;
PRBool stretchy = (NS_STRETCH_VARIABLE_MASK & aStretchHint) != 0;
PRBool largeopOnly = largeop && !stretchy;
PRBool isVertical = (direction == NS_STRETCH_DIRECTION_VERTICAL);
nscoord targetSize =
isVertical ? aContainerSize.ascent + aContainerSize.descent
: aContainerSize.rightBearing - aContainerSize.leftBearing;
if (maxWidth) {
// See if it is only necessary to consider glyphs up to some maximum size.
// Set the current height to the maximum size, and set aStretchHint to
// NS_STRETCH_SMALLER if the size is variable, so that only smaller sizes
// are considered. targetSize from GetMaxWidth() is 0.
if (stretchy) {
// variable size stretch - consider all sizes < maxsize
aStretchHint =
(aStretchHint & ~NS_STRETCH_VARIABLE_MASK) | NS_STRETCH_SMALLER;
}
// Use NS_MATHML_DELIMITER_FACTOR to allow some slightly larger glyphs as
// maxsize is not enforced exactly.
if (aMaxSize == NS_MATHML_OPERATOR_SIZE_INFINITY) {
aDesiredStretchSize.ascent = nscoord_MAX;
aDesiredStretchSize.descent = 0;
}
else {
nscoord height = aDesiredStretchSize.ascent + aDesiredStretchSize.descent;
if (height == 0) {
if (aMaxSizeIsAbsolute) {
aDesiredStretchSize.ascent =
NSToCoordRound(aMaxSize / NS_MATHML_DELIMITER_FACTOR);
aDesiredStretchSize.descent = 0;
}
// else: leave height as 0
}
else {
float scale = aMaxSizeIsAbsolute ? aMaxSize / height : aMaxSize;
scale /= NS_MATHML_DELIMITER_FACTOR;
aDesiredStretchSize.ascent =
NSToCoordRound(scale * aDesiredStretchSize.ascent);
aDesiredStretchSize.descent =
NSToCoordRound(scale * aDesiredStretchSize.descent);
}
}
}
if (!maxWidth && !largeop) {
// Doing Stretch() not GetMaxWidth(),
// and not a largeop in display mode; return if size fits
nscoord charSize =
isVertical ? aDesiredStretchSize.ascent + aDesiredStretchSize.descent
: aDesiredStretchSize.rightBearing - aDesiredStretchSize.leftBearing;
if ((targetSize <= 0) ||
((isVertical && charSize >= targetSize) ||
IsSizeOK(aPresContext, charSize, targetSize, aStretchHint)))
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////////
// 2/3. Search for a glyph or set of part glyphs of appropriate size
////////////////////////////////////////////////////////////////////////////////////
@ -1600,7 +1676,6 @@ nsMathMLChar::Stretch(nsPresContext* aPresContext,
nsAutoString cssFamilies;
cssFamilies = font.name;
mGlyph.font = -1; // will be updated if a better match is found
PRBool done = PR_FALSE;
// See if there are preferred fonts for the variants of this char
@ -1609,10 +1684,11 @@ nsMathMLChar::Stretch(nsPresContext* aPresContext,
font.name = families;
StretchEnumContext enumData(this, aPresContext, aRenderingContext,
targetSize, aStretchHint, font.name);
aStretchDirection, targetSize, aStretchHint,
aDesiredStretchSize, font.name);
enumData.mTryParts = PR_FALSE;
done = ! font.EnumerateFamilies(StretchEnumCallback, &enumData);
done = !font.EnumerateFamilies(StretchEnumContext::EnumCallback, &enumData);
}
// See if there are preferred fonts for the parts of this char
@ -1622,10 +1698,11 @@ nsMathMLChar::Stretch(nsPresContext* aPresContext,
font.name = families;
StretchEnumContext enumData(this, aPresContext, aRenderingContext,
targetSize, aStretchHint, font.name);
aStretchDirection, targetSize, aStretchHint,
aDesiredStretchSize, font.name);
enumData.mTryVariants = PR_FALSE;
done = ! font.EnumerateFamilies(StretchEnumCallback, &enumData);
done = !font.EnumerateFamilies(StretchEnumContext::EnumCallback, &enumData);
}
if (!done) { // normal case
@ -1642,22 +1719,74 @@ nsMathMLChar::Stretch(nsPresContext* aPresContext,
font.name, mData[0], mData[0]&0x00FF);
#endif
StretchEnumContext enumData(this, aPresContext, aRenderingContext,
targetSize, aStretchHint, font.name);
enumData.mTryParts = ! largeopOnly;
aStretchDirection, targetSize, aStretchHint,
aDesiredStretchSize, font.name);
enumData.mTryParts = !largeopOnly;
font.EnumerateFamilies(StretchEnumCallback, &enumData);
font.EnumerateFamilies(StretchEnumContext::EnumCallback, &enumData);
}
if (mGlyph.font == -1) { // nothing happened
// ensure that the char behaves like a normal char
return NS_OK;
}
nsresult
nsMathMLChar::Stretch(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
const nsBoundingMetrics& aContainerSize,
nsBoundingMetrics& aDesiredStretchSize,
PRUint32 aStretchHint)
{
NS_ASSERTION(!(aStretchHint &
~(NS_STRETCH_VARIABLE_MASK | NS_STRETCH_LARGEOP)),
"Unexpected stretch flags");
// This will be updated if a better match than the base character is found
mGlyph.font = -1;
mDirection = aStretchDirection;
nsresult rv =
StretchInternal(aPresContext, aRenderingContext, mDirection,
aContainerSize, aDesiredStretchSize, aStretchHint);
if (mGlyph.font == -1) { // no stretch happened
// ensure that the char later behaves like a normal char
// (will be reset back to its intrinsic value in case of dynamic updates)
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
}
else {
// will stretch
aDesiredStretchSize = mBoundingMetrics;
}
return NS_OK;
// Record the metrics
mBoundingMetrics = aDesiredStretchSize;
return rv;
}
// What happens here is that the StretchInternal algorithm is used but
// modified by passing the NS_STRETCH_MAXWIDTH stretch hint. That causes
// StretchInternal to return horizontal bounding metrics that are the maximum
// that might be returned from a Stretch.
//
// In order to avoid considering widths of some characters in fonts that will
// not be used for any stretch size, StretchInternal sets the initial height
// to infinity and looks for any characters smaller than this height. When a
// character built from parts is considered, (it will be used by Stretch for
// any characters greater than its minimum size, so) the height is set to its
// minimum size, so that only widths of smaller subsequent characters are
// considered.
nscoord
nsMathMLChar::GetMaxWidth(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRUint32 aStretchHint,
float aMaxSize, PRBool aMaxSizeIsAbsolute)
{
nsBoundingMetrics bm;
nsStretchDirection direction = NS_STRETCH_DIRECTION_VERTICAL;
const nsBoundingMetrics container; // zero target size
StretchInternal(aPresContext, aRenderingContext, direction, container,
bm, aStretchHint | NS_STRETCH_MAXWIDTH);
return PR_MAX(bm.width, bm.rightBearing) - PR_MIN(0, bm.leftBearing);
}
nsresult

View File

@ -47,11 +47,21 @@
class nsGlyphTable;
// Hints for Stretch() to indicate criteria for stretching
#define NS_STRETCH_NORMAL 0x00000001 // try to stretch to requested size - DEFAULT
#define NS_STRETCH_NEARER 0x00000002 // stretch very close to requested size
#define NS_STRETCH_SMALLER 0x00000004 // don't stretch more than requested size
#define NS_STRETCH_LARGER 0x00000008 // don't stretch less than requested size
#define NS_STRETCH_LARGEOP 0x00000010 // for a largeop in displaystyle
enum {
// Don't stretch
NS_STRETCH_NONE = 0x00,
// Variable size stretches
NS_STRETCH_VARIABLE_MASK = 0x0F,
NS_STRETCH_NORMAL = 0x01, // try to stretch to requested size
NS_STRETCH_NEARER = 0x02, // stretch very close to requested size
NS_STRETCH_SMALLER = 0x04, // don't stretch more than requested size
NS_STRETCH_LARGER = 0x08, // don't stretch less than requested size
// A largeop in displaystyle
NS_STRETCH_LARGEOP = 0x10,
// Intended for internal use:
// Find the widest metrics that might be returned from a vertical stretch
NS_STRETCH_MAXWIDTH = 0x20
};
// A single glyph in our internal representation is characterized by a 'code@font'
// pair. The 'code' is interpreted as a Unicode point or as the direct glyph index
@ -123,12 +133,12 @@ public:
// @param aContainerSize - IN - suggested size for the stretched char
// @param aDesiredStretchSize - OUT - the size that the char wants
nsresult
Stretch(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
nsBoundingMetrics& aContainerSize,
nsBoundingMetrics& aDesiredStretchSize,
PRUint32 aStretchHint = NS_STRETCH_NORMAL);
Stretch(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection aStretchDirection,
const nsBoundingMetrics& aContainerSize,
nsBoundingMetrics& aDesiredStretchSize,
PRUint32 aStretchHint = NS_STRETCH_NORMAL);
void
SetData(nsPresContext* aPresContext,
@ -175,6 +185,24 @@ public:
}
}
// Get the maximum width that the character might have after a vertical
// Stretch().
//
// @param aStretchHint can be the value that will be passed to Stretch().
// It is used to determine whether the operator is stretchy or a largeop.
// @param aMaxSize is the value of the "maxsize" attribute.
// @param aMaxSizeIsAbsolute indicates whether the aMaxSize is an absolute
// value in app units (PR_TRUE) or a multiplier of the base size (PR_FALSE).
nscoord
GetMaxWidth(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
PRUint32 aStretchHint = NS_STRETCH_NORMAL,
float aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
// Perhaps just nsOperatorFlags aFlags.
// But need DisplayStyle for largeOp,
// or remove the largeop bit from flags.
PRBool aMaxSizeIsAbsolute = PR_FALSE);
// Metrics that _exactly_ enclose the char. The char *must* have *already*
// being stretched before you can call the GetBoundingMetrics() method.
// IMPORTANT: since chars have their own style contexts, and may be rendered
@ -218,28 +246,19 @@ private:
// from the family in the nsStyleContext.
nsString mFamily;
class StretchEnumContext;
friend class StretchEnumContext;
// helper methods
PRBool
TryVariants(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsGlyphTable* aGlyphTable,
nscoord aTargetSize,
PRUint32 aStretchHint,
const nsAString& aFamilies);
PRBool
TryParts(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsGlyphTable* aGlyphTable,
nscoord aTargetSize,
PRUint32 aStretchHint,
const nsAString& aFamilies);
static PRBool
StretchResolverCallback (const nsAString& aFamily, void *aData);
static PRBool
StretchEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData);
nsresult
StretchInternal(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
nsStretchDirection& aStretchDirection,
const nsBoundingMetrics& aContainerSize,
nsBoundingMetrics& aDesiredStretchSize,
PRUint32 aStretchHint,
float aMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY,
PRBool aMaxSizeIsAbsolute = PR_FALSE);
nsresult
ComposeChildren(nsPresContext* aPresContext,

View File

@ -112,17 +112,22 @@ nsMathMLmoFrame::IsFrameInSelection(nsIFrame* aFrame)
return PR_TRUE;
}
PRBool
nsMathMLmoFrame::UseMathMLChar()
{
return (NS_MATHML_OPERATOR_GET_FORM(mFlags) &&
NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) ||
NS_MATHML_OPERATOR_IS_CENTERED(mFlags) ||
NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags);
}
NS_IMETHODIMP
nsMathMLmoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsresult rv = NS_OK;
PRBool useMathMLChar =
(NS_MATHML_OPERATOR_GET_FORM(mFlags) &&
NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) ||
NS_MATHML_OPERATOR_IS_CENTERED(mFlags) ||
NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags);
PRBool useMathMLChar = UseMathMLChar();
if (!useMathMLChar) {
// let the base class do everything
@ -503,7 +508,7 @@ nsMathMLmoFrame::ProcessOperatorData()
mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
// minsize = number [ v-unit | h-unit ] | namedspace
mMinSize = float(NS_UNCONSTRAINEDSIZE);
mMinSize = 0.0;
GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::minsize_,
value);
if (!value.IsEmpty()) {
@ -518,7 +523,7 @@ nsMathMLmoFrame::ProcessOperatorData()
mMinSize = cssValue.GetPercentValue();
else if (eCSSUnit_Null != unit) {
mMinSize = float(CalcLength(presContext, mStyleContext, cssValue));
mFlags |= NS_MATHML_OPERATOR_MINSIZE_EXPLICIT;
mFlags |= NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE;
}
if ((eCSSUnit_Number == unit) || (eCSSUnit_Percent == unit)) {
@ -529,7 +534,7 @@ nsMathMLmoFrame::ProcessOperatorData()
if (ParseNumericValue(value, cssValue)) {
if (cssValue.IsLengthUnit()) {
mMinSize *= float(CalcLength(presContext, mStyleContext, cssValue));
mFlags |= NS_MATHML_OPERATOR_MINSIZE_EXPLICIT;
mFlags |= NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE;
}
}
}
@ -538,7 +543,7 @@ nsMathMLmoFrame::ProcessOperatorData()
}
// maxsize = number [ v-unit | h-unit ] | namedspace | infinity
mMaxSize = float(NS_UNCONSTRAINEDSIZE);
mMaxSize = NS_MATHML_OPERATOR_SIZE_INFINITY;
GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::maxsize_,
value);
if (!value.IsEmpty()) {
@ -553,7 +558,7 @@ nsMathMLmoFrame::ProcessOperatorData()
mMaxSize = cssValue.GetPercentValue();
else if (eCSSUnit_Null != unit) {
mMaxSize = float(CalcLength(presContext, mStyleContext, cssValue));
mFlags |= NS_MATHML_OPERATOR_MAXSIZE_EXPLICIT;
mFlags |= NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE;
}
if ((eCSSUnit_Number == unit) || (eCSSUnit_Percent == unit)) {
@ -564,7 +569,7 @@ nsMathMLmoFrame::ProcessOperatorData()
if (ParseNumericValue(value, cssValue)) {
if (cssValue.IsLengthUnit()) {
mMaxSize *= float(CalcLength(presContext, mStyleContext, cssValue));
mFlags |= NS_MATHML_OPERATOR_MAXSIZE_EXPLICIT;
mFlags |= NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE;
}
}
}
@ -573,6 +578,41 @@ nsMathMLmoFrame::ProcessOperatorData()
}
}
static PRUint32
GetStretchHint(nsOperatorFlags aFlags, nsPresentationData aPresentationData,
PRBool aIsVertical)
{
PRUint32 stretchHint = NS_STRETCH_NONE;
// See if it is okay to stretch,
// starting from what the Operator Dictionary said
if (NS_MATHML_OPERATOR_IS_MUTABLE(aFlags)) {
// set the largeop or largeopOnly flags to suitably cover all the
// 8 possible cases depending on whether displaystyle, largeop,
// stretchy are true or false (see bug 69325).
// . largeopOnly is taken if largeop=true and stretchy=false
// . largeop is taken if largeop=true and stretchy=true
if (NS_MATHML_IS_DISPLAYSTYLE(aPresentationData.flags) &&
NS_MATHML_OPERATOR_IS_LARGEOP(aFlags)) {
stretchHint = NS_STRETCH_LARGEOP; // (largeopOnly, not mask!)
if (NS_MATHML_OPERATOR_IS_STRETCHY(aFlags)) {
stretchHint |= NS_STRETCH_NEARER | NS_STRETCH_LARGER;
}
}
else if(NS_MATHML_OPERATOR_IS_STRETCHY(aFlags)) {
if (aIsVertical) {
// TeX hint. Can impact some sloppy markups missing <mrow></mrow>
stretchHint = NS_STRETCH_NEARER;
}
else {
stretchHint = NS_STRETCH_NORMAL;
}
}
// else if the stretchy and largeop attributes have been disabled,
// the operator is not mutable
}
return stretchHint;
}
// NOTE: aDesiredStretchSize is an IN/OUT parameter
// On input - it contains our current size
// On output - the same size or the new size that we want
@ -606,11 +646,7 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
// Operators that are stretchy, or those that are to be centered
// to cater for fonts that are not math-aware, are handled by the MathMLChar
// ('form' is reset if stretch fails -- i.e., we don't bother to stretch next time)
PRBool useMathMLChar =
(NS_MATHML_OPERATOR_GET_FORM(mFlags) &&
NS_MATHML_OPERATOR_IS_MUTABLE(mFlags)) ||
NS_MATHML_OPERATOR_IS_CENTERED(mFlags) ||
NS_MATHML_OPERATOR_IS_INVISIBLE(mFlags);
PRBool useMathMLChar = UseMathMLChar();
nsBoundingMetrics charSize;
nsBoundingMetrics container = aDesiredStretchSize.mBoundingMetrics;
@ -618,44 +654,19 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
if (useMathMLChar) {
nsBoundingMetrics initialSize = aDesiredStretchSize.mBoundingMetrics;
PRUint32 stretchHint = NS_STRETCH_NORMAL;
if (((aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) ||
(aStretchDirection == NS_STRETCH_DIRECTION_DEFAULT)) &&
(mEmbellishData.direction == NS_STRETCH_DIRECTION_VERTICAL)) {
isVertical = PR_TRUE;
}
// see if it is okay to stretch, starting from what the Operator Dictionary said
PRBool isMutable = NS_MATHML_OPERATOR_IS_MUTABLE(mFlags);
// if the stretchy and largeop attributes have been disabled,
// the operator is not mutable
if (!NS_MATHML_OPERATOR_IS_STRETCHY(mFlags) &&
!NS_MATHML_OPERATOR_IS_LARGEOP(mFlags))
isMutable = PR_FALSE;
PRUint32 stretchHint =
GetStretchHint(mFlags, mPresentationData, isVertical);
if (isMutable) {
if (stretchHint != NS_STRETCH_NONE) {
container = aContainerSize;
if (((aStretchDirection == NS_STRETCH_DIRECTION_VERTICAL) ||
(aStretchDirection == NS_STRETCH_DIRECTION_DEFAULT)) &&
(mEmbellishData.direction == NS_STRETCH_DIRECTION_VERTICAL))
{
isVertical = PR_TRUE;
}
// set the largeop or largeopOnly flags to suitably cover all the
// 8 possible cases depending on whether displaystyle, largeop,
// stretchy are true or false (see bug 69325).
// . largeopOnly is taken if largeop=true and stretchy=false
// . largeop is taken if largeop=true and stretchy=true
if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) &&
NS_MATHML_OPERATOR_IS_LARGEOP(mFlags)) {
stretchHint = NS_STRETCH_LARGEOP; // (largeopOnly, not mask!)
if (NS_MATHML_OPERATOR_IS_STRETCHY(mFlags)) {
stretchHint |= NS_STRETCH_NEARER | NS_STRETCH_LARGER;
}
}
else if (isVertical) {
// TeX hint. Can impact some sloppy markups missing <mrow></mrow>
stretchHint = NS_STRETCH_NEARER;
}
// some adjustments if the operator is symmetric and vertical
if (isVertical && NS_MATHML_OPERATOR_IS_SYMMETRIC(mFlags)) {
@ -674,10 +685,10 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
// check for user-desired min-max size
if (mMaxSize != float(NS_UNCONSTRAINEDSIZE) && mMaxSize > 0.0f) {
if (mMaxSize != NS_MATHML_OPERATOR_SIZE_INFINITY && mMaxSize > 0.0f) {
// if we are here, there is a user defined maxsize ...
//XXX Set stretchHint = NS_STRETCH_NORMAL? to honor the maxsize as close as possible?
if (NS_MATHML_OPERATOR_MAXSIZE_IS_EXPLICIT(mFlags)) {
if (NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(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);
@ -707,7 +718,7 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
}
}
if (mMinSize != float(NS_UNCONSTRAINEDSIZE) && mMinSize > 0.0f) {
if (mMinSize > 0.0f) {
// if we are here, there is a user defined minsize ...
// always allow the char to stretch in its natural direction,
// even if it is different from the caller's direction
@ -718,7 +729,7 @@ nsMathMLmoFrame::Stretch(nsIRenderingContext& aRenderingContext,
// we should not use the caller's container size either
container = initialSize;
}
if (NS_MATHML_OPERATOR_MINSIZE_IS_EXPLICIT(mFlags)) {
if (NS_MATHML_OPERATOR_MINSIZE_IS_ABSOLUTE(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);
@ -985,9 +996,17 @@ nsMathMLmoFrame::MarkIntrinsicWidthsDirty()
nsMathMLmoFrame::GetIntrinsicWidth(nsIRenderingContext *aRenderingContext)
{
ProcessOperatorData();
// TODO: need to ask mMathMLChar for its maximum width if useMathMLChar
// (Bug 363240)
nscoord width = nsMathMLTokenFrame::GetIntrinsicWidth(aRenderingContext);
nscoord width;
if (UseMathMLChar()) {
PRUint32 stretchHint = GetStretchHint(mFlags, mPresentationData, PR_TRUE);
width = mMathMLChar.
GetMaxWidth(PresContext(), *aRenderingContext,
stretchHint, mMaxSize,
NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(mFlags));
}
else {
width = nsMathMLTokenFrame::GetIntrinsicWidth(aRenderingContext);
}
// leftSpace and rightSpace are actually applied to the outermost
// embellished container but for determining total intrinsic width it should

View File

@ -105,6 +105,8 @@ protected:
float mMinSize;
float mMaxSize;
PRBool UseMathMLChar();
// overload the base method so that we can setup our nsMathMLChar
virtual void ProcessTextData();

View File

@ -40,45 +40,49 @@
#include "nsCoord.h"
enum nsStretchDirection {
NS_STRETCH_DIRECTION_UNSUPPORTED = -1,
NS_STRETCH_DIRECTION_DEFAULT = 0,
NS_STRETCH_DIRECTION_HORIZONTAL = 1,
NS_STRETCH_DIRECTION_VERTICAL = 2
};
typedef PRUint32 nsOperatorFlags;
typedef PRInt32 nsStretchDirection;
enum {
// define the bits used to handle the operator
NS_MATHML_OPERATOR_MUTABLE = 1<<30,
NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR = 1<<29,
NS_MATHML_OPERATOR_EMBELLISH_ISOLATED = 1<<28,
NS_MATHML_OPERATOR_CENTERED = 1<<27,
NS_MATHML_OPERATOR_INVISIBLE = 1<<26,
#define NS_STRETCH_DIRECTION_UNSUPPORTED -1
#define NS_STRETCH_DIRECTION_DEFAULT 0
#define NS_STRETCH_DIRECTION_HORIZONTAL 1
#define NS_STRETCH_DIRECTION_VERTICAL 2
// define the bits used in the Operator Dictionary
// define the bits used to handle the operator
// the very last two bits tell us the form
NS_MATHML_OPERATOR_FORM = 0x3,
NS_MATHML_OPERATOR_FORM_INFIX = 1,
NS_MATHML_OPERATOR_FORM_PREFIX = 2,
NS_MATHML_OPERATOR_FORM_POSTFIX = 3,
// the next 2 bits tell us the stretchiness
NS_MATHML_OPERATOR_STRETCHY = 0xC,
NS_MATHML_OPERATOR_STRETCHY_VERT = 1<<2,
NS_MATHML_OPERATOR_STRETCHY_HORIZ = 1<<3,
// other bits used in the Operator Dictionary
NS_MATHML_OPERATOR_FENCE = 1<<4,
NS_MATHML_OPERATOR_ACCENT = 1<<5,
NS_MATHML_OPERATOR_LARGEOP = 1<<6,
NS_MATHML_OPERATOR_SEPARATOR = 1<<7,
NS_MATHML_OPERATOR_MOVABLELIMITS = 1<<8,
NS_MATHML_OPERATOR_SYMMETRIC = 1<<9,
#define NS_MATHML_OPERATOR_MUTABLE (1<<31)
#define NS_MATHML_OPERATOR_EMBELLISH_ANCESTOR (1<<30)
#define NS_MATHML_OPERATOR_EMBELLISH_ISOLATED (1<<29)
#define NS_MATHML_OPERATOR_CENTERED (1<<28)
#define NS_MATHML_OPERATOR_INVISIBLE (1<<27)
// define the bits used in the Operator Dictionary
#define NS_MATHML_OPERATOR_FORM 0x3 // the very last two bits tell us the form
#define NS_MATHML_OPERATOR_FORM_INFIX 1
#define NS_MATHML_OPERATOR_FORM_PREFIX 2
#define NS_MATHML_OPERATOR_FORM_POSTFIX 3
#define NS_MATHML_OPERATOR_STRETCHY 0xC // the 2 penultimate last bits are used
#define NS_MATHML_OPERATOR_STRETCHY_VERT (1<<2)
#define NS_MATHML_OPERATOR_STRETCHY_HORIZ (1<<3)
#define NS_MATHML_OPERATOR_FENCE (1<<4)
#define NS_MATHML_OPERATOR_ACCENT (1<<5)
#define NS_MATHML_OPERATOR_LARGEOP (1<<6)
#define NS_MATHML_OPERATOR_SEPARATOR (1<<7)
#define NS_MATHML_OPERATOR_MOVABLELIMITS (1<<8)
#define NS_MATHML_OPERATOR_SYMMETRIC (1<<9)
// Additional bits not stored in the dictionary
#define NS_MATHML_OPERATOR_MINSIZE_EXPLICIT (1<<10)
#define NS_MATHML_OPERATOR_MAXSIZE_EXPLICIT (1<<11)
#define NS_MATHML_OPERATOR_LEFTSPACE_ATTR (1<<12)
#define NS_MATHML_OPERATOR_RIGHTSPACE_ATTR (1<<13)
// Additional bits not stored in the dictionary
NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE = 1<<10,
NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE = 1<<11,
NS_MATHML_OPERATOR_LEFTSPACE_ATTR = 1<<12,
NS_MATHML_OPERATOR_RIGHTSPACE_ATTR = 1<<13
};
#define NS_MATHML_OPERATOR_SIZE_INFINITY NS_IEEEPositiveInfinity()
class nsMathMLOperators {
public:
@ -210,11 +214,11 @@ public:
#define NS_MATHML_OPERATOR_IS_SYMMETRIC(_flags) \
(NS_MATHML_OPERATOR_SYMMETRIC == ((_flags) & NS_MATHML_OPERATOR_SYMMETRIC))
#define NS_MATHML_OPERATOR_MINSIZE_IS_EXPLICIT(_flags) \
(NS_MATHML_OPERATOR_MINSIZE_EXPLICIT == ((_flags) & NS_MATHML_OPERATOR_MINSIZE_EXPLICIT))
#define NS_MATHML_OPERATOR_MINSIZE_IS_ABSOLUTE(_flags) \
(NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE == ((_flags) & NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE))
#define NS_MATHML_OPERATOR_MAXSIZE_IS_EXPLICIT(_flags) \
(NS_MATHML_OPERATOR_MAXSIZE_EXPLICIT == ((_flags) & NS_MATHML_OPERATOR_MAXSIZE_EXPLICIT))
#define NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(_flags) \
(NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE == ((_flags) & NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE))
#define NS_MATHML_OPERATOR_HAS_LEFTSPACE_ATTR(_flags) \
(NS_MATHML_OPERATOR_LEFTSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_LEFTSPACE_ATTR))