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