Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1898)

Unified Diff: src/ports/SkFontHost_FreeType.cpp

Issue 103923002: Speed up generateImage by re-using the outline/bitmap that has already been loaded. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/ports/SkFontHost_FreeType_common.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ports/SkFontHost_FreeType.cpp
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index fd87a66dc6a8f8d9da40fb993c459e8d4e52a966..a50939c7f47e4729e6f56d3c62bea36b433e9c74 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -190,6 +190,11 @@ private:
bool fDoLinearMetrics;
bool fLCDIsVert;
+ // since different scalercontext may share the same face
+ // using a ID to identify which settings are activated
+ // this can help us to skip some unnecessary FreeType2 calls
+ uint32_t fUniqueID;
+
// Need scalar versions for generateFontMetrics
SkVector fScale;
SkMatrix fMatrix22Scalar;
@@ -212,6 +217,14 @@ struct SkFaceRec {
uint32_t fRefCnt;
uint32_t fFontID;
+ // record some information about the last glyph loaded
+ // drawText will generateImage just after generateMetrics in most cases
+ // a simple check can help us to skip the unnecessary call to FT_Load_Glyph
+ // which is time consuming, especially for composite glyphs
+ uint32_t fActivatedContextID;
+ // glyph that has been already loaded, which is also ready for generateImage
+ uint16_t fGlyphLoaded;
+
// assumes ownership of the stream, will call unref() when its done
SkFaceRec(SkStream* strm, uint32_t fontID);
~SkFaceRec() {
@@ -349,6 +362,9 @@ public:
fRec = ref_ft_face(tf);
if (fRec) {
fFace = fRec->fFace;
+ // someone will access to the FreeType face
+ fRec->fActivatedContextID = 0;
+ fRec->fGlyphLoaded = 0;
}
}
@@ -772,6 +788,11 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
}
fFace = fFaceRec->fFace;
+ // set ID for current scaler context
+ // start from 1, regarding 0 as invalid
+ static uint32_t gScalerContextID = 1;
+ fUniqueID = gScalerContextID++;
+
// compute our factors from the record
SkMatrix m;
@@ -892,6 +913,11 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
{
FT_Error err;
+ // no activated scaler context setting for the face
+ fFaceRec->fActivatedContextID = 0;
+ // regarding glyph 0 as an invalid glyph outline that we need to reload
+ fFaceRec->fGlyphLoaded = 0;
+
err = FT_New_Size(fFace, &fFTSize);
if (err != 0) {
SkDEBUGF(("SkScalerContext_FreeType::FT_New_Size(%x): FT_Set_Char_Size(0x%x, 0x%x) returned 0x%x\n",
@@ -918,6 +944,9 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface,
}
FT_Set_Transform( fFace, &fMatrix22, NULL);
+
+ // current scaler context setting is enabled for the face
+ fFaceRec->fActivatedContextID = fUniqueID;
}
}
@@ -942,16 +971,24 @@ SkScalerContext_FreeType::~SkScalerContext_FreeType() {
this face with other context (at different sizes).
*/
FT_Error SkScalerContext_FreeType::setupSize() {
- FT_Error err = FT_Activate_Size(fFTSize);
+ FT_Error err = 0;
- if (err != 0) {
- SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
- fFaceRec->fFontID, fScaleX, fScaleY, err));
- fFTSize = NULL;
- } else {
- // seems we need to reset this every time (not sure why, but without it
- // I get random italics from some other fFTSize)
- FT_Set_Transform( fFace, &fMatrix22, NULL);
+ if (fFaceRec->fActivatedContextID != fUniqueID) {
+ // no scalercontext settings are activated for the FreeType face now
+ fFaceRec->fActivatedContextID = 0;
+ fFaceRec->fGlyphLoaded = 0;
+ err = FT_Activate_Size(fFTSize);
+ if (err != 0) {
+ SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n",
+ fFaceRec->fFontID, fScaleX, fScaleY, err));
+ fFTSize = NULL;
+ } else {
+ // seems we need to reset this every time (not sure why, but without it
+ // I get random italics from some other fFTSize)
+ FT_Set_Transform( fFace, &fMatrix22, NULL);
+ // current scalercontext settings are activated
+ fFaceRec->fActivatedContextID = fUniqueID;
+ }
}
return err;
}
@@ -1075,7 +1112,9 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
goto ERROR;
}
- err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
+ // this glyph will be loaded to FreeType glyph slot
+ fFaceRec->fGlyphLoaded = glyph->getGlyphID(fBaseGlyphCount);
+ err = FT_Load_Glyph( fFace, fFaceRec->fGlyphLoaded, fLoadGlyphFlags );
if (err != 0) {
#if 0
SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%x) returned 0x%x\n",
@@ -1083,8 +1122,11 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
#endif
ERROR:
glyph->zeroMetrics();
+ // glyph not loadded
+ fFaceRec->fGlyphLoaded = 0;
return;
}
+ emboldenIfNeeded(fFace, fFace->glyph);
switch ( fFace->glyph->format ) {
case FT_GLYPH_FORMAT_OUTLINE: {
@@ -1098,10 +1140,6 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
break;
}
- if (fRec.fFlags & kEmbolden_Flag) {
- emboldenOutline(fFace, &fFace->glyph->outline);
- }
-
getBBoxForCurrentGlyph(glyph, &bbox, true);
glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin));
@@ -1115,11 +1153,6 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
}
case FT_GLYPH_FORMAT_BITMAP:
- if (fRec.fFlags & kEmbolden_Flag) {
- FT_GlyphSlot_Own_Bitmap(fFace->glyph);
- FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
- }
-
if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
FT_Vector vector;
vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
@@ -1175,18 +1208,26 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
SkAutoMutexAcquire ac(gFTMutex);
FT_Error err;
+ uint16_t glyphLoaded;
if (this->setupSize()) {
goto ERROR;
}
- err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
- if (err != 0) {
- SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n",
- glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
- ERROR:
- memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
- return;
+ glyphLoaded = fFaceRec->fGlyphLoaded;
+ // no need to remember what is in the FreeType glyph slot
+ // since the skia glyph cache won't query image for the same glyph shortly
+ fFaceRec->fGlyphLoaded = 0;
+ if (glyphLoaded == 0 || glyphLoaded != glyph.getGlyphID(fBaseGlyphCount)) {
+ err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFlags);
+ if (err != 0) {
+ SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n",
+ glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
+ ERROR:
+ memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
+ return;
+ }
+ emboldenIfNeeded(fFace, fFace->glyph);
}
generateGlyphImage(fFace, glyph);
@@ -1208,6 +1249,8 @@ void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
+ // FreeType glyph slot will be invalid for generateImage
+ fFaceRec->fGlyphLoaded = 0;
FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flags);
if (err != 0) {
@@ -1216,6 +1259,7 @@ void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
path->reset();
return;
}
+ emboldenIfNeeded(fFace, fFace->glyph);
generateGlyphPath(fFace, path);
@@ -1286,10 +1330,10 @@ void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx,
const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x');
if (x_glyph) {
FT_BBox bbox;
+ // just set the glyph to be invalid for generateImage
+ fFaceRec->fGlyphLoaded = 0;
FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags);
- if (fRec.fFlags & kEmbolden_Flag) {
- emboldenOutline(fFace, &fFace->glyph->outline);
- }
+ emboldenIfNeeded(fFace, fFace->glyph);
FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
x_height = bbox.yMax / 64.0f;
} else {
« no previous file with comments | « no previous file | src/ports/SkFontHost_FreeType_common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698