mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
b=386895, speed up gfx text rendering (microbenchmark), r=roc
This commit is contained in:
parent
217327c738
commit
eebcddadb8
@ -172,6 +172,33 @@ ToDeviceUnits(double aAppUnits, double aDevUnitsPerAppUnit)
|
|||||||
return aAppUnits*aDevUnitsPerAppUnit;
|
return aAppUnits*aDevUnitsPerAppUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GlyphBuffer {
|
||||||
|
#define GLYPH_BUFFER_SIZE (2048/sizeof(cairo_glyph_t))
|
||||||
|
cairo_glyph_t mGlyphBuffer[GLYPH_BUFFER_SIZE];
|
||||||
|
unsigned int mNumGlyphs;
|
||||||
|
|
||||||
|
GlyphBuffer()
|
||||||
|
: mNumGlyphs(0) { }
|
||||||
|
|
||||||
|
cairo_glyph_t *AppendGlyph() {
|
||||||
|
return &mGlyphBuffer[mNumGlyphs++];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flush(cairo_t *cr, PRBool drawToPath, PRBool finish = PR_FALSE) {
|
||||||
|
if (!finish && mNumGlyphs != GLYPH_BUFFER_SIZE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (drawToPath)
|
||||||
|
cairo_glyph_path(cr, mGlyphBuffer, mNumGlyphs);
|
||||||
|
else
|
||||||
|
cairo_show_glyphs(cr, mGlyphBuffer, mNumGlyphs);
|
||||||
|
|
||||||
|
mNumGlyphs = 0;
|
||||||
|
}
|
||||||
|
#undef GLYPH_BUFFER_SIZE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||||
gfxContext *aContext, PRBool aDrawToPath, gfxPoint *aPt,
|
gfxContext *aContext, PRBool aDrawToPath, gfxPoint *aPt,
|
||||||
@ -185,21 +212,24 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
|||||||
const double devUnitsPerAppUnit = 1.0/double(appUnitsPerDevUnit);
|
const double devUnitsPerAppUnit = 1.0/double(appUnitsPerDevUnit);
|
||||||
PRBool isRTL = aTextRun->IsRightToLeft();
|
PRBool isRTL = aTextRun->IsRightToLeft();
|
||||||
double direction = aTextRun->GetDirection();
|
double direction = aTextRun->GetDirection();
|
||||||
nsAutoTArray<cairo_glyph_t,200> glyphBuffer;
|
|
||||||
PRUint32 i;
|
PRUint32 i;
|
||||||
// Current position in appunits
|
// Current position in appunits
|
||||||
double x = aPt->x;
|
double x = aPt->x;
|
||||||
double y = aPt->y;
|
double y = aPt->y;
|
||||||
|
|
||||||
|
cairo_t *cr = aContext->GetCairo();
|
||||||
|
SetupCairoFont(cr);
|
||||||
|
|
||||||
|
GlyphBuffer glyphs;
|
||||||
|
cairo_glyph_t *glyph;
|
||||||
|
|
||||||
if (aSpacing) {
|
if (aSpacing) {
|
||||||
x += direction*aSpacing[0].mBefore;
|
x += direction*aSpacing[0].mBefore;
|
||||||
}
|
}
|
||||||
for (i = aStart; i < aEnd; ++i) {
|
for (i = aStart; i < aEnd; ++i) {
|
||||||
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
|
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
|
||||||
if (glyphData->IsSimpleGlyph()) {
|
if (glyphData->IsSimpleGlyph()) {
|
||||||
cairo_glyph_t *glyph = glyphBuffer.AppendElement();
|
glyph = glyphs.AppendGlyph();
|
||||||
if (!glyph)
|
|
||||||
return;
|
|
||||||
glyph->index = glyphData->GetSimpleGlyph();
|
glyph->index = glyphData->GetSimpleGlyph();
|
||||||
double advance = glyphData->GetSimpleAdvance();
|
double advance = glyphData->GetSimpleAdvance();
|
||||||
// Perhaps we should put a scale in the cairo context instead of
|
// Perhaps we should put a scale in the cairo context instead of
|
||||||
@ -215,12 +245,11 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
|||||||
} else {
|
} else {
|
||||||
x += advance;
|
x += advance;
|
||||||
}
|
}
|
||||||
|
glyphs.Flush(cr, aDrawToPath);
|
||||||
} else if (glyphData->IsComplexCluster()) {
|
} else if (glyphData->IsComplexCluster()) {
|
||||||
const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i);
|
const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cairo_glyph_t *glyph = glyphBuffer.AppendElement();
|
glyph = glyphs.AppendGlyph();
|
||||||
if (!glyph)
|
|
||||||
return;
|
|
||||||
glyph->index = details->mGlyphID;
|
glyph->index = details->mGlyphID;
|
||||||
glyph->x = ToDeviceUnits(x + details->mXOffset, devUnitsPerAppUnit);
|
glyph->x = ToDeviceUnits(x + details->mXOffset, devUnitsPerAppUnit);
|
||||||
glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit);
|
glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit);
|
||||||
@ -232,6 +261,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
|||||||
if (details->mIsLastGlyph)
|
if (details->mIsLastGlyph)
|
||||||
break;
|
break;
|
||||||
++details;
|
++details;
|
||||||
|
glyphs.Flush(cr, aDrawToPath);
|
||||||
}
|
}
|
||||||
} else if (glyphData->IsMissing()) {
|
} else if (glyphData->IsMissing()) {
|
||||||
const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i);
|
const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i);
|
||||||
@ -261,20 +291,19 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*aPt = gfxPoint(x, y);
|
|
||||||
|
|
||||||
cairo_t *cr = aContext->GetCairo();
|
|
||||||
SetupCairoFont(cr);
|
|
||||||
if (aDrawToPath) {
|
|
||||||
cairo_glyph_path(cr, glyphBuffer.Elements(), glyphBuffer.Length());
|
|
||||||
} else {
|
|
||||||
cairo_show_glyphs(cr, glyphBuffer.Elements(), glyphBuffer.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gfxFontTestStore::CurrentStore()) {
|
if (gfxFontTestStore::CurrentStore()) {
|
||||||
|
/* This assumes that the tests won't have anything that results
|
||||||
|
* in more than GLYPH_BUFFER_SIZE glyphs. Do this before we
|
||||||
|
* flush, since that'll blow away the num_glyphs.
|
||||||
|
*/
|
||||||
gfxFontTestStore::CurrentStore()->AddItem(GetUniqueName(),
|
gfxFontTestStore::CurrentStore()->AddItem(GetUniqueName(),
|
||||||
glyphBuffer.Elements(), glyphBuffer.Length());
|
glyphs.mGlyphBuffer, glyphs.mNumGlyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw any remaining glyphs
|
||||||
|
glyphs.Flush(cr, aDrawToPath, PR_TRUE);
|
||||||
|
|
||||||
|
*aPt = gfxPoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxFont::RunMetrics
|
gfxFont::RunMetrics
|
||||||
|
Loading…
Reference in New Issue
Block a user