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