1
2/*
3 * Copyright 2011 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkFontHost.h"
11#include "SkDescriptor.h"
12#include "SkMMapStream.h"
13#include "SkPaint.h"
14#include "SkString.h"
15#include "SkStream.h"
16#include "SkThread.h"
17#include "SkTSearch.h"
18#include <stdio.h>
19
20#ifdef SK_BUILD_FOR_MAC
21    #define SK_FONT_FILE_PREFIX     "/Library/Fonts/"
22#else
23    #define SK_FONT_FILE_PREFIX          "/skimages/"
24#endif
25
26bool find_name_and_attributes(SkStream* stream, SkString* name,
27                              SkTypeface::Style* style, bool* isFixedWidth);
28
29static void GetFullPathForSysFonts(SkString* full, const char name[]) {
30    full->set(SK_FONT_FILE_PREFIX);
31    full->append(name);
32}
33
34///////////////////////////////////////////////////////////////////////////////
35
36struct FamilyRec;
37
38/*  This guy holds a mapping of a name -> family, used for looking up fonts.
39    Since it is stored in a stretchy array that doesn't preserve object
40    semantics, we don't use constructor/destructors, but just have explicit
41    helpers to manage our internal bookkeeping.
42*/
43struct NameFamilyPair {
44    const char* fName;      // we own this
45    FamilyRec*  fFamily;    // we don't own this, we just reference it
46
47    void construct(const char name[], FamilyRec* family) {
48        fName = strdup(name);
49        fFamily = family;   // we don't own this, so just record the referene
50    }
51
52    void destruct() {
53        free((char*)fName);
54        // we don't own family, so just ignore our reference
55    }
56};
57
58// we use atomic_inc to grow this for each typeface we create
59static int32_t gUniqueFontID;
60
61// this is the mutex that protects these globals
62SK_DECLARE_STATIC_MUTEX(gFamilyMutex);
63static FamilyRec* gFamilyHead;
64static SkTDArray<NameFamilyPair> gNameList;
65
66struct FamilyRec {
67    FamilyRec*  fNext;
68    SkTypeface* fFaces[4];
69
70    FamilyRec()
71    {
72        fNext = gFamilyHead;
73        memset(fFaces, 0, sizeof(fFaces));
74        gFamilyHead = this;
75    }
76};
77
78static SkTypeface* find_best_face(const FamilyRec* family,
79                                  SkTypeface::Style style) {
80    SkTypeface* const* faces = family->fFaces;
81
82    if (faces[style] != NULL) { // exact match
83        return faces[style];
84    }
85    // look for a matching bold
86    style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
87    if (faces[style] != NULL) {
88        return faces[style];
89    }
90    // look for the plain
91    if (faces[SkTypeface::kNormal] != NULL) {
92        return faces[SkTypeface::kNormal];
93    }
94    // look for anything
95    for (int i = 0; i < 4; i++) {
96        if (faces[i] != NULL) {
97            return faces[i];
98        }
99    }
100    // should never get here, since the faces list should not be empty
101    SkDEBUGFAIL("faces list is empty");
102    return NULL;
103}
104
105static FamilyRec* find_family(const SkTypeface* member) {
106    FamilyRec* curr = gFamilyHead;
107    while (curr != NULL) {
108        for (int i = 0; i < 4; i++) {
109            if (curr->fFaces[i] == member) {
110                return curr;
111            }
112        }
113        curr = curr->fNext;
114    }
115    return NULL;
116}
117
118/*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
119    is not modified.
120 */
121static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
122    FamilyRec* curr = gFamilyHead;
123    while (curr != NULL) {
124        for (int i = 0; i < 4; i++) {
125            SkTypeface* face = curr->fFaces[i];
126            if (face != NULL && face->uniqueID() == uniqueID) {
127                return face;
128            }
129        }
130        curr = curr->fNext;
131    }
132    return NULL;
133}
134
135/*  Remove reference to this face from its family. If the resulting family
136    is empty (has no faces), return that family, otherwise return NULL
137*/
138static FamilyRec* remove_from_family(const SkTypeface* face) {
139    FamilyRec* family = find_family(face);
140    SkASSERT(family->fFaces[face->style()] == face);
141    family->fFaces[face->style()] = NULL;
142
143    for (int i = 0; i < 4; i++) {
144        if (family->fFaces[i] != NULL) {    // family is non-empty
145            return NULL;
146        }
147    }
148    return family;  // return the empty family
149}
150
151// maybe we should make FamilyRec be doubly-linked
152static void detach_and_delete_family(FamilyRec* family) {
153    FamilyRec* curr = gFamilyHead;
154    FamilyRec* prev = NULL;
155
156    while (curr != NULL) {
157        FamilyRec* next = curr->fNext;
158        if (curr == family) {
159            if (prev == NULL) {
160                gFamilyHead = next;
161            } else {
162                prev->fNext = next;
163            }
164            SkDELETE(family);
165            return;
166        }
167        prev = curr;
168        curr = next;
169    }
170    SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete");
171}
172
173static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
174    NameFamilyPair* list = gNameList.begin();
175    int             count = gNameList.count();
176
177    int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
178
179    if (index >= 0) {
180        return find_best_face(list[index].fFamily, style);
181    }
182    return NULL;
183}
184
185static SkTypeface* find_typeface(const SkTypeface* familyMember,
186                                 SkTypeface::Style style) {
187    const FamilyRec* family = find_family(familyMember);
188    return family ? find_best_face(family, style) : NULL;
189}
190
191static void add_name(const char name[], FamilyRec* family) {
192    SkAutoAsciiToLC tolc(name);
193    name = tolc.lc();
194
195    NameFamilyPair* list = gNameList.begin();
196    int             count = gNameList.count();
197
198    int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
199
200    if (index < 0) {
201        list = gNameList.insert(~index);
202        list->construct(name, family);
203    }
204}
205
206static void remove_from_names(FamilyRec* emptyFamily)
207{
208#ifdef SK_DEBUG
209    for (int i = 0; i < 4; i++) {
210        SkASSERT(emptyFamily->fFaces[i] == NULL);
211    }
212#endif
213
214    SkTDArray<NameFamilyPair>& list = gNameList;
215
216    // must go backwards when removing
217    for (int i = list.count() - 1; i >= 0; --i) {
218        NameFamilyPair* pair = &list[i];
219        if (pair->fFamily == emptyFamily) {
220            pair->destruct();
221            list.remove(i);
222        }
223    }
224}
225
226///////////////////////////////////////////////////////////////////////////////
227
228class FamilyTypeface : public SkTypeface {
229public:
230    FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember)
231    : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) {
232        fIsSysFont = sysFont;
233
234        SkAutoMutexAcquire  ac(gFamilyMutex);
235
236        FamilyRec* rec = NULL;
237        if (familyMember) {
238            rec = find_family(familyMember);
239            SkASSERT(rec);
240        } else {
241            rec = SkNEW(FamilyRec);
242        }
243        rec->fFaces[style] = this;
244    }
245
246    virtual ~FamilyTypeface() {
247        SkAutoMutexAcquire  ac(gFamilyMutex);
248
249        // remove us from our family. If the family is now empty, we return
250        // that and then remove that family from the name list
251        FamilyRec* family = remove_from_family(this);
252        if (NULL != family) {
253            remove_from_names(family);
254            detach_and_delete_family(family);
255        }
256    }
257
258    bool isSysFont() const { return fIsSysFont; }
259
260    virtual SkStream* openStream() = 0;
261    virtual const char* getUniqueString() const = 0;
262    virtual const char* getFilePath() const = 0;
263
264private:
265    bool    fIsSysFont;
266
267    typedef SkTypeface INHERITED;
268};
269
270///////////////////////////////////////////////////////////////////////////////
271
272class StreamTypeface : public FamilyTypeface {
273public:
274    StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
275                   SkStream* stream)
276    : INHERITED(style, sysFont, familyMember) {
277        SkASSERT(stream);
278        stream->ref();
279        fStream = stream;
280    }
281    virtual ~StreamTypeface() {
282        fStream->unref();
283    }
284
285    // overrides
286    virtual SkStream* openStream() {
287        // we just ref our existing stream, since the caller will call unref()
288        // when they are through
289        fStream->ref();
290        return fStream;
291    }
292    virtual const char* getUniqueString() const { return NULL; }
293    virtual const char* getFilePath() const { return NULL; }
294
295private:
296    SkStream* fStream;
297
298    typedef FamilyTypeface INHERITED;
299};
300
301class FileTypeface : public FamilyTypeface {
302public:
303    FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
304                 const char path[])
305    : INHERITED(style, sysFont, familyMember) {
306        SkString fullpath;
307
308        if (sysFont) {
309            GetFullPathForSysFonts(&fullpath, path);
310            path = fullpath.c_str();
311        }
312        fPath.set(path);
313    }
314
315    // overrides
316    virtual SkStream* openStream() {
317        SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
318
319        // check for failure
320        if (stream->getLength() <= 0) {
321            SkDELETE(stream);
322            // maybe MMAP isn't supported. try FILE
323            stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
324            if (stream->getLength() <= 0) {
325                SkDELETE(stream);
326                stream = NULL;
327            }
328        }
329        return stream;
330    }
331    virtual const char* getUniqueString() const {
332        const char* str = strrchr(fPath.c_str(), '/');
333        if (str) {
334            str += 1;   // skip the '/'
335        }
336        return str;
337    }
338    virtual const char* getFilePath() const {
339        return fPath.c_str();
340    }
341
342private:
343    SkString fPath;
344
345    typedef FamilyTypeface INHERITED;
346};
347
348///////////////////////////////////////////////////////////////////////////////
349///////////////////////////////////////////////////////////////////////////////
350
351static bool get_name_and_style(const char path[], SkString* name,
352                               SkTypeface::Style* style, bool isExpected) {
353    SkString        fullpath;
354    GetFullPathForSysFonts(&fullpath, path);
355
356    SkMMAPStream stream(fullpath.c_str());
357    if (stream.getLength() > 0) {
358        return find_name_and_attributes(&stream, name, style, NULL);
359    }
360    else {
361        SkFILEStream stream(fullpath.c_str());
362        if (stream.getLength() > 0) {
363            return find_name_and_attributes(&stream, name, style, NULL);
364        }
365    }
366
367    if (isExpected) {
368        SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
369    }
370    return false;
371}
372
373// used to record our notion of the pre-existing fonts
374struct FontInitRec {
375    const char*         fFileName;
376    const char* const*  fNames;     // null-terminated list
377};
378
379static const char* gSansNames[] = {
380    "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
381};
382
383static const char* gSerifNames[] = {
384    "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
385    "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
386};
387
388static const char* gMonoNames[] = {
389    "monospace", "courier", "courier new", "monaco", NULL
390};
391
392// deliberately empty, but we use the address to identify fallback fonts
393static const char* gFBNames[] = { NULL };
394
395/*  Fonts must be grouped by family, with the first font in a family having the
396    list of names (even if that list is empty), and the following members having
397    null for the list. The names list must be NULL-terminated
398*/
399static const FontInitRec gSystemFonts[] = {
400    { "Arial.ttf",              gSansNames  },
401    { "Times.ttf",              gSerifNames  },
402    { "samplefont.ttf",              gSansNames  },
403};
404
405#define DEFAULT_NAMES   gSansNames
406
407// these globals are assigned (once) by load_system_fonts()
408static FamilyRec* gDefaultFamily;
409static SkTypeface* gDefaultNormal;
410
411/*  This is sized conservatively, assuming that it will never be a size issue.
412    It will be initialized in load_system_fonts(), and will be filled with the
413    fontIDs that can be used for fallback consideration, in sorted order (sorted
414    meaning element[0] should be used first, then element[1], etc. When we hit
415    a fontID==0 in the array, the list is done, hence our allocation size is
416    +1 the total number of possible system fonts. Also see NextLogicalFont().
417 */
418static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
419
420/*  Called once (ensured by the sentinel check at the beginning of our body).
421    Initializes all the globals, and register the system fonts.
422 */
423static void load_system_fonts() {
424    // check if we've already be called
425    if (NULL != gDefaultNormal) {
426        return;
427    }
428
429    const FontInitRec* rec = gSystemFonts;
430    SkTypeface* firstInFamily = NULL;
431    int fallbackCount = 0;
432
433    for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
434        // if we're the first in a new family, clear firstInFamily
435        if (rec[i].fNames != NULL) {
436            firstInFamily = NULL;
437        }
438
439        SkString name;
440        SkTypeface::Style style;
441
442        // we expect all the fonts, except the "fallback" fonts
443        bool isExpected = (rec[i].fNames != gFBNames);
444        if (!get_name_and_style(rec[i].fFileName, &name, &style, isExpected)) {
445            continue;
446        }
447
448        SkTypeface* tf = SkNEW_ARGS(FileTypeface,
449                                    (style,
450                                     true,  // system-font (cannot delete)
451                                     firstInFamily, // what family to join
452                                     rec[i].fFileName) // filename
453                                    );
454
455        if (rec[i].fNames != NULL) {
456            // see if this is one of our fallback fonts
457            if (rec[i].fNames == gFBNames) {
458            //    SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
459            //             rec[i].fFileName, fallbackCount, tf->uniqueID());
460                gFallbackFonts[fallbackCount++] = tf->uniqueID();
461            }
462
463            firstInFamily = tf;
464            FamilyRec* family = find_family(tf);
465            const char* const* names = rec[i].fNames;
466
467            // record the default family if this is it
468            if (names == DEFAULT_NAMES) {
469                gDefaultFamily = family;
470            }
471            // add the names to map to this family
472            while (*names) {
473                add_name(*names, family);
474                names += 1;
475            }
476        }
477    }
478
479    // do this after all fonts are loaded. This is our default font, and it
480    // acts as a sentinel so we only execute load_system_fonts() once
481    gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
482    // now terminate our fallback list with the sentinel value
483    gFallbackFonts[fallbackCount] = 0;
484}
485
486///////////////////////////////////////////////////////////////////////////////
487
488void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
489    const char* name = ((FamilyTypeface*)face)->getUniqueString();
490
491    stream->write8((uint8_t)face->style());
492
493    if (NULL == name || 0 == *name) {
494        stream->writePackedUInt(0);
495//        SkDebugf("--- fonthost serialize null\n");
496    } else {
497        uint32_t len = strlen(name);
498        stream->writePackedUInt(len);
499        stream->write(name, len);
500//      SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
501    }
502}
503
504SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
505    load_system_fonts();
506
507    int style = stream->readU8();
508
509    int len = stream->readPackedUInt();
510    if (len > 0) {
511        SkString str;
512        str.resize(len);
513        stream->read(str.writable_str(), len);
514
515        const FontInitRec* rec = gSystemFonts;
516        for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
517            if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
518                // backup until we hit the fNames
519                for (int j = i; j >= 0; --j) {
520                    if (rec[j].fNames != NULL) {
521                        return SkFontHost::CreateTypeface(NULL,
522                                    rec[j].fNames[0], (SkTypeface::Style)style);
523                    }
524                }
525            }
526        }
527    }
528    return NULL;
529}
530
531///////////////////////////////////////////////////////////////////////////////
532
533SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
534                                       const char familyName[],
535                                       SkTypeface::Style style) {
536    load_system_fonts();
537
538    SkAutoMutexAcquire  ac(gFamilyMutex);
539
540    // clip to legal style bits
541    style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
542
543    SkTypeface* tf = NULL;
544
545    if (NULL != familyFace) {
546        tf = find_typeface(familyFace, style);
547    } else if (NULL != familyName) {
548//        SkDebugf("======= familyName <%s>\n", familyName);
549        tf = find_typeface(familyName, style);
550    }
551
552    if (NULL == tf) {
553        tf = find_best_face(gDefaultFamily, style);
554    }
555
556    // we ref(), since the symantic is to return a new instance
557    tf->ref();
558    return tf;
559}
560
561SkStream* SkFontHost::OpenStream(uint32_t fontID) {
562    SkAutoMutexAcquire  ac(gFamilyMutex);
563
564    FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
565    SkStream* stream = tf ? tf->openStream() : NULL;
566
567    if (stream && stream->getLength() == 0) {
568        stream->unref();
569        stream = NULL;
570    }
571    return stream;
572}
573
574#if 0
575SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
576        uint32_t fontID,
577        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
578        const uint32_t* glyphIDs,
579        uint32_t glyphIDsCount) {
580    SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
581    return NULL;
582}
583#endif
584
585size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
586                               int32_t* index) {
587    SkAutoMutexAcquire  ac(gFamilyMutex);
588
589    FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
590    const char* src = tf ? tf->getFilePath() : NULL;
591
592    if (src) {
593        size_t size = strlen(src);
594        if (path) {
595            memcpy(path, src, SkMin32(size, length));
596        }
597        if (index) {
598            *index = 0; // we don't have collections (yet)
599        }
600        return size;
601    } else {
602        return 0;
603    }
604}
605
606SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
607    load_system_fonts();
608
609    /*  First see if fontID is already one of our fallbacks. If so, return
610        its successor. If fontID is not in our list, then return the first one
611        in our list. Note: list is zero-terminated, and returning zero means
612        we have no more fonts to use for fallbacks.
613     */
614    const uint32_t* list = gFallbackFonts;
615    for (int i = 0; list[i] != 0; i++) {
616        if (list[i] == currFontID) {
617            return list[i+1];
618        }
619    }
620    return list[0];
621}
622
623///////////////////////////////////////////////////////////////////////////////
624
625SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
626    if (NULL == stream || stream->getLength() <= 0) {
627        return NULL;
628    }
629
630    SkTypeface::Style style;
631    if (find_name_and_attributes(stream, NULL, &style, NULL)) {
632        return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream));
633    } else {
634        return NULL;
635    }
636}
637
638SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
639    SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
640    SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
641    // since we created the stream, we let go of our ref() here
642    stream->unref();
643    return face;
644}
645