diff --git a/layout/mathml/base/src/nsMathMLChar.cpp b/layout/mathml/base/src/nsMathMLChar.cpp index ffe4c16724f0..d38a49d8e76b 100644 --- a/layout/mathml/base/src/nsMathMLChar.cpp +++ b/layout/mathml/base/src/nsMathMLChar.cpp @@ -303,16 +303,16 @@ nsGlyphTable::DrawGlyph(nsIRenderingContext& aRenderingContext, } } -// Structure used to walk/try all the the glyph tables that we have. +// Class used to walk/try all the the glyph tables that we have. // Glyph tables are singly linked together through their next-table pointer. // ----------------------------------------------------------------------------------- -struct nsGlyphTableList { - +class nsGlyphTableList { +public: nsGlyphTableList(void) { - mFirstTable = nsnull; - mIsInitialized = PR_FALSE; + mFirstTable = nsnull; + mIsInitialized = PR_FALSE; } PRBool IsInitialized(void) @@ -335,7 +335,11 @@ struct nsGlyphTableList { nsGlyphTable* FindTableFor(nsMathMLCharEnum aCharEnum); - // ---- + // Check for existence of a glyph table. + PRBool + Has(nsGlyphTable* aGlyphTable); + +private: nsGlyphTable* mFirstTable; PRBool mIsInitialized; }; @@ -395,6 +399,20 @@ nsGlyphTableList::FindTableFor(nsMathMLCharEnum aCharEnum) return nsnull; } +PRBool +nsGlyphTableList::Has(nsGlyphTable* aGlyphTable) +{ + NS_ASSERTION(mIsInitialized, "glyph table list must be initialized first"); + nsGlyphTable* glyphTable = mFirstTable; + while (glyphTable) { + if (glyphTable == aGlyphTable) { + return PR_TRUE; + } + glyphTable = glyphTable->GetNextTable(); + } + return PR_FALSE; +} + // ----------------------------------------------------------------------------------- // Here is the global list of glyph tables that we will be using ... nsGlyphTableList gGlyphTableList; @@ -576,8 +594,27 @@ nsMathMLChar::SetData(nsIPresContext* aPresContext, { if (!gGlyphTableList.IsInitialized()) { gGlyphTableList.Init(aPresContext, gAllGlyphTables); - for (PRInt32 i = 0; i < eMathMLChar_COUNT; i++) + for (PRInt32 i = 0; i < eMathMLChar_COUNT; i++) { gCharInfo[i].mGlyphTable = &gGlyphTableUNDEFINED; + } + // let some particular chars have their preferred extension tables + if (gGlyphTableList.Has(&gGlyphTableMTExtra)) { + gCharInfo[eMathMLChar_OverCurlyBracket].mGlyphTable = &gGlyphTableMTExtra; + gCharInfo[eMathMLChar_UnderCurlyBracket].mGlyphTable = &gGlyphTableMTExtra; + } +#ifdef NS_DEBUG + // sanity check + for (PRInt32 j = 0; j < eMathMLChar_COUNT; j++) { + PRUnichar ci = gCharInfo[i].mUnicode; + for (PRInt32 k = 0; k < eMathMLChar_COUNT; k++) { + // hitting this assertion? + // check nsMathMLCharList to ensure that the same Unicode point + // is not associated to different enums + PRUnichar ck = gCharInfo[k].mUnicode; + NS_ASSERTION(!(ci == ck && i != k), "Duplicate Unicode point found"); + } + } +#endif } mData = aData; // some assumptions until proven otherwise! @@ -604,8 +641,8 @@ nsMathMLChar::SetData(nsIPresContext* aPresContext, mEnum = eMathMLChar_DONT_STRETCH; } #ifdef NS_DEBUG - // hitting this assertion? - // check nsMathMLCharList to ensure that enum and Unicode (of size0) match in MATHML_CHAR(index, enum, ...) + // hitting this assertion? + // check nsMathMLCharList to ensure that enum and Unicode (of size0) match in MATHML_CHAR(index, enum, ...) else NS_ASSERTION(mGlyphTable->Has(nsGlyphCode(mData[0])), "Something is wrong somewhere"); #endif } @@ -624,8 +661,27 @@ nsMathMLChar::SetEnum(nsIPresContext* aPresContext, NS_ASSERTION(aEnum < eMathMLChar_COUNT, "Something is wrong somewhere"); if (!gGlyphTableList.IsInitialized()) { gGlyphTableList.Init(aPresContext, gAllGlyphTables); - for (PRInt32 i = 0; i < eMathMLChar_COUNT; i++) + for (PRInt32 i = 0; i < eMathMLChar_COUNT; i++) { gCharInfo[i].mGlyphTable = &gGlyphTableUNDEFINED; + } + // let some particular chars have their preferred extension tables + if (gGlyphTableList.Has(&gGlyphTableMTExtra)) { + gCharInfo[eMathMLChar_OverCurlyBracket].mGlyphTable = &gGlyphTableMTExtra; + gCharInfo[eMathMLChar_UnderCurlyBracket].mGlyphTable = &gGlyphTableMTExtra; + } +#ifdef NS_DEBUG + // sanity check + for (PRInt32 j = 0; j < eMathMLChar_COUNT; j++) { + PRUnichar ci = gCharInfo[i].mUnicode; + for (PRInt32 k = 0; k < eMathMLChar_COUNT; k++) { + // hitting this assertion? + // check nsMathMLCharList to ensure that the same Unicode point + // is not associated to different enums + PRUnichar ck = gCharInfo[k].mUnicode; + NS_ASSERTION(!(ci == ck && i != k), "Duplicate Unicode point found"); + } + } +#endif } mEnum = aEnum; // some assumptions until proven otherwise! @@ -647,6 +703,8 @@ nsMathMLChar::SetEnum(nsIPresContext* aPresContext, mEnum = eMathMLChar_DONT_STRETCH; } #ifdef NS_DEBUG + // hitting this assertion? + // check nsMathMLCharList to ensure that enum and Unicode (of size0) match in MATHML_CHAR(index, enum, ...) else NS_ASSERTION(mGlyphTable->Has(nsGlyphCode(mData[0])), "Something is wrong somewhere"); #endif } @@ -659,7 +717,7 @@ nsMathMLChar::SetEnum(nsIPresContext* aPresContext, @param aContainerSize - suggested size for the stretched char @param aDesiredStretchSize - IN/OUT parameter. On input our current size or zero if current size is unknown, on output - the size after stretching. If not stretching is done, and the + the size after stretching. If no stretching is done, and the input was zero, the output will simply give the default size. How it works? @@ -716,9 +774,9 @@ IsSizeBetter(nscoord a, nscoord olda, nscoord b, PRInt32 aHint) if (aHint == NS_STRETCH_NORMAL) return PR_TRUE; else if (aHint == NS_STRETCH_SMALLER) - return PRBool(a <= b); + return PRBool(a <= olda); else if (aHint == NS_STRETCH_LARGER) - return PRBool(a >= b); + return PRBool(a >= olda); } return PR_FALSE; } @@ -727,6 +785,7 @@ static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData) { nsAutoString* familyList = (nsAutoString*)aData; + // XXX unreliable if aFamily is a substring of another family already in the list if (familyList->Find(aFamily, PR_TRUE) == kNotFound) { familyList->Append(','); // XXX could enclose in quotes if weird font problems develop @@ -944,7 +1003,19 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, // current glyph table is the one with the smallest glue, update the cache... gCharInfo[mEnum].mGlyphTable = glyphTable; lengthGlue = length; +#ifdef NOISY_SEARCH + char str[50]; + fontName.ToCString(str, sizeof(str)); + printf(" %s glue:%d Current best\n", str, lengthGlue); +#endif } +#ifdef NOISY_SEARCH + else { + char str[50]; + fontName.ToCString(str, sizeof(str)); + printf(" %s glue:%d Rejected!\n", str, length); + } +#endif } } glyphTable = glyphTable->GetNextTable(); @@ -954,7 +1025,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, gCharInfo[mEnum].mGlyphTable->GetFontName(fontName); char str[50]; fontName.ToCString(str, sizeof(str)); - printf(" Found %s font in the global list\n", str); + printf(" Found %s in the global list\n", str); } #endif } @@ -963,7 +1034,7 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, gCharInfo[mEnum].mGlyphTable->GetFontName(fontName); char str[50]; fontName.ToCString(str, sizeof(str)); - printf(" Found %s font in the cache\n", str); + printf(" Found %s in the cache\n", str); } else { printf(" no font found\n"); @@ -1010,8 +1081,8 @@ nsMathMLChar::Stretch(nsIPresContext* aPresContext, } // refine the flexibility depending on whether some parts are no there - if ((chdata[1] == chdata[0]) || // mid == top (or left) - (chdata[1] == chdata[2]) || // mid == bot (or right) + if ((chdata[1] == chdata[0]) || // mid == top (or mid == left) + (chdata[1] == chdata[2]) || // mid == bot (or mid == right) (chdata[1] == chdata[3])) // mid == glue { flex[0] = 0.5f; @@ -1189,9 +1260,8 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext, nsRect aRect) { nsresult rv = NS_OK; - nscoord dx = aRect.x; - nscoord dy = aRect.y; nsRect clipRect; + nscoord dx, dy; float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); @@ -1218,6 +1288,7 @@ nsMathMLChar::PaintVertically(nsIPresContext* aPresContext, chdata[i] = ch; bmdata[i] = bm; } + dx = aRect.x; for (i = 0; i < 3; i++) { ch = chdata[i]; bm = bmdata[i]; @@ -1307,12 +1378,7 @@ nsMathMLChar::PaintHorizontally(nsIPresContext* aPresContext, { nsresult rv = NS_OK; nsRect clipRect; - - nscoord dx = aRect.x; - nscoord dy = aRect.y; - // place the parts such that the operator as a whole is centered -// nscoord dx = aRect.x + (aRect.width - mBoundingMetrics.width)/2; -// nscoord dy = aRect.y - (aFontAscent - mBoundingMetrics.ascent); + nscoord dx, dy; float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); @@ -1370,11 +1436,9 @@ nsMathMLChar::PaintHorizontally(nsIPresContext* aPresContext, aRenderingContext.DrawRect(nsRect(start[i], aRect.y, end[i]-start[i], aRect.height+30*(i+1))); #endif dx = offset[i]; -// nscoord top = aRect.y; /*PR_MIN(dy, dy + aFontAscent - bm.ascent);*/ - nscoord top = aRect.y; - if (i==0) clipRect = nsRect(dx, top, aRect.width, aRect.height); - else if (i==1) clipRect = nsRect(end[0], top, start[2]-end[0], aRect.height); - else if (i==2) clipRect = nsRect(start[2], top, end[2]-start[2], aRect.height); + if (i==0) clipRect = nsRect(dx, aRect.y, aRect.width, aRect.height); + else if (i==1) clipRect = nsRect(end[0], aRect.y, start[2]-end[0], aRect.height); + else if (i==2) clipRect = nsRect(start[2], aRect.y, end[2]-start[2], aRect.height); if (!clipRect.IsEmpty()) { clipRect.Inflate(onePixel, onePixel); @@ -1388,9 +1452,7 @@ nsMathMLChar::PaintHorizontally(nsIPresContext* aPresContext, for (i = 0; i < 2; i++) { PRInt32 count = 0; dx = offset[i]; - nscoord top = aRect.y; -// nscoord top = PR_MIN(dy, dy + aFontAscent - bm.ascent); - clipRect = nsRect(end[i], top, start[i+1]-end[i], aRect.height); + clipRect = nsRect(end[i], aRect.y, start[i+1]-end[i], aRect.height); clipRect.Inflate(onePixel, onePixel); #ifdef SHOW_BORDERS // rectangles in-between that are to be filled diff --git a/layout/mathml/base/src/nsMathMLCharList.h b/layout/mathml/base/src/nsMathMLCharList.h index fa0ba2c8b75f..550fc391cd91 100644 --- a/layout/mathml/base/src/nsMathMLCharList.h +++ b/layout/mathml/base/src/nsMathMLCharList.h @@ -100,7 +100,7 @@ MATHML_CHAR(LeftSquareBracket, '[' , STRETCH_VERTICAL) MATHML_CHAR(RightSquareBracket, ']' , STRETCH_VERTICAL) MATHML_CHAR(LeftCurlyBracket, '{' , STRETCH_VERTICAL) MATHML_CHAR(RightCurlyBracket, '}' , STRETCH_VERTICAL) -MATHML_CHAR(VerticalBar, 0x007C, STRETCH_VERTICAL) // '|' +MATHML_CHAR(VertBar, 0x007C, STRETCH_VERTICAL) // '|' MATHML_CHAR(Integral, 0x222B, STRETCH_VERTICAL) MATHML_CHAR(DownArrow, 0x2193, STRETCH_VERTICAL) MATHML_CHAR(UpArrow, 0x2191, STRETCH_VERTICAL) @@ -123,7 +123,6 @@ MATHML_CHAR(RightFloor, 0x230B, STRETCH_VERTICAL) MATHML_CHAR(HorizontalLine, 0xE859, STRETCH_HORIZONTAL) MATHML_CHAR(VerticalLine, 0xE85A, STRETCH_VERTICAL) MATHML_CHAR(VerticalSeparator, 0xE85C, STRETCH_VERTICAL) -MATHML_CHAR(Implies, 0x21D2, STRETCH_HORIZONTAL) MATHML_CHAR(And, 0x2227, STRETCH_HORIZONTAL) MATHML_CHAR(Or, 0x2228, STRETCH_HORIZONTAL) MATHML_CHAR(DoubleLeftArrow, 0x21D0, STRETCH_HORIZONTAL) @@ -221,13 +220,11 @@ MATHML_CHAR(Tilde, 0x223C, STRETCH_HORIZONTAL) //UnionMultiply (UnionPlus?), 0x228E, STRETCH_VERTICAL, -// Oversight? \parallel (&DoubleVerticalBar, 0x2225) is not stretchy in -// the REC operator dictionary... - - // Extra stretchy operators that are not in the MathML REC Operator Dictionary // ----------------------------------------------------------------------------------- // XXX For these extra to work, they must also be added in nsMathMLOperators +MATHML_CHAR(VerticalBar, 0x2223, STRETCH_VERTICAL) +MATHML_CHAR(DoubleVerticalBar, 0x2225, STRETCH_VERTICAL) MATHML_CHAR(RightArrowAccent, 0x20D7, STRETCH_HORIZONTAL) MATHML_CHAR(LeftArrowAccent, 0x20D6, STRETCH_HORIZONTAL) MATHML_CHAR(LeftRightArrowAccent, 0x20E1, STRETCH_HORIZONTAL) @@ -235,6 +232,12 @@ MATHML_CHAR(RightHarpoonAccent, 0x20D1, STRETCH_HORIZONTAL) MATHML_CHAR(LeftHarpoonAccent, 0x20D0, STRETCH_HORIZONTAL) +// Duplicate stretchy chars (i.e., with same Unicode points) that are in the +// MathML REC Operator Dictionary shouldn't be added to the list, otherwise +// they get different enums and these play havoc with the setup +// ----------------------------------------------------------------------------------- +// These should not be added to the list +//MATHML_CHAR(Implies, 0x21D2, STRETCH_HORIZONTAL), see DoubleRightArrow #undef STRETCH_UNSUPPORTED @@ -261,7 +264,7 @@ MATHML_CHAR(60, LeftArrow, 0x2190 _ 0x0000 _ 0x0000 _ 0xF8E7, 0x2190) MATHML_CHAR(66, RightArrow, 0x0000 _ 0x0000 _ 0x2192 _ 0xF8E7, 0x2192) MATHML_CHAR(72, LeftRightArrow, 0x2190 _ 0x0000 _ 0x2192 _ 0xF8E7, 0x2194) MATHML_CHAR(78, OverBar, 0x0000 _ 0x0000 _ 0x0000 _ 0x00AF, 0x00AF) -MATHML_CHAR(84, VerticalBar, 0x0000 _ 0x0000 _ 0x0000 _ 0x007C, 0x007C) +MATHML_CHAR(84, VertBar, 0x0000 _ 0x0000 _ 0x0000 _ 0x007C, 0x007C) #endif // defined(WANT_SYMBOL_DATA) // Data for strecthy chars that are supported by the MT Extra font ------------------- @@ -269,11 +272,12 @@ MATHML_CHAR(84, VerticalBar, 0x0000 _ 0x0000 _ 0x0000 _ 0x007C, 0x007C) #if defined(WANT_MTEXTRA_DATA)//[top/left][middle][bot/right][glue] [size0 ... size{N-1}] MATHML_CHAR( 0, UnderCurlyBracket, 0xEC00 _ 0xEC01 _ 0xEC02 _ 0xEC03, 0xF613) MATHML_CHAR( 6, OverCurlyBracket, 0xEC04 _ 0xEC05 _ 0xEC06 _ 0xEC03, 0xF612) -MATHML_CHAR(12, LeftArrowAccent, 0x20D6 _ 0x0000 _ 0x0000 _ 0xEB00, 0x20D6) -MATHML_CHAR(18, RightArrowAccent, 0x0000 _ 0x0000 _ 0x20D7 _ 0xEB00, 0x20D7) -MATHML_CHAR(24, LeftRightArrowAccent,0x20D6 _ 0x0000 _ 0x20D7 _ 0xEB00, 0x20E1) -MATHML_CHAR(30, LeftHarpoonAccent, 0x20D0 _ 0x0000 _ 0x0000 _ 0xEB00, 0x20D0) -MATHML_CHAR(36, RightHarpoonAccent, 0x0000 _ 0x0000 _ 0x20D1 _ 0xEB00, 0x20D1) +//disable for now as they appear too small and don't align properly at default font-size +//MATHML_CHAR(12, LeftArrowAccent, 0x20D6 _ 0x0000 _ 0x0000 _ 0xEB00, 0x20D6) +//MATHML_CHAR(18, RightArrowAccent, 0x0000 _ 0x0000 _ 0x20D7 _ 0xEB00, 0x20D7) +//MATHML_CHAR(24, LeftRightArrowAccent,0x20D6 _ 0x0000 _ 0x20D7 _ 0xEB00, 0x20E1) +//MATHML_CHAR(30, LeftHarpoonAccent, 0x20D0 _ 0x0000 _ 0x0000 _ 0xEB00, 0x20D0) +//MATHML_CHAR(36, RightHarpoonAccent, 0x0000 _ 0x0000 _ 0x20D1 _ 0xEB00, 0x20D1) #endif // defined(WANT_MTEXTRA_DATA) // Data for strecthy chars that are supported by TeX's CMSY font --------------------- @@ -287,6 +291,8 @@ MATHML_CHAR(18, DoubleLeftRightArrow,0x21D0 _ 0x0000 _ 0x21D2 _ '=', 0x21D4) MATHML_CHAR(24, DoubleLongLeftArrow, 0x21D0 _ 0x0000 _ 0x0000 _ '=', 0xE200) MATHML_CHAR(30, DoubleLongRightArrow,0x0000 _ 0x0000 _ 0x21D2 _ '=', 0xE204) MATHML_CHAR(36, DoubleLongLeftRightArrow, 0x21D0 _ 0x0000 _ 0x21D2 _ '=', 0xE202) +MATHML_CHAR(42, VerticalBar, 0x0000 _ 0x0000 _ 0x0000 _ 0x2223, 0x2223) +MATHML_CHAR(48, DoubleVerticalBar, 0x0000 _ 0x0000 _ 0x0000 _ 0x2225, 0x2225) #endif // defined(WANT_CMSY_DATA) // Data for strecthy chars that are supported by TeX's CMEX font ---------------------