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

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

Issue 18666003: Remove old and unused Android font host code (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 5 months 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 | Annotate | Revision Log
« no previous file with comments | « src/ports/FontHostConfiguration_android.cpp ('k') | 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
(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 }
OLDNEW
« no previous file with comments | « src/ports/FontHostConfiguration_android.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698