bug 617905 pt 1 - refactor gfxFont::InitTextRun so that all platforms benefit from splitting huge text runs. r=karlt a=joe

This commit is contained in:
Jonathan Kew 2011-01-07 12:38:28 +00:00
parent d4322f4982
commit bd9aea4565
6 changed files with 111 additions and 88 deletions

View File

@ -150,6 +150,7 @@ public: // new functions
return &entry->mData;
}
protected:
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
@ -158,7 +159,6 @@ public: // new functions
PRInt32 aRunScript,
PRBool aPreferPlatformShaping = PR_FALSE);
protected:
void FillGlyphDataForChar(PRUint32 ch, CachedGlyphData *gd);
void AddRange(gfxTextRun *aTextRun, const PRUnichar *str, PRUint32 offset, PRUint32 len);

View File

@ -1435,13 +1435,12 @@ gfxFont::Measure(gfxTextRun *aTextRun,
// behavior on long runs with no whitespace.
PRBool
gfxFont::InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript,
PRBool aPreferPlatformShaping)
gfxFont::SplitAndInitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript)
{
PRBool ok;
@ -1492,27 +1491,9 @@ gfxFont::InitTextRun(gfxContext *aContext,
}
}
if (mHarfBuzzShaper && !aPreferPlatformShaping) {
if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >=
gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) {
ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString,
aRunStart, thisRunLength,
aRunScript);
}
}
ok = InitTextRun(aContext, aTextRun, aString,
aRunStart, thisRunLength, aRunScript);
if (!ok) {
if (!mPlatformShaper) {
CreatePlatformShaper();
NS_ASSERTION(mPlatformShaper, "no platform shaper available!");
}
if (mPlatformShaper) {
ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString,
aRunStart, thisRunLength,
aRunScript);
}
}
aRunStart += thisRunLength;
aRunLength -= thisRunLength;
} while (ok && aRunLength > 0);
@ -1521,6 +1502,41 @@ gfxFont::InitTextRun(gfxContext *aContext,
return ok;
}
PRBool
gfxFont::InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript,
PRBool aPreferPlatformShaping)
{
PRBool ok = PR_FALSE;
if (mHarfBuzzShaper && !aPreferPlatformShaping) {
if (gfxPlatform::GetPlatform()->UseHarfBuzzLevel() >=
gfxUnicodeProperties::ScriptShapingLevel(aRunScript)) {
ok = mHarfBuzzShaper->InitTextRun(aContext, aTextRun, aString,
aRunStart, aRunLength,
aRunScript);
}
}
if (!ok) {
if (!mPlatformShaper) {
CreatePlatformShaper();
NS_ASSERTION(mPlatformShaper, "no platform shaper available!");
}
if (mPlatformShaper) {
ok = mPlatformShaper->InitTextRun(aContext, aTextRun, aString,
aRunStart, aRunLength,
aRunScript);
}
}
return ok;
}
gfxGlyphExtents *
gfxFont::GetOrCreateGlyphExtents(PRUint32 aAppUnitsPerDevUnit) {
PRUint32 i;
@ -2359,10 +2375,6 @@ gfxFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
return textRun;
}
#define SMALL_GLYPH_RUN 128 // preallocated size of our auto arrays for per-glyph data;
// some testing indicates that 90%+ of glyph runs will fit
// without requiring a separate allocation
void
gfxFontGroup::InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
@ -2376,23 +2388,21 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
PRUint32 runStart = 0, runLimit = aLength;
PRInt32 runScript = HB_SCRIPT_LATIN;
while (scriptRuns.Next(runStart, runLimit, runScript)) {
InitTextRun(aContext, aTextRun, aString, aLength,
runStart, runLimit, runScript);
InitScriptRun(aContext, aTextRun, aString, aLength,
runStart, runLimit, runScript);
}
// Is this actually necessary? Without it, gfxTextRun::CopyGlyphDataFrom may assert
// "Glyphruns not coalesced", but does that matter?
aTextRun->SortGlyphRuns();
}
void
gfxFontGroup::InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aTotalLength,
PRUint32 aScriptRunStart,
PRUint32 aScriptRunEnd,
PRInt32 aRunScript)
gfxFontGroup::InitScriptRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aTotalLength,
PRUint32 aScriptRunStart,
PRUint32 aScriptRunEnd,
PRInt32 aRunScript)
{
gfxFont *mainFont = mFonts[0].get();
@ -2412,9 +2422,9 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
runStart, (matchedLength > 0));
if (matchedFont) {
// do glyph layout and record the resulting positioned glyphs
if (!matchedFont->InitTextRun(aContext, aTextRun, aString,
runStart, matchedLength,
aRunScript)) {
if (!matchedFont->SplitAndInitTextRun(aContext, aTextRun, aString,
runStart, matchedLength,
aRunScript)) {
// glyph layout failed! treat as missing glyphs
matchedFont = nsnull;
}

View File

@ -1186,18 +1186,15 @@ public:
return mFontEntry->GetUVSGlyph(aCh, aVS);
}
// Default simply calls m[Platform|HarfBuzz]Shaper->InitTextRun().
// Override if the font class wants to give special handling
// to shaper failure.
// Returns PR_FALSE if shaping failed (though currently we
// don't have any good way to handle that situation).
virtual PRBool InitTextRun(gfxContext *aContext,
// call the (virtual) InitTextRun method to do glyph generation/shaping,
// limiting the length of text passed by processing the run in multiple
// segments if necessary
PRBool SplitAndInitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript,
PRBool aPreferPlatformShaping = PR_FALSE);
PRInt32 aRunScript);
protected:
nsRefPtr<gfxFontEntry> mFontEntry;
@ -1248,6 +1245,19 @@ protected:
// some fonts have bad metrics, this method sanitize them.
// if this font has bad underline offset, aIsBadUnderlineFont should be true.
void SanitizeMetrics(gfxFont::Metrics *aMetrics, PRBool aIsBadUnderlineFont);
// Default simply calls m[Platform|HarfBuzz]Shaper->InitTextRun().
// Override if the font class wants to give special handling
// to shaper failure.
// Returns PR_FALSE if shaping failed (though currently we
// don't have any good way to handle that situation).
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript,
PRBool aPreferPlatformShaping = PR_FALSE);
};
// proportion of ascent used for x-height, if unable to read value from font
@ -2232,21 +2242,22 @@ protected:
// you should call this with the *first* bad font.
void InitMetricsForBadFont(gfxFont* aBadFont);
// Set up the textrun glyphs, by finding script and font ranges
// and calling each font's InitTextRun() as appropriate
// Set up the textrun glyphs for an entire text run:
// find script runs, and then call InitScriptRun for each
void InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aLength);
// InitTextRun helper to handle a single script run
void InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aTotalLength,
PRUint32 aScriptRunStart,
PRUint32 aScriptRunEnd,
PRInt32 aRunScript);
// InitTextRun helper to handle a single script run, by finding font ranges
// and calling each font's InitTextRun() as appropriate
void InitScriptRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aTotalLength,
PRUint32 aScriptRunStart,
PRUint32 aScriptRunEnd,
PRInt32 aRunScript);
/* If aResolveGeneric is true, then CSS/Gecko generic family names are
* replaced with preferred fonts.

View File

@ -76,6 +76,14 @@ public:
/* required for MathML to suppress effects of ClearType "padding" */
virtual gfxFont* CopyWithAntialiasOption(AntialiasOption anAAOption);
virtual PRBool ProvidesHintedWidths() const { return PR_TRUE; }
// get hinted glyph width in pixels as 16.16 fixed-point value
virtual PRInt32 GetHintedGlyphWidth(gfxContext *aCtx, PRUint16 aGID);
protected:
virtual void CreatePlatformShaper();
/* override to check for uniscribe failure and fall back to GDI */
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
@ -85,14 +93,6 @@ public:
PRInt32 aRunScript,
PRBool aPreferPlatformShaping = PR_FALSE);
virtual PRBool ProvidesHintedWidths() const { return PR_TRUE; }
// get hinted glyph width in pixels as 16.16 fixed-point value
virtual PRInt32 GetHintedGlyphWidth(gfxContext *aCtx, PRUint16 aGID);
protected:
virtual void CreatePlatformShaper();
void Initialize(); // creates metrics and Cairo fonts
void FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize);

View File

@ -57,14 +57,6 @@ public:
ATSFontRef GetATSFontRef() const { return mATSFont; }
CGFontRef GetCGFontRef() const { return mCGFont; }
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript,
PRBool aPreferPlatformShaping = PR_FALSE);
/* overrides for the pure virtual methods in gfxFont */
virtual const gfxFont::Metrics& GetMetrics() {
return mMetrics;
@ -83,6 +75,15 @@ public:
protected:
virtual void CreatePlatformShaper();
// override to prefer CoreText shaping with fonts that depend on AAT
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
PRUint32 aRunStart,
PRUint32 aRunLength,
PRInt32 aRunScript,
PRBool aPreferPlatformShaping = PR_FALSE);
void InitMetrics();
void InitMetricsFromATSMetrics();

View File

@ -696,6 +696,15 @@ public:
static already_AddRefed<gfxFcFont>
GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern);
// The PangoFont returned is owned by the gfxFcFont
PangoFont *GetPangoFont() {
if (!mPangoFont) {
MakePangoFont();
}
return mPangoFont;
}
protected:
virtual PRBool InitTextRun(gfxContext *aContext,
gfxTextRun *aTextRun,
const PRUnichar *aString,
@ -709,14 +718,6 @@ public:
PRUint32 aRunStart, PRUint32 aRunLength,
PangoScript aScript);
// The PangoFont returned is owned by the gfxFcFont
PangoFont *GetPangoFont() {
if (!mPangoFont) {
MakePangoFont();
}
return mPangoFont;
}
private:
static already_AddRefed<gfxFcFont> GetOrMakeFont(FcPattern *aPattern);
gfxFcFont(cairo_scaled_font_t *aCairoFont, gfxFcFontEntry *aFontEntry,