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