Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkFontConfigParser_android.h"
      9 #include "SkFontDescriptor.h"
     10 #include "SkFontHost_FreeType_common.h"
     11 #include "SkFontMgr.h"
     12 #include "SkFontStyle.h"
     13 #include "SkStream.h"
     14 #include "SkTDArray.h"
     15 #include "SkTSearch.h"
     16 #include "SkTypeface.h"
     17 #include "SkTypeface_android.h"
     18 #include "SkTypefaceCache.h"
     19 
     20 #include <limits>
     21 #include <stdlib.h>
     22 
     23 #ifndef SK_FONT_FILE_PREFIX
     24 #    define SK_FONT_FILE_PREFIX "/fonts/"
     25 #endif
     26 
     27 #ifndef SK_DEBUG_FONTS
     28     #define SK_DEBUG_FONTS 0
     29 #endif
     30 
     31 #if SK_DEBUG_FONTS
     32 #    define DEBUG_FONT(args) SkDebugf args
     33 #else
     34 #    define DEBUG_FONT(args)
     35 #endif
     36 
     37 // For test only.
     38 static const char* gTestMainConfigFile = NULL;
     39 static const char* gTestFallbackConfigFile = NULL;
     40 static const char* gTestFontFilePrefix = NULL;
     41 
     42 class SkTypeface_Android : public SkTypeface_FreeType {
     43 public:
     44     SkTypeface_Android(int index,
     45                        Style style,
     46                        bool isFixedPitch,
     47                        const SkString familyName)
     48         : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
     49         , fIndex(index)
     50         , fFamilyName(familyName) { }
     51 
     52 protected:
     53     virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE {
     54         *familyName = fFamilyName;
     55     }
     56 
     57     int fIndex;
     58     SkString fFamilyName;
     59 
     60 private:
     61     typedef SkTypeface_FreeType INHERITED;
     62 };
     63 
     64 class SkTypeface_AndroidSystem : public SkTypeface_Android {
     65 public:
     66     SkTypeface_AndroidSystem(const SkString pathName,
     67                              int index,
     68                              Style style,
     69                              bool isFixedPitch,
     70                              const SkString familyName,
     71                              const SkLanguage& lang,
     72                              FontVariant variantStyle)
     73         : INHERITED(index, style, isFixedPitch, familyName)
     74         , fPathName(pathName)
     75         , fLang(lang)
     76         , fVariantStyle(variantStyle) { }
     77 
     78     virtual void onGetFontDescriptor(SkFontDescriptor* desc,
     79                                      bool* serialize) const SK_OVERRIDE {
     80         SkASSERT(desc);
     81         SkASSERT(serialize);
     82         desc->setFamilyName(fFamilyName.c_str());
     83         desc->setFontFileName(fPathName.c_str());
     84         desc->setFontIndex(fIndex);
     85         *serialize = false;
     86     }
     87     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
     88         *ttcIndex = fIndex;
     89         return SkStream::NewFromFile(fPathName.c_str());
     90     }
     91 
     92     const SkString fPathName;
     93     const SkLanguage fLang;
     94     const FontVariant fVariantStyle;
     95 
     96     typedef SkTypeface_Android INHERITED;
     97 };
     98 
     99 class SkTypeface_AndroidStream : public SkTypeface_Android {
    100 public:
    101     SkTypeface_AndroidStream(SkStream* stream,
    102                              int index,
    103                              Style style,
    104                              bool isFixedPitch,
    105                              const SkString familyName)
    106         : INHERITED(index, style, isFixedPitch, familyName)
    107         , fStream(SkRef(stream)) { }
    108 
    109     virtual void onGetFontDescriptor(SkFontDescriptor* desc,
    110                                      bool* serialize) const SK_OVERRIDE {
    111         SkASSERT(desc);
    112         SkASSERT(serialize);
    113         desc->setFamilyName(fFamilyName.c_str());
    114         desc->setFontFileName(NULL);
    115         *serialize = true;
    116     }
    117 
    118     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
    119         *ttcIndex = fIndex;
    120         return fStream->duplicate();
    121     }
    122 
    123 private:
    124     SkAutoTUnref<SkStream> fStream;
    125 
    126     typedef SkTypeface_Android INHERITED;
    127 };
    128 
    129 void get_path_for_sys_fonts(const char* basePath, const SkString& name, SkString* full) {
    130     if (basePath) {
    131         full->set(basePath);
    132     } else {
    133         full->set(getenv("ANDROID_ROOT"));
    134         full->append(SK_FONT_FILE_PREFIX);
    135     }
    136     full->append(name);
    137 }
    138 
    139 class SkFontStyleSet_Android : public SkFontStyleSet {
    140 public:
    141     explicit SkFontStyleSet_Android(const FontFamily& family, const char* basePath) {
    142         const SkString* cannonicalFamilyName = NULL;
    143         if (family.fNames.count() > 0) {
    144             cannonicalFamilyName = &family.fNames[0];
    145         }
    146         // TODO? make this lazy
    147         for (int i = 0; i < family.fFonts.count(); ++i) {
    148             const FontFileInfo& fontFile = family.fFonts[i];
    149 
    150             SkString pathName;
    151             get_path_for_sys_fonts(basePath, fontFile.fFileName, &pathName);
    152 
    153             SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str()));
    154             if (!stream.get()) {
    155                 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str()));
    156                 continue;
    157             }
    158 
    159             const int ttcIndex = fontFile.fIndex;
    160             SkString familyName;
    161             SkTypeface::Style style;
    162             bool isFixedWidth;
    163             if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex,
    164                                                &familyName, &style, &isFixedWidth)) {
    165                 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str()));
    166                 continue;
    167             }
    168 
    169             const SkLanguage& lang = family.fLanguage;
    170             uint32_t variant = family.fVariant;
    171             if (kDefault_FontVariant == variant) {
    172                 variant = kCompact_FontVariant | kElegant_FontVariant;
    173             }
    174 
    175             // The first specified family name overrides the family name found in the font.
    176             // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
    177             // all of the specified family names in addition to the names found in the font.
    178             if (cannonicalFamilyName != NULL) {
    179                 familyName = *cannonicalFamilyName;
    180             }
    181 
    182             fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
    183                                                  (pathName, ttcIndex,
    184                                                   style, isFixedWidth, familyName,
    185                                                   lang, variant)));
    186         }
    187     }
    188 
    189     virtual int count() SK_OVERRIDE {
    190         return fStyles.count();
    191     }
    192     virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
    193         if (index < 0 || fStyles.count() <= index) {
    194             return;
    195         }
    196         if (style) {
    197             *style = this->style(index);
    198         }
    199         if (name) {
    200             name->reset();
    201         }
    202     }
    203     virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
    204         if (index < 0 || fStyles.count() <= index) {
    205             return NULL;
    206         }
    207         return SkRef(fStyles[index].get());
    208     }
    209 
    210     /** Find the typeface in this style set that most closely matches the given pattern.
    211      *  TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
    212      *  this simpler version using match_score() passes all our tests.
    213      */
    214     virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
    215         if (0 == fStyles.count()) {
    216             return NULL;
    217         }
    218         SkTypeface_AndroidSystem* closest = fStyles[0];
    219         int minScore = std::numeric_limits<int>::max();
    220         for (int i = 0; i < fStyles.count(); ++i) {
    221             SkFontStyle style = this->style(i);
    222             int score = match_score(pattern, style);
    223             if (score < minScore) {
    224                 closest = fStyles[i];
    225                 minScore = score;
    226             }
    227         }
    228         return SkRef(closest);
    229     }
    230 
    231 private:
    232     SkFontStyle style(int index) {
    233         return SkFontStyle(this->weight(index), SkFontStyle::kNormal_Width,
    234                            this->slant(index));
    235     }
    236     SkFontStyle::Weight weight(int index) {
    237         if (fStyles[index]->isBold()) return SkFontStyle::kBold_Weight;
    238         return SkFontStyle::kNormal_Weight;
    239     }
    240     SkFontStyle::Slant slant(int index) {
    241         if (fStyles[index]->isItalic()) return SkFontStyle::kItalic_Slant;
    242         return SkFontStyle::kUpright_Slant;
    243     }
    244     static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
    245         int score = 0;
    246         score += abs((pattern.width() - candidate.width()) * 100);
    247         score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
    248         score += abs(pattern.weight() - candidate.weight());
    249         return score;
    250     }
    251 
    252     SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
    253 
    254     friend struct NameToFamily;
    255     friend class SkFontMgr_Android;
    256 
    257     typedef SkFontStyleSet INHERITED;
    258 };
    259 
    260 /** On Android a single family can have many names, but our API assumes unique names.
    261  *  Map names to the back end so that all names for a given family refer to the same
    262  *  (non-replicated) set of typefaces.
    263  *  SkTDict<> doesn't let us do index-based lookup, so we write our own mapping.
    264  */
    265 struct NameToFamily {
    266     SkString name;
    267     SkFontStyleSet_Android* styleSet;
    268 };
    269 
    270 class SkFontMgr_Android : public SkFontMgr {
    271 public:
    272     SkFontMgr_Android() {
    273         SkTDArray<FontFamily*> fontFamilies;
    274         SkFontConfigParser::GetFontFamilies(fontFamilies);
    275         this->buildNameToFamilyMap(fontFamilies, NULL);
    276         this->findDefaultFont();
    277     }
    278     SkFontMgr_Android(const char* mainConfigFile, const char* fallbackConfigFile,
    279                       const char* basePath)
    280     {
    281         SkTDArray<FontFamily*> fontFamilies;
    282         SkFontConfigParser::GetTestFontFamilies(fontFamilies, mainConfigFile, fallbackConfigFile);
    283         this->buildNameToFamilyMap(fontFamilies, basePath);
    284         this->findDefaultFont();
    285     }
    286 
    287 protected:
    288     /** Returns not how many families we have, but how many unique names
    289      *  exist among the families.
    290      */
    291     virtual int onCountFamilies() const SK_OVERRIDE {
    292         return fNameToFamilyMap.count();
    293     }
    294 
    295     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
    296         if (index < 0 || fNameToFamilyMap.count() <= index) {
    297             familyName->reset();
    298             return;
    299         }
    300         familyName->set(fNameToFamilyMap[index].name);
    301     }
    302 
    303     virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
    304         if (index < 0 || fNameToFamilyMap.count() <= index) {
    305             return NULL;
    306         }
    307         return SkRef(fNameToFamilyMap[index].styleSet);
    308     }
    309 
    310     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
    311         if (!familyName) {
    312             return NULL;
    313         }
    314         SkAutoAsciiToLC tolc(familyName);
    315         for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
    316             if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
    317                 return SkRef(fNameToFamilyMap[i].styleSet);
    318             }
    319         }
    320         // TODO: eventually we should not need to name fallback families.
    321         for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
    322             if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
    323                 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
    324             }
    325         }
    326         return NULL;
    327     }
    328 
    329     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
    330                                            const SkFontStyle& style) const SK_OVERRIDE {
    331         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
    332         return sset->matchStyle(style);
    333     }
    334 
    335     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
    336                                          const SkFontStyle& style) const SK_OVERRIDE {
    337         for (int i = 0; i < fFontStyleSets.count(); ++i) {
    338             for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
    339                 if (fFontStyleSets[i]->fStyles[j] == typeface) {
    340                     return fFontStyleSets[i]->matchStyle(style);
    341                 }
    342             }
    343         }
    344         return NULL;
    345     }
    346 
    347 static SkTypeface_AndroidSystem* find_family_style_character(
    348         const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
    349         const SkFontStyle& style, bool elegant,
    350         const SkString& langTag, SkUnichar character)
    351 {
    352     for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
    353         SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
    354         SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
    355 
    356         if (!langTag.isEmpty() && !face->fLang.getTag().startsWith(langTag.c_str())) {
    357             continue;
    358         }
    359 
    360         if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
    361             continue;
    362         }
    363 
    364         SkPaint paint;
    365         paint.setTypeface(face);
    366         paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
    367 
    368         uint16_t glyphID;
    369         paint.textToGlyphs(&character, sizeof(character), &glyphID);
    370         if (glyphID != 0) {
    371             return face.detach();
    372         }
    373     }
    374     return NULL;
    375 }
    376 #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
    377     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
    378                                                     const SkFontStyle& style,
    379                                                     const char* bcp47[],
    380                                                     int bcp47Count,
    381                                                     SkUnichar character) const SK_OVERRIDE
    382     {
    383 #else
    384     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
    385                                                     const SkFontStyle& style,
    386                                                     const char bcp47_val[],
    387                                                     SkUnichar character) const SK_OVERRIDE
    388     {
    389         const char** bcp47 = &bcp47_val;
    390         int bcp47Count = bcp47_val ? 1 : 0;
    391 #endif
    392         // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
    393         // The variant 'default' means 'compact and elegant'.
    394         // As a result, it is not possible to know the variant context from the font alone.
    395         // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
    396 
    397         // The first time match anything elegant, second time anything not elegant.
    398         for (int elegant = 2; elegant --> 0;) {
    399             for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
    400                 SkLanguage lang(bcp47[bcp47Index]);
    401                 while (!lang.getTag().isEmpty()) {
    402                     SkTypeface_AndroidSystem* matchingTypeface =
    403                         find_family_style_character(fFallbackNameToFamilyMap,
    404                                                     style, SkToBool(elegant),
    405                                                     lang.getTag(), character);
    406                     if (matchingTypeface) {
    407                         return matchingTypeface;
    408                     }
    409 
    410                     lang = lang.getParent();
    411                 }
    412             }
    413             SkTypeface_AndroidSystem* matchingTypeface =
    414                 find_family_style_character(fFallbackNameToFamilyMap,
    415                                             style, SkToBool(elegant),
    416                                             SkString(), character);
    417             if (matchingTypeface) {
    418                 return matchingTypeface;
    419             }
    420         }
    421         return NULL;
    422     }
    423 
    424     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
    425         SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
    426         return this->createFromStream(stream, ttcIndex);
    427     }
    428 
    429     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
    430         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
    431         return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
    432     }
    433 
    434     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
    435         bool isFixedPitch;
    436         SkTypeface::Style style;
    437         SkString name;
    438         if (!SkTypeface_FreeType::ScanFont(stream, ttcIndex, &name, &style, &isFixedPitch)) {
    439             return NULL;
    440         }
    441         return SkNEW_ARGS(SkTypeface_AndroidStream, (stream, ttcIndex,
    442                                                      style, isFixedPitch, name));
    443     }
    444 
    445 
    446     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
    447                                                unsigned styleBits) const SK_OVERRIDE {
    448         SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
    449         SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
    450                                                  ? SkFontStyle::kBold_Weight
    451                                                  : SkFontStyle::kNormal_Weight,
    452                                         SkFontStyle::kNormal_Width,
    453                                         oldStyle & SkTypeface::kItalic
    454                                                  ? SkFontStyle::kItalic_Slant
    455                                                  : SkFontStyle::kUpright_Slant);
    456 
    457         if (familyName) {
    458             // On Android, we must return NULL when we can't find the requested
    459             // named typeface so that the system/app can provide their own recovery
    460             // mechanism. On other platforms we'd provide a typeface from the
    461             // default family instead.
    462             return this->onMatchFamilyStyle(familyName, style);
    463         }
    464         return fDefaultFamily->matchStyle(style);
    465     }
    466 
    467 
    468 private:
    469 
    470     SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
    471     SkFontStyleSet* fDefaultFamily;
    472     SkTypeface* fDefaultTypeface;
    473 
    474     SkTDArray<NameToFamily> fNameToFamilyMap;
    475     SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
    476 
    477     void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const char* basePath) {
    478         for (int i = 0; i < families.count(); i++) {
    479             FontFamily& family = *families[i];
    480 
    481             SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
    482             if (family.fIsFallbackFont) {
    483                 nameToFamily = &fFallbackNameToFamilyMap;
    484 
    485                 if (0 == family.fNames.count()) {
    486                     SkString& fallbackName = family.fNames.push_back();
    487                     fallbackName.printf("%.2x##fallback", i);
    488                 }
    489             }
    490 
    491             SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family, basePath));
    492             if (0 == newSet->count()) {
    493                 SkDELETE(newSet);
    494                 continue;
    495             }
    496             fFontStyleSets.push_back().reset(newSet);
    497 
    498             for (int j = 0; j < family.fNames.count(); j++) {
    499                 NameToFamily* nextEntry = nameToFamily->append();
    500                 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j]));
    501                 nextEntry->styleSet = newSet;
    502             }
    503         }
    504     }
    505 
    506     void findDefaultFont() {
    507         SkASSERT(!fFontStyleSets.empty());
    508 
    509         static const char* gDefaultNames[] = { "sans-serif" };
    510         for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
    511             SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
    512             if (NULL == set) {
    513                 continue;
    514             }
    515             SkTypeface* tf = set->matchStyle(SkFontStyle());
    516             if (NULL == tf) {
    517                 continue;
    518             }
    519             fDefaultFamily = set;
    520             fDefaultTypeface = tf;
    521             break;
    522         }
    523         if (NULL == fDefaultTypeface) {
    524             fDefaultFamily = fFontStyleSets[0];
    525             fDefaultTypeface = fDefaultFamily->createTypeface(0);
    526         }
    527         SkASSERT(fDefaultFamily);
    528         SkASSERT(fDefaultTypeface);
    529     }
    530 
    531     typedef SkFontMgr INHERITED;
    532 };
    533 
    534 ///////////////////////////////////////////////////////////////////////////////
    535 
    536 SkFontMgr* SkFontMgr::Factory() {
    537     // The call to SkGetTestFontConfiguration is so that Chromium can override the environment.
    538     // TODO: these globals need to be removed, in favor of a constructor / separate Factory
    539     // which can be used instead.
    540     const char* mainConfigFile;
    541     const char* fallbackConfigFile;
    542     const char* basePath;
    543     SkGetTestFontConfiguration(&mainConfigFile, &fallbackConfigFile, &basePath);
    544     if (mainConfigFile) {
    545         return SkNEW_ARGS(SkFontMgr_Android, (mainConfigFile, fallbackConfigFile, basePath));
    546     }
    547 
    548     return SkNEW(SkFontMgr_Android);
    549 }
    550 
    551 void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
    552                              const char* fontsdir) {
    553     gTestMainConfigFile = mainconf;
    554     gTestFallbackConfigFile = fallbackconf;
    555     gTestFontFilePrefix = fontsdir;
    556     SkASSERT(gTestMainConfigFile);
    557     SkASSERT(gTestFallbackConfigFile);
    558     SkASSERT(gTestFontFilePrefix);
    559     SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
    560               gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
    561 }
    562 
    563 void SkGetTestFontConfiguration(const char** mainconf, const char** fallbackconf,
    564                                 const char** fontsdir) {
    565     *mainconf = gTestMainConfigFile;
    566     *fallbackconf = gTestFallbackConfigFile;
    567     *fontsdir = gTestFontFilePrefix;
    568 }
    569