| 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 {
|
|
|