Home | History | Annotate | Download | only in ports
      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 
     26 bool find_name_and_attributes(SkStream* stream, SkString* name,
     27                               SkTypeface::Style* style, bool* isFixedWidth);
     28 
     29 static void GetFullPathForSysFonts(SkString* full, const char name[]) {
     30     full->set(SK_FONT_FILE_PREFIX);
     31     full->append(name);
     32 }
     33 
     34 ///////////////////////////////////////////////////////////////////////////////
     35 
     36 struct 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 */
     43 struct 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
     59 static int32_t gUniqueFontID;
     60 
     61 // this is the mutex that protects these globals
     62 SK_DECLARE_STATIC_MUTEX(gFamilyMutex);
     63 static FamilyRec* gFamilyHead;
     64 static SkTDArray<NameFamilyPair> gNameList;
     65 
     66 struct 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 
     78 static 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 
    105 static 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  */
    121 static 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 */
    138 static 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
    152 static 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 
    173 static 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 
    185 static 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 
    191 static 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 
    206 static 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 
    228 class FamilyTypeface : public SkTypeface {
    229 public:
    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 
    264 private:
    265     bool    fIsSysFont;
    266 
    267     typedef SkTypeface INHERITED;
    268 };
    269 
    270 ///////////////////////////////////////////////////////////////////////////////
    271 
    272 class StreamTypeface : public FamilyTypeface {
    273 public:
    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 
    295 private:
    296     SkStream* fStream;
    297 
    298     typedef FamilyTypeface INHERITED;
    299 };
    300 
    301 class FileTypeface : public FamilyTypeface {
    302 public:
    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 
    342 private:
    343     SkString fPath;
    344 
    345     typedef FamilyTypeface INHERITED;
    346 };
    347 
    348 ///////////////////////////////////////////////////////////////////////////////
    349 ///////////////////////////////////////////////////////////////////////////////
    350 
    351 static 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
    374 struct FontInitRec {
    375     const char*         fFileName;
    376     const char* const*  fNames;     // null-terminated list
    377 };
    378 
    379 static const char* gSansNames[] = {
    380     "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
    381 };
    382 
    383 static const char* gSerifNames[] = {
    384     "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
    385     "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
    386 };
    387 
    388 static const char* gMonoNames[] = {
    389     "monospace", "courier", "courier new", "monaco", NULL
    390 };
    391 
    392 // deliberately empty, but we use the address to identify fallback fonts
    393 static 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 */
    399 static 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()
    408 static FamilyRec* gDefaultFamily;
    409 static 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  */
    418 static 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  */
    423 static 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 
    488 void 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 
    504 SkTypeface* 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], NULL, 0, (SkTypeface::Style)style);
    523                     }
    524                 }
    525             }
    526         }
    527     }
    528     return NULL;
    529 }
    530 
    531 ///////////////////////////////////////////////////////////////////////////////
    532 
    533 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
    534                                        const char familyName[],
    535                                        const void* data, size_t bytelength,
    536                                        SkTypeface::Style style) {
    537     load_system_fonts();
    538 
    539     SkAutoMutexAcquire  ac(gFamilyMutex);
    540 
    541     // clip to legal style bits
    542     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
    543 
    544     SkTypeface* tf = NULL;
    545 
    546     if (NULL != familyFace) {
    547         tf = find_typeface(familyFace, style);
    548     } else if (NULL != familyName) {
    549 //        SkDebugf("======= familyName <%s>\n", familyName);
    550         tf = find_typeface(familyName, style);
    551     }
    552 
    553     if (NULL == tf) {
    554         tf = find_best_face(gDefaultFamily, style);
    555     }
    556 
    557     // we ref(), since the symantic is to return a new instance
    558     tf->ref();
    559     return tf;
    560 }
    561 
    562 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
    563     SkAutoMutexAcquire  ac(gFamilyMutex);
    564 
    565     FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
    566     SkStream* stream = tf ? tf->openStream() : NULL;
    567 
    568     if (stream && stream->getLength() == 0) {
    569         stream->unref();
    570         stream = NULL;
    571     }
    572     return stream;
    573 }
    574 
    575 #if 0
    576 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
    577         uint32_t fontID,
    578         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
    579     SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
    580     return NULL;
    581 }
    582 #endif
    583 
    584 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
    585                                int32_t* index) {
    586     SkAutoMutexAcquire  ac(gFamilyMutex);
    587 
    588     FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
    589     const char* src = tf ? tf->getFilePath() : NULL;
    590 
    591     if (src) {
    592         size_t size = strlen(src);
    593         if (path) {
    594             memcpy(path, src, SkMin32(size, length));
    595         }
    596         if (index) {
    597             *index = 0; // we don't have collections (yet)
    598         }
    599         return size;
    600     } else {
    601         return 0;
    602     }
    603 }
    604 
    605 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
    606     load_system_fonts();
    607 
    608     /*  First see if fontID is already one of our fallbacks. If so, return
    609         its successor. If fontID is not in our list, then return the first one
    610         in our list. Note: list is zero-terminated, and returning zero means
    611         we have no more fonts to use for fallbacks.
    612      */
    613     const uint32_t* list = gFallbackFonts;
    614     for (int i = 0; list[i] != 0; i++) {
    615         if (list[i] == currFontID) {
    616             return list[i+1];
    617         }
    618     }
    619     return list[0];
    620 }
    621 
    622 ///////////////////////////////////////////////////////////////////////////////
    623 
    624 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
    625     if (NULL == stream || stream->getLength() <= 0) {
    626         return NULL;
    627     }
    628 
    629     SkTypeface::Style style;
    630     if (find_name_and_attributes(stream, NULL, &style, NULL)) {
    631         return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream));
    632     } else {
    633         return NULL;
    634     }
    635 }
    636 
    637 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
    638     SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
    639     SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
    640     // since we created the stream, we let go of our ref() here
    641     stream->unref();
    642     return face;
    643 }
    644 
    645