Home | History | Annotate | Download | only in ports
      1 
      2 /*
      3  * Copyright 2013 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 #include "SkFontConfigInterface.h"
     10 #include "SkTypeface_android.h"
     11 
     12 #include "SkFontConfigParser_android.h"
     13 #include "SkFontConfigTypeface.h"
     14 #include "SkFontMgr.h"
     15 #include "SkGlyphCache.h"
     16 #include "SkPaint.h"
     17 #include "SkString.h"
     18 #include "SkStream.h"
     19 #include "SkThread.h"
     20 #include "SkTypefaceCache.h"
     21 #include "SkTArray.h"
     22 #include "SkTDict.h"
     23 #include "SkTSearch.h"
     24 
     25 #include <stdio.h>
     26 #include <string.h>
     27 
     28 #ifndef SK_DEBUG_FONTS
     29     #define SK_DEBUG_FONTS 0
     30 #endif
     31 
     32 #if SK_DEBUG_FONTS
     33     #define DEBUG_FONT(args) SkDebugf args
     34 #else
     35     #define DEBUG_FONT(args)
     36 #endif
     37 
     38 ///////////////////////////////////////////////////////////////////////////////
     39 
     40 // For test only.
     41 static const char* gTestMainConfigFile = NULL;
     42 static const char* gTestFallbackConfigFile = NULL;
     43 static const char* gTestFontFilePrefix = NULL;
     44 
     45 ///////////////////////////////////////////////////////////////////////////////
     46 
     47 typedef int32_t FontRecID;
     48 #define INVALID_FONT_REC_ID -1
     49 
     50 typedef int32_t FamilyRecID;
     51 #define INVALID_FAMILY_REC_ID -1
     52 
     53 // used to record our notion of the pre-existing fonts
     54 struct FontRec {
     55     SkRefPtr<SkTypeface> fTypeface;
     56     SkString fFileName;
     57     SkTypeface::Style fStyle;
     58     bool fIsValid;
     59     FamilyRecID fFamilyRecID;
     60 };
     61 
     62 struct FamilyRec {
     63     FamilyRec() {
     64         memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID));
     65     }
     66 
     67     static const int FONT_STYLE_COUNT = 4;
     68     FontRecID fFontRecID[FONT_STYLE_COUNT];
     69     bool fIsFallbackFont;
     70     SkPaintOptionsAndroid fPaintOptions;
     71 };
     72 
     73 
     74 typedef SkTDArray<FamilyRecID> FallbackFontList;
     75 
     76 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
     77 public:
     78     SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies);
     79     virtual ~SkFontConfigInterfaceAndroid();
     80 
     81     virtual bool matchFamilyName(const char familyName[],
     82                                  SkTypeface::Style requested,
     83                                  FontIdentity* outFontIdentifier,
     84                                  SkString* outFamilyName,
     85                                  SkTypeface::Style* outStyle) SK_OVERRIDE;
     86     virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE;
     87 
     88     // new APIs
     89     virtual SkDataTable* getFamilyNames() SK_OVERRIDE;
     90     virtual bool matchFamilySet(const char inFamilyName[],
     91                                 SkString* outFamilyName,
     92                                 SkTArray<FontIdentity>*) SK_OVERRIDE;
     93 
     94     /**
     95      *  Get the family name of the font in the default fallback font list that
     96      *  contains the specified chararacter. if no font is found, returns false.
     97      */
     98     bool getFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name);
     99     /**
    100      *
    101      */
    102     SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style,
    103                                    SkPaintOptionsAndroid::FontVariant fontVariant);
    104     SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
    105                                     const SkPaintOptionsAndroid& options);
    106     SkTypeface* getTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface,
    107                                       const SkPaintOptionsAndroid& options,
    108                                       int* lowerBounds, int* upperBounds);
    109 
    110 private:
    111     void addFallbackFamily(FamilyRecID fontRecID);
    112     SkTypeface* getTypefaceForFontRec(FontRecID fontRecID);
    113     FallbackFontList* getCurrentLocaleFallbackFontList();
    114     FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOriginal = true);
    115 
    116     SkTArray<FontRec> fFonts;
    117     SkTArray<FamilyRec> fFontFamilies;
    118     SkTDict<FamilyRecID> fFamilyNameDict;
    119     FamilyRecID fDefaultFamilyRecID;
    120 
    121     // (SkLanguage)<->(fallback chain index) translation
    122     SkTDict<FallbackFontList*> fFallbackFontDict;
    123     SkTDict<FallbackFontList*> fFallbackFontAliasDict;
    124     FallbackFontList fDefaultFallbackList;
    125 
    126     // fallback info for current locale
    127     SkString fCachedLocale;
    128     FallbackFontList* fLocaleFallbackFontList;
    129 };
    130 
    131 ///////////////////////////////////////////////////////////////////////////////
    132 
    133 static SkFontConfigInterfaceAndroid* getSingletonInterface() {
    134     SK_DECLARE_STATIC_MUTEX(gMutex);
    135     static SkFontConfigInterfaceAndroid* gFontConfigInterface;
    136 
    137     SkAutoMutexAcquire ac(gMutex);
    138     if (NULL == gFontConfigInterface) {
    139         // load info from a configuration file that we can use to populate the
    140         // system/fallback font structures
    141         SkTDArray<FontFamily*> fontFamilies;
    142         if (!gTestMainConfigFile) {
    143             SkFontConfigParser::GetFontFamilies(fontFamilies);
    144         } else {
    145             SkFontConfigParser::GetTestFontFamilies(fontFamilies, gTestMainConfigFile,
    146                                                     gTestFallbackConfigFile);
    147         }
    148 
    149         gFontConfigInterface = new SkFontConfigInterfaceAndroid(fontFamilies);
    150 
    151         // cleanup the data we received from the parser
    152         fontFamilies.deleteAll();
    153     }
    154     return gFontConfigInterface;
    155 }
    156 
    157 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
    158     return getSingletonInterface();
    159 }
    160 
    161 ///////////////////////////////////////////////////////////////////////////////
    162 
    163 static bool has_font(const SkTArray<FontRec>& array, const SkString& filename) {
    164     for (int i = 0; i < array.count(); i++) {
    165         if (array[i].fFileName == filename) {
    166             return true;
    167         }
    168     }
    169     return false;
    170 }
    171 
    172 #ifndef SK_FONT_FILE_PREFIX
    173     #define SK_FONT_FILE_PREFIX          "/fonts/"
    174 #endif
    175 
    176 static void get_path_for_sys_fonts(SkString* full, const char name[]) {
    177     if (gTestFontFilePrefix) {
    178         full->set(gTestFontFilePrefix);
    179     } else {
    180         full->set(getenv("ANDROID_ROOT"));
    181         full->append(SK_FONT_FILE_PREFIX);
    182     }
    183     full->append(name);
    184 }
    185 
    186 static void insert_into_name_dict(SkTDict<FamilyRecID>& familyNameDict,
    187                                   const char* name, FamilyRecID familyRecID) {
    188     SkAutoAsciiToLC tolc(name);
    189     if (familyNameDict.find(tolc.lc())) {
    190         SkDebugf("---- system font attempting to use a the same name [%s] for"
    191                  "multiple families. skipping subsequent occurrences", tolc.lc());
    192     } else {
    193         familyNameDict.set(tolc.lc(), familyRecID);
    194     }
    195 }
    196 
    197 // Defined in SkFontHost_FreeType.cpp
    198 bool find_name_and_attributes(SkStream* stream, SkString* name,
    199                               SkTypeface::Style* style, bool* isFixedWidth);
    200 
    201 ///////////////////////////////////////////////////////////////////////////////
    202 
    203 SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies) :
    204         fFonts(fontFamilies.count()),
    205         fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT),
    206         fFamilyNameDict(1024),
    207         fDefaultFamilyRecID(INVALID_FAMILY_REC_ID),
    208         fFallbackFontDict(128),
    209         fFallbackFontAliasDict(128),
    210         fLocaleFallbackFontList(NULL) {
    211 
    212     for (int i = 0; i < fontFamilies.count(); ++i) {
    213         FontFamily* family = fontFamilies[i];
    214 
    215         // defer initializing the familyRec until we can be sure that at least
    216         // one of it's children contains a valid font file
    217         FamilyRec* familyRec = NULL;
    218         FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
    219 
    220         for (int j = 0; j < family->fFontFiles.count(); ++j) {
    221             SkString filename;
    222             get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName);
    223 
    224             if (has_font(fFonts, filename)) {
    225                 SkDebugf("---- system font and fallback font files specify a duplicate "
    226                         "font %s, skipping the second occurrence", filename.c_str());
    227                 continue;
    228             }
    229 
    230             FontRec& fontRec = fFonts.push_back();
    231             fontRec.fFileName = filename;
    232             fontRec.fStyle = SkTypeface::kNormal;
    233             fontRec.fIsValid = false;
    234             fontRec.fFamilyRecID = familyRecID;
    235 
    236             const FontRecID fontRecID = fFonts.count() - 1;
    237 
    238             SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
    239             if (stream.get() != NULL) {
    240                 bool isFixedWidth;
    241                 SkString name;
    242                 fontRec.fIsValid = find_name_and_attributes(stream.get(), &name,
    243                                                             &fontRec.fStyle, &isFixedWidth);
    244             } else {
    245                 if (!family->fIsFallbackFont) {
    246                     SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
    247                 }
    248             }
    249 
    250             if (fontRec.fIsValid) {
    251                 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s",
    252                            i, fFonts.count() - 1, family->fIsFallbackFont, filename.c_str()));
    253             } else {
    254                 DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVALID)",
    255                            i, fFonts.count() - 1, family->fIsFallbackFont, filename.c_str()));
    256                 continue;
    257             }
    258 
    259             // create a familyRec now that we know that at least one font in
    260             // the family is valid
    261             if (familyRec == NULL) {
    262                 familyRec = &fFontFamilies.push_back();
    263                 familyRecID = fFontFamilies.count() - 1;
    264                 fontRec.fFamilyRecID = familyRecID;
    265 
    266                 familyRec->fIsFallbackFont = family->fIsFallbackFont;
    267                 familyRec->fPaintOptions = family->fFontFiles[j]->fPaintOptions;
    268 
    269                 // if this is a fallback font then add it to the appropriate fallback chains
    270                 if (familyRec->fIsFallbackFont) {
    271                     addFallbackFamily(familyRecID);
    272                 }
    273             } else if (familyRec->fPaintOptions != family->fFontFiles[j]->fPaintOptions) {
    274                 SkDebugf("Every font file within a family must have identical"
    275                          "language and variant attributes");
    276                 sk_throw();
    277             }
    278 
    279             // add this font to the current familyRec
    280             if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) {
    281                 DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d)",
    282                             fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle],
    283                             fontRecID));
    284             }
    285             familyRec->fFontRecID[fontRec.fStyle] = fontRecID;
    286 
    287             // add the fallback file name to the name dictionary.  This is needed
    288             // by getFallbackFamilyNameForChar() so that fallback families can be
    289             // requested by the filenames of the fonts they contain.
    290             if (familyRec && familyRec->fIsFallbackFont) {
    291                 insert_into_name_dict(fFamilyNameDict, fontRec.fFileName.c_str(), familyRecID);
    292             }
    293         }
    294 
    295         // add the names that map to this family to the dictionary for easy lookup
    296         if (familyRec && !familyRec->fIsFallbackFont) {
    297             SkTDArray<const char*> names = family->fNames;
    298             if (names.isEmpty()) {
    299                 SkDEBUGFAIL("ERROR: non-fallback font with no name");
    300                 continue;
    301             }
    302 
    303             for (int i = 0; i < names.count(); i++) {
    304                 insert_into_name_dict(fFamilyNameDict, names[i], familyRecID);
    305             }
    306         }
    307 
    308     }
    309 
    310     DEBUG_FONT(("---- We have %d system fonts", fFonts.count()));
    311 
    312     if (fFontFamilies.count() > 0) {
    313         fDefaultFamilyRecID = 0;
    314     }
    315 
    316     // scans the default fallback font chain, adding every entry to every other
    317     // fallback font chain to which it does not belong. this results in every
    318     // language-specific fallback font chain having all of its fallback fonts at
    319     // the front of the chain, and everything else at the end.
    320     FallbackFontList* fallbackList;
    321     SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict);
    322     const char* fallbackLang = iter.next(&fallbackList);
    323     while(fallbackLang != NULL) {
    324         for (int i = 0; i < fDefaultFallbackList.count(); i++) {
    325             FamilyRecID familyRecID = fDefaultFallbackList[i];
    326             const SkString& fontLang = fFontFamilies[familyRecID].fPaintOptions.getLanguage().getTag();
    327             if (strcmp(fallbackLang, fontLang.c_str()) != 0) {
    328                 fallbackList->push(familyRecID);
    329             }
    330         }
    331         // move to the next fallback list in the dictionary
    332         fallbackLang = iter.next(&fallbackList);
    333     }
    334 }
    335 
    336 SkFontConfigInterfaceAndroid::~SkFontConfigInterfaceAndroid() {
    337     // iterate through and cleanup fFallbackFontDict
    338     SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict);
    339     FallbackFontList* fallbackList;
    340     while(iter.next(&fallbackList) != NULL) {
    341         SkDELETE(fallbackList);
    342     }
    343 }
    344 
    345 void SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) {
    346     SkASSERT(familyRecID < fFontFamilies.count());
    347     const FamilyRec& familyRec = fFontFamilies[familyRecID];
    348     SkASSERT(familyRec.fIsFallbackFont);
    349 
    350     // add to the default fallback list
    351     fDefaultFallbackList.push(familyRecID);
    352 
    353     // stop here if it is the default language tag
    354     const SkString& languageTag = familyRec.fPaintOptions.getLanguage().getTag();
    355     if (languageTag.isEmpty()) {
    356         return;
    357     }
    358 
    359     // add to the appropriate language's custom fallback list
    360     FallbackFontList* customList = NULL;
    361     if (!fFallbackFontDict.find(languageTag.c_str(), &customList)) {
    362         DEBUG_FONT(("----  Created fallback list for \"%s\"", languageTag.c_str()));
    363         customList = SkNEW(FallbackFontList);
    364         fFallbackFontDict.set(languageTag.c_str(), customList);
    365     }
    366     SkASSERT(customList != NULL);
    367     customList->push(familyRecID);
    368 }
    369 
    370 
    371 static FontRecID find_best_style(const FamilyRec& family, SkTypeface::Style style) {
    372 
    373     const FontRecID* fontRecIDs = family.fFontRecID;
    374 
    375     if (fontRecIDs[style] != INVALID_FONT_REC_ID) { // exact match
    376         return fontRecIDs[style];
    377     }
    378     // look for a matching bold
    379     style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
    380     if (fontRecIDs[style] != INVALID_FONT_REC_ID) {
    381         return fontRecIDs[style];
    382     }
    383     // look for the plain
    384     if (fontRecIDs[SkTypeface::kNormal] != INVALID_FONT_REC_ID) {
    385         return fontRecIDs[SkTypeface::kNormal];
    386     }
    387     // look for anything
    388     for (int i = 0; i < FamilyRec::FONT_STYLE_COUNT; i++) {
    389         if (fontRecIDs[i] != INVALID_FONT_REC_ID) {
    390             return fontRecIDs[i];
    391         }
    392     }
    393     // should never get here, since the fontRecID list should not be empty
    394     SkDEBUGFAIL("No valid fonts exist for this family");
    395     return -1;
    396 }
    397 
    398 bool SkFontConfigInterfaceAndroid::matchFamilyName(const char familyName[],
    399                                                    SkTypeface::Style style,
    400                                                    FontIdentity* outFontIdentifier,
    401                                                    SkString* outFamilyName,
    402                                                    SkTypeface::Style* outStyle) {
    403     // clip to legal style bits
    404     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
    405 
    406     bool exactNameMatch = false;
    407 
    408     FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
    409     if (NULL != familyName) {
    410         SkAutoAsciiToLC tolc(familyName);
    411         if (fFamilyNameDict.find(tolc.lc(), &familyRecID)) {
    412             exactNameMatch = true;
    413         }
    414     } else {
    415         familyRecID = fDefaultFamilyRecID;
    416 
    417     }
    418 
    419     // If no matching family name is found then return false. This allows clients
    420     // to be able to search for other fonts instead of forcing them to use the
    421     // default font.
    422     if (INVALID_FAMILY_REC_ID == familyRecID) {
    423         return false;
    424     }
    425 
    426     FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], style);
    427     FontRec& fontRec = fFonts[fontRecID];
    428 
    429     if (NULL != outFontIdentifier) {
    430         outFontIdentifier->fID = fontRecID;
    431         outFontIdentifier->fTTCIndex = 0;
    432         outFontIdentifier->fString.set(fontRec.fFileName);
    433 //        outFontIdentifier->fStyle = fontRec.fStyle;
    434     }
    435 
    436     if (NULL != outFamilyName) {
    437         if (exactNameMatch) {
    438             outFamilyName->set(familyName);
    439         } else {
    440             // find familyName from list of names
    441             const char* familyName = NULL;
    442             SkAssertResult(fFamilyNameDict.findKey(familyRecID, &familyName));
    443             SkASSERT(familyName);
    444             outFamilyName->set(familyName);
    445         }
    446     }
    447 
    448     if (NULL != outStyle) {
    449         *outStyle = fontRec.fStyle;
    450     }
    451 
    452     return true;
    453 }
    454 
    455 SkStream* SkFontConfigInterfaceAndroid::openStream(const FontIdentity& identity) {
    456     return SkStream::NewFromFile(identity.fString.c_str());
    457 }
    458 
    459 SkDataTable* SkFontConfigInterfaceAndroid::getFamilyNames() {
    460     SkTDArray<const char*> names;
    461     SkTDArray<size_t> sizes;
    462 
    463     SkTDict<FamilyRecID>::Iter iter(fFamilyNameDict);
    464     const char* familyName = iter.next(NULL);
    465     while(familyName != NULL) {
    466         *names.append() = familyName;
    467         *sizes.append() = strlen(familyName) + 1;
    468 
    469         // move to the next familyName in the dictionary
    470         familyName = iter.next(NULL);
    471     }
    472 
    473     return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
    474                                       sizes.begin(), names.count());
    475 }
    476 
    477 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[],
    478                                                   SkString* outFamilyName,
    479                                                   SkTArray<FontIdentity>*) {
    480     return false;
    481 }
    482 
    483 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
    484     const FontRecID* fontRecID = (const FontRecID*)ctx;
    485     FontRecID currFontRecID = ((FontConfigTypeface*)face)->getIdentity().fID;
    486     return currFontRecID == *fontRecID;
    487 }
    488 
    489 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRecID) {
    490     FontRec& fontRec = fFonts[fontRecID];
    491     SkTypeface* face = fontRec.fTypeface.get();
    492     if (!face) {
    493         // look for it in the typeface cache
    494         face = SkTypefaceCache::FindByProcAndRef(find_proc, &fontRecID);
    495 
    496         // if it is not in the cache then create it
    497         if (!face) {
    498             const char* familyName = NULL;
    499             SkAssertResult(fFamilyNameDict.findKey(fontRec.fFamilyRecID, &familyName));
    500             SkASSERT(familyName);
    501             face = SkTypeface::CreateFromName(familyName, fontRec.fStyle);
    502         }
    503 
    504         // store the result for subsequent lookups
    505         fontRec.fTypeface = face;
    506     }
    507     SkASSERT(face);
    508     return face;
    509 }
    510 
    511 bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni,
    512                                                                 const char* lang,
    513                                                                 SkString* name) {
    514     FallbackFontList* fallbackFontList = NULL;
    515     const SkString langTag(lang);
    516     if (langTag.isEmpty()) {
    517         fallbackFontList = this->getCurrentLocaleFallbackFontList();
    518     } else {
    519         fallbackFontList = this->findFallbackFontList(langTag);
    520     }
    521 
    522     for (int i = 0; i < fallbackFontList->count(); i++) {
    523         FamilyRecID familyRecID = fallbackFontList->getAt(i);
    524 
    525         // if it is not one of the accepted variants then move to the next family
    526         int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant |
    527                                    SkPaintOptionsAndroid::kElegant_Variant;
    528         if (!(fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants)) {
    529             continue;
    530         }
    531 
    532         FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkTypeface::kNormal);
    533         SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
    534 
    535         SkPaint paint;
    536         paint.setTypeface(face);
    537         paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
    538 
    539         uint16_t glyphID;
    540         paint.textToGlyphs(&uni, sizeof(uni), &glyphID);
    541         if (glyphID != 0) {
    542             name->set(fFonts[fontRecID].fFileName);
    543             return true;
    544         }
    545     }
    546     return false;
    547 }
    548 
    549 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni,
    550                                                              SkTypeface::Style style,
    551                                                              SkPaintOptionsAndroid::FontVariant fontVariant) {
    552     FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], style);
    553     SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
    554 
    555     SkPaintOptionsAndroid paintOptions;
    556     paintOptions.setFontVariant(fontVariant);
    557     paintOptions.setUseFontFallbacks(true);
    558 
    559     SkPaint paint;
    560     paint.setTypeface(face);
    561     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    562     paint.setPaintOptionsAndroid(paintOptions);
    563 
    564     SkAutoGlyphCache autoCache(paint, NULL, NULL);
    565     SkGlyphCache*    cache = autoCache.getCache();
    566 
    567     SkScalerContext* ctx = cache->getScalerContext();
    568     if (ctx) {
    569         SkFontID fontID = ctx->findTypefaceIdForChar(uni);
    570         return SkTypefaceCache::FindByID(fontID);
    571     }
    572     return NULL;
    573 }
    574 
    575 FallbackFontList* SkFontConfigInterfaceAndroid::getCurrentLocaleFallbackFontList() {
    576     SkString locale = SkFontConfigParser::GetLocale();
    577     if (NULL == fLocaleFallbackFontList || locale != fCachedLocale) {
    578         fCachedLocale = locale;
    579         fLocaleFallbackFontList = this->findFallbackFontList(locale);
    580     }
    581     return fLocaleFallbackFontList;
    582 }
    583 
    584 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLanguage& lang,
    585                                                                      bool isOriginal) {
    586     const SkString& langTag = lang.getTag();
    587     if (langTag.isEmpty()) {
    588         return &fDefaultFallbackList;
    589     }
    590 
    591     FallbackFontList* fallbackFontList;
    592     if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontList) ||
    593         fFallbackFontAliasDict.find(langTag.c_str(), langTag.size(), &fallbackFontList)) {
    594         return fallbackFontList;
    595     }
    596 
    597     // attempt a recursive fuzzy match
    598     SkLanguage parent = lang.getParent();
    599     fallbackFontList = findFallbackFontList(parent, false);
    600 
    601     // cache the original lang so we don't have to do the recursion again.
    602     if (isOriginal) {
    603         DEBUG_FONT(("----  Created fallback list alias for \"%s\"", langTag.c_str()));
    604         fFallbackFontAliasDict.set(langTag.c_str(), fallbackFontList);
    605     }
    606     return fallbackFontList;
    607 }
    608 
    609 SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontID,
    610                                                               SkFontID origFontID,
    611                                                               const SkPaintOptionsAndroid& opts) {
    612     // Skia does not support font fallback by default. This enables clients such
    613     // as WebKit to customize their font selection. In any case, clients can use
    614     // GetFallbackFamilyNameForChar() to get the fallback font for individual
    615     // characters.
    616     if (!opts.isUsingFontFallbacks()) {
    617         return NULL;
    618     }
    619 
    620     FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
    621     SkASSERT(currentFallbackList);
    622 
    623     SkTypeface::Style origStyle = SkTypeface::kNormal;
    624     const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID);
    625     if (NULL != origTypeface) {
    626         origStyle = origTypeface->style();
    627     }
    628 
    629     // we must convert currTypeface into a FontRecID
    630     FontRecID currFontRecID = INVALID_FONT_REC_ID;
    631     const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
    632     // non-system fonts are not in the font cache so if we are asked to fallback
    633     // for a non-system font we will start at the front of the chain.
    634     if (NULL != currTypeface) {
    635         currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity().fID;
    636         SkASSERT(INVALID_FONT_REC_ID != currFontRecID);
    637     }
    638 
    639     FamilyRecID currFamilyRecID = INVALID_FAMILY_REC_ID;
    640     if (INVALID_FONT_REC_ID != currFontRecID) {
    641         currFamilyRecID = fFonts[currFontRecID].fFamilyRecID;
    642     }
    643 
    644     // lookup the index next font in the chain
    645     int currFallbackFontIndex = currentFallbackList->find(currFamilyRecID);
    646     // We add 1 to the returned index for 2 reasons: (1) if find succeeds it moves
    647     // our index to the next entry in the list; (2) if find() fails it returns
    648     // -1 and incrementing it will set our starting index to 0 (the head of the list)
    649     int nextFallbackFontIndex = currFallbackFontIndex + 1;
    650 
    651     if(nextFallbackFontIndex >= currentFallbackList->count()) {
    652         return NULL;
    653     }
    654 
    655     // If a rec object is set to prefer "kDefault_Variant" it means they have no preference
    656     // In this case, we set the value to "kCompact_Variant"
    657     SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant();
    658     if (variant == SkPaintOptionsAndroid::kDefault_Variant) {
    659         variant = SkPaintOptionsAndroid::kCompact_Variant;
    660     }
    661 
    662     int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
    663 
    664     SkTypeface* nextLogicalTypeface = 0;
    665     while (nextFallbackFontIndex < currentFallbackList->count()) {
    666         FamilyRecID familyRecID = currentFallbackList->getAt(nextFallbackFontIndex);
    667         if ((fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) {
    668             FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle);
    669             nextLogicalTypeface = this->getTypefaceForFontRec(matchedFont);
    670             break;
    671         }
    672         nextFallbackFontIndex++;
    673     }
    674 
    675     DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=%d, "
    676                 "lang=%s, variant=%d, nextFallbackIndex[%d,%d] => nextLogicalTypeface=%d",
    677                 currFontID, origFontID, currFontRecID, opts.getLanguage().getTag().c_str(),
    678                 variant, nextFallbackFontIndex, currentFallbackList->getAt(nextFallbackFontIndex),
    679                 (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0));
    680     return SkSafeRef(nextLogicalTypeface);
    681 }
    682 
    683 SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForGlyphID(uint16_t glyphID,
    684                                                                 const SkTypeface* origTypeface,
    685                                                                 const SkPaintOptionsAndroid& opts,
    686                                                                 int* lBounds, int* uBounds) {
    687     // If we aren't using fallbacks then we shouldn't be calling this
    688     SkASSERT(opts.isUsingFontFallbacks());
    689     SkASSERT(origTypeface);
    690 
    691     SkTypeface* currentTypeface = NULL;
    692     int lowerBounds = 0; //inclusive
    693     int upperBounds = origTypeface->countGlyphs(); //exclusive
    694 
    695     // check to see if the glyph is in the bounds of the origTypeface
    696     if (glyphID < upperBounds) {
    697         currentTypeface = const_cast<SkTypeface*>(origTypeface);
    698     } else {
    699         FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
    700         SkASSERT(currentFallbackList);
    701 
    702         // If an object is set to prefer "kDefault_Variant" it means they have no preference
    703         // In this case, we set the value to "kCompact_Variant"
    704         SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant();
    705         if (variant == SkPaintOptionsAndroid::kDefault_Variant) {
    706             variant = SkPaintOptionsAndroid::kCompact_Variant;
    707         }
    708 
    709         int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
    710         SkTypeface::Style origStyle = origTypeface->style();
    711 
    712         for (int x = 0; x < currentFallbackList->count(); ++x) {
    713             const FamilyRecID familyRecID = currentFallbackList->getAt(x);
    714             const SkPaintOptionsAndroid& familyOptions = fFontFamilies[familyRecID].fPaintOptions;
    715             if ((familyOptions.getFontVariant() & acceptedVariants) != 0) {
    716                 FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle);
    717                 currentTypeface = this->getTypefaceForFontRec(matchedFont);
    718                 lowerBounds = upperBounds;
    719                 upperBounds += currentTypeface->countGlyphs();
    720                 if (glyphID < upperBounds) {
    721                     break;
    722                 }
    723             }
    724         }
    725     }
    726 
    727     if (NULL != currentTypeface) {
    728         if (lBounds) {
    729             *lBounds = lowerBounds;
    730         }
    731         if (uBounds) {
    732             *uBounds = upperBounds;
    733         }
    734     }
    735     return currentTypeface;
    736 }
    737 
    738 ///////////////////////////////////////////////////////////////////////////////
    739 
    740 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
    741     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
    742     return fontConfig->getFallbackFamilyNameForChar(uni, NULL, name);
    743 }
    744 
    745 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name) {
    746     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
    747     return fontConfig->getFallbackFamilyNameForChar(uni, lang, name);
    748 }
    749 
    750 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
    751                              const char* fontsdir) {
    752     gTestMainConfigFile = mainconf;
    753     gTestFallbackConfigFile = fallbackconf;
    754     gTestFontFilePrefix = fontsdir;
    755     SkASSERT(gTestMainConfigFile);
    756     SkASSERT(gTestFallbackConfigFile);
    757     SkASSERT(gTestFontFilePrefix);
    758     SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
    759               gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
    760 }
    761 
    762 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
    763                                          const SkPaintOptionsAndroid& options) {
    764     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
    765     return fontConfig->nextLogicalTypeface(currFontID, origFontID, options);
    766 
    767 }
    768 
    769 SkTypeface* SkGetTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface,
    770                                     const SkPaintOptionsAndroid& options,
    771                                     int* lowerBounds, int* upperBounds) {
    772     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
    773     return fontConfig->getTypefaceForGlyphID(glyphID, origTypeface, options,
    774                                              lowerBounds, upperBounds);
    775 }
    776 
    777 ///////////////////////////////////////////////////////////////////////////////
    778 
    779 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    780 
    781 struct HB_UnicodeMapping {
    782     // TODO: when the WebView no longer needs harfbuzz_old, remove
    783     HB_Script script_old;
    784     hb_script_t script;
    785     const SkUnichar unicode;
    786 };
    787 
    788 /*
    789  * The following scripts are not complex fonts and we do not expect them to be parsed by this table
    790  * HB_SCRIPT_COMMON,
    791  * HB_SCRIPT_GREEK,
    792  * HB_SCRIPT_CYRILLIC,
    793  * HB_SCRIPT_HANGUL
    794  * HB_SCRIPT_INHERITED
    795  */
    796 
    797 /* Harfbuzz (old) is missing a number of scripts in its table. For these,
    798  * we include a value which can never happen. We won't get complex script
    799  * shaping in these cases, but the library wouldn't know how to shape
    800  * them anyway. */
    801 #define HB_Script_Unknown HB_ScriptCount
    802 
    803 static HB_UnicodeMapping HB_UnicodeMappingArray[] = {
    804     {HB_Script_Armenian,   HB_SCRIPT_ARMENIAN,    0x0531},
    805     {HB_Script_Hebrew,     HB_SCRIPT_HEBREW,      0x0591},
    806     {HB_Script_Arabic,     HB_SCRIPT_ARABIC,      0x0600},
    807     {HB_Script_Syriac,     HB_SCRIPT_SYRIAC,      0x0710},
    808     {HB_Script_Thaana,     HB_SCRIPT_THAANA,      0x0780},
    809     {HB_Script_Nko,        HB_SCRIPT_NKO,         0x07C0},
    810     {HB_Script_Devanagari, HB_SCRIPT_DEVANAGARI,  0x0901},
    811     {HB_Script_Bengali,    HB_SCRIPT_BENGALI,     0x0981},
    812     {HB_Script_Gurmukhi,   HB_SCRIPT_GURMUKHI,    0x0A10},
    813     {HB_Script_Gujarati,   HB_SCRIPT_GUJARATI,    0x0A90},
    814     {HB_Script_Oriya,      HB_SCRIPT_ORIYA,       0x0B10},
    815     {HB_Script_Tamil,      HB_SCRIPT_TAMIL,       0x0B82},
    816     {HB_Script_Telugu,     HB_SCRIPT_TELUGU,      0x0C10},
    817     {HB_Script_Kannada,    HB_SCRIPT_KANNADA,     0x0C90},
    818     {HB_Script_Malayalam,  HB_SCRIPT_MALAYALAM,   0x0D10},
    819     {HB_Script_Sinhala,    HB_SCRIPT_SINHALA,     0x0D90},
    820     {HB_Script_Thai,       HB_SCRIPT_THAI,        0x0E01},
    821     {HB_Script_Lao,        HB_SCRIPT_LAO,         0x0E81},
    822     {HB_Script_Tibetan,    HB_SCRIPT_TIBETAN,     0x0F00},
    823     {HB_Script_Myanmar,    HB_SCRIPT_MYANMAR,     0x1000},
    824     {HB_Script_Georgian,   HB_SCRIPT_GEORGIAN,    0x10A0},
    825     {HB_Script_Unknown,    HB_SCRIPT_ETHIOPIC,    0x1200},
    826     {HB_Script_Unknown,    HB_SCRIPT_CHEROKEE,    0x13A0},
    827     {HB_Script_Ogham,      HB_SCRIPT_OGHAM,       0x1680},
    828     {HB_Script_Runic,      HB_SCRIPT_RUNIC,       0x16A0},
    829     {HB_Script_Khmer,      HB_SCRIPT_KHMER,       0x1780},
    830     {HB_Script_Unknown,    HB_SCRIPT_TAI_LE,      0x1950},
    831     {HB_Script_Unknown,    HB_SCRIPT_NEW_TAI_LUE, 0x1980},
    832     {HB_Script_Unknown,    HB_SCRIPT_TAI_THAM,    0x1A20},
    833     {HB_Script_Unknown,    HB_SCRIPT_CHAM,        0xAA00},
    834 };
    835 
    836 static hb_script_t getHBScriptFromHBScriptOld(HB_Script script_old) {
    837     hb_script_t script = HB_SCRIPT_INVALID;
    838     int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping);
    839     for (int i = 0; i < numSupportedFonts; i++) {
    840         if (script_old == HB_UnicodeMappingArray[i].script_old) {
    841             script = HB_UnicodeMappingArray[i].script;
    842             break;
    843         }
    844     }
    845     return script;
    846 }
    847 
    848 // returns 0 for "Not Found"
    849 static SkUnichar getUnicodeFromHBScript(hb_script_t script) {
    850     SkUnichar unichar = 0;
    851     int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping);
    852     for (int i = 0; i < numSupportedFonts; i++) {
    853         if (script == HB_UnicodeMappingArray[i].script) {
    854             unichar = HB_UnicodeMappingArray[i].unicode;
    855             break;
    856         }
    857     }
    858     return unichar;
    859 }
    860 
    861 struct TypefaceLookupStruct {
    862     hb_script_t script;
    863     SkTypeface::Style style;
    864     SkPaintOptionsAndroid::FontVariant fontVariant;
    865     SkTypeface* typeface;
    866 };
    867 
    868 SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex);  // This is the mutex for gTypefaceTable
    869 static SkTDArray<TypefaceLookupStruct> gTypefaceTable;  // This is protected by gTypefaceTableMutex
    870 
    871 static int typefaceLookupCompare(const TypefaceLookupStruct& first,
    872                                  const TypefaceLookupStruct& second) {
    873     if (first.script != second.script) {
    874         return (first.script > second.script) ? 1 : -1;
    875     }
    876     if (first.style != second.style) {
    877         return (first.style > second.style) ? 1 : -1;
    878     }
    879     if (first.fontVariant != second.fontVariant) {
    880         return (first.fontVariant > second.fontVariant) ? 1 : -1;
    881     }
    882     return 0;
    883 }
    884 
    885 SkTypeface* SkCreateTypefaceForScriptNG(hb_script_t script, SkTypeface::Style style,
    886                                         SkPaintOptionsAndroid::FontVariant fontVariant) {
    887     SkAutoMutexAcquire ac(gTypefaceTableMutex);
    888 
    889     TypefaceLookupStruct key;
    890     key.script = script;
    891     key.style = style;
    892     key.fontVariant = fontVariant;
    893 
    894     int index = SkTSearch<TypefaceLookupStruct>(
    895             (const TypefaceLookupStruct*) gTypefaceTable.begin(),
    896             gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct),
    897             typefaceLookupCompare);
    898 
    899     SkTypeface* retTypeface = NULL;
    900     if (index >= 0) {
    901         retTypeface = gTypefaceTable[index].typeface;
    902     }
    903     else {
    904         SkUnichar unichar = getUnicodeFromHBScript(script);
    905         if (!unichar) {
    906             return NULL;
    907         }
    908 
    909         SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
    910         retTypeface = fontConfig->getTypefaceForChar(unichar, style, fontVariant);
    911 
    912         // add to the lookup table
    913         key.typeface = retTypeface;
    914         *gTypefaceTable.insert(~index) = key;
    915     }
    916 
    917     // we ref(), the caller is expected to unref when they are done
    918     return SkSafeRef(retTypeface);
    919 }
    920 
    921 SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style,
    922                                       SkPaintOptionsAndroid::FontVariant fontVariant) {
    923     return SkCreateTypefaceForScriptNG(getHBScriptFromHBScriptOld(script), style, fontVariant);
    924 }
    925 
    926 #endif
    927 
    928 ///////////////////////////////////////////////////////////////////////////////
    929 
    930 SkFontMgr* SkFontMgr::Factory() {
    931     return NULL;
    932 }
    933