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