Bug 407761. Don't try to get/use extents for missing glyphs, and tolerate glyph extents that might be missing due to OOM. r=vlad

This commit is contained in:
roc+@cs.cmu.edu 2007-12-20 23:09:50 -08:00
Родитель d64ce5e03c
Коммит bdc1c51761
2 изменённых файлов: 41 добавлений и 11 удалений

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

@ -272,7 +272,10 @@ public:
}
// Get glyph extents; a rectangle relative to the left baseline origin
gfxRect GetTightGlyphExtentsAppUnits(gfxFont *aFont, gfxContext *aContext, PRUint32 aGlyphID);
// Returns true on success. Can fail on OOM or when aContext is null
// and extents were not (successfully) prefetched.
PRBool GetTightGlyphExtentsAppUnits(gfxFont *aFont, gfxContext *aContext,
PRUint32 aGlyphID, gfxRect *aExtents);
void SetContainedGlyphWidthAppUnits(PRUint32 aGlyphID, PRUint16 aWidth) {
mContainedGlyphWidths.Set(aGlyphID, aWidth);
@ -488,6 +491,8 @@ public:
* the advance width for the character run,y=-(font ascent), and height=
* font ascent + font descent). Otherwise, we must return as tight as possible
* an approximation to the area actually painted by glyphs.
* @param aContextForTightBoundingBox when aTight is true, this must
* be non-null.
* @param aSpacing spacing to insert before and after glyphs. The bounding box
* need not include the spacing itself, but the spacing affects the glyph
* positions. null if there is no spacing.
@ -1203,6 +1208,12 @@ public:
void SetMissingGlyph(PRUint32 aCharIndex, PRUint32 aUnicodeChar);
void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, PRUint32 aCharIndex);
/**
* Prefetch all the glyph extents needed to ensure that Measure calls
* on this textrun with aTightBoundingBox false will succeed. Note
* that some glyph extents might not be fetched due to OOM or other
* errors.
*/
void FetchGlyphExtents(gfxContext *aRefContext);
// API for access to the raw glyph data, needed by gfxFont::Draw
@ -1402,6 +1413,7 @@ public:
* Make a textrun for a given string.
* If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
* textrun will copy it.
* This calls FetchGlyphExtents on the textrun.
*/
virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags) = 0;
@ -1409,6 +1421,7 @@ public:
* Make a textrun for a given string.
* If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
* textrun will copy it.
* This calls FetchGlyphExtents on the textrun.
*/
virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
const Parameters *aParams, PRUint32 aFlags) = 0;

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

@ -405,14 +405,18 @@ gfxFont::Measure(gfxTextRun *aTextRun,
double advance = glyphData->GetSimpleAdvance();
// Only get the real glyph horizontal extent if we were asked
// for the tight bounding box or we're in quality mode
if (aTightBoundingBox || NeedsGlyphExtents(aTextRun)) {
if ((aTightBoundingBox || NeedsGlyphExtents(aTextRun)) && extents) {
PRUint32 glyphIndex = glyphData->GetSimpleGlyph();
PRUint16 extentsWidth = extents->GetContainedGlyphWidthAppUnits(glyphIndex);
if (extentsWidth != gfxGlyphExtents::INVALID_WIDTH && !aTightBoundingBox) {
UnionWithXPoint(&metrics.mBoundingBox, x + direction*extentsWidth);
} else {
gfxRect glyphRect =
extents->GetTightGlyphExtentsAppUnits(this, aRefContext, glyphIndex);
gfxRect glyphRect;
if (!extents->GetTightGlyphExtentsAppUnits(this,
aRefContext, glyphIndex, &glyphRect)) {
glyphRect = gfxRect(0, metrics.mBoundingBox.Y(),
advance, metrics.mBoundingBox.Height());
}
if (isRTL) {
glyphRect.pos.x -= advance;
}
@ -429,8 +433,15 @@ gfxFont::Measure(gfxTextRun *aTextRun,
PRUint32 glyphIndex = details->mGlyphID;
gfxPoint glyphPt(x + details->mXOffset, details->mYOffset);
double advance = details->mAdvance;
gfxRect glyphRect =
extents->GetTightGlyphExtentsAppUnits(this, aRefContext, glyphIndex);
gfxRect glyphRect;
if (glyphData->IsMissing() || !extents ||
!extents->GetTightGlyphExtentsAppUnits(this,
aRefContext, glyphIndex, &glyphRect)) {
// We might have failed to get glyph extents due to
// OOM or something
glyphRect = gfxRect(0, metrics.mBoundingBox.Y(),
advance, metrics.mBoundingBox.Height());
}
if (isRTL) {
glyphRect.pos.x -= advance;
}
@ -522,12 +533,17 @@ gfxGlyphExtents::~gfxGlyphExtents()
MOZ_COUNT_DTOR(gfxGlyphExtents);
}
gfxRect
PRBool
gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
gfxContext *aContext, PRUint32 aGlyphID)
gfxContext *aContext, PRUint32 aGlyphID, gfxRect *aExtents)
{
HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID);
if (!entry) {
if (!aContext) {
NS_WARNING("Could not get glyph extents (no aContext)");
return PR_FALSE;
}
aFont->SetupCairoFont(aContext);
#ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
++gGlyphExtentsSetupLazyTight;
@ -536,11 +552,12 @@ gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont,
entry = mTightGlyphExtents.GetEntry(aGlyphID);
if (!entry) {
NS_WARNING("Could not get glyph extents");
return gfxRect(0,0,0,0);
return PR_FALSE;
}
}
return gfxRect(entry->x, entry->y, entry->width, entry->height);
*aExtents = gfxRect(entry->x, entry->y, entry->width, entry->height);
return PR_TRUE;
}
gfxGlyphExtents::GlyphWidths::~GlyphWidths()
@ -1931,7 +1948,7 @@ gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext)
font->SetupGlyphExtents(aRefContext, glyphIndex, PR_FALSE, extents);
}
}
} else {
} else if (!glyphData->IsMissing()) {
PRUint32 k;
PRUint32 glyphCount = glyphData->GetGlyphCount();
const gfxTextRun::DetailedGlyph *details = GetDetailedGlyphs(j);