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 |