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

Side by Side Diff: src/ports/SkFontHost_FreeType.cpp

Issue 742483004: Clean up FreeType library ref counting. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Line lengths. Created 6 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698