| OLD | NEW |
| 1 | |
| 2 /* | 1 /* |
| 3 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 4 * | 3 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 7 */ | 6 */ |
| 8 | 7 |
| 9 #include "SkAdvancedTypefaceMetrics.h" | 8 #include "SkAdvancedTypefaceMetrics.h" |
| 10 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 11 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
| 12 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 13 #include "SkDescriptor.h" | 12 #include "SkDescriptor.h" |
| 14 #include "SkFDot6.h" | 13 #include "SkFDot6.h" |
| 15 #include "SkFloatingPoint.h" | |
| 16 #include "SkFontHost.h" | 14 #include "SkFontHost.h" |
| 17 #include "SkFontHost_FreeType_common.h" | 15 #include "SkFontHost_FreeType_common.h" |
| 18 #include "SkGlyph.h" | 16 #include "SkGlyph.h" |
| 19 #include "SkMask.h" | 17 #include "SkMask.h" |
| 20 #include "SkMaskGamma.h" | 18 #include "SkMaskGamma.h" |
| 21 #include "SkMatrix22.h" | 19 #include "SkMatrix22.h" |
| 22 #include "SkOTUtils.h" | 20 #include "SkOTUtils.h" |
| 23 #include "SkOnce.h" | |
| 24 #include "SkScalerContext.h" | 21 #include "SkScalerContext.h" |
| 25 #include "SkStream.h" | 22 #include "SkStream.h" |
| 26 #include "SkString.h" | 23 #include "SkString.h" |
| 27 #include "SkTemplates.h" | 24 #include "SkTemplates.h" |
| 28 #include "SkThread.h" | 25 #include "SkThread.h" |
| 26 #include "SkTypes.h" |
| 29 | 27 |
| 30 #if defined(SK_CAN_USE_DLOPEN) | 28 #if defined(SK_CAN_USE_DLOPEN) |
| 31 #include <dlfcn.h> | 29 #include <dlfcn.h> |
| 32 #endif | 30 #endif |
| 33 #include <ft2build.h> | 31 #include <ft2build.h> |
| 34 #include FT_ADVANCES_H | 32 #include FT_ADVANCES_H |
| 35 #include FT_BITMAP_H | 33 #include FT_BITMAP_H |
| 36 #include FT_FREETYPE_H | 34 #include FT_FREETYPE_H |
| 37 #include FT_LCD_FILTER_H | 35 #include FT_LCD_FILTER_H |
| 36 #include FT_MODULE_H |
| 38 #include FT_OUTLINE_H | 37 #include FT_OUTLINE_H |
| 39 #include FT_SIZES_H | 38 #include FT_SIZES_H |
| 39 #include FT_SYSTEM_H |
| 40 #include FT_TRUETYPE_TABLES_H | 40 #include FT_TRUETYPE_TABLES_H |
| 41 #include FT_TYPE1_TABLES_H | 41 #include FT_TYPE1_TABLES_H |
| 42 #include FT_XFREE86_H | 42 #include FT_XFREE86_H |
| 43 | 43 |
| 44 // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA | 44 // FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA |
| 45 // were introduced in FreeType 2.5.0. | 45 // were introduced in FreeType 2.5.0. |
| 46 // The following may be removed once FreeType 2.5.0 is required to build. | 46 // The following may be removed once FreeType 2.5.0 is required to build. |
| 47 #ifndef FT_LOAD_COLOR | 47 #ifndef FT_LOAD_COLOR |
| 48 # define FT_LOAD_COLOR ( 1L << 20 ) | 48 # define FT_LOAD_COLOR ( 1L << 20 ) |
| 49 # define FT_PIXEL_MODE_BGRA 7 | 49 # define FT_PIXEL_MODE_BGRA 7 |
| 50 #endif | 50 #endif |
| 51 | 51 |
| 52 // FT_HAS_COLOR and the corresponding FT_FACE_FLAG_COLOR | 52 // FT_HAS_COLOR and the corresponding FT_FACE_FLAG_COLOR |
| 53 // were introduced in FreeType 2.5.1 | 53 // were introduced in FreeType 2.5.1 |
| 54 // The following may be removed once FreeType 2.5.1 is required to build. | 54 // The following may be removed once FreeType 2.5.1 is required to build. |
| 55 #ifndef FT_HAS_COLOR | 55 #ifndef FT_HAS_COLOR |
| 56 # define FT_HAS_COLOR(face) false | 56 # define FT_HAS_COLOR(face) false |
| 57 #endif | 57 #endif |
| 58 | 58 |
| 59 //#define ENABLE_GLYPH_SPEW // for tracing calls | 59 //#define ENABLE_GLYPH_SPEW // for tracing calls |
| 60 //#define DUMP_STRIKE_CREATION | 60 //#define DUMP_STRIKE_CREATION |
| 61 //#define SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER | 61 //#define SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER |
| 62 //#define SK_FONTHOST_FREETYPE_RUNTIME_VERSION | 62 //#define SK_FONTHOST_FREETYPE_RUNTIME_VERSION |
| 63 //#define SK_GAMMA_APPLY_TO_A8 | 63 //#define SK_GAMMA_APPLY_TO_A8 |
| 64 | 64 |
| 65 using namespace skia_advanced_typeface_metrics_utils; | 65 using namespace skia_advanced_typeface_metrics_utils; |
| 66 | 66 |
| 67 static bool isLCD(const SkScalerContext::Rec& rec) { | 67 static bool isLCD(const SkScalerContext::Rec& rec) { |
| 68 switch (rec.fMaskFormat) { | 68 return SkMask::kLCD16_Format == rec.fMaskFormat; |
| 69 case SkMask::kLCD16_Format: | |
| 70 return true; | |
| 71 default: | |
| 72 return false; | |
| 73 } | |
| 74 } | 69 } |
| 75 | 70 |
| 76 ////////////////////////////////////////////////////////////////////////// | 71 ////////////////////////////////////////////////////////////////////////// |
| 77 | 72 |
| 73 extern "C" { |
| 74 static void* sk_ft_alloc(FT_Memory, long size) { |
| 75 return sk_malloc_throw(size); |
| 76 } |
| 77 static void sk_ft_free(FT_Memory, void* block) { |
| 78 sk_free(block); |
| 79 } |
| 80 static void* sk_ft_realloc(FT_Memory, long cur_size, long new_size, void* bl
ock) { |
| 81 return sk_realloc_throw(block, new_size); |
| 82 } |
| 83 }; |
| 84 FT_MemoryRec_ gFTMemory = { NULL, sk_ft_alloc, sk_ft_free, sk_ft_realloc }; |
| 85 |
| 86 class FreeTypeLibrary : SkNoncopyable { |
| 87 public: |
| 88 FreeTypeLibrary() : fLibrary(NULL), fIsLCDSupported(false), fLCDExtra(0) { |
| 89 if (FT_New_Library(&gFTMemory, &fLibrary)) { |
| 90 return; |
| 91 } |
| 92 FT_Add_Default_Modules(fLibrary); |
| 93 |
| 94 // Setup LCD filtering. This reduces color fringes for LCD smoothed glyp
hs. |
| 95 // Default { 0x10, 0x40, 0x70, 0x40, 0x10 } adds up to 0x110, simulating
ink spread. |
| 96 // SetLcdFilter must be called before SetLcdFilterWeights. |
| 97 if (FT_Library_SetLcdFilter(fLibrary, FT_LCD_FILTER_DEFAULT) == 0) { |
| 98 fIsLCDSupported = true; |
| 99 fLCDExtra = 2; //Using a filter adds one full pixel to each side. |
| 100 |
| 101 #ifdef SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER |
| 102 // Adds to 0x110 simulating ink spread, but provides better results
than default. |
| 103 static unsigned char gGaussianLikeHeavyWeights[] = { 0x1A, 0x43, 0x5
6, 0x43, 0x1A, }; |
| 104 |
| 105 # if SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400 |
| 106 FT_Library_SetLcdFilterWeights(fLibrary, gGaussianLikeHeavyWeights); |
| 107 # elif SK_CAN_USE_DLOPEN == 1 |
| 108 //The FreeType library is already loaded, so symbols are available i
n process. |
| 109 void* self = dlopen(NULL, RTLD_LAZY); |
| 110 if (self) { |
| 111 FT_Library_SetLcdFilterWeightsProc setLcdFilterWeights; |
| 112 //The following cast is non-standard, but safe for POSIX. |
| 113 *reinterpret_cast<void**>(&setLcdFilterWeights) = |
| 114 dlsym(self, "FT_Library_SetLcdFilterWeights"); |
| 115 dlclose(self); |
| 116 |
| 117 if (setLcdFilterWeights) { |
| 118 setLcdFilterWeights(fLibrary, gGaussianLikeHeavyWeights); |
| 119 } |
| 120 } |
| 121 # endif |
| 122 #endif |
| 123 } |
| 124 } |
| 125 ~FreeTypeLibrary() { |
| 126 if (fLibrary) { |
| 127 FT_Done_Library(fLibrary); |
| 128 } |
| 129 } |
| 130 |
| 131 FT_Library library() { return fLibrary; } |
| 132 bool isLCDSupported() { return fIsLCDSupported; } |
| 133 int lcdExtra() { return fLCDExtra; } |
| 134 |
| 135 private: |
| 136 FT_Library fLibrary; |
| 137 bool fIsLCDSupported; |
| 138 int fLCDExtra; |
| 139 |
| 140 // FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0. |
| 141 // The following platforms provide FreeType of at least 2.4.0. |
| 142 // Ubuntu >= 11.04 (previous deprecated April 2013) |
| 143 // Debian >= 6.0 (good) |
| 144 // OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergre
en 11.2) |
| 145 // Fedora >= 14 (good) |
| 146 // Android >= Gingerbread (good) |
| 147 typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned
char*); |
| 148 }; |
| 149 |
| 78 struct SkFaceRec; | 150 struct SkFaceRec; |
| 79 | 151 |
| 80 SK_DECLARE_STATIC_MUTEX(gFTMutex); | 152 SK_DECLARE_STATIC_MUTEX(gFTMutex); |
| 81 static int gFTCount; | 153 static FreeTypeLibrary* gFTLibrary; |
| 82 static FT_Library gFTLibrary; | 154 static SkFaceRec* gFaceRecHead; |
| 83 static SkFaceRec* gFaceRecHead; | |
| 84 static bool gLCDSupportValid; // true iff |gLCDSupport| has been set. | |
| 85 static bool gLCDSupport; // true iff LCD is supported by the runtime. | |
| 86 static int gLCDExtra; // number of extra pixels for filtering. | |
| 87 | 155 |
| 88 ///////////////////////////////////////////////////////////////////////// | 156 // Private to RefFreeType and UnrefFreeType |
| 89 | 157 static int gFTCount; |
| 90 // FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0. | |
| 91 // The following platforms provide FreeType of at least 2.4.0. | |
| 92 // Ubuntu >= 11.04 (previous deprecated April 2013) | |
| 93 // Debian >= 6.0 (good) | |
| 94 // OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 1
1.2) | |
| 95 // Fedora >= 14 (good) | |
| 96 // Android >= Gingerbread (good) | |
| 97 typedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char
*); | |
| 98 | 158 |
| 99 // Caller must lock gFTMutex before calling this function. | 159 // Caller must lock gFTMutex before calling this function. |
| 100 static bool InitFreetype() { | 160 static bool ref_ft_library() { |
| 101 gFTMutex.assertHeld(); | 161 gFTMutex.assertHeld(); |
| 162 SkASSERT(gFTCount >= 0); |
| 102 | 163 |
| 103 FT_Error err = FT_Init_FreeType(&gFTLibrary); | 164 if (0 == gFTCount) { |
| 104 if (err) { | 165 SkASSERT(NULL == gFTLibrary); |
| 105 return false; | 166 gFTLibrary = SkNEW(FreeTypeLibrary); |
| 106 } | 167 } |
| 107 | 168 ++gFTCount; |
| 108 // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs. | 169 return gFTLibrary->library(); |
| 109 // Use default { 0x10, 0x40, 0x70, 0x40, 0x10 }, as it adds up to 0x110, sim
ulating ink spread. | |
| 110 // SetLcdFilter must be called before SetLcdFilterWeights. | |
| 111 err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); | |
| 112 if (0 == err) { | |
| 113 gLCDSupport = true; | |
| 114 gLCDExtra = 2; //Using a filter adds one full pixel to each side. | |
| 115 | |
| 116 #ifdef SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER | |
| 117 // This also adds to 0x110 simulating ink spread, but provides better re
sults than default. | |
| 118 static unsigned char gGaussianLikeHeavyWeights[] = { 0x1A, 0x43, 0x56, 0
x43, 0x1A, }; | |
| 119 | |
| 120 #if SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400 | |
| 121 err = FT_Library_SetLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeigh
ts); | |
| 122 #elif SK_CAN_USE_DLOPEN == 1 | |
| 123 //The FreeType library is already loaded, so symbols are available in pr
ocess. | |
| 124 void* self = dlopen(NULL, RTLD_LAZY); | |
| 125 if (self) { | |
| 126 FT_Library_SetLcdFilterWeightsProc setLcdFilterWeights; | |
| 127 //The following cast is non-standard, but safe for POSIX. | |
| 128 *reinterpret_cast<void**>(&setLcdFilterWeights) = dlsym(self, "FT_Li
brary_SetLcdFilterWeights"); | |
| 129 dlclose(self); | |
| 130 | |
| 131 if (setLcdFilterWeights) { | |
| 132 err = setLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights)
; | |
| 133 } | |
| 134 } | |
| 135 #endif | |
| 136 #endif | |
| 137 } | |
| 138 gLCDSupportValid = true; | |
| 139 | |
| 140 return true; | |
| 141 } | 170 } |
| 142 | 171 |
| 143 // Called while holding gFTMutex. | 172 // Caller must lock gFTMutex before calling this function. |
| 144 static void determine_lcd_support(bool* lcdSupported) { | 173 static void unref_ft_library() { |
| 145 if (!gLCDSupportValid) { | 174 gFTMutex.assertHeld(); |
| 146 // This will determine LCD support as a side effect. | 175 SkASSERT(gFTCount > 0); |
| 147 InitFreetype(); | 176 |
| 148 FT_Done_FreeType(gFTLibrary); | 177 --gFTCount; |
| 178 if (0 == gFTCount) { |
| 179 SkASSERT(NULL != gFTLibrary); |
| 180 SkDELETE(gFTLibrary); |
| 181 SkDEBUGCODE(gFTLibrary = NULL;) |
| 149 } | 182 } |
| 150 SkASSERT(gLCDSupportValid); | |
| 151 *lcdSupported = gLCDSupport; | |
| 152 } | |
| 153 | |
| 154 // Lazy, once, wrapper to ask the FreeType Library if it can support LCD text | |
| 155 static bool is_lcd_supported() { | |
| 156 static bool lcdSupported = false; | |
| 157 SkOnce(&gLCDSupportValid, &gFTMutex, determine_lcd_support, &lcdSupported); | |
| 158 return lcdSupported; | |
| 159 } | 183 } |
| 160 | 184 |
| 161 class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { | 185 class SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { |
| 162 public: | 186 public: |
| 163 SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc); | 187 SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc); |
| 164 virtual ~SkScalerContext_FreeType(); | 188 virtual ~SkScalerContext_FreeType(); |
| 165 | 189 |
| 166 bool success() const { | 190 bool success() const { |
| 167 return fFaceRec != NULL && | 191 return fFaceRec != NULL && |
| 168 fFTSize != NULL && | 192 fFTSize != NULL && |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 uint32_t fFontID; | 241 uint32_t fFontID; |
| 218 | 242 |
| 219 // assumes ownership of the stream, will call unref() when its done | 243 // assumes ownership of the stream, will call unref() when its done |
| 220 SkFaceRec(SkStream* strm, uint32_t fontID); | 244 SkFaceRec(SkStream* strm, uint32_t fontID); |
| 221 ~SkFaceRec() { | 245 ~SkFaceRec() { |
| 222 fSkStream->unref(); | 246 fSkStream->unref(); |
| 223 } | 247 } |
| 224 }; | 248 }; |
| 225 | 249 |
| 226 extern "C" { | 250 extern "C" { |
| 227 static unsigned long sk_stream_read(FT_Stream stream, | 251 static unsigned long sk_ft_stream_io(FT_Stream stream, |
| 228 unsigned long offset, | 252 unsigned long offset, |
| 229 unsigned char* buffer, | 253 unsigned char* buffer, |
| 230 unsigned long count ) { | 254 unsigned long count) |
| 255 { |
| 231 SkStream* str = (SkStream*)stream->descriptor.pointer; | 256 SkStream* str = (SkStream*)stream->descriptor.pointer; |
| 232 | 257 |
| 233 if (count) { | 258 if (count) { |
| 234 if (!str->rewind()) { | 259 if (!str->rewind()) { |
| 235 return 0; | 260 return 0; |
| 236 } else { | 261 } |
| 237 unsigned long ret; | 262 if (offset) { |
| 238 if (offset) { | 263 if (str->skip(offset) != offset) { |
| 239 ret = str->read(NULL, offset); | |
| 240 if (ret != offset) { | |
| 241 return 0; | |
| 242 } | |
| 243 } | |
| 244 ret = str->read(buffer, count); | |
| 245 if (ret != count) { | |
| 246 return 0; | 264 return 0; |
| 247 } | 265 } |
| 248 count = ret; | |
| 249 } | 266 } |
| 267 count = str->read(buffer, count); |
| 250 } | 268 } |
| 251 return count; | 269 return count; |
| 252 } | 270 } |
| 253 | 271 |
| 254 static void sk_stream_close(FT_Stream) {} | 272 static void sk_ft_stream_close(FT_Stream) {} |
| 255 } | 273 } |
| 256 | 274 |
| 257 SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) | 275 SkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) |
| 258 : fNext(NULL), fSkStream(strm), fRefCnt(1), fFontID(fontID) { | 276 : fNext(NULL), fSkStream(strm), fRefCnt(1), fFontID(fontID) { |
| 259 // SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm)); | 277 // SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm)); |
| 260 | 278 |
| 261 sk_bzero(&fFTStream, sizeof(fFTStream)); | 279 sk_bzero(&fFTStream, sizeof(fFTStream)); |
| 262 fFTStream.size = fSkStream->getLength(); | 280 fFTStream.size = fSkStream->getLength(); |
| 263 fFTStream.descriptor.pointer = fSkStream; | 281 fFTStream.descriptor.pointer = fSkStream; |
| 264 fFTStream.read = sk_stream_read; | 282 fFTStream.read = sk_ft_stream_io; |
| 265 fFTStream.close = sk_stream_close; | 283 fFTStream.close = sk_ft_stream_close; |
| 266 } | 284 } |
| 267 | 285 |
| 268 // Will return 0 on failure | 286 // Will return 0 on failure |
| 269 // Caller must lock gFTMutex before calling this function. | 287 // Caller must lock gFTMutex before calling this function. |
| 270 static SkFaceRec* ref_ft_face(const SkTypeface* typeface) { | 288 static SkFaceRec* ref_ft_face(const SkTypeface* typeface) { |
| 271 gFTMutex.assertHeld(); | 289 gFTMutex.assertHeld(); |
| 272 | 290 |
| 273 const SkFontID fontID = typeface->uniqueID(); | 291 const SkFontID fontID = typeface->uniqueID(); |
| 274 SkFaceRec* rec = gFaceRecHead; | 292 SkFaceRec* rec = gFaceRecHead; |
| 275 while (rec) { | 293 while (rec) { |
| 276 if (rec->fFontID == fontID) { | 294 if (rec->fFontID == fontID) { |
| 277 SkASSERT(rec->fFace); | 295 SkASSERT(rec->fFace); |
| 278 rec->fRefCnt += 1; | 296 rec->fRefCnt += 1; |
| 279 return rec; | 297 return rec; |
| 280 } | 298 } |
| 281 rec = rec->fNext; | 299 rec = rec->fNext; |
| 282 } | 300 } |
| 283 | 301 |
| 284 int face_index; | 302 int face_index; |
| 285 SkStream* strm = typeface->openStream(&face_index); | 303 SkStream* strm = typeface->openStream(&face_index); |
| 286 if (NULL == strm) { | 304 if (NULL == strm) { |
| 287 return NULL; | 305 return NULL; |
| 288 } | 306 } |
| 289 | 307 |
| 290 // this passes ownership of strm to the rec | 308 // this passes ownership of strm to the rec |
| 291 rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); | 309 rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); |
| 292 | 310 |
| 293 FT_Open_Args args; | 311 FT_Open_Args args; |
| 294 memset(&args, 0, sizeof(args)); | 312 memset(&args, 0, sizeof(args)); |
| 295 const void* memoryBase = strm->getMemoryBase(); | 313 const void* memoryBase = strm->getMemoryBase(); |
| 296 | 314 |
| 297 if (memoryBase) { | 315 if (memoryBase) { |
| 298 args.flags = FT_OPEN_MEMORY; | 316 args.flags = FT_OPEN_MEMORY; |
| 299 args.memory_base = (const FT_Byte*)memoryBase; | 317 args.memory_base = (const FT_Byte*)memoryBase; |
| 300 args.memory_size = strm->getLength(); | 318 args.memory_size = strm->getLength(); |
| 301 } else { | 319 } else { |
| 302 args.flags = FT_OPEN_STREAM; | 320 args.flags = FT_OPEN_STREAM; |
| 303 args.stream = &rec->fFTStream; | 321 args.stream = &rec->fFTStream; |
| 304 } | 322 } |
| 305 | 323 |
| 306 FT_Error err = FT_Open_Face(gFTLibrary, &args, face_index, &rec->fFace); | 324 FT_Error err = FT_Open_Face(gFTLibrary->library(), &args, face_index, &rec->
fFace); |
| 307 if (err) { // bad filename, try the default font | 325 if (err) { // bad filename, try the default font |
| 308 SkDEBUGF(("ERROR: unable to open font '%x'\n", fontID)); | 326 SkDEBUGF(("ERROR: unable to open font '%x'\n", fontID)); |
| 309 SkDELETE(rec); | 327 SkDELETE(rec); |
| 310 return NULL; | 328 return NULL; |
| 311 } else { | |
| 312 SkASSERT(rec->fFace); | |
| 313 rec->fNext = gFaceRecHead; | |
| 314 gFaceRecHead = rec; | |
| 315 return rec; | |
| 316 } | 329 } |
| 330 SkASSERT(rec->fFace); |
| 331 rec->fNext = gFaceRecHead; |
| 332 gFaceRecHead = rec; |
| 333 return rec; |
| 317 } | 334 } |
| 318 | 335 |
| 319 // Caller must lock gFTMutex before calling this function. | 336 // Caller must lock gFTMutex before calling this function. |
| 320 static void unref_ft_face(FT_Face face) { | 337 static void unref_ft_face(FT_Face face) { |
| 321 gFTMutex.assertHeld(); | 338 gFTMutex.assertHeld(); |
| 322 | 339 |
| 323 SkFaceRec* rec = gFaceRecHead; | 340 SkFaceRec* rec = gFaceRecHead; |
| 324 SkFaceRec* prev = NULL; | 341 SkFaceRec* prev = NULL; |
| 325 while (rec) { | 342 while (rec) { |
| 326 SkFaceRec* next = rec->fNext; | 343 SkFaceRec* next = rec->fNext; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 339 prev = rec; | 356 prev = rec; |
| 340 rec = next; | 357 rec = next; |
| 341 } | 358 } |
| 342 SkDEBUGFAIL("shouldn't get here, face not in list"); | 359 SkDEBUGFAIL("shouldn't get here, face not in list"); |
| 343 } | 360 } |
| 344 | 361 |
| 345 class AutoFTAccess { | 362 class AutoFTAccess { |
| 346 public: | 363 public: |
| 347 AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { | 364 AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { |
| 348 gFTMutex.acquire(); | 365 gFTMutex.acquire(); |
| 349 if (1 == ++gFTCount) { | 366 if (!ref_ft_library()) { |
| 350 if (!InitFreetype()) { | 367 sk_throw(); |
| 351 sk_throw(); | |
| 352 } | |
| 353 } | 368 } |
| 354 fRec = ref_ft_face(tf); | 369 fRec = ref_ft_face(tf); |
| 355 if (fRec) { | 370 if (fRec) { |
| 356 fFace = fRec->fFace; | 371 fFace = fRec->fFace; |
| 357 } | 372 } |
| 358 } | 373 } |
| 359 | 374 |
| 360 ~AutoFTAccess() { | 375 ~AutoFTAccess() { |
| 361 if (fFace) { | 376 if (fFace) { |
| 362 unref_ft_face(fFace); | 377 unref_ft_face(fFace); |
| 363 } | 378 } |
| 364 if (0 == --gFTCount) { | 379 unref_ft_library(); |
| 365 FT_Done_FreeType(gFTLibrary); | |
| 366 } | |
| 367 gFTMutex.release(); | 380 gFTMutex.release(); |
| 368 } | 381 } |
| 369 | 382 |
| 370 SkFaceRec* rec() { return fRec; } | 383 SkFaceRec* rec() { return fRec; } |
| 371 FT_Face face() { return fFace; } | 384 FT_Face face() { return fFace; } |
| 372 | 385 |
| 373 private: | 386 private: |
| 374 SkFaceRec* fRec; | 387 SkFaceRec* fRec; |
| 375 FT_Face fFace; | 388 FT_Face fFace; |
| 376 }; | 389 }; |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 } | 690 } |
| 678 | 691 |
| 679 void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { | 692 void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { |
| 680 //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 | 693 //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 |
| 681 //Cap the requested size as larger sizes give bogus values. | 694 //Cap the requested size as larger sizes give bogus values. |
| 682 //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. | 695 //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. |
| 683 if (rec->fTextSize > SkIntToScalar(1 << 14)) { | 696 if (rec->fTextSize > SkIntToScalar(1 << 14)) { |
| 684 rec->fTextSize = SkIntToScalar(1 << 14); | 697 rec->fTextSize = SkIntToScalar(1 << 14); |
| 685 } | 698 } |
| 686 | 699 |
| 687 if (!is_lcd_supported() && isLCD(*rec)) { | 700 AutoFTAccess fta(this); |
| 701 if (!gFTLibrary->isLCDSupported() && isLCD(*rec)) { |
| 688 // If the runtime Freetype library doesn't support LCD mode, we disable | 702 // If the runtime Freetype library doesn't support LCD mode, we disable |
| 689 // it here. | 703 // it here. |
| 690 rec->fMaskFormat = SkMask::kA8_Format; | 704 rec->fMaskFormat = SkMask::kA8_Format; |
| 691 } | 705 } |
| 692 | 706 |
| 693 SkPaint::Hinting h = rec->getHinting(); | 707 SkPaint::Hinting h = rec->getHinting(); |
| 694 if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { | 708 if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { |
| 695 // collapse full->normal hinting if we're not doing LCD | 709 // collapse full->normal hinting if we're not doing LCD |
| 696 h = SkPaint::kNormal_Hinting; | 710 h = SkPaint::kNormal_Hinting; |
| 697 } | 711 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 } | 796 } |
| 783 } | 797 } |
| 784 return chosenStrikeIndex; | 798 return chosenStrikeIndex; |
| 785 } | 799 } |
| 786 | 800 |
| 787 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, | 801 SkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, |
| 788 const SkDescriptor* desc) | 802 const SkDescriptor* desc) |
| 789 : SkScalerContext_FreeType_Base(typeface, desc) { | 803 : SkScalerContext_FreeType_Base(typeface, desc) { |
| 790 SkAutoMutexAcquire ac(gFTMutex); | 804 SkAutoMutexAcquire ac(gFTMutex); |
| 791 | 805 |
| 792 if (gFTCount == 0) { | 806 if (!ref_ft_library()) { |
| 793 if (!InitFreetype()) { | 807 sk_throw(); |
| 794 sk_throw(); | |
| 795 } | |
| 796 } | 808 } |
| 797 ++gFTCount; | |
| 798 | 809 |
| 799 // load the font file | 810 // load the font file |
| 800 fStrikeIndex = -1; | 811 fStrikeIndex = -1; |
| 801 fFTSize = NULL; | 812 fFTSize = NULL; |
| 802 fFace = NULL; | 813 fFace = NULL; |
| 803 fFaceRec = ref_ft_face(typeface); | 814 fFaceRec = ref_ft_face(typeface); |
| 804 if (NULL == fFaceRec) { | 815 if (NULL == fFaceRec) { |
| 805 return; | 816 return; |
| 806 } | 817 } |
| 807 fFace = fFaceRec->fFace; | 818 fFace = fFaceRec->fFace; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 SkScalerContext_FreeType::~SkScalerContext_FreeType() { | 994 SkScalerContext_FreeType::~SkScalerContext_FreeType() { |
| 984 SkAutoMutexAcquire ac(gFTMutex); | 995 SkAutoMutexAcquire ac(gFTMutex); |
| 985 | 996 |
| 986 if (fFTSize != NULL) { | 997 if (fFTSize != NULL) { |
| 987 FT_Done_Size(fFTSize); | 998 FT_Done_Size(fFTSize); |
| 988 } | 999 } |
| 989 | 1000 |
| 990 if (fFace != NULL) { | 1001 if (fFace != NULL) { |
| 991 unref_ft_face(fFace); | 1002 unref_ft_face(fFace); |
| 992 } | 1003 } |
| 993 if (--gFTCount == 0) { | 1004 |
| 994 FT_Done_FreeType(gFTLibrary); | 1005 unref_ft_library(); |
| 995 SkDEBUGCODE(gFTLibrary = NULL;) | |
| 996 } | |
| 997 } | 1006 } |
| 998 | 1007 |
| 999 /* We call this before each use of the fFace, since we may be sharing | 1008 /* We call this before each use of the fFace, since we may be sharing |
| 1000 this face with other context (at different sizes). | 1009 this face with other context (at different sizes). |
| 1001 */ | 1010 */ |
| 1002 FT_Error SkScalerContext_FreeType::setupSize() { | 1011 FT_Error SkScalerContext_FreeType::setupSize() { |
| 1003 FT_Error err = FT_Activate_Size(fFTSize); | 1012 FT_Error err = FT_Activate_Size(fFTSize); |
| 1004 if (err != 0) { | 1013 if (err != 0) { |
| 1005 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re
turned 0x%x\n", | 1014 SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) re
turned 0x%x\n", |
| 1006 fFaceRec->fFontID, fScaleX, fScaleY, err)); | 1015 fFaceRec->fFontID, fScaleX, fScaleY, err)); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 return false; | 1126 return false; |
| 1118 } | 1127 } |
| 1119 emboldenIfNeeded(fFace, fFace->glyph); | 1128 emboldenIfNeeded(fFace, fFace->glyph); |
| 1120 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); | 1129 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); |
| 1121 return true; | 1130 return true; |
| 1122 } | 1131 } |
| 1123 | 1132 |
| 1124 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { | 1133 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { |
| 1125 if (isLCD(fRec)) { | 1134 if (isLCD(fRec)) { |
| 1126 if (fLCDIsVert) { | 1135 if (fLCDIsVert) { |
| 1127 glyph->fHeight += gLCDExtra; | 1136 glyph->fHeight += gFTLibrary->lcdExtra(); |
| 1128 glyph->fTop -= gLCDExtra >> 1; | 1137 glyph->fTop -= gFTLibrary->lcdExtra() >> 1; |
| 1129 } else { | 1138 } else { |
| 1130 glyph->fWidth += gLCDExtra; | 1139 glyph->fWidth += gFTLibrary->lcdExtra(); |
| 1131 glyph->fLeft -= gLCDExtra >> 1; | 1140 glyph->fLeft -= gFTLibrary->lcdExtra() >> 1; |
| 1132 } | 1141 } |
| 1133 } | 1142 } |
| 1134 } | 1143 } |
| 1135 | 1144 |
| 1136 inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) { | 1145 inline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) { |
| 1137 glyph.fWidth *= scale; | 1146 glyph.fWidth *= scale; |
| 1138 glyph.fHeight *= scale; | 1147 glyph.fHeight *= scale; |
| 1139 glyph.fTop *= scale; | 1148 glyph.fTop *= scale; |
| 1140 glyph.fLeft *= scale; | 1149 glyph.fLeft *= scale; |
| 1141 | 1150 |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 return 0; | 1606 return 0; |
| 1598 } | 1607 } |
| 1599 } | 1608 } |
| 1600 | 1609 |
| 1601 return size; | 1610 return size; |
| 1602 } | 1611 } |
| 1603 | 1612 |
| 1604 /////////////////////////////////////////////////////////////////////////////// | 1613 /////////////////////////////////////////////////////////////////////////////// |
| 1605 /////////////////////////////////////////////////////////////////////////////// | 1614 /////////////////////////////////////////////////////////////////////////////// |
| 1606 | 1615 |
| 1607 | 1616 SkTypeface_FreeType::Scanner::Scanner() : fLibrary(NULL) { |
| 1608 SkTypeface_FreeType::Scanner::Scanner() { | 1617 if (FT_New_Library(&gFTMemory, &fLibrary)) { |
| 1609 if (FT_Init_FreeType(&fLibrary)) { | 1618 return; |
| 1610 fLibrary = NULL; | |
| 1611 } | 1619 } |
| 1620 FT_Add_Default_Modules(fLibrary); |
| 1612 } | 1621 } |
| 1613 SkTypeface_FreeType::Scanner::~Scanner() { | 1622 SkTypeface_FreeType::Scanner::~Scanner() { |
| 1614 FT_Done_FreeType(fLibrary); | 1623 if (fLibrary) { |
| 1624 FT_Done_Library(fLibrary); |
| 1625 } |
| 1615 } | 1626 } |
| 1616 | 1627 |
| 1617 FT_Face SkTypeface_FreeType::Scanner::openFace(SkStream* stream, int ttcIndex, | 1628 FT_Face SkTypeface_FreeType::Scanner::openFace(SkStream* stream, int ttcIndex, |
| 1618 FT_Stream ftStream) const | 1629 FT_Stream ftStream) const |
| 1619 { | 1630 { |
| 1620 if (fLibrary == NULL) { | 1631 if (fLibrary == NULL) { |
| 1621 return NULL; | 1632 return NULL; |
| 1622 } | 1633 } |
| 1623 | 1634 |
| 1624 FT_Open_Args args; | 1635 FT_Open_Args args; |
| 1625 memset(&args, 0, sizeof(args)); | 1636 memset(&args, 0, sizeof(args)); |
| 1626 | 1637 |
| 1627 const void* memoryBase = stream->getMemoryBase(); | 1638 const void* memoryBase = stream->getMemoryBase(); |
| 1628 | 1639 |
| 1629 if (memoryBase) { | 1640 if (memoryBase) { |
| 1630 args.flags = FT_OPEN_MEMORY; | 1641 args.flags = FT_OPEN_MEMORY; |
| 1631 args.memory_base = (const FT_Byte*)memoryBase; | 1642 args.memory_base = (const FT_Byte*)memoryBase; |
| 1632 args.memory_size = stream->getLength(); | 1643 args.memory_size = stream->getLength(); |
| 1633 } else { | 1644 } else { |
| 1634 memset(ftStream, 0, sizeof(*ftStream)); | 1645 memset(ftStream, 0, sizeof(*ftStream)); |
| 1635 ftStream->size = stream->getLength(); | 1646 ftStream->size = stream->getLength(); |
| 1636 ftStream->descriptor.pointer = stream; | 1647 ftStream->descriptor.pointer = stream; |
| 1637 ftStream->read = sk_stream_read; | 1648 ftStream->read = sk_ft_stream_io; |
| 1638 ftStream->close = sk_stream_close; | 1649 ftStream->close = sk_ft_stream_close; |
| 1639 | 1650 |
| 1640 args.flags = FT_OPEN_STREAM; | 1651 args.flags = FT_OPEN_STREAM; |
| 1641 args.stream = ftStream; | 1652 args.stream = ftStream; |
| 1642 } | 1653 } |
| 1643 | 1654 |
| 1644 FT_Face face; | 1655 FT_Face face; |
| 1645 if (FT_Open_Face(fLibrary, &args, ttcIndex, &face)) { | 1656 if (FT_Open_Face(fLibrary, &args, ttcIndex, &face)) { |
| 1646 return NULL; | 1657 return NULL; |
| 1647 } | 1658 } |
| 1648 return face; | 1659 return face; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1736 if (style) { | 1747 if (style) { |
| 1737 *style = SkFontStyle(weight, width, slant); | 1748 *style = SkFontStyle(weight, width, slant); |
| 1738 } | 1749 } |
| 1739 if (isFixedPitch) { | 1750 if (isFixedPitch) { |
| 1740 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1751 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
| 1741 } | 1752 } |
| 1742 | 1753 |
| 1743 FT_Done_Face(face); | 1754 FT_Done_Face(face); |
| 1744 return true; | 1755 return true; |
| 1745 } | 1756 } |
| OLD | NEW |