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#include "SkGlyphCache.h"
31#include "SkLanguage.h"
32#include "SkTypeface_android.h"
33#include "SkTArray.h"
34#include "SkTDict.h"
35#include "SkTSearch.h"
36
37//#define SkDEBUGF(args       )       SkDebugf args
38
39#ifndef SK_FONT_FILE_PREFIX
40    #define SK_FONT_FILE_PREFIX          "/fonts/"
41#endif
42
43// Defined in SkFontHost_FreeType.cpp
44bool find_name_and_attributes(SkStream* stream, SkString* name,
45                              SkTypeface::Style* style, bool* isFixedWidth);
46
47static void getFullPathForSysFonts(SkString* full, const char name[]) {
48    full->set(getenv("ANDROID_ROOT"));
49    full->append(SK_FONT_FILE_PREFIX);
50    full->append(name);
51}
52
53static bool getNameAndStyle(const char path[], SkString* name,
54                               SkTypeface::Style* style,
55                               bool* isFixedWidth, bool isExpected) {
56    SkString        fullpath;
57    getFullPathForSysFonts(&fullpath, path);
58
59    SkMMAPStream stream(fullpath.c_str());
60    if (stream.getLength() > 0) {
61        return find_name_and_attributes(&stream, name, style, isFixedWidth);
62    }
63    else {
64        SkFILEStream stream(fullpath.c_str());
65        if (stream.getLength() > 0) {
66            return find_name_and_attributes(&stream, name, style, isFixedWidth);
67        }
68    }
69
70    if (isExpected) {
71        SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
72    }
73    return false;
74}
75
76static SkTypeface* deserializeLocked(SkStream* stream);
77static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace,
78        const char familyName[], const void* data, size_t bytelength,
79        SkTypeface::Style style);
80static SkStream* openStreamLocked(uint32_t fontID);
81static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index);
82static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec);
83static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream);
84
85
86///////////////////////////////////////////////////////////////////////////////
87
88struct FamilyRec;
89
90/*  This guy holds a mapping of a name -> family, used for looking up fonts.
91    Since it is stored in a stretchy array that doesn't preserve object
92    semantics, we don't use constructor/destructors, but just have explicit
93    helpers to manage our internal bookkeeping.
94*/
95struct NameFamilyPair {
96    const char* fName;      // we own this
97    FamilyRec*  fFamily;    // we don't own this, we just reference it
98
99    void construct(const char name[], FamilyRec* family) {
100        fName = strdup(name);
101        fFamily = family;   // we don't own this, so just record the reference
102    }
103
104    void destruct() {
105        free((char*)fName);
106        // we don't own family, so just ignore our reference
107    }
108};
109typedef SkTDArray<NameFamilyPair> NameFamilyPairList;
110
111// we use atomic_inc to grow this for each typeface we create
112static int32_t gUniqueFontID;
113
114// this is the mutex that protects all of the global data structures in this module
115// functions with the Locked() suffix must be called while holding this mutex
116SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex);
117static FamilyRec* gFamilyHead = NULL;
118static SkTDArray<NameFamilyPair> gFallbackFilenameList;
119static NameFamilyPairList gNameList;
120
121struct FamilyRec {
122    FamilyRec*  fNext;
123    SkTypeface* fFaces[4];
124
125    FamilyRec() : fNext(NULL) {
126        memset(fFaces, 0, sizeof(fFaces));
127    }
128};
129
130static SkTypeface* findBestFaceLocked(const FamilyRec* family,
131                                  SkTypeface::Style style) {
132    SkTypeface* const* faces = family->fFaces;
133
134    if (faces[style] != NULL) { // exact match
135        return faces[style];
136    }
137    // look for a matching bold
138    style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
139    if (faces[style] != NULL) {
140        return faces[style];
141    }
142    // look for the plain
143    if (faces[SkTypeface::kNormal] != NULL) {
144        return faces[SkTypeface::kNormal];
145    }
146    // look for anything
147    for (int i = 0; i < 4; i++) {
148        if (faces[i] != NULL) {
149            return faces[i];
150        }
151    }
152    // should never get here, since the faces list should not be empty
153    SkDEBUGFAIL("faces list is empty");
154    return NULL;
155}
156
157static SkTypeface* FindBestFace(const FamilyRec* family,
158            SkTypeface::Style style) {
159    SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
160    return findBestFaceLocked(family, style);
161}
162
163static FamilyRec* findFamilyLocked(const SkTypeface* member) {
164    FamilyRec* curr = gFamilyHead;
165    while (curr != NULL) {
166        for (int i = 0; i < 4; i++) {
167            if (curr->fFaces[i] == member) {
168                return curr;
169            }
170        }
171        curr = curr->fNext;
172    }
173    return NULL;
174}
175
176/*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
177    is not modified.
178 */
179static SkTypeface* findFromUniqueIDLocked(uint32_t uniqueID) {
180    FamilyRec* curr = gFamilyHead;
181    while (curr != NULL) {
182        for (int i = 0; i < 4; i++) {
183            SkTypeface* face = curr->fFaces[i];
184            if (face != NULL && face->uniqueID() == uniqueID) {
185                return face;
186            }
187        }
188        curr = curr->fNext;
189    }
190    return NULL;
191}
192
193/*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
194    is not modified.
195 */
196static SkTypeface* FindFromUniqueID(uint32_t uniqueID) {
197    SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
198    return findFromUniqueIDLocked(uniqueID);
199}
200
201/*  Remove reference to this face from its family. If the resulting family
202    is empty (has no faces), return that family, otherwise return NULL
203*/
204static FamilyRec* removeFromFamilyLocked(const SkTypeface* face) {
205    FamilyRec* family = findFamilyLocked(face);
206    if (family) {
207        SkASSERT(family->fFaces[face->style()] == face);
208        family->fFaces[face->style()] = NULL;
209
210        for (int i = 0; i < 4; i++) {
211            if (family->fFaces[i] != NULL) {    // family is non-empty
212                return NULL;
213            }
214        }
215    } else {
216//        SkDebugf("removeFromFamilyLocked(%p) face not found", face);
217    }
218    return family;  // return the empty family
219}
220
221// maybe we should make FamilyRec be doubly-linked
222static void detachAndDeleteFamilyLocked(FamilyRec* family) {
223    FamilyRec* curr = gFamilyHead;
224    FamilyRec* prev = NULL;
225
226    while (curr != NULL) {
227        FamilyRec* next = curr->fNext;
228        if (curr == family) {
229            if (prev == NULL) {
230                gFamilyHead = next;
231            } else {
232                prev->fNext = next;
233            }
234            SkDELETE(family);
235            return;
236        }
237        prev = curr;
238        curr = next;
239    }
240    SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
241}
242
243static SkTypeface* findTypefaceLocked(const char name[], SkTypeface::Style style) {
244    int count = gNameList.count();
245    NameFamilyPair* list = gNameList.begin();
246    int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
247    if (index >= 0) {
248        return findBestFaceLocked(list[index].fFamily, style);
249    }
250    return NULL;
251}
252
253static SkTypeface* findTypefaceLocked(const SkTypeface* familyMember,
254                                 SkTypeface::Style style) {
255    const FamilyRec* family = findFamilyLocked(familyMember);
256    return family ? findBestFaceLocked(family, style) : NULL;
257}
258
259static void addNameLocked(const char name[], FamilyRec* family) {
260    SkAutoAsciiToLC tolc(name);
261    name = tolc.lc();
262
263    int count = gNameList.count();
264    NameFamilyPair* list = gNameList.begin();
265    int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
266    if (index < 0) {
267        list = gNameList.insert(~index);
268        list->construct(name, family);
269    }
270}
271
272static void removeFromNamesLocked(FamilyRec* emptyFamily) {
273#ifdef SK_DEBUG
274    for (int i = 0; i < 4; i++) {
275        SkASSERT(emptyFamily->fFaces[i] == NULL);
276    }
277#endif
278
279    // must go backwards when removing
280    for (int i = gNameList.count() - 1; i >= 0; --i) {
281        NameFamilyPair& pair = gNameList[i];
282        if (pair.fFamily == emptyFamily) {
283            pair.destruct();
284            gNameList.remove(i);
285        }
286    }
287}
288
289static void addTypefaceLocked(SkTypeface* typeface, SkTypeface* familyMember) {
290    FamilyRec* rec = NULL;
291    if (familyMember) {
292        rec = findFamilyLocked(familyMember);
293        SkASSERT(rec);
294    } else {
295        rec = SkNEW(FamilyRec);
296        rec->fNext = gFamilyHead;
297        gFamilyHead = rec;
298    }
299    rec->fFaces[typeface->style()] = typeface;
300}
301
302static void removeTypeface(SkTypeface* typeface) {
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 = removeFromFamilyLocked(typeface);
308    if (NULL != family) {
309        removeFromNamesLocked(family);
310        detachAndDeleteFamilyLocked(family);
311    }
312}
313
314///////////////////////////////////////////////////////////////////////////////
315
316class FamilyTypeface : public SkTypeface {
317protected:
318    FamilyTypeface(Style style, bool sysFont, bool isFixedWidth)
319    : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
320        fIsSysFont = sysFont;
321    }
322
323public:
324    virtual ~FamilyTypeface() {
325        removeTypeface(this);
326    }
327
328    bool isSysFont() const { return fIsSysFont; }
329
330    virtual SkStream* openStream() = 0;
331    virtual const char* getUniqueString() const = 0;
332    virtual const char* getFilePath() const = 0;
333
334private:
335    bool    fIsSysFont;
336
337    typedef SkTypeface INHERITED;
338};
339
340///////////////////////////////////////////////////////////////////////////////
341
342class StreamTypeface : public FamilyTypeface {
343public:
344    StreamTypeface(Style style, bool sysFont, SkStream* stream, bool isFixedWidth)
345    : INHERITED(style, sysFont, isFixedWidth) {
346        SkASSERT(stream);
347        stream->ref();
348        fStream = stream;
349    }
350
351    virtual ~StreamTypeface() {
352        fStream->unref();
353    }
354
355    // overrides
356    virtual SkStream* openStream() {
357        // we just ref our existing stream, since the caller will call unref()
358        // when they are through
359        fStream->ref();
360        // must rewind each time, since the caller assumes a "new" stream
361        fStream->rewind();
362        return fStream;
363    }
364    virtual const char* getUniqueString() const { return NULL; }
365    virtual const char* getFilePath() const { return NULL; }
366
367private:
368    SkStream* fStream;
369
370    typedef FamilyTypeface INHERITED;
371};
372
373class FileTypeface : public FamilyTypeface {
374public:
375    FileTypeface(Style style, bool sysFont, const char path[], bool isFixedWidth)
376    : INHERITED(style, sysFont, isFixedWidth) {
377        fPath.set(path);
378    }
379
380    // overrides
381    virtual SkStream* openStream() {
382        SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
383
384        // check for failure
385        if (stream->getLength() <= 0) {
386            SkDELETE(stream);
387            // maybe MMAP isn't supported. try FILE
388            stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
389            if (stream->getLength() <= 0) {
390                SkDELETE(stream);
391                stream = NULL;
392            }
393        }
394        return stream;
395    }
396    virtual const char* getUniqueString() const {
397        const char* str = strrchr(fPath.c_str(), '/');
398        if (str) {
399            str += 1;   // skip the '/'
400        }
401        return str;
402    }
403    virtual const char* getFilePath() const {
404        return fPath.c_str();
405    }
406
407private:
408    SkString fPath;
409
410    typedef FamilyTypeface INHERITED;
411};
412
413///////////////////////////////////////////////////////////////////////////////
414///////////////////////////////////////////////////////////////////////////////
415
416// used to record our notion of the pre-existing fonts
417struct FontInitRec {
418    const char*          fFileName;
419    const char* const*   fNames;     // null-terminated list
420    SkPaint::FontVariant fVariant;
421    SkLanguage           fLanguage;
422};
423
424//used to record information about the fallback fonts
425struct FallbackFontRec {
426    SkFontID             fFontID;
427    SkPaint::FontVariant fVariant;
428};
429
430struct FallbackFontList {
431    FallbackFontList(const SkLanguage& language) : fLanguage(language) { }
432    SkTDArray<FallbackFontRec> fList;
433    SkLanguage                 fLanguage;
434};
435
436// deliberately empty, but we use the address to identify fallback fonts
437static const char* gFBNames[] = { NULL };
438
439/*  Fonts are grouped by family, with the first font in a family having the
440    list of names (even if that list is empty), and the following members having
441    null for the list. The names list must be NULL-terminated.
442*/
443static SkTArray<FontInitRec> gSystemFonts;
444static SkTDArray<FallbackFontList*> gFallbackFontLists;
445
446// these globals are assigned (once) by loadSystemFontsLocked()
447static FamilyRec* gDefaultFamily = NULL;
448static SkTypeface* gDefaultNormal = NULL;
449static char** gDefaultNames = NULL;
450
451static FallbackFontList* getFallbackFontListLocked(const SkLanguage& lang);
452static void dumpGlobalsLocked() {
453    SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal,
454             gDefaultNormal ? gDefaultNormal->uniqueID() : 0,
455             gDefaultNormal ? gDefaultNormal->getRefCnt() : 0);
456
457    if (gDefaultFamily) {
458        SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
459                 gDefaultFamily,
460                 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0,
461                 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0,
462                 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0,
463                 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0,
464                 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0,
465                 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0,
466                 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0,
467                 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0);
468    } else {
469        SkDebugf("gDefaultFamily=%p", gDefaultFamily);
470    }
471
472    FallbackFontList* defaultFallbackList =
473            getFallbackFontListLocked(SkLanguage());
474    SkASSERT(defaultFallbackList != NULL);
475    SkDebugf("gSystemFonts.count()=%d defaultFallbackList->fList.count()=%d",
476           gSystemFonts.count(), defaultFallbackList->fList.count());
477
478    for (int i = 0; i < gSystemFonts.count(); ++i) {
479        SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName);
480        size_t namesIndex = 0;
481        if (gSystemFonts[i].fNames)
482            for (const char* fontName = gSystemFonts[i].fNames[namesIndex];
483                    fontName != 0;
484                    fontName = gSystemFonts[i].fNames[++namesIndex]) {
485                SkDebugf("       name[%u]=%s", namesIndex, fontName);
486            }
487    }
488
489    if (gFamilyHead) {
490        FamilyRec* rec = gFamilyHead;
491        int i=0;
492        while (rec) {
493            SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
494                     i++, rec,
495                     rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0,
496                     rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0,
497                     rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0,
498                     rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0,
499                     rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0,
500                     rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0,
501                     rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0,
502                     rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0);
503            rec = rec->fNext;
504        }
505    } else {
506        SkDebugf("gFamilyHead=%p", gFamilyHead);
507    }
508
509}
510
511
512static bool haveSystemFont(const char* filename) {
513    for (int i = 0; i < gSystemFonts.count(); i++) {
514        if (strcmp(gSystemFonts[i].fFileName, filename) == 0) {
515            return true;
516        }
517    }
518    return false;
519}
520
521// (SkLanguage)<->(fallback chain index) translation
522static const size_t kLangDictSize = 128;
523static SkTDict<FallbackFontList*> gLangTagToFallbackFontList(kLangDictSize);
524static bool gIsOKToUseFallbackFontListCache = false;
525
526// crawl fallback font lists by hand looking for a specific language
527static FallbackFontList* getFallbackFontListNoCacheLocked(
528        const SkLanguage& lang) {
529    unsigned int numLists = gFallbackFontLists.count();
530    for (unsigned int listIdx = 0; listIdx < numLists; ++listIdx) {
531        FallbackFontList* list = gFallbackFontLists[listIdx];
532        SkASSERT(list != NULL);
533        if (list->fLanguage == lang) {
534            return list;
535        }
536    }
537    return NULL;
538}
539
540// perform fancy fuzzy-matching memoized query for a fallback font list.
541// should only be called after fallback font lists are fully loaded.
542static FallbackFontList* getFallbackFontListLocked(const SkLanguage& lang) {
543    SkASSERT(gIsOKToUseFallbackFontListCache);
544    const SkString& langTag = lang.getTag();
545    FallbackFontList* fallbackFontList;
546    if (gLangTagToFallbackFontList.find(langTag.c_str(), langTag.size(),
547            &fallbackFontList)) {
548        // cache hit!
549        return fallbackFontList;
550    }
551
552    // try again without the cache
553    fallbackFontList = getFallbackFontListNoCacheLocked(lang);
554    if (fallbackFontList != NULL) {
555        // found it - cache and return
556        gLangTagToFallbackFontList.set(langTag.c_str(), langTag.size(),
557                fallbackFontList);
558        SkDEBUGF(("new fallback cache entry: \"%s\"", langTag.c_str()));
559        return fallbackFontList;
560    }
561
562    // no hit - can we fuzzy-match?
563    if (lang.getTag().isEmpty()) {
564        // nope! this happens if attempting to direct match with no default
565        return NULL;
566    }
567
568    // attempt fuzzy match
569    SkLanguage parent = lang.getParent();
570    fallbackFontList = getFallbackFontListLocked(parent);
571    if (fallbackFontList != NULL) {
572        // found it - cache and return
573        gLangTagToFallbackFontList.set(langTag.c_str(), langTag.size(),
574                fallbackFontList);
575        SkDEBUGF(("new fallback cache entry: \"%s\" -> \"%s\"", langTag.c_str(),
576                fallbackFontList->fLanguage.getTag().c_str()));
577        return fallbackFontList;
578    }
579
580    // utter failure. this happens if attempting to fuzzy-match with no default
581    SkASSERT(fallbackFontList != NULL);
582    return NULL;
583}
584
585// creates a new fallback font list for the specified language
586static FallbackFontList* createFallbackFontListLocked(const SkLanguage& lang) {
587    SkASSERT(!gIsOKToUseFallbackFontListCache);
588    SkDEBUGF(("new fallback list: \"%s\"", lang.getTag().c_str()));
589    FallbackFontList* fallbackFontList = new FallbackFontList(lang);
590    gFallbackFontLists.push(fallbackFontList);
591    return fallbackFontList;
592}
593
594// adds a fallback font record to both the default fallback chain and the
595// language-specific fallback chain to which it belongs, if any
596static void addFallbackFontLocked(const FallbackFontRec& fallbackRec,
597        const SkLanguage& lang) {
598    SkASSERT(!gIsOKToUseFallbackFontListCache);
599    SkDEBUGF(("new fallback font: %d, in \"%s\"", fallbackRec.fFontID,
600            lang.getTag().c_str()));
601    // add to the default fallback list
602    FallbackFontList* fallbackList =
603            getFallbackFontListNoCacheLocked(SkLanguage());
604    if (fallbackList == NULL) {
605        // oops! no default list yet. create one.
606        fallbackList = createFallbackFontListLocked(SkLanguage());
607    }
608    SkASSERT(fallbackList != NULL);
609    fallbackList->fList.push(fallbackRec);
610    if (lang.getTag().isEmpty()) {
611        return;
612    }
613    // also add to the appropriate language's fallback list
614    fallbackList = getFallbackFontListNoCacheLocked(lang);
615    if (fallbackList == NULL) {
616        // first entry for this list!
617        fallbackList = createFallbackFontListLocked(lang);
618    }
619    SkASSERT(fallbackList != NULL);
620    fallbackList->fList.push(fallbackRec);
621}
622
623static int getSystemFontIndexForFontID(SkFontID fontID) {
624    // font unique id = one-based index in system font table
625    SkASSERT(fontID - 1 < gSystemFonts.count());
626    return fontID - 1;
627}
628
629// scans the default fallback font chain, adding every entry to every other
630// fallback font chain to which it does not belong. this results in every
631// language-specific fallback font chain having all of its fallback fonts at
632// the front of the chain, and everything else at the end. after this has been
633// run, it is ok to use the fallback font chain lookup table.
634static void finaliseFallbackFontListsLocked() {
635    SkASSERT(!gIsOKToUseFallbackFontListCache);
636    // if we have more than one list, we need to finalise non-default lists
637    unsigned int numLists = gFallbackFontLists.count();
638    if (numLists > 1) {
639        // pull fonts off of the default list...
640        FallbackFontList* defaultList = getFallbackFontListNoCacheLocked(
641                SkLanguage());
642        SkASSERT(defaultList != NULL);
643        int numDefaultFonts = defaultList->fList.count();
644        for (int fontIdx = 0; fontIdx < numDefaultFonts; ++fontIdx) {
645            // figure out which language they represent
646            SkFontID fontID = defaultList->fList[fontIdx].fFontID;
647            int sysFontIdx = getSystemFontIndexForFontID(fontID);
648            const SkLanguage& lang = gSystemFonts[sysFontIdx].fLanguage;
649            for (unsigned int listIdx = 0; listIdx < numLists; ++listIdx) {
650                // and add them to every other language's list
651                FallbackFontList* thisList = gFallbackFontLists[listIdx];
652                SkASSERT(thisList != NULL);
653                if (thisList != defaultList && thisList->fLanguage != lang) {
654                    thisList->fList.push(defaultList->fList[fontIdx]);
655                }
656            }
657        }
658    }
659    gIsOKToUseFallbackFontListCache = true;
660}
661
662static void resetFallbackFontListsLocked() {
663    // clear cache
664    gLangTagToFallbackFontList.reset();
665    // clear the data it pointed at
666    int numFallbackLists = gFallbackFontLists.count();
667    for (int fallbackIdx = 0; fallbackIdx < numFallbackLists; ++fallbackIdx) {
668        delete gFallbackFontLists[fallbackIdx];
669    }
670    gFallbackFontLists.reset();
671    gIsOKToUseFallbackFontListCache = false;
672}
673
674/*  Load info from a configuration file that populates the system/fallback font structures
675*/
676static void loadFontInfoLocked() {
677    resetFallbackFontListsLocked();
678
679    SkTDArray<FontFamily*> fontFamilies;
680    getFontFamilies(fontFamilies);
681
682    gSystemFonts.reset();
683
684    for (int i = 0; i < fontFamilies.count(); ++i) {
685        FontFamily *family = fontFamilies[i];
686        for (int j = 0; j < family->fFontFileArray.count(); ++j) {
687            const char* filename = family->fFontFileArray[j]->fFileName;
688            if (haveSystemFont(filename)) {
689                SkDebugf("---- system font and fallback font files specify a duplicate "
690                        "font %s, skipping the second occurrence", filename);
691                continue;
692            }
693
694            FontInitRec fontInfoRecord;
695            fontInfoRecord.fFileName = filename;
696            fontInfoRecord.fVariant = family->fFontFileArray[j]->fVariant;
697            fontInfoRecord.fLanguage = family->fFontFileArray[j]->fLanguage;
698            if (j == 0) {
699                if (family->fNames.count() == 0) {
700                    // Fallback font
701                    fontInfoRecord.fNames = (char **)gFBNames;
702                } else {
703                    SkTDArray<const char*> names = family->fNames;
704                    const char **nameList = (const char**)
705                            malloc((names.count() + 1) * sizeof(char*));
706                    if (nameList == NULL) {
707                        // shouldn't get here
708                        break;
709                    }
710                    if (gDefaultNames == NULL) {
711                        gDefaultNames = (char**) nameList;
712                    }
713                    for (int i = 0; i < names.count(); ++i) {
714                        nameList[i] = names[i];
715                    }
716                    nameList[names.count()] = NULL;
717                    fontInfoRecord.fNames = nameList;
718                }
719            } else {
720                fontInfoRecord.fNames = NULL;
721            }
722            gSystemFonts.push_back(fontInfoRecord);
723        }
724    }
725    fontFamilies.deleteAll();
726
727    SkDEBUGF(("---- We have %d system fonts", gSystemFonts.count()));
728    for (int i = 0; i < gSystemFonts.count(); ++i) {
729        SkDEBUGF(("---- gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName));
730    }
731}
732
733/*
734 *  Called once (ensured by the sentinel check at the beginning of our body).
735 *  Initializes all the globals, and register the system fonts.
736 */
737static void initSystemFontsLocked() {
738    // check if we've already been called
739    if (gDefaultNormal) {
740        return;
741    }
742
743    SkASSERT(gUniqueFontID == 0);
744
745    loadFontInfoLocked();
746
747    SkTypeface* firstInFamily = NULL;
748    for (int i = 0; i < gSystemFonts.count(); i++) {
749        // if we're the first in a new family, clear firstInFamily
750        const char* const* names = gSystemFonts[i].fNames;
751        if (names != NULL) {
752            firstInFamily = NULL;
753        }
754
755        bool isFixedWidth;
756        SkString name;
757        SkTypeface::Style style;
758
759        // we expect all the fonts, except the "fallback" fonts
760        bool isExpected = (names != gFBNames);
761        if (!getNameAndStyle(gSystemFonts[i].fFileName, &name, &style,
762                &isFixedWidth, isExpected)) {
763            // We need to increase gUniqueFontID here so that the unique id of
764            // each font matches its index in gSystemFonts array, as expected
765            // by findUniqueIDLocked.
766            sk_atomic_inc(&gUniqueFontID);
767            continue;
768        }
769
770        SkString fullpath;
771        getFullPathForSysFonts(&fullpath, gSystemFonts[i].fFileName);
772
773        SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style,
774                true,  // system-font (cannot delete)
775                fullpath.c_str(), // filename
776                isFixedWidth));
777        addTypefaceLocked(tf, firstInFamily);
778
779        SkDEBUGF(("---- SkTypeface[%d] %s fontID %d\n",
780                  i, gSystemFonts[i].fFileName, tf->uniqueID()));
781
782        if (names != NULL) {
783            // see if this is one of our fallback fonts
784            if (names == gFBNames) {
785                // add to appropriate fallback chains
786                FallbackFontRec fallbackRec;
787                fallbackRec.fFontID = tf->uniqueID();
788                fallbackRec.fVariant = gSystemFonts[i].fVariant;
789                addFallbackFontLocked(fallbackRec, gSystemFonts[i].fLanguage);
790            }
791
792            firstInFamily = tf;
793            FamilyRec* family = findFamilyLocked(tf);
794
795            // record the default family if this is it
796            if (names == gDefaultNames) {
797                gDefaultFamily = family;
798            }
799            // add the names to map to this family
800            while (*names) {
801                addNameLocked(*names, family);
802                names += 1;
803            }
804        }
805    }
806    finaliseFallbackFontListsLocked();
807
808    // do this after all fonts are loaded. This is our default font, and it
809    // acts as a sentinel so we only execute loadSystemFontsLocked() once
810    gDefaultNormal = findBestFaceLocked(gDefaultFamily, SkTypeface::kNormal);
811
812    SkDEBUGCODE(dumpGlobalsLocked());
813}
814
815static int findFallbackFontIndex(SkFontID fontId, FallbackFontList* currentFallbackList) {
816    for (int i = 0; i < currentFallbackList->fList.count(); i++) {
817        if (currentFallbackList->fList[i].fFontID == fontId) {
818            return i;
819        }
820    }
821    return -1;
822}
823
824static void loadSystemFontsLocked() {
825    if (!gDefaultNormal) {
826        initSystemFontsLocked();
827    }
828}
829
830///////////////////////////////////////////////////////////////////////////////
831
832void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
833    // lookup and record if the font is custom (i.e. not a system font)
834    bool isCustomFont = !((FamilyTypeface*)face)->isSysFont();
835    stream->writeBool(isCustomFont);
836
837    if (isCustomFont) {
838        SkStream* fontStream = ((FamilyTypeface*)face)->openStream();
839
840        // store the length of the custom font
841        uint32_t len = fontStream->getLength();
842        stream->write32(len);
843
844        // store the entire font in the serialized stream
845        void* fontData = malloc(len);
846
847        fontStream->read(fontData, len);
848        stream->write(fontData, len);
849
850        fontStream->unref();
851        free(fontData);
852//      SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len);
853
854    } else {
855        const char* name = ((FamilyTypeface*)face)->getUniqueString();
856
857        stream->write8((uint8_t)face->style());
858
859        if (NULL == name || 0 == *name) {
860            stream->writePackedUInt(0);
861//          SkDebugf("--- fonthost serialize null\n");
862        } else {
863            uint32_t len = strlen(name);
864            stream->writePackedUInt(len);
865            stream->write(name, len);
866//          SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
867        }
868    }
869}
870
871SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
872    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
873    return deserializeLocked(stream);
874}
875
876static SkTypeface* deserializeLocked(SkStream* stream) {
877    loadSystemFontsLocked();
878
879    // check if the font is a custom or system font
880    bool isCustomFont = stream->readBool();
881
882    if (isCustomFont) {
883
884        // read the length of the custom font from the stream
885        uint32_t len = stream->readU32();
886
887        // generate a new stream to store the custom typeface
888        SkMemoryStream* fontStream = new SkMemoryStream(len);
889        stream->read((void*)fontStream->getMemoryBase(), len);
890
891        SkTypeface* face = createTypefaceFromStreamLocked(fontStream);
892
893        fontStream->unref();
894
895//      SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len);
896        return face;
897
898    } else {
899        int style = stream->readU8();
900
901        int len = stream->readPackedUInt();
902        if (len > 0) {
903            SkString str;
904            str.resize(len);
905            stream->read(str.writable_str(), len);
906
907            for (int i = 0; i < gSystemFonts.count(); i++) {
908                if (strcmp(gSystemFonts[i].fFileName, str.c_str()) == 0) {
909                    // backup until we hit the fNames
910                    for (int j = i; j >= 0; --j) {
911                        if (gSystemFonts[j].fNames != NULL) {
912                            return createTypefaceLocked(NULL,
913                                    gSystemFonts[j].fNames[0], NULL, 0,
914                                    (SkTypeface::Style)style);
915                        }
916                    }
917                }
918            }
919        }
920    }
921    return NULL;
922}
923
924///////////////////////////////////////////////////////////////////////////////
925
926SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
927                                       const char familyName[],
928                                       const void* data, size_t bytelength,
929                                       SkTypeface::Style style) {
930    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
931    return createTypefaceLocked(familyFace, familyName, data, bytelength, style);
932}
933
934static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace,
935        const char familyName[], const void* data, size_t bytelength,
936        SkTypeface::Style style) {
937    loadSystemFontsLocked();
938
939    // clip to legal style bits
940    style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
941
942    SkTypeface* tf = NULL;
943
944    if (NULL != familyFace) {
945        tf = findTypefaceLocked(familyFace, style);
946    } else if (NULL != familyName) {
947//        SkDebugf("======= familyName <%s>\n", familyName);
948        tf = findTypefaceLocked(familyName, style);
949    }
950
951    if (NULL == tf) {
952        tf = findBestFaceLocked(gDefaultFamily, style);
953    }
954
955    // we ref(), since the semantic is to return a new instance
956    tf->ref();
957    return tf;
958}
959
960SkStream* SkFontHost::OpenStream(uint32_t fontID) {
961    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
962    return openStreamLocked(fontID);
963}
964
965static SkStream* openStreamLocked(uint32_t fontID) {
966    FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID);
967    SkStream* stream = tf ? tf->openStream() : NULL;
968
969    if (stream && stream->getLength() == 0) {
970        stream->unref();
971        stream = NULL;
972    }
973    return stream;
974}
975
976size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
977                               int32_t* index) {
978    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
979    return getFileNameLocked(fontID, path, length, index);
980}
981
982static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index) {
983    FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID);
984    const char* src = tf ? tf->getFilePath() : NULL;
985
986    if (src) {
987        size_t size = strlen(src);
988        if (path) {
989            memcpy(path, src, SkMin32(size, length));
990        }
991        if (index) {
992            *index = 0; // we don't have collections (yet)
993        }
994        return size;
995    } else {
996        return 0;
997    }
998}
999
1000SkFontID SkFontHost::NextLogicalFont(const SkScalerContext::Rec& rec) {
1001    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
1002    return nextLogicalFontLocked(rec);
1003}
1004
1005static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec) {
1006    loadSystemFontsLocked();
1007
1008    const SkTypeface* origTypeface = findFromUniqueIDLocked(rec.fOrigFontID);
1009    const SkTypeface* currTypeface = findFromUniqueIDLocked(rec.fFontID);
1010
1011    FallbackFontList* currentFallbackList =
1012            getFallbackFontListLocked(rec.fLanguage);
1013    SkASSERT(currentFallbackList);
1014
1015    SkASSERT(origTypeface != 0);
1016    SkASSERT(currTypeface != 0);
1017
1018    // Our fallback list always stores the id of the plain in each fallback
1019    // family, so we transform currFontID to its plain equivalent.
1020    SkFontID plainFontID = findTypefaceLocked(currTypeface, SkTypeface::kNormal)->uniqueID();
1021
1022    /*  First see if fontID is already one of our fallbacks. If so, return
1023        its successor. If fontID is not in our list, then return the first one
1024        in our list. Note: list is zero-terminated, and returning zero means
1025        we have no more fonts to use for fallbacks.
1026     */
1027    int plainFallbackFontIndex = findFallbackFontIndex(plainFontID, currentFallbackList);
1028    int nextFallbackFontIndex = plainFallbackFontIndex + 1;
1029
1030    // If a rec object is set to prefer "kDefault_Variant" it means they have no preference
1031    // In this case, we set the value to "kCompact_Variant"
1032    SkPaint::FontVariant recPreference = rec.fFontVariant;
1033    if (recPreference == SkPaint::kDefault_Variant) {
1034        recPreference = SkPaint::kCompact_Variant;
1035    }
1036    SkFontID nextFontID = 0;
1037    while (nextFallbackFontIndex < currentFallbackList->fList.count()) {
1038        bool normalFont =
1039                (currentFallbackList->fList[nextFallbackFontIndex].fVariant == SkPaint::kDefault_Variant);
1040        bool fontChosen = (currentFallbackList->fList[nextFallbackFontIndex].fVariant == recPreference);
1041        if (normalFont || fontChosen) {
1042            const SkTypeface* nextTypeface =
1043                    findFromUniqueIDLocked(currentFallbackList->fList[nextFallbackFontIndex].fFontID);
1044            nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID();
1045            break;
1046        }
1047        nextFallbackFontIndex++;
1048    }
1049
1050    SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, "
1051            "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d "
1052            "=> nextFontID=%d", rec.fFontID, rec.fOrigFontID, plainFontID,
1053            plainFallbackFontIndex, nextFallbackFontIndex, nextFontID));
1054    return nextFontID;
1055}
1056
1057///////////////////////////////////////////////////////////////////////////////
1058
1059SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
1060    SkAutoMutexAcquire  ac(gFamilyHeadAndNameListMutex);
1061    return createTypefaceFromStreamLocked(stream);
1062}
1063
1064static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream) {
1065    if (NULL == stream || stream->getLength() <= 0) {
1066        return NULL;
1067    }
1068
1069    // Make sure system fonts are loaded first to comply with the assumption
1070    // that the font's uniqueID can be found using the findUniqueIDLocked method.
1071    loadSystemFontsLocked();
1072
1073    bool isFixedWidth;
1074    SkTypeface::Style style;
1075
1076    if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) {
1077        SkTypeface* typeface = SkNEW_ARGS(StreamTypeface, (style, false, stream, isFixedWidth));
1078        addTypefaceLocked(typeface, NULL);
1079        return typeface;
1080    } else {
1081        return NULL;
1082    }
1083}
1084
1085SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
1086    SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
1087    SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
1088    // since we created the stream, we let go of our ref() here
1089    stream->unref();
1090    return face;
1091}
1092
1093///////////////////////////////////////////////////////////////////////////////
1094// Function from SkTypeface_android.h
1095///////////////////////////////////////////////////////////////////////////////
1096
1097static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style,
1098        SkPaint::FontVariant fontVariant) {
1099    SkTypeface* face = FindBestFace(gDefaultFamily, style);
1100    if (!face) {
1101        return 0;
1102    }
1103
1104    SkPaint paint;
1105    paint.setTypeface(face);
1106    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
1107    paint.setFontVariant(fontVariant);
1108
1109    SkAutoGlyphCache autoCache(paint, NULL);
1110    SkGlyphCache*    cache = autoCache.getCache();
1111    SkFontID         fontID = 0;
1112
1113    SkScalerContext* ctx = cache->getScalerContext();
1114    if (ctx) {
1115        return ctx->findTypefaceIdForChar(uni);
1116    }
1117    return 0;
1118}
1119
1120struct HB_UnicodeMapping {
1121    HB_Script script;
1122    const SkUnichar unicode;
1123};
1124
1125/*
1126 * The following scripts are not complex fonts and we do not expect them to be parsed by this table
1127 * HB_Script_Common,
1128 * HB_Script_Greek,
1129 * HB_Script_Cyrillic,
1130 * HB_Script_Hangul
1131 * HB_Script_Inherited
1132 */
1133
1134static HB_UnicodeMapping HB_UnicodeMappingArray[] {
1135    {HB_Script_Armenian,      0x0531},
1136    {HB_Script_Hebrew,        0x0591},
1137    {HB_Script_Arabic,        0x0600},
1138    {HB_Script_Syriac,        0x0710},
1139    {HB_Script_Thaana,        0x0780},
1140    {HB_Script_Nko,           0x07C0},
1141    {HB_Script_Devanagari,    0x0901},
1142    {HB_Script_Bengali,       0x0981},
1143    {HB_Script_Gurmukhi,      0x0A10},
1144    {HB_Script_Gujarati,      0x0A90},
1145    {HB_Script_Oriya,         0x0B10},
1146    {HB_Script_Tamil,         0x0B82},
1147    {HB_Script_Telugu,        0x0C10},
1148    {HB_Script_Kannada,       0x0C90},
1149    {HB_Script_Malayalam,     0x0D10},
1150    {HB_Script_Sinhala,       0x0D90},
1151    {HB_Script_Thai,          0x0E01},
1152    {HB_Script_Lao,           0x0E81},
1153    {HB_Script_Tibetan,       0x0F00},
1154    {HB_Script_Myanmar,       0x1000},
1155    {HB_Script_Georgian,      0x10A0},
1156    // we don't currently support HB_Script_Ethiopic, it is a placeholder for an upstream merge
1157    //{HB_Script_Ethiopic,    0x1200},
1158    {HB_Script_Ogham,         0x1680},
1159    {HB_Script_Runic,         0x16A0},
1160    {HB_Script_Khmer,         0x1780},
1161};
1162
1163// returns 0 for "Not Found"
1164static SkUnichar getUnicodeFromHBScript(HB_Script script) {
1165    SkUnichar unichar = 0;
1166    int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping);
1167    for (int i = 0; i < numSupportedFonts; i++) {
1168        if (script == HB_UnicodeMappingArray[i].script) {
1169            unichar = HB_UnicodeMappingArray[i].unicode;
1170            break;
1171        }
1172    }
1173    return unichar;
1174}
1175
1176struct TypefaceLookupStruct {
1177    HB_Script            script;
1178    SkTypeface::Style    style;
1179    SkPaint::FontVariant fontVariant;
1180    SkTypeface*          typeface;
1181};
1182
1183SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex);  // This is the mutex for gTypefaceTable
1184static SkTDArray<TypefaceLookupStruct> gTypefaceTable;  // This is protected by gTypefaceTableMutex
1185
1186static int typefaceLookupCompare(const TypefaceLookupStruct& first,
1187        const TypefaceLookupStruct& second) {
1188    if (first.script != second.script) {
1189        return (first.script > second.script) ? 1 : -1;
1190    }
1191    if (first.style != second.style) {
1192        return (first.style > second.style) ? 1 : -1;
1193    }
1194    if (first.fontVariant != second.fontVariant) {
1195        return (first.fontVariant > second.fontVariant) ? 1 : -1;
1196    }
1197    return 0;
1198}
1199
1200SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
1201        SkPaint::FontVariant fontVariant) {
1202    SkTypeface* retTypeface = NULL;
1203
1204    SkAutoMutexAcquire ac(gTypefaceTableMutex); // Note: NOT gFamilyHeadAndNameListMutex
1205    TypefaceLookupStruct key;
1206    key.script = script;
1207    key.style = style;
1208    key.fontVariant = fontVariant;
1209    int index = SkTSearch<TypefaceLookupStruct>(
1210            (const TypefaceLookupStruct*) gTypefaceTable.begin(),
1211            gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct),
1212            &typefaceLookupCompare);
1213    if (index >= 0) {
1214        retTypeface = gTypefaceTable[index].typeface;
1215    }
1216    else {
1217        SkUnichar unichar = getUnicodeFromHBScript(script);
1218        if (!unichar) {
1219            return NULL;
1220        }
1221        SkFontID newFontID = findFontIDForChar(unichar, style, fontVariant);
1222        // retrieve the typeface that corresponds to this fontID
1223        retTypeface = FindFromUniqueID(newFontID);
1224        key.typeface = retTypeface;
1225        index = ~index;
1226        *gTypefaceTable.insert(index) = key;
1227    }
1228    // we ref(), the caller is expected to unref when they are done
1229    SkSafeRef(retTypeface);
1230    return retTypeface;
1231}
1232