gfx/skia/trunk/src/ports/SkFontConfigInterface_android.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
     9 #include "SkFontConfigInterface.h"
    10 #include "SkTypeface_android.h"
    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"
    25 #include <stdio.h>
    26 #include <string.h>
    28 #ifndef SK_DEBUG_FONTS
    29     #define SK_DEBUG_FONTS 0
    30 #endif
    32 #if SK_DEBUG_FONTS
    33     #define DEBUG_FONT(args) SkDebugf args
    34 #else
    35     #define DEBUG_FONT(args)
    36 #endif
    38 ///////////////////////////////////////////////////////////////////////////////
    40 // For test only.
    41 static const char* gTestMainConfigFile = NULL;
    42 static const char* gTestFallbackConfigFile = NULL;
    43 static const char* gTestFontFilePrefix = NULL;
    45 ///////////////////////////////////////////////////////////////////////////////
    47 typedef int32_t FontRecID;
    48 #define INVALID_FONT_REC_ID -1
    50 typedef int32_t FamilyRecID;
    51 #define INVALID_FAMILY_REC_ID -1
    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 };
    62 struct FamilyRec {
    63     FamilyRec() {
    64         memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID));
    65     }
    67     static const int FONT_STYLE_COUNT = 4;
    68     FontRecID fFontRecID[FONT_STYLE_COUNT];
    69     bool fIsFallbackFont;
    70     SkString fFallbackName;
    71     SkPaintOptionsAndroid fPaintOptions;
    72 };
    75 typedef SkTDArray<FamilyRecID> FallbackFontList;
    77 class SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
    78 public:
    79     SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies);
    80     virtual ~SkFontConfigInterfaceAndroid();
    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;
    89     // new APIs
    90     virtual SkDataTable* getFamilyNames() SK_OVERRIDE;
    91     virtual bool matchFamilySet(const char inFamilyName[],
    92                                 SkString* outFamilyName,
    93                                 SkTArray<FontIdentity>*) SK_OVERRIDE;
    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);
   111 private:
   112     void addFallbackFamily(FamilyRecID fontRecID);
   113     SkTypeface* getTypefaceForFontRec(FontRecID fontRecID);
   114     FallbackFontList* getCurrentLocaleFallbackFontList();
   115     FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOriginal = true);
   117     SkTArray<FontRec> fFonts;
   118     SkTArray<FamilyRec> fFontFamilies;
   119     SkTDict<FamilyRecID> fFamilyNameDict;
   120     FamilyRecID fDefaultFamilyRecID;
   122     // (SkLanguage)<->(fallback chain index) translation
   123     SkTDict<FallbackFontList*> fFallbackFontDict;
   124     SkTDict<FallbackFontList*> fFallbackFontAliasDict;
   125     FallbackFontList fDefaultFallbackList;
   127     // fallback info for current locale
   128     SkString fCachedLocale;
   129     FallbackFontList* fLocaleFallbackFontList;
   130 };
   132 ///////////////////////////////////////////////////////////////////////////////
   134 static SkFontConfigInterfaceAndroid* getSingletonInterface() {
   135     SK_DECLARE_STATIC_MUTEX(gMutex);
   136     static SkFontConfigInterfaceAndroid* gFontConfigInterface;
   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         }
   150         gFontConfigInterface = new SkFontConfigInterfaceAndroid(fontFamilies);
   152         // cleanup the data we received from the parser
   153         fontFamilies.deleteAll();
   154     }
   155     return gFontConfigInterface;
   156 }
   158 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
   159     return getSingletonInterface();
   160 }
   162 ///////////////////////////////////////////////////////////////////////////////
   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 }
   173 #ifndef SK_FONT_FILE_PREFIX
   174     #define SK_FONT_FILE_PREFIX          "/fonts/"
   175 #endif
   177 static void get_path_for_sys_fonts(SkString* full, const char 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 }
   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 }
   198 // Defined in SkFontHost_FreeType.cpp
   199 bool find_name_and_attributes(SkStream* stream, SkString* name,
   200                               SkTypeface::Style* style, bool* isFixedWidth);
   202 ///////////////////////////////////////////////////////////////////////////////
   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) {
   213     for (int i = 0; i < fontFamilies.count(); ++i) {
   214         FontFamily* family = fontFamilies[i];
   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;
   221         for (int j = 0; j < family->fFontFiles.count(); ++j) {
   222             SkString filename;
   223             get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName);
   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             }
   231             FontRec& fontRec = fFonts.push_back();
   232             fontRec.fFileName = filename;
   233             fontRec.fStyle = SkTypeface::kNormal;
   234             fontRec.fIsValid = false;
   235             fontRec.fFamilyRecID = familyRecID;
   237             const FontRecID fontRecID = fFonts.count() - 1;
   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             }
   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             }
   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;
   267                 familyRec->fIsFallbackFont = family->fIsFallbackFont;
   268                 familyRec->fPaintOptions = family->fFontFiles[j]->fPaintOptions;
   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             }
   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         }
   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 SkTDArray<const char*>& names = family->fNames;
   293                 if (names.isEmpty()) {
   294                     SkDEBUGFAIL("ERROR: non-fallback font with no name");
   295                     continue;
   296                 }
   298                 for (int i = 0; i < names.count(); i++) {
   299                     insert_into_name_dict(fFamilyNameDict, names[i], familyRecID);
   300                 }
   301             }
   302         }
   303     }
   305     DEBUG_FONT(("---- We have %d system fonts", fFonts.count()));
   307     if (fFontFamilies.count() > 0) {
   308         fDefaultFamilyRecID = 0;
   309     }
   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 }
   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 }
   340 void SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) {
   341     SkASSERT(familyRecID < fFontFamilies.count());
   342     FamilyRec& familyRec = fFontFamilies[familyRecID];
   343     SkASSERT(familyRec.fIsFallbackFont);
   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);
   352     // add to the default fallback list
   353     fDefaultFallbackList.push(familyRecID);
   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     }
   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 }
   373 static FontRecID find_best_style(const FamilyRec& family, SkTypeface::Style style) {
   375     const FontRecID* fontRecIDs = family.fFontRecID;
   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 }
   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);
   408     bool exactNameMatch = false;
   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;
   419     }
   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     }
   428     FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], style);
   429     FontRec& fontRec = fFonts[fontRecID];
   431     if (NULL != outFontIdentifier) {
   432         outFontIdentifier->fID = fontRecID;
   433         outFontIdentifier->fTTCIndex = 0;
   434         outFontIdentifier->fString.set(fontRec.fFileName);
   435 //        outFontIdentifier->fStyle = fontRec.fStyle;
   436     }
   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     }
   450     if (NULL != outStyle) {
   451         *outStyle = fontRec.fStyle;
   452     }
   454     return true;
   455 }
   457 SkStream* SkFontConfigInterfaceAndroid::openStream(const FontIdentity& identity) {
   458     return SkStream::NewFromFile(identity.fString.c_str());
   459 }
   461 SkDataTable* SkFontConfigInterfaceAndroid::getFamilyNames() {
   462     SkTDArray<const char*> names;
   463     SkTDArray<size_t> sizes;
   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;
   471         // move to the next familyName in the dictionary
   472         familyName = iter.next(NULL);
   473     }
   475     return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
   476                                       sizes.begin(), names.count());
   477 }
   479 bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[],
   480                                                   SkString* outFamilyName,
   481                                                   SkTArray<FontIdentity>*) {
   482     return false;
   483 }
   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 }
   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);
   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         }
   506         // store the result for subsequent lookups
   507         fontRec.fTypeface = face;
   508     }
   509     SkASSERT(face);
   510     return face;
   511 }
   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     }
   524     for (int i = 0; i < fallbackFontList->count(); i++) {
   525         FamilyRecID familyRecID = fallbackFontList->getAt(i);
   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         }
   534         FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkTypeface::kNormal);
   535         SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
   537         SkPaint paint;
   538         paint.setTypeface(face);
   539         paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
   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 }
   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);
   557     SkPaintOptionsAndroid paintOptions;
   558     paintOptions.setFontVariant(fontVariant);
   559     paintOptions.setUseFontFallbacks(true);
   561     SkPaint paint;
   562     paint.setTypeface(face);
   563     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
   564     paint.setPaintOptionsAndroid(paintOptions);
   566     SkAutoGlyphCache autoCache(paint, NULL, NULL);
   567     SkGlyphCache*    cache = autoCache.getCache();
   569     SkScalerContext* ctx = cache->getScalerContext();
   570     if (ctx) {
   571         SkFontID fontID = ctx->findTypefaceIdForChar(uni);
   572         return SkTypefaceCache::FindByID(fontID);
   573     }
   574     return NULL;
   575 }
   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 }
   586 FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLanguage& lang,
   587                                                                      bool isOriginal) {
   588     const SkString& langTag = lang.getTag();
   589     if (langTag.isEmpty()) {
   590         return &fDefaultFallbackList;
   591     }
   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     }
   599     // attempt a recursive fuzzy match
   600     SkLanguage parent = lang.getParent();
   601     fallbackFontList = findFallbackFontList(parent, false);
   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 }
   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     }
   622     FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
   623     SkASSERT(currentFallbackList);
   625     SkTypeface::Style origStyle = SkTypeface::kNormal;
   626     const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID);
   627     if (NULL != origTypeface) {
   628         origStyle = origTypeface->style();
   629     }
   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     }
   641     FamilyRecID currFamilyRecID = INVALID_FAMILY_REC_ID;
   642     if (INVALID_FONT_REC_ID != currFontRecID) {
   643         currFamilyRecID = fFonts[currFontRecID].fFamilyRecID;
   644     }
   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;
   653     if(nextFallbackFontIndex >= currentFallbackList->count()) {
   654         return NULL;
   655     }
   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     }
   664     int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
   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     }
   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 }
   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);
   693     SkTypeface* currentTypeface = NULL;
   694     int lowerBounds = 0; //inclusive
   695     int upperBounds = origTypeface->countGlyphs(); //exclusive
   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);
   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         }
   711         int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
   712         SkTypeface::Style origStyle = origTypeface->style();
   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     }
   729     if (NULL != currentTypeface) {
   730         if (lBounds) {
   731             *lBounds = lowerBounds;
   732         }
   733         if (uBounds) {
   734             *uBounds = upperBounds;
   735         }
   736     }
   737     return currentTypeface;
   738 }
   740 ///////////////////////////////////////////////////////////////////////////////
   742 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
   743     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
   744     return fontConfig->getFallbackFamilyNameForChar(uni, NULL, name);
   745 }
   747 bool SkGetFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name) {
   748     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
   749     return fontConfig->getFallbackFamilyNameForChar(uni, lang, name);
   750 }
   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 }
   764 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
   765                                          const SkPaintOptionsAndroid& options) {
   766     SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
   767     return fontConfig->nextLogicalTypeface(currFontID, origFontID, options);
   769 }
   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 }
   779 ///////////////////////////////////////////////////////////////////////////////
   781 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
   783 struct HB_UnicodeMapping {
   784     hb_script_t script;
   785     const SkUnichar unicode;
   786 };
   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  */
   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
   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 };
   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 }
   849 struct TypefaceLookupStruct {
   850     hb_script_t script;
   851     SkTypeface::Style style;
   852     SkPaintOptionsAndroid::FontVariant fontVariant;
   853     SkTypeface* typeface;
   854 };
   856 SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex);  // This is the mutex for gTypefaceTable
   857 static SkTDArray<TypefaceLookupStruct> gTypefaceTable;  // This is protected by gTypefaceTableMutex
   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 }
   873 SkTypeface* SkCreateTypefaceForScript(hb_script_t script, SkTypeface::Style style,
   874                                       SkPaintOptionsAndroid::FontVariant fontVariant) {
   875     SkAutoMutexAcquire ac(gTypefaceTableMutex);
   877     TypefaceLookupStruct key;
   878     key.script = script;
   879     key.style = style;
   880     key.fontVariant = fontVariant;
   882     int index = SkTSearch<TypefaceLookupStruct>(
   883             (const TypefaceLookupStruct*) gTypefaceTable.begin(),
   884             gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct),
   885             typefaceLookupCompare);
   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         }
   897         SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
   898         retTypeface = fontConfig->getTypefaceForChar(unichar, style, fontVariant);
   900         // add to the lookup table
   901         key.typeface = retTypeface;
   902         *gTypefaceTable.insert(~index) = key;
   903     }
   905     // we ref(), the caller is expected to unref when they are done
   906     return SkSafeRef(retTypeface);
   907 }
   909 #endif
   911 ///////////////////////////////////////////////////////////////////////////////
   913 SkFontMgr* SkFontMgr::Factory() {
   914     return NULL;
   915 }

mercurial