OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2006 The Android Open Source Project | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkFontHost.h" | |
9 #include "SkFontHost_FreeType_common.h" | |
10 #include "SkFontDescriptor.h" | |
11 #include "SkGraphics.h" | |
12 #include "SkDescriptor.h" | |
13 #include "SkPaint.h" | |
14 #include "SkString.h" | |
15 #include "SkStream.h" | |
16 #include "SkThread.h" | |
17 #include "SkTSearch.h" | |
18 #include "SkTypeface_android.h" | |
19 #include "FontHostConfiguration_android.h" | |
20 | |
21 #ifndef SK_FONT_FILE_PREFIX | |
22 #define SK_FONT_FILE_PREFIX "/fonts/" | |
23 #endif | |
24 | |
25 #ifndef SK_DEBUG_FONTS | |
26 #define SK_DEBUG_FONTS 0 | |
27 #endif | |
28 | |
29 // For test only. | |
30 static const char* gTestMainConfigFile = NULL; | |
31 static const char* gTestFallbackConfigFile = NULL; | |
32 static const char* gTestFontFilePrefix = NULL; | |
33 | |
34 bool find_name_and_attributes(SkStream* stream, SkString* name, | |
35 SkTypeface::Style* style, bool* isFixedPitch); | |
36 | |
37 static void GetFullPathForSysFonts(SkString* full, const char name[]) { | |
38 if (gTestFontFilePrefix) { | |
39 full->set(gTestFontFilePrefix); | |
40 } else { | |
41 full->set(getenv("ANDROID_ROOT")); | |
42 full->append(SK_FONT_FILE_PREFIX); | |
43 } | |
44 full->append(name); | |
45 } | |
46 | |
47 /////////////////////////////////////////////////////////////////////////////// | |
48 | |
49 struct FamilyRec; | |
50 | |
51 /* This guy holds a mapping of a name -> family, used for looking up fonts. | |
52 Since it is stored in a stretchy array that doesn't preserve object | |
53 semantics, we don't use constructor/destructors, but just have explicit | |
54 helpers to manage our internal bookkeeping. | |
55 */ | |
56 struct NameFamilyPair { | |
57 const char* fName; // we own this | |
58 FamilyRec* fFamily; // we don't own this, we just reference it | |
59 | |
60 void construct(const char name[], FamilyRec* family) { | |
61 fName = strdup(name); | |
62 fFamily = family; // we don't own this, so just record the referene | |
63 } | |
64 | |
65 void destruct() { | |
66 free((char*)fName); | |
67 // we don't own family, so just ignore our reference | |
68 } | |
69 }; | |
70 typedef SkTDArray<NameFamilyPair> NameFamilyPairList; | |
71 | |
72 // we use atomic_inc to grow this for each typeface we create | |
73 static int32_t gUniqueFontID; | |
74 | |
75 // this is the mutex that protects gFamilyHead and GetNameList() | |
76 SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex); | |
77 static FamilyRec* gFamilyHead; | |
78 | |
79 static NameFamilyPairList& GetNameList() { | |
80 /* | |
81 * It is assumed that the caller has already acquired a lock on | |
82 * gFamilyHeadAndNameListMutex before calling this. | |
83 */ | |
84 static NameFamilyPairList* gNameList; | |
85 if (NULL == gNameList) { | |
86 gNameList = SkNEW(NameFamilyPairList); | |
87 // register a delete proc with sk_atexit(..) when available | |
88 } | |
89 return *gNameList; | |
90 } | |
91 | |
92 struct FamilyRec { | |
93 FamilyRec* fNext; | |
94 SkTypeface* fFaces[4]; | |
95 | |
96 FamilyRec() | |
97 { | |
98 fNext = gFamilyHead; | |
99 memset(fFaces, 0, sizeof(fFaces)); | |
100 gFamilyHead = this; | |
101 } | |
102 }; | |
103 | |
104 static SkTypeface* find_best_face(const FamilyRec* family, | |
105 SkTypeface::Style style) { | |
106 SkTypeface* const* faces = family->fFaces; | |
107 | |
108 if (faces[style] != NULL) { // exact match | |
109 return faces[style]; | |
110 } | |
111 // look for a matching bold | |
112 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); | |
113 if (faces[style] != NULL) { | |
114 return faces[style]; | |
115 } | |
116 // look for the plain | |
117 if (faces[SkTypeface::kNormal] != NULL) { | |
118 return faces[SkTypeface::kNormal]; | |
119 } | |
120 // look for anything | |
121 for (int i = 0; i < 4; i++) { | |
122 if (faces[i] != NULL) { | |
123 return faces[i]; | |
124 } | |
125 } | |
126 // should never get here, since the faces list should not be empty | |
127 SkDEBUGFAIL("faces list is empty"); | |
128 return NULL; | |
129 } | |
130 | |
131 static FamilyRec* find_family(const SkTypeface* member) { | |
132 FamilyRec* curr = gFamilyHead; | |
133 while (curr != NULL) { | |
134 for (int i = 0; i < 4; i++) { | |
135 if (curr->fFaces[i] == member) { | |
136 return curr; | |
137 } | |
138 } | |
139 curr = curr->fNext; | |
140 } | |
141 return NULL; | |
142 } | |
143 | |
144 // gFamilyHeadAndNameListMutex must already be acquired | |
145 static const char* find_family_name(const SkTypeface* member) { | |
146 FamilyRec* family = find_family(member); | |
147 if (NULL == family) { | |
148 return NULL; | |
149 } | |
150 | |
151 NameFamilyPairList& namelist = GetNameList(); | |
152 NameFamilyPair* list = namelist.begin(); | |
153 int count = namelist.count(); | |
154 | |
155 for (int i = 0; i < count; i++) { | |
156 NameFamilyPair* pair = &list[i]; | |
157 if (pair->fFamily == family) { | |
158 return pair->fName; | |
159 } | |
160 } | |
161 | |
162 return NULL; | |
163 } | |
164 | |
165 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt | |
166 is not modified. | |
167 */ | |
168 static SkTypeface* find_from_uniqueID(uint32_t uniqueID) { | |
169 FamilyRec* curr = gFamilyHead; | |
170 while (curr != NULL) { | |
171 for (int i = 0; i < 4; i++) { | |
172 SkTypeface* face = curr->fFaces[i]; | |
173 if (face != NULL && face->uniqueID() == uniqueID) { | |
174 return face; | |
175 } | |
176 } | |
177 curr = curr->fNext; | |
178 } | |
179 return NULL; | |
180 } | |
181 | |
182 /* Remove reference to this face from its family. If the resulting family | |
183 is empty (has no faces), return that family, otherwise return NULL | |
184 */ | |
185 static FamilyRec* remove_from_family(const SkTypeface* face) { | |
186 FamilyRec* family = find_family(face); | |
187 if (family) { | |
188 SkASSERT(family->fFaces[face->style()] == face); | |
189 family->fFaces[face->style()] = NULL; | |
190 | |
191 for (int i = 0; i < 4; i++) { | |
192 if (family->fFaces[i] != NULL) { // family is non-empty | |
193 return NULL; | |
194 } | |
195 } | |
196 } else { | |
197 // SkDebugf("remove_from_family(%p) face not found", face); | |
198 } | |
199 return family; // return the empty family | |
200 } | |
201 | |
202 // maybe we should make FamilyRec be doubly-linked | |
203 static void detach_and_delete_family(FamilyRec* family) { | |
204 FamilyRec* curr = gFamilyHead; | |
205 FamilyRec* prev = NULL; | |
206 | |
207 while (curr != NULL) { | |
208 FamilyRec* next = curr->fNext; | |
209 if (curr == family) { | |
210 if (prev == NULL) { | |
211 gFamilyHead = next; | |
212 } else { | |
213 prev->fNext = next; | |
214 } | |
215 SkDELETE(family); | |
216 return; | |
217 } | |
218 prev = curr; | |
219 curr = next; | |
220 } | |
221 SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); | |
222 } | |
223 | |
224 // gFamilyHeadAndNameListMutex must already be acquired | |
225 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { | |
226 NameFamilyPairList& namelist = GetNameList(); | |
227 NameFamilyPair* list = namelist.begin(); | |
228 int count = namelist.count(); | |
229 | |
230 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); | |
231 | |
232 if (index >= 0) { | |
233 return find_best_face(list[index].fFamily, style); | |
234 } | |
235 return NULL; | |
236 } | |
237 | |
238 // gFamilyHeadAndNameListMutex must already be acquired | |
239 static SkTypeface* find_typeface(const SkTypeface* familyMember, | |
240 SkTypeface::Style style) { | |
241 const FamilyRec* family = find_family(familyMember); | |
242 return family ? find_best_face(family, style) : NULL; | |
243 } | |
244 | |
245 // gFamilyHeadAndNameListMutex must already be acquired | |
246 static void add_name(const char name[], FamilyRec* family) { | |
247 SkAutoAsciiToLC tolc(name); | |
248 name = tolc.lc(); | |
249 | |
250 NameFamilyPairList& namelist = GetNameList(); | |
251 NameFamilyPair* list = namelist.begin(); | |
252 int count = namelist.count(); | |
253 | |
254 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); | |
255 | |
256 if (index < 0) { | |
257 list = namelist.insert(~index); | |
258 list->construct(name, family); | |
259 } | |
260 } | |
261 | |
262 // gFamilyHeadAndNameListMutex must already be acquired | |
263 static void remove_from_names(FamilyRec* emptyFamily) { | |
264 #ifdef SK_DEBUG | |
265 for (int i = 0; i < 4; i++) { | |
266 SkASSERT(emptyFamily->fFaces[i] == NULL); | |
267 } | |
268 #endif | |
269 | |
270 SkTDArray<NameFamilyPair>& list = GetNameList(); | |
271 | |
272 // must go backwards when removing | |
273 for (int i = list.count() - 1; i >= 0; --i) { | |
274 NameFamilyPair* pair = &list[i]; | |
275 if (pair->fFamily == emptyFamily) { | |
276 pair->destruct(); | |
277 list.remove(i); | |
278 } | |
279 } | |
280 } | |
281 | |
282 /////////////////////////////////////////////////////////////////////////////// | |
283 | |
284 class FamilyTypeface : public SkTypeface_FreeType { | |
285 public: | |
286 FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember, | |
287 bool isFixedPitch) | |
288 : INHERITED(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedPitch) { | |
289 fIsSysFont = sysFont; | |
290 | |
291 // our caller has acquired the gFamilyHeadAndNameListMutex so this is sa
fe | |
292 FamilyRec* rec = NULL; | |
293 if (familyMember) { | |
294 rec = find_family(familyMember); | |
295 SkASSERT(rec); | |
296 } else { | |
297 rec = SkNEW(FamilyRec); | |
298 } | |
299 rec->fFaces[style] = this; | |
300 } | |
301 | |
302 virtual ~FamilyTypeface() { | |
303 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
304 | |
305 // remove us from our family. If the family is now empty, we return | |
306 // that and then remove that family from the name list | |
307 FamilyRec* family = remove_from_family(this); | |
308 if (NULL != family) { | |
309 remove_from_names(family); | |
310 detach_and_delete_family(family); | |
311 } | |
312 } | |
313 | |
314 bool isSysFont() const { return fIsSysFont; } | |
315 | |
316 virtual const char* getUniqueString() const = 0; | |
317 virtual const char* getFilePath() const = 0; | |
318 | |
319 protected: | |
320 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; | |
321 | |
322 private: | |
323 bool fIsSysFont; | |
324 | |
325 typedef SkTypeface_FreeType INHERITED; | |
326 }; | |
327 | |
328 /////////////////////////////////////////////////////////////////////////////// | |
329 | |
330 class StreamTypeface : public FamilyTypeface { | |
331 public: | |
332 StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember, | |
333 SkStream* stream, bool isFixedPitch) | |
334 : INHERITED(style, sysFont, familyMember, isFixedPitch) { | |
335 SkASSERT(stream); | |
336 stream->ref(); | |
337 fStream = stream; | |
338 } | |
339 virtual ~StreamTypeface() { | |
340 fStream->unref(); | |
341 } | |
342 | |
343 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } | |
344 virtual const char* getFilePath() const SK_OVERRIDE { return NULL; } | |
345 | |
346 protected: | |
347 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | |
348 *ttcIndex = 0; | |
349 // we just ref our existing stream, since the caller will call unref() | |
350 // when they are through | |
351 fStream->ref(); | |
352 // must rewind each time, since the caller assumes a "new" stream | |
353 fStream->rewind(); | |
354 return fStream; | |
355 } | |
356 | |
357 private: | |
358 SkStream* fStream; | |
359 | |
360 typedef FamilyTypeface INHERITED; | |
361 }; | |
362 | |
363 class FileTypeface : public FamilyTypeface { | |
364 public: | |
365 FileTypeface(Style style, bool sysFont, SkTypeface* familyMember, | |
366 const char path[], bool isFixedPitch) | |
367 : INHERITED(style, sysFont, familyMember, isFixedPitch) { | |
368 SkString fullpath; | |
369 | |
370 if (sysFont) { | |
371 GetFullPathForSysFonts(&fullpath, path); | |
372 path = fullpath.c_str(); | |
373 } | |
374 fPath.set(path); | |
375 } | |
376 | |
377 virtual const char* getUniqueString() const SK_OVERRIDE { | |
378 const char* str = strrchr(fPath.c_str(), '/'); | |
379 if (str) { | |
380 str += 1; // skip the '/' | |
381 } | |
382 return str; | |
383 } | |
384 | |
385 virtual const char* getFilePath() const SK_OVERRIDE { | |
386 return fPath.c_str(); | |
387 } | |
388 | |
389 protected: | |
390 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | |
391 *ttcIndex = 0; | |
392 return SkStream::NewFromFile(fPath.c_str()); | |
393 } | |
394 | |
395 private: | |
396 SkString fPath; | |
397 | |
398 typedef FamilyTypeface INHERITED; | |
399 }; | |
400 | |
401 /////////////////////////////////////////////////////////////////////////////// | |
402 /////////////////////////////////////////////////////////////////////////////// | |
403 | |
404 static bool get_name_and_style(const char path[], SkString* name, | |
405 SkTypeface::Style* style, | |
406 bool* isFixedPitch, bool isExpected) { | |
407 SkString fullpath; | |
408 GetFullPathForSysFonts(&fullpath, path); | |
409 | |
410 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(fullpath.c_str())); | |
411 if (stream.get()) { | |
412 return find_name_and_attributes(stream, name, style, isFixedPitch); | |
413 } else { | |
414 if (isExpected) { | |
415 SkDebugf("---- failed to open <%s> as a font", fullpath.c_str()); | |
416 } | |
417 return false; | |
418 } | |
419 } | |
420 | |
421 // used to record our notion of the pre-existing fonts | |
422 struct FontInitRec { | |
423 const char* fFileName; | |
424 const char* const* fNames; // null-terminated list | |
425 }; | |
426 | |
427 // deliberately empty, but we use the address to identify fallback fonts | |
428 static const char* gFBNames[] = { NULL }; | |
429 | |
430 /* Fonts are grouped by family, with the first font in a family having the | |
431 list of names (even if that list is empty), and the following members having | |
432 null for the list. The names list must be NULL-terminated. | |
433 */ | |
434 static FontInitRec *gSystemFonts; | |
435 static size_t gNumSystemFonts = 0; | |
436 | |
437 // these globals are assigned (once) by load_system_fonts() | |
438 static FamilyRec* gDefaultFamily; | |
439 static SkTypeface* gDefaultNormal; | |
440 static char** gDefaultNames = NULL; | |
441 static uint32_t *gFallbackFonts; | |
442 | |
443 #if SK_DEBUG_FONTS | |
444 static void dump_globals() { | |
445 SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal, | |
446 gDefaultNormal ? gDefaultNormal->uniqueID() : 0, | |
447 gDefaultNormal ? gDefaultNormal->getRefCnt() : 0); | |
448 | |
449 if (gDefaultFamily) { | |
450 SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", | |
451 gDefaultFamily, | |
452 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID
() : 0, | |
453 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID
() : 0, | |
454 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID
() : 0, | |
455 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID
() : 0, | |
456 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCn
t() : 0, | |
457 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCn
t() : 0, | |
458 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCn
t() : 0, | |
459 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCn
t() : 0); | |
460 } else { | |
461 SkDebugf("gDefaultFamily=%p", gDefaultFamily); | |
462 } | |
463 | |
464 SkDebugf("gNumSystemFonts=%d gSystemFonts=%p gFallbackFonts=%p", | |
465 gNumSystemFonts, gSystemFonts, gFallbackFonts); | |
466 | |
467 for (size_t i = 0; i < gNumSystemFonts; ++i) { | |
468 SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName); | |
469 size_t namesIndex = 0; | |
470 if (gSystemFonts[i].fNames) | |
471 for (const char* fontName = gSystemFonts[i].fNames[namesIndex]; | |
472 fontName != 0; | |
473 fontName = gSystemFonts[i].fNames[++namesIndex]) { | |
474 SkDebugf(" name[%u]=%s", namesIndex, fontName); | |
475 } | |
476 } | |
477 | |
478 if (gFamilyHead) { | |
479 FamilyRec* rec = gFamilyHead; | |
480 int i=0; | |
481 while (rec) { | |
482 SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%
d}", | |
483 i++, rec, | |
484 rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0, | |
485 rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0, | |
486 rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0, | |
487 rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0, | |
488 rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0, | |
489 rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0, | |
490 rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0, | |
491 rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0); | |
492 rec = rec->fNext; | |
493 } | |
494 } else { | |
495 SkDebugf("gFamilyHead=%p", gFamilyHead); | |
496 } | |
497 | |
498 } | |
499 #endif | |
500 | |
501 | |
502 /* Load info from a configuration file that populates the system/fallback font
structures | |
503 */ | |
504 static void load_font_info() { | |
505 SkTDArray<FontFamily*> fontFamilies; | |
506 if (gTestMainConfigFile) { | |
507 getTestFontFamilies(fontFamilies, gTestMainConfigFile, gTestFallbackConf
igFile); | |
508 } else { | |
509 getFontFamilies(fontFamilies); | |
510 } | |
511 | |
512 SkTDArray<FontInitRec> fontInfo; | |
513 for (int i = 0; i < fontFamilies.count(); ++i) { | |
514 FontFamily *family = fontFamilies[i]; | |
515 for (int j = 0; j < family->fFileNames.count(); ++j) { | |
516 FontInitRec fontInfoRecord; | |
517 fontInfoRecord.fFileName = family->fFileNames[j]; | |
518 if (j == 0) { | |
519 if (family->fNames.count() == 0) { | |
520 // Fallback font | |
521 fontInfoRecord.fNames = (char **)gFBNames; | |
522 } else { | |
523 SkTDArray<const char*> names = family->fNames; | |
524 const char **nameList = (const char**) | |
525 malloc((names.count() + 1) * sizeof(char*)); | |
526 if (nameList == NULL) { | |
527 // shouldn't get here | |
528 SkDEBUGFAIL("Failed to allocate nameList"); | |
529 break; | |
530 } | |
531 if (gDefaultNames == NULL) { | |
532 gDefaultNames = (char**) nameList; | |
533 } | |
534 for (int i = 0; i < names.count(); ++i) { | |
535 nameList[i] = names[i]; | |
536 } | |
537 nameList[names.count()] = NULL; | |
538 fontInfoRecord.fNames = nameList; | |
539 } | |
540 } else { | |
541 fontInfoRecord.fNames = NULL; | |
542 } | |
543 *fontInfo.append() = fontInfoRecord; | |
544 } | |
545 } | |
546 gNumSystemFonts = fontInfo.count(); | |
547 gSystemFonts = (FontInitRec*) malloc(gNumSystemFonts * sizeof(FontInitRec)); | |
548 gFallbackFonts = (uint32_t*) malloc((gNumSystemFonts + 1) * sizeof(uint32_t)
); | |
549 if (gSystemFonts == NULL) { | |
550 // shouldn't get here | |
551 SkDEBUGFAIL("No system fonts were found"); | |
552 gNumSystemFonts = 0; | |
553 } | |
554 | |
555 #if SK_DEBUG_FONTS | |
556 SkDebugf("---- We have %d system fonts", gNumSystemFonts); | |
557 #endif | |
558 for (size_t i = 0; i < gNumSystemFonts; ++i) { | |
559 gSystemFonts[i].fFileName = fontInfo[i].fFileName; | |
560 gSystemFonts[i].fNames = fontInfo[i].fNames; | |
561 #if SK_DEBUG_FONTS | |
562 SkDebugf("---- gSystemFonts[%d] fileName=%s", i, fontInfo[i].fFileName); | |
563 #endif | |
564 } | |
565 fontFamilies.deleteAll(); | |
566 } | |
567 | |
568 /* | |
569 * Called once (ensured by the sentinel check at the beginning of our body). | |
570 * Initializes all the globals, and register the system fonts. | |
571 * | |
572 * gFamilyHeadAndNameListMutex must already be acquired. | |
573 */ | |
574 static void init_system_fonts() { | |
575 // check if we've already been called | |
576 if (gDefaultNormal) { | |
577 return; | |
578 } | |
579 | |
580 SkASSERT(gUniqueFontID == 0); | |
581 | |
582 load_font_info(); | |
583 | |
584 FontInitRec* rec = gSystemFonts; | |
585 SkTypeface* firstInFamily = NULL; | |
586 int fallbackCount = 0; | |
587 | |
588 for (size_t i = 0; i < gNumSystemFonts; i++) { | |
589 // if we're the first in a new family, clear firstInFamily | |
590 if (rec[i].fNames != NULL) { | |
591 firstInFamily = NULL; | |
592 } | |
593 | |
594 bool isFixedPitch; | |
595 SkString name; | |
596 SkTypeface::Style style; | |
597 | |
598 // we expect all the fonts, except the "fallback" fonts | |
599 bool isExpected = (rec[i].fNames != gFBNames); | |
600 if (!get_name_and_style(rec[i].fFileName, &name, &style, | |
601 &isFixedPitch, isExpected)) { | |
602 // We need to increase gUniqueFontID here so that the unique id of | |
603 // each font matches its index in gSystemFonts array, as expected | |
604 // by find_uniqueID. | |
605 sk_atomic_inc(&gUniqueFontID); | |
606 continue; | |
607 } | |
608 | |
609 SkTypeface* tf = SkNEW_ARGS(FileTypeface, | |
610 (style, | |
611 true, // system-font (cannot delete) | |
612 firstInFamily, // what family to join | |
613 rec[i].fFileName, | |
614 isFixedPitch) // filename | |
615 ); | |
616 #if SK_DEBUG_FONTS | |
617 SkDebugf("---- SkTypeface[%d] %s fontID %d", | |
618 i, rec[i].fFileName, tf->uniqueID()); | |
619 #endif | |
620 | |
621 if (rec[i].fNames != NULL) { | |
622 // see if this is one of our fallback fonts | |
623 if (rec[i].fNames == gFBNames) { | |
624 #if SK_DEBUG_FONTS | |
625 SkDebugf("---- adding %s as fallback[%d] fontID %d", | |
626 rec[i].fFileName, fallbackCount, tf->uniqueID()); | |
627 #endif | |
628 gFallbackFonts[fallbackCount++] = tf->uniqueID(); | |
629 | |
630 // Use the font file name as the name of the typeface. | |
631 const char **nameList = (const char**)malloc(2 * sizeof(char*)); | |
632 if (nameList == NULL) { | |
633 // shouldn't get here | |
634 SkDEBUGFAIL("Failed to allocate nameList"); | |
635 break; | |
636 } | |
637 nameList[0] = rec[i].fFileName; | |
638 nameList[1] = NULL; | |
639 rec[i].fNames = nameList; | |
640 } | |
641 | |
642 firstInFamily = tf; | |
643 FamilyRec* family = find_family(tf); | |
644 const char* const* names = rec[i].fNames; | |
645 | |
646 // record the default family if this is it | |
647 if (names == gDefaultNames) { | |
648 gDefaultFamily = family; | |
649 } | |
650 // add the names to map to this family | |
651 while (*names) { | |
652 add_name(*names, family); | |
653 names += 1; | |
654 } | |
655 } | |
656 } | |
657 | |
658 // do this after all fonts are loaded. This is our default font, and it | |
659 // acts as a sentinel so we only execute load_system_fonts() once | |
660 gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); | |
661 // now terminate our fallback list with the sentinel value | |
662 gFallbackFonts[fallbackCount] = 0; | |
663 | |
664 #if SK_DEBUG_FONTS | |
665 SkDEBUGCODE(dump_globals()); | |
666 #endif | |
667 } | |
668 | |
669 static size_t find_uniqueID(const char* filename) { | |
670 // uniqueID is the index, offset by one, of the associated element in | |
671 // gSystemFonts[] (assumes system fonts are loaded before external fonts) | |
672 // return 0 if not found | |
673 const FontInitRec* rec = gSystemFonts; | |
674 for (size_t i = 0; i < gNumSystemFonts; i++) { | |
675 if (strcmp(rec[i].fFileName, filename) == 0) { | |
676 return i+1; | |
677 } | |
678 } | |
679 return 0; | |
680 } | |
681 | |
682 static void reload_fallback_fonts() { | |
683 if (gTestFallbackConfigFile) { | |
684 // No need to reload fallback fonts in test environment. | |
685 return; | |
686 } | |
687 | |
688 SkGraphics::PurgeFontCache(); | |
689 | |
690 SkTDArray<FontFamily*> fallbackFamilies; | |
691 getFallbackFontFamilies(fallbackFamilies); | |
692 | |
693 int fallbackCount = 0; | |
694 for (int i = 0; i < fallbackFamilies.count(); ++i) { | |
695 FontFamily *family = fallbackFamilies[i]; | |
696 | |
697 for (int j = 0; j < family->fFileNames.count(); ++j) { | |
698 if (family->fFileNames[j]) { | |
699 | |
700 // ensure the fallback font exists before adding it to the list | |
701 bool isFixedPitch; | |
702 SkString name; | |
703 SkTypeface::Style style; | |
704 if (!get_name_and_style(family->fFileNames[j], &name, &style, | |
705 &isFixedPitch, false)) { | |
706 continue; | |
707 } | |
708 | |
709 size_t uniqueID = find_uniqueID(family->fFileNames[j]); | |
710 SkASSERT(uniqueID != 0); | |
711 #if SK_DEBUG_FONTS | |
712 SkDebugf("---- reload %s as fallback[%d] fontID %d oldFontID %d"
, | |
713 family->fFileNames[j], fallbackCount, uniqueID, | |
714 gFallbackFonts[fallbackCount]); | |
715 #endif | |
716 gFallbackFonts[fallbackCount++] = uniqueID; | |
717 break; // The fallback set contains only the first font of each
family | |
718 } | |
719 } | |
720 } | |
721 // reset the sentinel the end of the newly ordered array | |
722 gFallbackFonts[fallbackCount] = 0; | |
723 } | |
724 | |
725 static void load_system_fonts() { | |
726 static AndroidLocale prevLocale; | |
727 AndroidLocale locale; | |
728 | |
729 getLocale(locale); | |
730 | |
731 if (!gDefaultNormal) { | |
732 prevLocale = locale; | |
733 init_system_fonts(); | |
734 } else if (strncmp(locale.language, prevLocale.language, 2) || | |
735 strncmp(locale.region, prevLocale.region, 2)) { | |
736 prevLocale = locale; | |
737 reload_fallback_fonts(); | |
738 } | |
739 } | |
740 | |
741 /////////////////////////////////////////////////////////////////////////////// | |
742 | |
743 void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | |
744 bool* isLocalStream) const { | |
745 { | |
746 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
747 desc->setFamilyName(find_family_name(this)); | |
748 desc->setFontFileName(this->getUniqueString()); | |
749 } | |
750 *isLocalStream = !this->isSysFont(); | |
751 } | |
752 | |
753 #if 0 // do we need this different name lookup for Deserialize? | |
754 SkTypeface* SkFontHost::Deserialize(SkStream* stream) { | |
755 ... | |
756 if (NULL != fontFileName && 0 != *fontFileName) { | |
757 const FontInitRec* rec = gSystemFonts; | |
758 for (size_t i = 0; i < gNumSystemFonts; i++) { | |
759 if (strcmp(rec[i].fFileName, fontFileName) == 0) { | |
760 // backup until we hit the fNames | |
761 for (int j = i; j >= 0; --j) { | |
762 if (rec[j].fNames != NULL) { | |
763 return SkFontHost::CreateTypeface(NULL, | |
764 rec[j].fNames[0], style); | |
765 } | |
766 } | |
767 } | |
768 } | |
769 } | |
770 ... | |
771 } | |
772 #endif | |
773 | |
774 /////////////////////////////////////////////////////////////////////////////// | |
775 | |
776 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, | |
777 const char familyName[], | |
778 SkTypeface::Style style) { | |
779 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
780 | |
781 load_system_fonts(); | |
782 | |
783 // clip to legal style bits | |
784 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); | |
785 | |
786 SkTypeface* tf = NULL; | |
787 | |
788 if (NULL != familyFace) { | |
789 tf = find_typeface(familyFace, style); | |
790 } else if (NULL != familyName) { | |
791 // SkDebugf("======= familyName <%s>\n", familyName); | |
792 tf = find_typeface(familyName, style); | |
793 } | |
794 | |
795 if (NULL == tf) { | |
796 tf = find_best_face(gDefaultFamily, style); | |
797 } | |
798 | |
799 // we ref(), since the semantic is to return a new instance | |
800 tf->ref(); | |
801 return tf; | |
802 } | |
803 | |
804 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontI
D, | |
805 const SkPaintOptionsAndroid& options) { | |
806 // Skia does not support font fallback by default for ndk applications. This | |
807 // enables clients such as WebKit to customize their font selection. In any | |
808 // case clients can use GetFallbackFamilyNameForChar() to get the fallback | |
809 // font for individual characters. | |
810 if (!options.isUsingFontFallbacks()) { | |
811 return NULL; | |
812 } | |
813 | |
814 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
815 | |
816 load_system_fonts(); | |
817 | |
818 const SkTypeface* origTypeface = find_from_uniqueID(origFontID); | |
819 const SkTypeface* currTypeface = find_from_uniqueID(currFontID); | |
820 | |
821 SkASSERT(origTypeface != 0); | |
822 SkASSERT(currTypeface != 0); | |
823 SkASSERT(gFallbackFonts); | |
824 | |
825 // Our fallback list always stores the id of the plain in each fallback | |
826 // family, so we transform currFontID to its plain equivalent. | |
827 currFontID = find_typeface(currTypeface, SkTypeface::kNormal)->uniqueID(); | |
828 | |
829 /* First see if fontID is already one of our fallbacks. If so, return | |
830 its successor. If fontID is not in our list, then return the first one | |
831 in our list. Note: list is zero-terminated, and returning zero means | |
832 we have no more fonts to use for fallbacks. | |
833 */ | |
834 const uint32_t* list = gFallbackFonts; | |
835 for (int i = 0; list[i] != 0; i++) { | |
836 if (list[i] == currFontID) { | |
837 if (list[i+1] == 0) | |
838 return NULL; | |
839 const SkTypeface* nextTypeface = find_from_uniqueID(list[i+1]); | |
840 return SkRef(find_typeface(nextTypeface, origTypeface->style())); | |
841 } | |
842 } | |
843 | |
844 // If we get here, currFontID was not a fallback, so we start at the | |
845 // beginning of our list. Assuming there is at least one fallback font, | |
846 // i.e. gFallbackFonts[0] != 0. | |
847 const SkTypeface* firstTypeface = find_from_uniqueID(list[0]); | |
848 return SkRef(find_typeface(firstTypeface, origTypeface->style())); | |
849 } | |
850 | |
851 /////////////////////////////////////////////////////////////////////////////// | |
852 | |
853 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { | |
854 if (NULL == stream || stream->getLength() <= 0) { | |
855 return NULL; | |
856 } | |
857 | |
858 bool isFixedPitch; | |
859 SkTypeface::Style style; | |
860 | |
861 if (find_name_and_attributes(stream, NULL, &style, &isFixedPitch)) { | |
862 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
863 // Make sure system fonts are loaded to comply with the assumption of | |
864 // unique id offset by one in find_uniqueID. | |
865 load_system_fonts(); | |
866 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedPi
tch)); | |
867 } else { | |
868 return NULL; | |
869 } | |
870 } | |
871 | |
872 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { | |
873 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | |
874 return stream.get() ? SkFontHost::CreateTypefaceFromStream(stream) : NULL; | |
875 } | |
876 | |
877 /////////////////////////////////////////////////////////////////////////////// | |
878 // Function from SkTypeface_android.h | |
879 /////////////////////////////////////////////////////////////////////////////// | |
880 | |
881 // this function can't be called if the gFamilyHeadAndNameListMutex is already l
ocked | |
882 static bool typefaceContainsChar(SkTypeface* face, SkUnichar uni) { | |
883 SkPaint paint; | |
884 paint.setTypeface(face); | |
885 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); | |
886 | |
887 uint16_t glyphID; | |
888 paint.textToGlyphs(&uni, sizeof(uni), &glyphID); | |
889 return glyphID != 0; | |
890 } | |
891 | |
892 // this function can't be called if the gFamilyHeadAndNameListMutex is already l
ocked | |
893 static SkTypeface* findFallbackTypefaceForChar(SkUnichar uni) { | |
894 SkASSERT(gFallbackFonts); | |
895 const uint32_t* list = gFallbackFonts; | |
896 for (int i = 0; list[i] != 0; i++) { | |
897 SkTypeface* face; | |
898 { | |
899 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
900 face = find_from_uniqueID(list[i]); | |
901 } | |
902 if (typefaceContainsChar(face, uni)) { | |
903 return face; | |
904 } | |
905 } | |
906 return 0; | |
907 } | |
908 | |
909 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) { | |
910 SkASSERT(name); | |
911 { | |
912 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
913 load_system_fonts(); | |
914 } | |
915 | |
916 const SkTypeface* tf = findFallbackTypefaceForChar(uni); | |
917 if (!tf) { | |
918 return false; | |
919 } | |
920 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); | |
921 name->set(find_family_name(tf)); | |
922 return true; | |
923 } | |
924 | |
925 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf, | |
926 const char* fontsdir) { | |
927 gTestMainConfigFile = mainconf; | |
928 gTestFallbackConfigFile = fallbackconf; | |
929 gTestFontFilePrefix = fontsdir; | |
930 SkASSERT(gTestMainConfigFile); | |
931 SkASSERT(gTestFallbackConfigFile); | |
932 SkASSERT(gTestFontFilePrefix); | |
933 SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s", | |
934 gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix)
); | |
935 } | |
936 | |
937 /////////////////////////////////////////////////////////////////////////////// | |
938 | |
939 #include "SkFontMgr.h" | |
940 | |
941 SkFontMgr* SkFontMgr::Factory() { | |
942 // todo | |
943 return NULL; | |
944 } | |
OLD | NEW |