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