Home | History | Annotate | Download | only in ports
      1 
      2 /*
      3  * Copyright 2006 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 "SkOSFile.h"
     14 #include "SkPaint.h"
     15 #include "SkString.h"
     16 #include "SkStream.h"
     17 #include "SkThread.h"
     18 #include "SkTSearch.h"
     19 #include <stdio.h>
     20 
     21 #ifndef SK_FONT_FILE_PREFIX
     22     #define SK_FONT_FILE_PREFIX      "/usr/share/fonts/truetype/msttcorefonts/"
     23 #endif
     24 
     25 bool find_name_and_attributes(SkStream* stream, SkString* name,
     26                               SkTypeface::Style* style, bool* isFixedWidth);
     27 
     28 static void GetFullPathForSysFonts(SkString* full, const char name[])
     29 {
     30     full->append(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     {
     49         fName = strdup(name);
     50         fFamily = family;   // we don't own this, so just record the referene
     51     }
     52     void destruct()
     53     {
     54         free((char*)fName);
     55         // we don't own family, so just ignore our reference
     56     }
     57 };
     58 
     59 // we use atomic_inc to grow this for each typeface we create
     60 static int32_t gUniqueFontID;
     61 
     62 // this is the mutex that protects these globals
     63 SK_DECLARE_STATIC_MUTEX(gFamilyMutex);
     64 static FamilyRec* gFamilyHead;
     65 static SkTDArray<NameFamilyPair> gNameList;
     66 
     67 struct FamilyRec {
     68     FamilyRec*  fNext;
     69     SkTypeface* fFaces[4];
     70 
     71     FamilyRec()
     72     {
     73         fNext = gFamilyHead;
     74         memset(fFaces, 0, sizeof(fFaces));
     75         gFamilyHead = this;
     76     }
     77 };
     78 
     79 static SkTypeface* find_best_face(const FamilyRec* family,
     80                                   SkTypeface::Style style) {
     81     SkTypeface* const* faces = family->fFaces;
     82 
     83     if (faces[style] != NULL) { // exact match
     84         return faces[style];
     85     }
     86     // look for a matching bold
     87     style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
     88     if (faces[style] != NULL) {
     89         return faces[style];
     90     }
     91     // look for the plain
     92     if (faces[SkTypeface::kNormal] != NULL) {
     93         return faces[SkTypeface::kNormal];
     94     }
     95     // look for anything
     96     for (int i = 0; i < 4; i++) {
     97         if (faces[i] != NULL) {
     98             return faces[i];
     99         }
    100     }
    101     // should never get here, since the faces list should not be empty
    102     SkDEBUGFAIL("faces list is empty");
    103     return NULL;
    104 }
    105 
    106 static FamilyRec* find_family(const SkTypeface* member) {
    107     FamilyRec* curr = gFamilyHead;
    108     while (curr != NULL) {
    109         for (int i = 0; i < 4; i++) {
    110             if (curr->fFaces[i] == member) {
    111                 return curr;
    112             }
    113         }
    114         curr = curr->fNext;
    115     }
    116     return NULL;
    117 }
    118 
    119 static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
    120     FamilyRec* curr = gFamilyHead;
    121     while (curr != NULL) {
    122         for (int i = 0; i < 4; i++) {
    123             SkTypeface* face = curr->fFaces[i];
    124             if (face != NULL && face->uniqueID() == uniqueID) {
    125                 return face;
    126             }
    127         }
    128         curr = curr->fNext;
    129     }
    130     return NULL;
    131 }
    132 
    133 static bool valid_uniqueID(uint32_t uniqueID) {
    134     return find_from_uniqueID(uniqueID) != NULL;
    135 }
    136 
    137 /*  Remove reference to this face from its family. If the resulting family
    138  is empty (has no faces), return that family, otherwise return NULL
    139  */
    140 static FamilyRec* remove_from_family(const SkTypeface* face) {
    141     FamilyRec* family = find_family(face);
    142     SkASSERT(family->fFaces[face->style()] == face);
    143     family->fFaces[face->style()] = NULL;
    144 
    145     for (int i = 0; i < 4; i++) {
    146         if (family->fFaces[i] != NULL) {    // family is non-empty
    147             return NULL;
    148         }
    149     }
    150     return family;  // return the empty family
    151 }
    152 
    153 // maybe we should make FamilyRec be doubly-linked
    154 static void detach_and_delete_family(FamilyRec* family) {
    155     FamilyRec* curr = gFamilyHead;
    156     FamilyRec* prev = NULL;
    157 
    158     while (curr != NULL) {
    159         FamilyRec* next = curr->fNext;
    160         if (curr == family) {
    161             if (prev == NULL) {
    162                 gFamilyHead = next;
    163             } else {
    164                 prev->fNext = next;
    165             }
    166             SkDELETE(family);
    167             return;
    168         }
    169         prev = curr;
    170         curr = next;
    171     }
    172     SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete");
    173 }
    174 
    175 static FamilyRec* find_familyrec(const char name[]) {
    176     const NameFamilyPair* list = gNameList.begin();
    177     int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name,
    178                               sizeof(list[0]));
    179     return index >= 0 ? list[index].fFamily : NULL;
    180 }
    181 
    182 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
    183     FamilyRec* rec = find_familyrec(name);
    184     return rec ? find_best_face(rec, style) : NULL;
    185 }
    186 
    187 static SkTypeface* find_typeface(const SkTypeface* familyMember,
    188                                  SkTypeface::Style style) {
    189     const FamilyRec* family = find_family(familyMember);
    190     return family ? find_best_face(family, style) : NULL;
    191 }
    192 
    193 static void add_name(const char name[], FamilyRec* family) {
    194     SkAutoAsciiToLC tolc(name);
    195     name = tolc.lc();
    196 
    197     NameFamilyPair* list = gNameList.begin();
    198     int             count = gNameList.count();
    199 
    200     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
    201 
    202     if (index < 0) {
    203         list = gNameList.insert(~index);
    204         list->construct(name, family);
    205     }
    206 }
    207 
    208 static void remove_from_names(FamilyRec* emptyFamily) {
    209 #ifdef SK_DEBUG
    210     for (int i = 0; i < 4; i++) {
    211         SkASSERT(emptyFamily->fFaces[i] == NULL);
    212     }
    213 #endif
    214 
    215     SkTDArray<NameFamilyPair>& list = gNameList;
    216 
    217     // must go backwards when removing
    218     for (int i = list.count() - 1; i >= 0; --i) {
    219         NameFamilyPair* pair = &list[i];
    220         if (pair->fFamily == emptyFamily) {
    221             pair->destruct();
    222             list.remove(i);
    223         }
    224     }
    225 }
    226 
    227 ///////////////////////////////////////////////////////////////////////////////
    228 
    229 class FamilyTypeface : public SkTypeface {
    230 public:
    231     FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedWidth)
    232     : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
    233         fIsSysFont = sysFont;
    234 
    235         SkAutoMutexAcquire  ac(gFamilyMutex);
    236 
    237         if (NULL == family) {
    238             family = SkNEW(FamilyRec);
    239         }
    240         family->fFaces[style] = this;
    241         fFamilyRec = family;    // just record it so we can return it if asked
    242     }
    243 
    244     virtual ~FamilyTypeface() {
    245         SkAutoMutexAcquire  ac(gFamilyMutex);
    246 
    247         // remove us from our family. If the family is now empty, we return
    248         // that and then remove that family from the name list
    249         FamilyRec* family = remove_from_family(this);
    250         if (NULL != family) {
    251             remove_from_names(family);
    252             detach_and_delete_family(family);
    253         }
    254     }
    255 
    256     bool isSysFont() const { return fIsSysFont; }
    257     FamilyRec* getFamily() const { return fFamilyRec; }
    258     // openStream returns a SkStream that has been ref-ed
    259     virtual SkStream* openStream() = 0;
    260     virtual const char* getUniqueString() const = 0;
    261 
    262 private:
    263     FamilyRec*  fFamilyRec; // we don't own this, just point to it
    264     bool        fIsSysFont;
    265 
    266     typedef SkTypeface INHERITED;
    267 };
    268 
    269 ///////////////////////////////////////////////////////////////////////////////
    270 
    271 /* This subclass is just a place holder for when we have no fonts available.
    272     It exists so that our globals (e.g. gFamilyHead) that expect *something*
    273     will not be null.
    274  */
    275 class EmptyTypeface : public FamilyTypeface {
    276 public:
    277     EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {}
    278 
    279     // overrides
    280     virtual SkStream* openStream() { return NULL; }
    281     virtual const char* getUniqueString() const { return NULL; }
    282 
    283 private:
    284     typedef FamilyTypeface INHERITED;
    285 };
    286 
    287 class StreamTypeface : public FamilyTypeface {
    288 public:
    289     StreamTypeface(Style style, bool sysFont, FamilyRec* family,
    290                    SkStream* stream, bool isFixedWidth)
    291     : INHERITED(style, sysFont, family, isFixedWidth) {
    292         stream->ref();
    293         fStream = stream;
    294     }
    295     virtual ~StreamTypeface() {
    296         fStream->unref();
    297     }
    298 
    299     // overrides
    300     virtual SkStream* openStream()
    301     {
    302       // openStream returns a refed stream.
    303       fStream->ref();
    304       return fStream;
    305     }
    306     virtual const char* getUniqueString() const { return NULL; }
    307 
    308 private:
    309     SkStream* fStream;
    310 
    311     typedef FamilyTypeface INHERITED;
    312 };
    313 
    314 class FileTypeface : public FamilyTypeface {
    315 public:
    316     FileTypeface(Style style, bool sysFont, FamilyRec* family,
    317                  const char path[], bool isFixedWidth)
    318         : INHERITED(style, sysFont, family, isFixedWidth) {
    319         fPath.set(path);
    320     }
    321 
    322     // overrides
    323     virtual SkStream* openStream()
    324     {
    325         SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
    326 
    327         // check for failure
    328         if (stream->getLength() <= 0) {
    329             SkDELETE(stream);
    330             // maybe MMAP isn't supported. try FILE
    331             stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
    332             if (stream->getLength() <= 0) {
    333                 SkDELETE(stream);
    334                 stream = NULL;
    335             }
    336         }
    337         return stream;
    338     }
    339 
    340     virtual const char* getUniqueString() const {
    341         const char* str = strrchr(fPath.c_str(), '/');
    342         if (str) {
    343             str += 1;   // skip the '/'
    344         }
    345         return str;
    346     }
    347 
    348 private:
    349     SkString fPath;
    350 
    351     typedef FamilyTypeface INHERITED;
    352 };
    353 
    354 ///////////////////////////////////////////////////////////////////////////////
    355 ///////////////////////////////////////////////////////////////////////////////
    356 
    357 static bool get_name_and_style(const char path[], SkString* name,
    358                                SkTypeface::Style* style, bool* isFixedWidth) {
    359     SkMMAPStream stream(path);
    360     if (stream.getLength() > 0) {
    361         return find_name_and_attributes(&stream, name, style, isFixedWidth);
    362     }
    363     else {
    364         SkFILEStream stream(path);
    365         if (stream.getLength() > 0) {
    366             return find_name_and_attributes(&stream, name, style, isFixedWidth);
    367         }
    368     }
    369 
    370     SkDebugf("---- failed to open <%s> as a font\n", path);
    371     return false;
    372 }
    373 
    374 // these globals are assigned (once) by load_system_fonts()
    375 static SkTypeface* gFallBackTypeface;
    376 static FamilyRec* gDefaultFamily;
    377 static SkTypeface* gDefaultNormal;
    378 
    379 static void load_system_fonts() {
    380     // check if we've already be called
    381     if (NULL != gDefaultNormal) {
    382 //        printf("---- default font %p\n", gDefaultNormal);
    383         return;
    384     }
    385 
    386     SkOSFile::Iter  iter(SK_FONT_FILE_PREFIX, ".ttf");
    387     SkString        name;
    388     int             count = 0;
    389 
    390     while (iter.next(&name, false)) {
    391         SkString filename;
    392         GetFullPathForSysFonts(&filename, name.c_str());
    393 
    394         bool isFixedWidth;
    395         SkString realname;
    396         SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning
    397 
    398         if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedWidth)) {
    399             SkDebugf("------ can't load <%s> as a font\n", filename.c_str());
    400             continue;
    401         }
    402 
    403 //        SkDebugf("font: <%s> %d <%s>\n", realname.c_str(), style, filename.c_str());
    404 
    405         FamilyRec* family = find_familyrec(realname.c_str());
    406         if (family && family->fFaces[style]) {
    407 //            SkDebugf("---- skipping duplicate typeface %s style %d\n",
    408 //                     realname.c_str(), style);
    409             continue;
    410         }
    411 
    412         // this constructor puts us into the global gFamilyHead llist
    413         FamilyTypeface* tf = SkNEW_ARGS(FileTypeface,
    414                                         (style,
    415                                          true,  // system-font (cannot delete)
    416                                          family, // what family to join
    417                                          filename.c_str(),
    418                                          isFixedWidth) // filename
    419                                         );
    420 
    421         if (NULL == family) {
    422             add_name(realname.c_str(), tf->getFamily());
    423         }
    424         count += 1;
    425     }
    426 
    427     if (0 == count) {
    428         SkNEW(EmptyTypeface);
    429     }
    430 
    431     // do this after all fonts are loaded. This is our default font, and it
    432     // acts as a sentinel so we only execute load_system_fonts() once
    433     static const char* gDefaultNames[] = {
    434         "Arial", "Verdana", "Times New Roman", NULL
    435     };
    436     const char** names = gDefaultNames;
    437     while (*names) {
    438         SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal);
    439         if (tf) {
    440             gDefaultNormal = tf;
    441             break;
    442         }
    443     }
    444     // check if we found *something*
    445     if (NULL == gDefaultNormal) {
    446         if (NULL == gFamilyHead) {
    447             sk_throw();
    448         }
    449         for (int i = 0; i < 4; i++) {
    450             if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) {
    451                 break;
    452             }
    453         }
    454     }
    455     if (NULL == gDefaultNormal) {
    456         sk_throw();
    457     }
    458     gFallBackTypeface = gDefaultNormal;
    459     gDefaultFamily = find_family(gDefaultNormal);
    460 
    461 //    SkDebugf("---- default %p head %p family %p\n", gDefaultNormal, gFamilyHead, gDefaultFamily);
    462 }
    463 
    464 ///////////////////////////////////////////////////////////////////////////////
    465 
    466 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
    467 #if 0
    468     const char* name = ((FamilyTypeface*)face)->getUniqueString();
    469 
    470     stream->write8((uint8_t)face->getStyle());
    471 
    472     if (NULL == name || 0 == *name) {
    473         stream->writePackedUInt(0);
    474         //        SkDebugf("--- fonthost serialize null\n");
    475     } else {
    476         uint32_t len = strlen(name);
    477         stream->writePackedUInt(len);
    478         stream->write(name, len);
    479         //      SkDebugf("--- fonthost serialize <%s> %d\n", name, face->getStyle());
    480     }
    481 #endif
    482     sk_throw();
    483 }
    484 
    485 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
    486 #if 0
    487     load_system_fonts();
    488 
    489     int style = stream->readU8();
    490 
    491     int len = stream->readPackedUInt();
    492     if (len > 0) {
    493         SkString str;
    494         str.resize(len);
    495         stream->read(str.writable_str(), len);
    496 
    497         const FontInitRec* rec = gSystemFonts;
    498         for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
    499             if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
    500                 // backup until we hit the fNames
    501                 for (int j = i; j >= 0; --j) {
    502                     if (rec[j].fNames != NULL) {
    503                         return SkFontHost::CreateTypeface(NULL, rec[j].fNames[0], NULL, 0,
    504                                                           (SkTypeface::Style)style);
    505                     }
    506                 }
    507             }
    508         }
    509     }
    510     return SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, (SkTypeface::Style)style);
    511 #endif
    512     sk_throw();
    513     return NULL;
    514 }
    515 
    516 ///////////////////////////////////////////////////////////////////////////////
    517 
    518 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
    519                                        const char familyName[],
    520                                        const void* data, size_t bytelength,
    521                                        SkTypeface::Style style) {
    522     load_system_fonts();
    523 
    524     SkAutoMutexAcquire  ac(gFamilyMutex);
    525 
    526     // clip to legal style bits
    527     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
    528 
    529     SkTypeface* tf = NULL;
    530 
    531     if (NULL != familyFace) {
    532         tf = find_typeface(familyFace, style);
    533     } else if (NULL != familyName) {
    534         //        SkDebugf("======= familyName <%s>\n", familyName);
    535         tf = find_typeface(familyName, style);
    536     }
    537 
    538     if (NULL == tf) {
    539         tf = find_best_face(gDefaultFamily, style);
    540     }
    541 
    542     SkSafeRef(tf);
    543     return tf;
    544 }
    545 
    546 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
    547     FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
    548     SkStream* stream = tf ? tf->openStream() : NULL;
    549 
    550     if (stream && stream->getLength() == 0) {
    551         stream->unref();
    552         stream = NULL;
    553     }
    554     return stream;
    555 }
    556 
    557 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
    558                                int32_t* index) {
    559     SkDebugf("SkFontHost::GetFileName unimplemented\n");
    560     return 0;
    561 }
    562 
    563 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
    564     return 0;
    565 }
    566 
    567 ///////////////////////////////////////////////////////////////////////////////
    568 
    569 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
    570     if (NULL == stream || stream->getLength() <= 0) {
    571         SkDELETE(stream);
    572         return NULL;
    573     }
    574 
    575     bool isFixedWidth;
    576     SkTypeface::Style style;
    577     if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) {
    578         return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
    579     } else {
    580         return NULL;
    581     }
    582 }
    583 
    584 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
    585     SkTypeface* face = NULL;
    586     SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path));
    587 
    588     if (stream->isValid()) {
    589         face = CreateTypefaceFromStream(stream);
    590     }
    591     stream->unref();
    592     return face;
    593 }
    594 
    595