bug 33032 - synthesize various Unicode space characters rather than showing missing glyphs. r=jdaggett

This commit is contained in:
Jonathan Kew 2011-05-02 10:01:55 +01:00
parent 81d6a97ce8
commit 798129b691
2 changed files with 57 additions and 2 deletions

View File

@ -1817,6 +1817,29 @@ gfxFont::SanitizeMetrics(gfxFont::Metrics *aMetrics, PRBool aIsBadUnderlineFont)
}
}
gfxFloat
gfxFont::SynthesizeSpaceWidth(PRUint32 aCh)
{
// return an appropriate width for various Unicode space characters
// that we "fake" if they're not actually present in the font;
// returns negative value if the char is not a known space.
switch (aCh) {
case 0x2000: // en quad
case 0x2002: return GetAdjustedSize() / 2; // en space
case 0x2001: // em quad
case 0x2003: return GetAdjustedSize(); // em space
case 0x2004: return GetAdjustedSize() / 3; // three-per-em space
case 0x2005: return GetAdjustedSize() / 4; // four-per-em space
case 0x2006: return GetAdjustedSize() / 6; // six-per-em space
case 0x2007: return GetMetrics().zeroOrAveCharWidth; // figure space
case 0x2008: return GetMetrics().spaceWidth; // punctuation space
case 0x2009: return GetAdjustedSize() / 5; // thin space
case 0x200a: return GetAdjustedSize() / 10; // hair space
case 0x202f: return GetAdjustedSize() / 5; // narrow no-break space
default: return -1.0;
}
}
gfxGlyphExtents::~gfxGlyphExtents()
{
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
@ -2473,7 +2496,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
if (!matchedFont) {
for (PRUint32 index = runStart; index < runStart + matchedLength; index++) {
// Record the char code so we can draw a box with the Unicode value
if (NS_IS_HIGH_SURROGATE(aString[index]) &&
PRUint32 ch = aString[index];
if (NS_IS_HIGH_SURROGATE(ch) &&
index + 1 < aScriptRunEnd &&
NS_IS_LOW_SURROGATE(aString[index+1])) {
aTextRun->SetMissingGlyph(index,
@ -2481,7 +2505,27 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
aString[index+1]));
index++;
} else {
aTextRun->SetMissingGlyph(index, aString[index]);
gfxFloat wid = mainFont->SynthesizeSpaceWidth(ch);
if (wid >= 0.0) {
nscoord advance =
aTextRun->GetAppUnitsPerDevUnit() * NS_floor(wid + 0.5);
gfxTextRun::CompressedGlyph g;
if (gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance)) {
aTextRun->SetSimpleGlyph(index,
g.SetSimpleGlyph(advance,
mainFont->GetSpaceGlyph()));
} else {
gfxTextRun::DetailedGlyph detailedGlyph;
detailedGlyph.mGlyphID = mainFont->GetSpaceGlyph();
detailedGlyph.mAdvance = advance;
detailedGlyph.mXOffset = detailedGlyph.mYOffset = 0;
g.SetComplex(PR_TRUE, PR_TRUE, 1);
aTextRun->SetGlyphs(index,
g, &detailedGlyph);
}
} else {
aTextRun->SetMissingGlyph(index, ch);
}
}
}
}
@ -2548,6 +2592,15 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh,
return selectedFont.forget();
}
// for known "space" characters, don't do a full system-fallback search;
// we'll synthesize appropriate-width spaces instead of missing-glyph boxes
if (gfxUnicodeProperties::GetGeneralCategory(aCh) ==
HB_CATEGORY_SPACE_SEPARATOR &&
GetFontAt(0)->SynthesizeSpaceWidth(aCh) >= 0.0)
{
return nsnull;
}
// -- otherwise look for other stuff
if (!selectedFont) {
selectedFont = WhichSystemFontSupportsChar(aCh);

View File

@ -1024,6 +1024,8 @@ public:
return -1;
}
gfxFloat SynthesizeSpaceWidth(PRUint32 aCh);
// Font metrics
struct Metrics {
gfxFloat xHeight;