| Index: src/ports/SkFontHost_FreeType.cpp
|
| diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
|
| index 0c28cc28904231d87f9cf76713c2dfe08e41b4e3..7f70d4e045af56959119309503da2169a4cbf0fc 100644
|
| --- a/src/ports/SkFontHost_FreeType.cpp
|
| +++ b/src/ports/SkFontHost_FreeType.cpp
|
| @@ -31,36 +31,15 @@
|
| #include <dlfcn.h>
|
| #endif
|
| #include <ft2build.h>
|
| +#include FT_ADVANCES_H
|
| +#include FT_BITMAP_H
|
| #include FT_FREETYPE_H
|
| +#include FT_LCD_FILTER_H
|
| #include FT_OUTLINE_H
|
| #include FT_SIZES_H
|
| #include FT_TRUETYPE_TABLES_H
|
| #include FT_TYPE1_TABLES_H
|
| -#include FT_BITMAP_H
|
| -// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
|
| -#include FT_SYNTHESIS_H
|
| #include FT_XFREE86_H
|
| -#ifdef FT_LCD_FILTER_H
|
| -#include FT_LCD_FILTER_H
|
| -#endif
|
| -
|
| -// Defined in FreeType 2.3.8 and later.
|
| -// This is a silly build time check, we would need a runtime check if we really cared.
|
| -#ifdef FT_ADVANCES_H
|
| -#include FT_ADVANCES_H
|
| -#endif
|
| -
|
| -#if 0
|
| -// Also include the files by name for build tools which require this.
|
| -#include <freetype/freetype.h>
|
| -#include <freetype/ftoutln.h>
|
| -#include <freetype/ftsizes.h>
|
| -#include <freetype/tttables.h>
|
| -#include <freetype/ftadvanc.h>
|
| -#include <freetype/ftlcdfil.h>
|
| -#include <freetype/ftbitmap.h>
|
| -#include <freetype/ftsynth.h>
|
| -#endif
|
|
|
| // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA
|
| // were introduced in FreeType 2.5.0.
|
| @@ -79,7 +58,8 @@
|
|
|
| //#define ENABLE_GLYPH_SPEW // for tracing calls
|
| //#define DUMP_STRIKE_CREATION
|
| -
|
| +//#define SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER
|
| +//#define SK_FONTHOST_FREETYPE_RUNTIME_VERSION
|
| //#define SK_GAMMA_APPLY_TO_A8
|
|
|
| using namespace skia_advanced_typeface_metrics_utils;
|
| @@ -118,13 +98,14 @@ typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char
|
|
|
| // Caller must lock gFTMutex before calling this function.
|
| static bool InitFreetype() {
|
| + gFTMutex.assertHeld();
|
| +
|
| FT_Error err = FT_Init_FreeType(&gFTLibrary);
|
| if (err) {
|
| return false;
|
| }
|
|
|
| // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs.
|
| -#ifdef FT_LCD_FILTER_H
|
| // Use default { 0x10, 0x40, 0x70, 0x40, 0x10 }, as it adds up to 0x110, simulating ink spread.
|
| // SetLcdFilter must be called before SetLcdFilterWeights.
|
| err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT);
|
| @@ -136,10 +117,9 @@ static bool InitFreetype() {
|
| // This also adds to 0x110 simulating ink spread, but provides better results than default.
|
| static unsigned char gGaussianLikeHeavyWeights[] = { 0x1A, 0x43, 0x56, 0x43, 0x1A, };
|
|
|
| -#if defined(SK_FONTHOST_FREETYPE_RUNTIME_VERSION) && \
|
| - SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400
|
| +#if SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400
|
| err = FT_Library_SetLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights);
|
| -#elif defined(SK_CAN_USE_DLOPEN) && SK_CAN_USE_DLOPEN == 1
|
| +#elif SK_CAN_USE_DLOPEN == 1
|
| //The FreeType library is already loaded, so symbols are available in process.
|
| void* self = dlopen(NULL, RTLD_LAZY);
|
| if (self) {
|
| @@ -155,9 +135,6 @@ static bool InitFreetype() {
|
| #endif
|
| #endif
|
| }
|
| -#else
|
| - gLCDSupport = false;
|
| -#endif
|
| gLCDSupportValid = true;
|
|
|
| return true;
|
| @@ -291,6 +268,8 @@ SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID)
|
| // Will return 0 on failure
|
| // Caller must lock gFTMutex before calling this function.
|
| static SkFaceRec* ref_ft_face(const SkTypeface* typeface) {
|
| + gFTMutex.assertHeld();
|
| +
|
| const SkFontID fontID = typeface->uniqueID();
|
| SkFaceRec* rec = gFaceRecHead;
|
| while (rec) {
|
| @@ -316,24 +295,21 @@ static SkFaceRec* ref_ft_face(const SkTypeface* typeface) {
|
| const void* memoryBase = strm->getMemoryBase();
|
|
|
| if (memoryBase) {
|
| -//printf("mmap(%s)\n", keyString.c_str());
|
| args.flags = FT_OPEN_MEMORY;
|
| args.memory_base = (const FT_Byte*)memoryBase;
|
| args.memory_size = strm->getLength();
|
| } else {
|
| -//printf("fopen(%s)\n", keyString.c_str());
|
| args.flags = FT_OPEN_STREAM;
|
| args.stream = &rec->fFTStream;
|
| }
|
|
|
| FT_Error err = FT_Open_Face(gFTLibrary, &args, face_index, &rec->fFace);
|
| if (err) { // bad filename, try the default font
|
| - fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID);
|
| + SkDEBUGF(("ERROR: unable to open font '%x'\n", fontID));
|
| SkDELETE(rec);
|
| return NULL;
|
| } else {
|
| SkASSERT(rec->fFace);
|
| - //fprintf(stderr, "Opened font '%s'\n", filename.c_str());
|
| rec->fNext = gFaceRecHead;
|
| gFaceRecHead = rec;
|
| return rec;
|
| @@ -342,6 +318,8 @@ static SkFaceRec* ref_ft_face(const SkTypeface* typeface) {
|
|
|
| // Caller must lock gFTMutex before calling this function.
|
| static void unref_ft_face(FT_Face face) {
|
| + gFTMutex.assertHeld();
|
| +
|
| SkFaceRec* rec = gFaceRecHead;
|
| SkFaceRec* prev = NULL;
|
| while (rec) {
|
| @@ -399,57 +377,15 @@ private:
|
|
|
| ///////////////////////////////////////////////////////////////////////////
|
|
|
| -// Work around for old versions of freetype.
|
| -static FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count,
|
| - FT_Int32 loadFlags, FT_Fixed* advances) {
|
| -#ifdef FT_ADVANCES_H
|
| - return FT_Get_Advances(face, start, count, loadFlags, advances);
|
| -#else
|
| - if (!face || start >= face->num_glyphs ||
|
| - start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) {
|
| - return 6; // "Invalid argument."
|
| - }
|
| - if (count == 0)
|
| - return 0;
|
| -
|
| - for (int i = 0; i < count; i++) {
|
| - FT_Error err = FT_Load_Glyph(face, start + i, FT_LOAD_NO_SCALE);
|
| - if (err)
|
| - return err;
|
| - advances[i] = face->glyph->advance.x;
|
| - }
|
| -
|
| - return 0;
|
| -#endif
|
| -}
|
| -
|
| static bool canEmbed(FT_Face face) {
|
| -#ifdef FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING
|
| FT_UShort fsType = FT_Get_FSType_Flags(face);
|
| return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
|
| FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0;
|
| -#else
|
| - // No embedding is 0x2 and bitmap embedding only is 0x200.
|
| - TT_OS2* os2_table;
|
| - if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
|
| - return (os2_table->fsType & 0x202) == 0;
|
| - }
|
| - return false; // We tried, fail safe.
|
| -#endif
|
| }
|
|
|
| static bool canSubset(FT_Face face) {
|
| -#ifdef FT_FSTYPE_NO_SUBSETTING
|
| FT_UShort fsType = FT_Get_FSType_Flags(face);
|
| return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0;
|
| -#else
|
| - // No subset is 0x100.
|
| - TT_OS2* os2_table;
|
| - if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) {
|
| - return (os2_table->fsType & 0x100) == 0;
|
| - }
|
| - return false; // We tried, fail safe.
|
| -#endif
|
| }
|
|
|
| static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
|
| @@ -464,7 +400,7 @@ static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
|
|
|
| static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) {
|
| FT_Fixed advance = 0;
|
| - if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
|
| + if (FT_Get_Advances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
|
| return false;
|
| }
|
| SkASSERT(data);
|
| @@ -472,8 +408,7 @@ static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) {
|
| return true;
|
| }
|
|
|
| -static void populate_glyph_to_unicode(FT_Face& face,
|
| - SkTDArray<SkUnichar>* glyphToUnicode) {
|
| +static void populate_glyph_to_unicode(FT_Face& face, SkTDArray<SkUnichar>* glyphToUnicode) {
|
| // Check and see if we have Unicode cmaps.
|
| for (int i = 0; i < face->num_charmaps; ++i) {
|
| // CMaps known to support Unicode:
|
| @@ -666,10 +601,10 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
|
| for (int gID = 0; gID < face->num_glyphs; gID += 128) {
|
| FT_Fixed advances[128];
|
| int advanceCount = 128;
|
| - if (gID + advanceCount > face->num_glyphs)
|
| + if (gID + advanceCount > face->num_glyphs) {
|
| advanceCount = face->num_glyphs - gID;
|
| - getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE,
|
| - advances);
|
| + }
|
| + FT_Get_Advances(face, gID, advanceCount, FT_LOAD_NO_SCALE, advances);
|
| for (int i = 0; i < advanceCount; i++) {
|
| int16_t advance = advances[i];
|
| info->fGlyphWidths->fAdvance.append(1, &advance);
|
| @@ -1103,7 +1038,6 @@ SkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) {
|
| }
|
|
|
| void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
|
| -#ifdef FT_ADVANCES_H
|
| /* unhinted and light hinted text have linearly scaled advances
|
| * which are very cheap to compute with some font formats...
|
| */
|
| @@ -1129,7 +1063,7 @@ void SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
|
| return;
|
| }
|
| }
|
| -#endif /* FT_ADVANCES_H */
|
| +
|
| /* otherwise, we need to load/hint the glyph, which is slower */
|
| this->generateMetrics(glyph);
|
| return;
|
| @@ -1176,10 +1110,12 @@ void SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph,
|
|
|
| bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) {
|
| const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter);
|
| - if (!glyph_id)
|
| + if (!glyph_id) {
|
| return false;
|
| - if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0)
|
| + }
|
| + if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) {
|
| return false;
|
| + }
|
| emboldenIfNeeded(fFace, fFace->glyph);
|
| FT_Outline_Get_CBox(&fFace->glyph->outline, bbox);
|
| return true;
|
| @@ -1314,22 +1250,23 @@ void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
|
| #endif
|
| }
|
|
|
| +static void clear_glyph_image(const SkGlyph& glyph) {
|
| + sk_bzero(glyph.fImage, glyph.rowBytes() * glyph.fHeight);
|
| +}
|
|
|
| void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
|
| SkAutoMutexAcquire ac(gFTMutex);
|
|
|
| - FT_Error err;
|
| -
|
| if (this->setupSize()) {
|
| - goto ERROR;
|
| + clear_glyph_image(glyph);
|
| + return;
|
| }
|
|
|
| - err = FT_Load_Glyph( fFace, glyph.getGlyphID(), fLoadGlyphFlags);
|
| + FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), 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(), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
|
| - ERROR:
|
| - memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
|
| + glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err));
|
| + clear_glyph_image(glyph);
|
| return;
|
| }
|
|
|
| @@ -1338,8 +1275,7 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
|
| }
|
|
|
|
|
| -void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph,
|
| - SkPath* path) {
|
| +void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path) {
|
| SkAutoMutexAcquire ac(gFTMutex);
|
|
|
| SkASSERT(path);
|
|
|