support drawing non-BMP characters for stretchy operators (bug 407439). r=karlt

--HG--
extra : rebase_source : 8a0351a8a0b45de4e783050608e513582b8a345c
This commit is contained in:
Frédéric Wang 2011-06-22 11:49:11 -04:00
Родитель bdf202b283
Коммит 8beebf2153
2 изменённых файлов: 43 добавлений и 27 удалений

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

@ -74,7 +74,7 @@ using namespace mozilla;
// -----------------------------------------------------------------------------------
static const PRUnichar kSpaceCh = PRUnichar(' ');
static const nsGlyphCode kNullGlyph = {0, 0};
static const nsGlyphCode kNullGlyph = {{0, 0}, 0};
typedef enum {eExtension_base, eExtension_variants, eExtension_parts}
nsMathfontPrefExtension;
@ -248,8 +248,8 @@ private:
// excludes the '@' symbol and explicitly inserts all optional '0' that indicates
// the primary font identifier. Specifically therefore, the k-th glyph is
// characterized by :
// 1) mGlyphCache[2*k] : its Unicode point (or glyph index -- depending on mType),
// 2) mGlyphCache[2*k+1] : the numeric identifier of the font where it comes from.
// 1) mGlyphCache[3*k],mGlyphCache[3*k+1] : its Unicode point (or glyph index -- depending on mType),
// 2) mGlyphCache[3*k+2] : the numeric identifier of the font where it comes from.
// A font identifier of '0' means the default primary font associated to this
// table. Other digits map to the "external" fonts that may have been specified
// in the MathFont Property File.
@ -311,7 +311,7 @@ nsGlyphTable::ElementAt(nsPresContext* aPresContext, nsMathMLChar* aChar, PRUint
// external font '1', the property line looks like \uNNNN = \uNNNN\uNNNN@1\uNNNN.
// This is where mGlyphCache is pre-processed to explicitly store all glyph codes
// as combined pairs of 'code@font', excluding the '@' separator. This means that
// mGlyphCache[2*k] will later be rendered with mFontName[mGlyphCache[2*k+1]]
// mGlyphCache[3*k],mGlyphCache[3*k+1] will later be rendered with mFontName[mGlyphCache[3*k+2]]
// Note: font identifier is internally an ASCII digit to avoid the null char issue
nsAutoString buffer;
PRInt32 length = value.Length();
@ -320,7 +320,7 @@ nsGlyphTable::ElementAt(nsPresContext* aPresContext, nsMathMLChar* aChar, PRUint
while (i < length) {
PRUnichar code = value[i];
++i;
PRUnichar font = 0;
buffer.Append(code);
// see if we are at the beginning of a child char
if (code == kSpaceCh) {
// reset the annotation indicator to be 0 for the next code point
@ -346,8 +346,18 @@ nsGlyphTable::ElementAt(nsPresContext* aPresContext, nsMathMLChar* aChar, PRUint
++i;
}
#endif
// Read the next word if we have a non-BMP character.
if (i < length && NS_IS_HIGH_SURROGATE(code)) {
code = value[i];
++i;
} else {
code = PRUnichar('\0');
}
buffer.Append(code);
// See if an external font is needed for the code point.
// Limit of 9 external fonts
PRUnichar font = 0;
if (i+1 < length && value[i] == PRUnichar('@') &&
value[i+1] >= PRUnichar('0') && value[i+1] <= PRUnichar('9')) {
++i;
@ -362,7 +372,6 @@ nsGlyphTable::ElementAt(nsPresContext* aPresContext, nsMathMLChar* aChar, PRUint
return kNullGlyph;
}
}
buffer.Append(code);
buffer.Append(font);
++j;
}
@ -390,14 +399,15 @@ nsGlyphTable::ElementAt(nsPresContext* aPresContext, nsMathMLChar* aChar, PRUint
offset += 5; // skip the 4 partial glyphs + the whitespace separator
child = child->mSibling;
}
length = 2*(offset + 4); // stay confined in the 4 partial glyphs of this child
length = 3*(offset + 4); // stay confined in the 4 partial glyphs of this child
}
PRUint32 index = 2*(offset + aPosition); // 2* is to account for the code@font pairs
if (index+1 >= length) return kNullGlyph;
PRUint32 index = 3*(offset + aPosition); // 3* is to account for the code@font pairs
if (index+2 >= length) return kNullGlyph;
nsGlyphCode ch;
ch.code = mGlyphCache.CharAt(index);
ch.font = mGlyphCache.CharAt(index + 1);
return (ch.code == PRUnichar(0xFFFD)) ? kNullGlyph : ch;
ch.code[0] = mGlyphCache.CharAt(index);
ch.code[1] = mGlyphCache.CharAt(index + 1);
ch.font = mGlyphCache.CharAt(index + 2);
return ch.code[0] == PRUnichar(0xFFFD) ? kNullGlyph : ch;
}
PRBool
@ -409,9 +419,9 @@ nsGlyphTable::IsComposite(nsPresContext* aPresContext, nsMathMLChar* aChar)
// shortcut to sync the cache with this char...
mCharCache = 0; mGlyphCache.Truncate(); ElementAt(aPresContext, aChar, 0);
// the cache remained empty if the char wasn't found in this table
if (8 >= mGlyphCache.Length()) return PR_FALSE;
if (4*3 >= mGlyphCache.Length()) return PR_FALSE;
// the lists of glyphs of a composite char are space-separated
return (kSpaceCh == mGlyphCache.CharAt(8));
return (kSpaceCh == mGlyphCache.CharAt(4*3));
}
PRInt32
@ -1137,11 +1147,13 @@ nsMathMLChar::StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
SetFontFamily(mChar->mStyleContext->PresContext(), mRenderingContext,
font, aGlyphTable, ch, aFamily);
NS_ASSERTION(maxWidth || ch.code != mChar->mGlyph.code ||
NS_ASSERTION(maxWidth || ch.code[0] != mChar->mGlyph.code[0] ||
ch.code[1] != mChar->mGlyph.code[1] ||
!font.name.Equals(mChar->mFamily),
"glyph table incorrectly set -- duplicate found");
nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(&ch.code, 1);
nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(ch.code,
ch.Length());
nscoord charSize =
isVertical ? bm.ascent + bm.descent
: bm.rightBearing - bm.leftBearing;
@ -1259,7 +1271,8 @@ nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable,
else {
SetFontFamily(mChar->mStyleContext->PresContext(), mRenderingContext,
font, aGlyphTable, ch, aFamily);
nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(&ch.code, 1);
nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(ch.code,
ch.Length());
// TODO: For the generic Unicode table, ideally we should check that the
// glyphs are actually found and that they each come from the same
@ -2063,7 +2076,8 @@ nsMathMLChar::PaintForeground(nsPresContext* aPresContext,
if (mGlyph.Exists()) {
//printf("Painting %04X with a glyph of appropriate size\n", mData[0]);
//aRenderingContext.SetColor(NS_RGB(0,0,255));
aRenderingContext.DrawString(&mGlyph.code, 1, 0, mUnscaledAscent);
aRenderingContext.DrawString(mGlyph.code, mGlyph.Length(),
0, mUnscaledAscent);
}
else { // paint by parts
//aRenderingContext.SetColor(NS_RGB(0,255,0));
@ -2153,7 +2167,7 @@ nsMathMLChar::PaintVertically(nsPresContext* aPresContext,
if (ch.Exists()) {
SetFontFamily(aPresContext, aRenderingContext,
aFont, aGlyphTable, ch, mFamily);
bmdata[i] = aRenderingContext.GetBoundingMetrics(&ch.code, 1);
bmdata[i] = aRenderingContext.GetBoundingMetrics(ch.code, ch.Length());
}
chdata[i] = ch;
++i;
@ -2238,7 +2252,7 @@ nsMathMLChar::PaintVertically(nsPresContext* aPresContext,
AutoPushClipRect clip(aRenderingContext, clipRect);
SetFontFamily(aPresContext, aRenderingContext,
aFont, aGlyphTable, ch, mFamily);
aRenderingContext.DrawString(&ch.code, 1, dx, dy);
aRenderingContext.DrawString(ch.code, ch.Length(), dx, dy);
}
}
}
@ -2314,7 +2328,7 @@ nsMathMLChar::PaintVertically(nsPresContext* aPresContext,
clipRect.height = NS_MIN(bm.ascent + bm.descent, fillEnd - dy);
AutoPushClipRect clip(aRenderingContext, clipRect);
dy += bm.ascent;
aRenderingContext.DrawString(&chGlue.code, 1, dx, dy);
aRenderingContext.DrawString(chGlue.code, chGlue.Length(), dx, dy);
dy += bm.descent;
}
#ifdef SHOW_BORDERS
@ -2381,7 +2395,7 @@ nsMathMLChar::PaintHorizontally(nsPresContext* aPresContext,
if (ch.Exists()) {
SetFontFamily(aPresContext, aRenderingContext,
aFont, aGlyphTable, ch, mFamily);
bmdata[i] = aRenderingContext.GetBoundingMetrics(&ch.code, 1);
bmdata[i] = aRenderingContext.GetBoundingMetrics(ch.code, ch.Length());
}
chdata[i] = ch;
++i;
@ -2461,7 +2475,7 @@ nsMathMLChar::PaintHorizontally(nsPresContext* aPresContext,
AutoPushClipRect clip(aRenderingContext, clipRect);
SetFontFamily(aPresContext, aRenderingContext,
aFont, aGlyphTable, ch, mFamily);
aRenderingContext.DrawString(&ch.code, 1, dx, dy);
aRenderingContext.DrawString(ch.code, ch.Length(), dx, dy);
}
}
}
@ -2536,7 +2550,7 @@ nsMathMLChar::PaintHorizontally(nsPresContext* aPresContext,
clipRect.width = NS_MIN(bm.rightBearing - bm.leftBearing, fillEnd - dx);
AutoPushClipRect clip(aRenderingContext, clipRect);
dx -= bm.leftBearing;
aRenderingContext.DrawString(&chGlue.code, 1, dx, dy);
aRenderingContext.DrawString(chGlue.code, chGlue.Length(), dx, dy);
dx += bm.rightBearing;
}
#ifdef SHOW_BORDERS

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

@ -71,16 +71,18 @@ enum {
// (depending on the type of nsGlyphTable where this comes from). The 'font' is a
// numeric identifier given to the font to which the glyph belongs.
struct nsGlyphCode {
PRUnichar code;
PRUnichar code[2];
PRInt32 font;
PRInt32 Length() { return (code[1] == PRUnichar('\0') ? 1 : 2); }
PRBool Exists() const
{
return (code != 0);
return (code[0] != 0);
}
PRBool operator==(const nsGlyphCode& other) const
{
return other.code == code && other.font == font;
return (other.code[0] == code[0] && other.code[1] == code[1] &&
other.font == font);
}
PRBool operator!=(const nsGlyphCode& other) const
{