• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/ports/SkFontHost_android.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkFontHost.h"
19 #include "SkGraphics.h"
20 #include "SkDescriptor.h"
21 #include "SkMMapStream.h"
22 #include "SkPaint.h"
23 #include "SkString.h"
24 #include "SkStream.h"
25 #include "SkThread.h"
26 #include "SkTSearch.h"
27 #include "FontHostConfiguration_android.h"
28 #include <stdio.h>
29 #include <string.h>
30 
31 //#define SkDEBUGF(args       )       SkDebugf args
32 
33 #ifndef SK_FONT_FILE_PREFIX
34     #define SK_FONT_FILE_PREFIX          "/fonts/"
35 #endif
36 
37 // Defined in SkFontHost_FreeType.cpp
38 bool find_name_and_attributes(SkStream* stream, SkString* name,
39                               SkTypeface::Style* style, bool* isFixedWidth);
40 
getFullPathForSysFonts(SkString * full,const char name[])41 static void getFullPathForSysFonts(SkString* full, const char name[]) {
42     full->set(getenv("ANDROID_ROOT"));
43     full->append(SK_FONT_FILE_PREFIX);
44     full->append(name);
45 }
46 
getNameAndStyle(const char path[],SkString * name,SkTypeface::Style * style,bool * isFixedWidth,bool isExpected)47 static bool getNameAndStyle(const char path[], SkString* name,
48                                SkTypeface::Style* style,
49                                bool* isFixedWidth, bool isExpected) {
50     SkString        fullpath;
51     getFullPathForSysFonts(&fullpath, path);
52 
53     SkMMAPStream stream(fullpath.c_str());
54     if (stream.getLength() > 0) {
55         return find_name_and_attributes(&stream, name, style, isFixedWidth);
56     }
57     else {
58         SkFILEStream stream(fullpath.c_str());
59         if (stream.getLength() > 0) {
60             return find_name_and_attributes(&stream, name, style, isFixedWidth);
61         }
62     }
63 
64     if (isExpected) {
65         SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
66     }
67     return false;
68 }
69 
70 static SkTypeface* deserializeLocked(SkStream* stream);
71 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace,
72         const char familyName[], const void* data, size_t bytelength,
73         SkTypeface::Style style);
74 static SkStream* openStreamLocked(uint32_t fontID);
75 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index);
76 static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID);
77 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream);
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 
81 struct FamilyRec;
82 
83 /*  This guy holds a mapping of a name -> family, used for looking up fonts.
84     Since it is stored in a stretchy array that doesn't preserve object
85     semantics, we don't use constructor/destructors, but just have explicit
86     helpers to manage our internal bookkeeping.
87 */
88 struct NameFamilyPair {
89     const char* fName;      // we own this
90     FamilyRec*  fFamily;    // we don't own this, we just reference it
91 
constructNameFamilyPair92     void construct(const char name[], FamilyRec* family) {
93         fName = strdup(name);
94         fFamily = family;   // we don't own this, so just record the reference
95     }
96 
destructNameFamilyPair97     void destruct() {
98         free((char*)fName);
99         // we don't own family, so just ignore our reference
100     }
101 };
102 typedef SkTDArray<NameFamilyPair> NameFamilyPairList;
103 
104 // we use atomic_inc to grow this for each typeface we create
105 static int32_t gUniqueFontID;
106 
107 // this is the mutex that protects all of the global data structures in this module
108 // functions with the Locked() suffix must be called while holding this mutex
109 SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex);
110 static FamilyRec* gFamilyHead = NULL;
111 static SkTDArray<NameFamilyPair> gFallbackFilenameList;
112 static NameFamilyPairList gNameList;
113 
114 struct FamilyRec {
115     FamilyRec*  fNext;
116     SkTypeface* fFaces[4];
117 
FamilyRecFamilyRec118     FamilyRec() : fNext(NULL) {
119         memset(fFaces, 0, sizeof(fFaces));
120     }
121 };
122 
findBestFaceLocked(const FamilyRec * family,SkTypeface::Style style)123 static SkTypeface* findBestFaceLocked(const FamilyRec* family,
124                                   SkTypeface::Style style) {
125     SkTypeface* const* faces = family->fFaces;
126 
127     if (faces[style] != NULL) { // exact match
128         return faces[style];
129     }
130     // look for a matching bold
131     style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
132     if (faces[style] != NULL) {
133         return faces[style];
134     }
135     // look for the plain
136     if (faces[SkTypeface::kNormal] != NULL) {
137         return faces[SkTypeface::kNormal];
138     }
139     // look for anything
140     for (int i = 0; i < 4; i++) {
141         if (faces[i] != NULL) {
142             return faces[i];
143         }
144     }
145     // should never get here, since the faces list should not be empty
146     SkDEBUGFAIL("faces list is empty");
147     return NULL;
148 }
149 
findFamilyLocked(const SkTypeface * member)150 static FamilyRec* findFamilyLocked(const SkTypeface* member) {
151     FamilyRec* curr = gFamilyHead;
152     while (curr != NULL) {
153         for (int i = 0; i < 4; i++) {
154             if (curr->fFaces[i] == member) {
155                 return curr;
156             }
157         }
158         curr = curr->fNext;
159     }
160     return NULL;
161 }
162 
163 /*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
164     is not modified.
165  */
findFromUniqueIDLocked(uint32_t uniqueID)166 static SkTypeface* findFromUniqueIDLocked(uint32_t uniqueID) {
167     FamilyRec* curr = gFamilyHead;
168     while (curr != NULL) {
169         for (int i = 0; i < 4; i++) {
170             SkTypeface* face = curr->fFaces[i];
171             if (face != NULL && face->uniqueID() == uniqueID) {
172                 return face;
173             }
174         }
175         curr = curr->fNext;
176     }
177     return NULL;
178 }
179 
180 /*  Remove reference to this face from its family. If the resulting family
181     is empty (has no faces), return that family, otherwise return NULL
182 */
removeFromFamilyLocked(const SkTypeface * face)183 static FamilyRec* removeFromFamilyLocked(const SkTypeface* face) {
184     FamilyRec* family = findFamilyLocked(face);
185     if (family) {
186         SkASSERT(family->fFaces[face->style()] == face);
187         family->fFaces[face->style()] = NULL;
188 
189         for (int i = 0; i < 4; i++) {
190             if (family->fFaces[i] != NULL) {    // family is non-empty
191                 return NULL;
192             }
193         }
194     } else {
195 //        SkDebugf("removeFromFamilyLocked(%p) face not found", face);
196     }
197     return family;  // return the empty family
198 }
199 
200 // maybe we should make FamilyRec be doubly-linked
detachAndDeleteFamilyLocked(FamilyRec * family)201 static void detachAndDeleteFamilyLocked(FamilyRec* family) {
202     FamilyRec* curr = gFamilyHead;
203     FamilyRec* prev = NULL;
204 
205     while (curr != NULL) {
206         FamilyRec* next = curr->fNext;
207         if (curr == family) {
208             if (prev == NULL) {
209                 gFamilyHead = next;
210             } else {
211                 prev->fNext = next;
212             }
213             SkDELETE(family);
214             return;
215         }
216         prev = curr;
217         curr = next;
218     }
219     SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
220 }
221 
findTypefaceLocked(const char name[],SkTypeface::Style style)222 static SkTypeface* findTypefaceLocked(const char name[], SkTypeface::Style style) {
223     int count = gNameList.count();
224     NameFamilyPair* list = gNameList.begin();
225     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
226     if (index >= 0) {
227         return findBestFaceLocked(list[index].fFamily, style);
228     }
229     return NULL;
230 }
231 
findTypefaceLocked(const SkTypeface * familyMember,SkTypeface::Style style)232 static SkTypeface* findTypefaceLocked(const SkTypeface* familyMember,
233                                  SkTypeface::Style style) {
234     const FamilyRec* family = findFamilyLocked(familyMember);
235     return family ? findBestFaceLocked(family, style) : NULL;
236 }
237 
addNameLocked(const char name[],FamilyRec * family)238 static void addNameLocked(const char name[], FamilyRec* family) {
239     SkAutoAsciiToLC tolc(name);
240     name = tolc.lc();
241 
242     int count = gNameList.count();
243     NameFamilyPair* list = gNameList.begin();
244     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
245     if (index < 0) {
246         list = gNameList.insert(~index);
247         list->construct(name, family);
248     }
249 }
250 
removeFromNamesLocked(FamilyRec * emptyFamily)251 static void removeFromNamesLocked(FamilyRec* emptyFamily) {
252 #ifdef SK_DEBUG
253     for (int i = 0; i < 4; i++) {
254         SkASSERT(emptyFamily->fFaces[i] == NULL);
255     }
256 #endif
257 
258     // must go backwards when removing
259     for (int i = gNameList.count() - 1; i >= 0; --i) {
260         NameFamilyPair& pair = gNameList[i];
261         if (pair.fFamily == emptyFamily) {
262             pair.destruct();
263             gNameList.remove(i);
264         }
265     }
266 }
267 
addTypefaceLocked(SkTypeface * typeface,SkTypeface * familyMember)268 static void addTypefaceLocked(SkTypeface* typeface, SkTypeface* familyMember) {
269     FamilyRec* rec = NULL;
270     if (familyMember) {
271         rec = findFamilyLocked(familyMember);
272         SkASSERT(rec);
273     } else {
274         rec = SkNEW(FamilyRec);
275         rec->fNext = gFamilyHead;
276         gFamilyHead = rec;
277     }
278     rec->fFaces[typeface->style()] = typeface;
279 }
280 
removeTypeface(SkTypeface * typeface)281 static void removeTypeface(SkTypeface* typeface) {
282     SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
283 
284     // remove us from our family. If the family is now empty, we return
285     // that and then remove that family from the name list
286     FamilyRec* family = removeFromFamilyLocked(typeface);
287     if (NULL != family) {
288         removeFromNamesLocked(family);
289         detachAndDeleteFamilyLocked(family);
290     }
291 }
292 
293 ///////////////////////////////////////////////////////////////////////////////
294 
295 class FamilyTypeface : public SkTypeface {
296 protected:
FamilyTypeface(Style style,bool sysFont,bool isFixedWidth)297     FamilyTypeface(Style style, bool sysFont, bool isFixedWidth)
298     : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
299         fIsSysFont = sysFont;
300     }
301 
302 public:
~FamilyTypeface()303     virtual ~FamilyTypeface() {
304         removeTypeface(this);
305     }
306 
isSysFont() const307     bool isSysFont() const { return fIsSysFont; }
308 
309     virtual SkStream* openStream() = 0;
310     virtual const char* getUniqueString() const = 0;
311     virtual const char* getFilePath() const = 0;
312 
313 private:
314     bool    fIsSysFont;
315 
316     typedef SkTypeface INHERITED;
317 };
318 
319 ///////////////////////////////////////////////////////////////////////////////
320 
321 class StreamTypeface : public FamilyTypeface {
322 public:
StreamTypeface(Style style,bool sysFont,SkStream * stream,bool isFixedWidth)323     StreamTypeface(Style style, bool sysFont, SkStream* stream, bool isFixedWidth)
324     : INHERITED(style, sysFont, isFixedWidth) {
325         SkASSERT(stream);
326         stream->ref();
327         fStream = stream;
328     }
329 
~StreamTypeface()330     virtual ~StreamTypeface() {
331         fStream->unref();
332     }
333 
334     // overrides
openStream()335     virtual SkStream* openStream() {
336         // we just ref our existing stream, since the caller will call unref()
337         // when they are through
338         fStream->ref();
339         // must rewind each time, since the caller assumes a "new" stream
340         fStream->rewind();
341         return fStream;
342     }
getUniqueString() const343     virtual const char* getUniqueString() const { return NULL; }
getFilePath() const344     virtual const char* getFilePath() const { return NULL; }
345 
346 private:
347     SkStream* fStream;
348 
349     typedef FamilyTypeface INHERITED;
350 };
351 
352 class FileTypeface : public FamilyTypeface {
353 public:
FileTypeface(Style style,bool sysFont,const char path[],bool isFixedWidth)354     FileTypeface(Style style, bool sysFont, const char path[], bool isFixedWidth)
355     : INHERITED(style, sysFont, isFixedWidth) {
356         fPath.set(path);
357     }
358 
359     // overrides
openStream()360     virtual SkStream* openStream() {
361         SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
362 
363         // check for failure
364         if (stream->getLength() <= 0) {
365             SkDELETE(stream);
366             // maybe MMAP isn't supported. try FILE
367             stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
368             if (stream->getLength() <= 0) {
369                 SkDELETE(stream);
370                 stream = NULL;
371             }
372         }
373         return stream;
374     }
getUniqueString() const375     virtual const char* getUniqueString() const {
376         const char* str = strrchr(fPath.c_str(), '/');
377         if (str) {
378             str += 1;   // skip the '/'
379         }
380         return str;
381     }
getFilePath() const382     virtual const char* getFilePath() const {
383         return fPath.c_str();
384     }
385 
386 private:
387     SkString fPath;
388 
389     typedef FamilyTypeface INHERITED;
390 };
391 
392 ///////////////////////////////////////////////////////////////////////////////
393 ///////////////////////////////////////////////////////////////////////////////
394 
395 // used to record our notion of the pre-existing fonts
396 struct FontInitRec {
397     const char*         fFileName;
398     const char* const*  fNames;     // null-terminated list
399 };
400 
401 // deliberately empty, but we use the address to identify fallback fonts
402 static const char* gFBNames[] = { NULL };
403 
404 
405 /*  Fonts are grouped by family, with the first font in a family having the
406     list of names (even if that list is empty), and the following members having
407     null for the list. The names list must be NULL-terminated.
408 */
409 static SkTDArray<FontInitRec> gSystemFonts;
410 static SkTDArray<SkFontID> gFallbackFonts;
411 
412 // these globals are assigned (once) by loadSystemFontsLocked()
413 static FamilyRec* gDefaultFamily = NULL;
414 static SkTypeface* gDefaultNormal = NULL;
415 static char** gDefaultNames = NULL;
416 
dumpGlobalsLocked()417 static void dumpGlobalsLocked() {
418     SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal,
419              gDefaultNormal ? gDefaultNormal->uniqueID() : 0,
420              gDefaultNormal ? gDefaultNormal->getRefCnt() : 0);
421 
422     if (gDefaultFamily) {
423         SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
424                  gDefaultFamily,
425                  gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0,
426                  gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0,
427                  gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0,
428                  gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0,
429                  gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0,
430                  gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0,
431                  gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0,
432                  gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0);
433     } else {
434         SkDebugf("gDefaultFamily=%p", gDefaultFamily);
435     }
436 
437     SkDebugf("gSystemFonts.count()=%d gFallbackFonts.count()=%d",
438             gSystemFonts.count(), gFallbackFonts.count());
439 
440     for (int i = 0; i < gSystemFonts.count(); ++i) {
441         SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName);
442         size_t namesIndex = 0;
443         if (gSystemFonts[i].fNames)
444             for (const char* fontName = gSystemFonts[i].fNames[namesIndex];
445                     fontName != 0;
446                     fontName = gSystemFonts[i].fNames[++namesIndex]) {
447                 SkDebugf("       name[%u]=%s", namesIndex, fontName);
448             }
449     }
450 
451     if (gFamilyHead) {
452         FamilyRec* rec = gFamilyHead;
453         int i=0;
454         while (rec) {
455             SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
456                      i++, rec,
457                      rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0,
458                      rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0,
459                      rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0,
460                      rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0,
461                      rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0,
462                      rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0,
463                      rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0,
464                      rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0);
465             rec = rec->fNext;
466         }
467     } else {
468         SkDebugf("gFamilyHead=%p", gFamilyHead);
469     }
470 
471 }
472 
473 
haveSystemFont(const char * filename)474 static bool haveSystemFont(const char* filename) {
475     for (int i = 0; i < gSystemFonts.count(); i++) {
476         if (strcmp(gSystemFonts[i].fFileName, filename) == 0) {
477             return true;
478         }
479     }
480     return false;
481 }
482 
483 /*  Load info from a configuration file that populates the system/fallback font structures
484 */
loadFontInfoLocked()485 static void loadFontInfoLocked() {
486     SkTDArray<FontFamily*> fontFamilies;
487     getFontFamilies(fontFamilies);
488 
489     gSystemFonts.reset();
490 
491     for (int i = 0; i < fontFamilies.count(); ++i) {
492         FontFamily *family = fontFamilies[i];
493         for (int j = 0; j < family->fFileNames.count(); ++j) {
494             const char* filename = family->fFileNames[j];
495             if (haveSystemFont(filename)) {
496                 SkDebugf("---- system font and fallback font files specify a duplicate "
497                         "font %s, skipping the second occurrence", filename);
498                 continue;
499             }
500 
501             FontInitRec fontInfoRecord;
502             fontInfoRecord.fFileName = filename;
503             if (j == 0) {
504                 if (family->fNames.count() == 0) {
505                     // Fallback font
506                     fontInfoRecord.fNames = (char **)gFBNames;
507                 } else {
508                     SkTDArray<const char*> names = family->fNames;
509                     const char **nameList = (const char**)
510                             malloc((names.count() + 1) * sizeof(char*));
511                     if (nameList == NULL) {
512                         // shouldn't get here
513                         break;
514                     }
515                     if (gDefaultNames == NULL) {
516                         gDefaultNames = (char**) nameList;
517                     }
518                     for (int i = 0; i < names.count(); ++i) {
519                         nameList[i] = names[i];
520                     }
521                     nameList[names.count()] = NULL;
522                     fontInfoRecord.fNames = nameList;
523                 }
524             } else {
525                 fontInfoRecord.fNames = NULL;
526             }
527             *gSystemFonts.append() = fontInfoRecord;
528         }
529     }
530     fontFamilies.deleteAll();
531 
532     SkDEBUGF(("---- We have %d system fonts", gSystemFonts.count()));
533     for (int i = 0; i < gSystemFonts.count(); ++i) {
534         SkDEBUGF(("---- gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName));
535     }
536 }
537 
538 
539 /*
540  *  Called once (ensured by the sentinel check at the beginning of our body).
541  *  Initializes all the globals, and register the system fonts.
542  */
initSystemFontsLocked()543 static void initSystemFontsLocked() {
544     // check if we've already been called
545     if (gDefaultNormal) {
546         return;
547     }
548 
549     SkASSERT(gUniqueFontID == 0);
550 
551     loadFontInfoLocked();
552 
553     gFallbackFonts.reset();
554 
555     SkTypeface* firstInFamily = NULL;
556     for (int i = 0; i < gSystemFonts.count(); i++) {
557         // if we're the first in a new family, clear firstInFamily
558         const char* const* names = gSystemFonts[i].fNames;
559         if (names != NULL) {
560             firstInFamily = NULL;
561         }
562 
563         bool isFixedWidth;
564         SkString name;
565         SkTypeface::Style style;
566 
567         // we expect all the fonts, except the "fallback" fonts
568         bool isExpected = (names != gFBNames);
569         if (!getNameAndStyle(gSystemFonts[i].fFileName, &name, &style,
570                 &isFixedWidth, isExpected)) {
571             // We need to increase gUniqueFontID here so that the unique id of
572             // each font matches its index in gSystemFonts array, as expected
573             // by findUniqueIDLocked.
574             sk_atomic_inc(&gUniqueFontID);
575             continue;
576         }
577 
578         SkString fullpath;
579         getFullPathForSysFonts(&fullpath, gSystemFonts[i].fFileName);
580 
581         SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style,
582                 true,  // system-font (cannot delete)
583                 fullpath.c_str(), // filename
584                 isFixedWidth));
585         addTypefaceLocked(tf, firstInFamily);
586 
587         SkDEBUGF(("---- SkTypeface[%d] %s fontID %d\n",
588                   i, gSystemFonts[i].fFileName, tf->uniqueID()));
589 
590         if (names != NULL) {
591             // see if this is one of our fallback fonts
592             if (names == gFBNames) {
593                 SkDEBUGF(("---- adding %s as fallback[%d] fontID %d\n",
594                         gSystemFonts[i].fFileName, gFallbackFonts.count(), tf->uniqueID()));
595                 *gFallbackFonts.append() = tf->uniqueID();
596             }
597 
598             firstInFamily = tf;
599             FamilyRec* family = findFamilyLocked(tf);
600 
601             // record the default family if this is it
602             if (names == gDefaultNames) {
603                 gDefaultFamily = family;
604             }
605             // add the names to map to this family
606             while (*names) {
607                 addNameLocked(*names, family);
608                 names += 1;
609             }
610         }
611     }
612 
613     // do this after all fonts are loaded. This is our default font, and it
614     // acts as a sentinel so we only execute loadSystemFontsLocked() once
615     gDefaultNormal = findBestFaceLocked(gDefaultFamily, SkTypeface::kNormal);
616 
617     SkDEBUGCODE(dumpGlobalsLocked());
618 }
619 
findUniqueIDLocked(const char * filename)620 static SkFontID findUniqueIDLocked(const char* filename) {
621     // uniqueID is the index, offset by one, of the associated element in
622     // gSystemFonts[] (assumes system fonts are loaded before external fonts)
623     // return 0 if not found
624     for (int i = 0; i < gSystemFonts.count(); i++) {
625         if (strcmp(gSystemFonts[i].fFileName, filename) == 0) {
626             return i + 1; // assume unique id of i'th system font is i + 1
627         }
628     }
629     return 0;
630 }
631 
findFallbackFontIndex(SkFontID fontId)632 static int findFallbackFontIndex(SkFontID fontId) {
633     for (int i = 0; i < gFallbackFonts.count(); i++) {
634         if (gFallbackFonts[i] == fontId) {
635             return i;
636         }
637     }
638     return -1;
639 }
640 
reloadFallbackFontsLocked()641 static void reloadFallbackFontsLocked() {
642     SkGraphics::PurgeFontCache();
643 
644     SkTDArray<FontFamily*> fallbackFamilies;
645     getFallbackFontFamilies(fallbackFamilies);
646 
647     gFallbackFonts.reset();
648 
649     for (int i = 0; i < fallbackFamilies.count(); ++i) {
650         FontFamily *family = fallbackFamilies[i];
651 
652         for (int j = 0; j < family->fFileNames.count(); ++j) {
653             const char* filename = family->fFileNames[j];
654             if (filename) {
655                 if (!haveSystemFont(filename)) {
656                     SkDebugf("---- skipping fallback font %s because it was not "
657                             "previously loaded as a system font", filename);
658                     continue;
659                 }
660 
661                 // ensure the fallback font exists before adding it to the list
662                 bool isFixedWidth;
663                 SkString name;
664                 SkTypeface::Style style;
665                 if (!getNameAndStyle(filename, &name, &style,
666                                         &isFixedWidth, false)) {
667                     continue;
668                 }
669 
670                 SkFontID uniqueID = findUniqueIDLocked(filename);
671                 SkASSERT(uniqueID != 0);
672                 if (findFallbackFontIndex(uniqueID) >= 0) {
673                     SkDebugf("---- system font and fallback font files specify a duplicate "
674                             "font %s, skipping the second occurrence", filename);
675                     continue;
676                 }
677 
678                 SkDEBUGF(("---- reload %s as fallback[%d] fontID %d\n",
679                           filename, gFallbackFonts.count(), uniqueID));
680 
681                 *gFallbackFonts.append() = uniqueID;
682                 break;  // The fallback set contains only the first font of each family
683             }
684         }
685     }
686 
687     fallbackFamilies.deleteAll();
688 }
689 
loadSystemFontsLocked()690 static void loadSystemFontsLocked() {
691 #if !defined(SK_BUILD_FOR_ANDROID_NDK)
692     static char prevLanguage[3];
693     static char prevRegion[3];
694     char language[3] = "";
695     char region[3] = "";
696 
697     getLocale(language, region);
698 
699     if (!gDefaultNormal) {
700         strncpy(prevLanguage, language, 2);
701         strncpy(prevRegion, region, 2);
702         initSystemFontsLocked();
703     } else if (strncmp(language, prevLanguage, 2) || strncmp(region, prevRegion, 2)) {
704         strncpy(prevLanguage, language, 2);
705         strncpy(prevRegion, region, 2);
706         reloadFallbackFontsLocked();
707     }
708 #else
709     if (!gDefaultNormal) {
710         initSystemFontsLocked();
711         reloadFallbackFontsLocked();
712     }
713 #endif
714 }
715 
716 ///////////////////////////////////////////////////////////////////////////////
717 
Serialize(const SkTypeface * face,SkWStream * stream)718 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
719     // lookup and record if the font is custom (i.e. not a system font)
720     bool isCustomFont = !((FamilyTypeface*)face)->isSysFont();
721     stream->writeBool(isCustomFont);
722 
723     if (isCustomFont) {
724         SkStream* fontStream = ((FamilyTypeface*)face)->openStream();
725 
726         // store the length of the custom font
727         uint32_t len = fontStream->getLength();
728         stream->write32(len);
729 
730         // store the entire font in the serialized stream
731         void* fontData = malloc(len);
732 
733         fontStream->read(fontData, len);
734         stream->write(fontData, len);
735 
736         fontStream->unref();
737         free(fontData);
738 //      SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len);
739 
740     } else {
741         const char* name = ((FamilyTypeface*)face)->getUniqueString();
742 
743         stream->write8((uint8_t)face->style());
744 
745         if (NULL == name || 0 == *name) {
746             stream->writePackedUInt(0);
747 //          SkDebugf("--- fonthost serialize null\n");
748         } else {
749             uint32_t len = strlen(name);
750             stream->writePackedUInt(len);
751             stream->write(name, len);
752 //          SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
753         }
754     }
755 }
756 
Deserialize(SkStream * stream)757 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
758     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
759     return deserializeLocked(stream);
760 }
761 
deserializeLocked(SkStream * stream)762 static SkTypeface* deserializeLocked(SkStream* stream) {
763     loadSystemFontsLocked();
764 
765     // check if the font is a custom or system font
766     bool isCustomFont = stream->readBool();
767 
768     if (isCustomFont) {
769 
770         // read the length of the custom font from the stream
771         uint32_t len = stream->readU32();
772 
773         // generate a new stream to store the custom typeface
774         SkMemoryStream* fontStream = new SkMemoryStream(len);
775         stream->read((void*)fontStream->getMemoryBase(), len);
776 
777         SkTypeface* face = createTypefaceFromStreamLocked(fontStream);
778 
779         fontStream->unref();
780 
781 //      SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len);
782         return face;
783 
784     } else {
785         int style = stream->readU8();
786 
787         int len = stream->readPackedUInt();
788         if (len > 0) {
789             SkString str;
790             str.resize(len);
791             stream->read(str.writable_str(), len);
792 
793             for (int i = 0; i < gSystemFonts.count(); i++) {
794                 if (strcmp(gSystemFonts[i].fFileName, str.c_str()) == 0) {
795                     // backup until we hit the fNames
796                     for (int j = i; j >= 0; --j) {
797                         if (gSystemFonts[j].fNames != NULL) {
798                             return createTypefaceLocked(NULL,
799                                     gSystemFonts[j].fNames[0], NULL, 0,
800                                     (SkTypeface::Style)style);
801                         }
802                     }
803                 }
804             }
805         }
806     }
807     return NULL;
808 }
809 
810 ///////////////////////////////////////////////////////////////////////////////
811 
CreateTypeface(const SkTypeface * familyFace,const char familyName[],const void * data,size_t bytelength,SkTypeface::Style style)812 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
813                                        const char familyName[],
814                                        const void* data, size_t bytelength,
815                                        SkTypeface::Style style) {
816     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
817     return createTypefaceLocked(familyFace, familyName, data, bytelength, style);
818 }
819 
createTypefaceLocked(const SkTypeface * familyFace,const char familyName[],const void * data,size_t bytelength,SkTypeface::Style style)820 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace,
821         const char familyName[], const void* data, size_t bytelength,
822         SkTypeface::Style style) {
823     loadSystemFontsLocked();
824 
825     // clip to legal style bits
826     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
827 
828     SkTypeface* tf = NULL;
829 
830     if (NULL != familyFace) {
831         tf = findTypefaceLocked(familyFace, style);
832     } else if (NULL != familyName) {
833 //        SkDebugf("======= familyName <%s>\n", familyName);
834         tf = findTypefaceLocked(familyName, style);
835     }
836 
837     if (NULL == tf) {
838         tf = findBestFaceLocked(gDefaultFamily, style);
839     }
840 
841     // we ref(), since the semantic is to return a new instance
842     tf->ref();
843     return tf;
844 }
845 
OpenStream(uint32_t fontID)846 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
847     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
848     return openStreamLocked(fontID);
849 }
850 
openStreamLocked(uint32_t fontID)851 static SkStream* openStreamLocked(uint32_t fontID) {
852     FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID);
853     SkStream* stream = tf ? tf->openStream() : NULL;
854 
855     if (stream && stream->getLength() == 0) {
856         stream->unref();
857         stream = NULL;
858     }
859     return stream;
860 }
861 
GetFileName(SkFontID fontID,char path[],size_t length,int32_t * index)862 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
863                                int32_t* index) {
864     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
865     return getFileNameLocked(fontID, path, length, index);
866 }
867 
getFileNameLocked(SkFontID fontID,char path[],size_t length,int32_t * index)868 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index) {
869     FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID);
870     const char* src = tf ? tf->getFilePath() : NULL;
871 
872     if (src) {
873         size_t size = strlen(src);
874         if (path) {
875             memcpy(path, src, SkMin32(size, length));
876         }
877         if (index) {
878             *index = 0; // we don't have collections (yet)
879         }
880         return size;
881     } else {
882         return 0;
883     }
884 }
885 
NextLogicalFont(SkFontID currFontID,SkFontID origFontID)886 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
887     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
888     return nextLogicalFontLocked(currFontID, origFontID);
889 }
890 
nextLogicalFontLocked(SkFontID currFontID,SkFontID origFontID)891 static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID) {
892     loadSystemFontsLocked();
893 
894     const SkTypeface* origTypeface = findFromUniqueIDLocked(origFontID);
895     const SkTypeface* currTypeface = findFromUniqueIDLocked(currFontID);
896 
897     SkASSERT(origTypeface != 0);
898     SkASSERT(currTypeface != 0);
899 
900     // Our fallback list always stores the id of the plain in each fallback
901     // family, so we transform currFontID to its plain equivalent.
902     SkFontID plainFontID = findTypefaceLocked(currTypeface, SkTypeface::kNormal)->uniqueID();
903 
904     /*  First see if fontID is already one of our fallbacks. If so, return
905         its successor. If fontID is not in our list, then return the first one
906         in our list. Note: list is zero-terminated, and returning zero means
907         we have no more fonts to use for fallbacks.
908      */
909     int plainFallbackFontIndex = findFallbackFontIndex(plainFontID);
910     int nextFallbackFontIndex = plainFallbackFontIndex + 1;
911     SkFontID nextFontID;
912     if (nextFallbackFontIndex == gFallbackFonts.count()) {
913         nextFontID = 0; // no more fallbacks
914     } else {
915         const SkTypeface* nextTypeface = findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex]);
916         nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID();
917     }
918 
919     SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, "
920             "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d "
921             "=> nextFontID=%d", currFontID, origFontID, plainFontID,
922             plainFallbackFontIndex, nextFallbackFontIndex, nextFontID));
923     return nextFontID;
924 }
925 
926 ///////////////////////////////////////////////////////////////////////////////
927 
CreateTypefaceFromStream(SkStream * stream)928 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
929     SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
930     return createTypefaceFromStreamLocked(stream);
931 }
932 
createTypefaceFromStreamLocked(SkStream * stream)933 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream) {
934     if (NULL == stream || stream->getLength() <= 0) {
935         return NULL;
936     }
937 
938     // Make sure system fonts are loaded first to comply with the assumption
939     // that the font's uniqueID can be found using the findUniqueIDLocked method.
940     loadSystemFontsLocked();
941 
942     bool isFixedWidth;
943     SkTypeface::Style style;
944 
945     if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) {
946         SkTypeface* typeface = SkNEW_ARGS(StreamTypeface, (style, false, stream, isFixedWidth));
947         addTypefaceLocked(typeface, NULL);
948         return typeface;
949     } else {
950         return NULL;
951     }
952 }
953 
CreateTypefaceFromFile(const char path[])954 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
955     SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
956     SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
957     // since we created the stream, we let go of our ref() here
958     stream->unref();
959     return face;
960 }
961