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 <limits>
     31 
     32 class SkData;
     33 
     34 class SkTypeface_Android : public SkTypeface_FreeType {
     35 public:
     36     SkTypeface_Android(const SkFontStyle& style,
     37                        bool isFixedPitch,
     38                        const SkString& familyName)
     39         : INHERITED(style, isFixedPitch)
     40         , fFamilyName(familyName)
     41         { }
     42 
     43 protected:
     44     void onGetFamilyName(SkString* familyName) const override {
     45         *familyName = fFamilyName;
     46     }
     47 
     48     SkString fFamilyName;
     49 
     50 private:
     51     typedef SkTypeface_FreeType INHERITED;
     52 };
     53 
     54 class SkTypeface_AndroidSystem : public SkTypeface_Android {
     55 public:
     56     SkTypeface_AndroidSystem(const SkString& pathName,
     57                              const bool cacheFontFiles,
     58                              int index,
     59                              const SkFixed* axes, int axesCount,
     60                              const SkFontStyle& style,
     61                              bool isFixedPitch,
     62                              const SkString& familyName,
     63                              const SkLanguage& lang,
     64                              FontVariant variantStyle)
     65         : INHERITED(style, isFixedPitch, familyName)
     66         , fPathName(pathName)
     67         , fIndex(index)
     68         , fAxes(axes, axesCount)
     69         , fLang(lang)
     70         , fVariantStyle(variantStyle)
     71         , fFile(cacheFontFiles ? sk_fopen(fPathName.c_str(), kRead_SkFILE_Flag) : nullptr) {
     72         if (cacheFontFiles) {
     73             SkASSERT(fFile);
     74         }
     75     }
     76 
     77     std::unique_ptr<SkStreamAsset> makeStream() const {
     78         if (fFile) {
     79             sk_sp<SkData> data(SkData::MakeFromFILE(fFile));
     80             return data ? skstd::make_unique<SkMemoryStream>(std::move(data)) : nullptr;
     81         }
     82         return SkStream::MakeFromFile(fPathName.c_str());
     83     }
     84 
     85     virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const override {
     86         SkASSERT(desc);
     87         SkASSERT(serialize);
     88         desc->setFamilyName(fFamilyName.c_str());
     89         desc->setStyle(this->fontStyle());
     90         *serialize = false;
     91     }
     92     SkStreamAsset* onOpenStream(int* ttcIndex) const override {
     93         *ttcIndex = fIndex;
     94         return this->makeStream().release();
     95     }
     96     std::unique_ptr<SkFontData> onMakeFontData() const override {
     97         return skstd::make_unique<SkFontData>(this->makeStream(), fIndex,
     98                                               fAxes.begin(), fAxes.count());
     99     }
    100 
    101     const SkString fPathName;
    102     int fIndex;
    103     const SkSTArray<4, SkFixed, true> fAxes;
    104     const SkLanguage fLang;
    105     const FontVariant fVariantStyle;
    106     SkAutoTCallVProc<FILE, sk_fclose> fFile;
    107 
    108     typedef SkTypeface_Android INHERITED;
    109 };
    110 
    111 class SkTypeface_AndroidStream : public SkTypeface_Android {
    112 public:
    113     SkTypeface_AndroidStream(std::unique_ptr<SkFontData> data,
    114                              const SkFontStyle& style,
    115                              bool isFixedPitch,
    116                              const SkString& familyName)
    117         : INHERITED(style, isFixedPitch, familyName)
    118         , fData(std::move(data))
    119     { }
    120 
    121     virtual void onGetFontDescriptor(SkFontDescriptor* desc,
    122                                      bool* serialize) const override {
    123         SkASSERT(desc);
    124         SkASSERT(serialize);
    125         desc->setFamilyName(fFamilyName.c_str());
    126         *serialize = true;
    127     }
    128 
    129     SkStreamAsset* onOpenStream(int* ttcIndex) const override {
    130         *ttcIndex = fData->getIndex();
    131         return fData->getStream()->duplicate();
    132     }
    133 
    134     std::unique_ptr<SkFontData> onMakeFontData() const override {
    135         return skstd::make_unique<SkFontData>(*fData);
    136     }
    137 
    138 private:
    139     const std::unique_ptr<const SkFontData> fData;
    140     typedef SkTypeface_Android INHERITED;
    141 };
    142 
    143 class SkFontStyleSet_Android : public SkFontStyleSet {
    144     typedef SkTypeface_FreeType::Scanner Scanner;
    145 
    146 public:
    147     explicit SkFontStyleSet_Android(const FontFamily& family, const Scanner& scanner,
    148                                     const bool cacheFontFiles) {
    149         const SkString* cannonicalFamilyName = nullptr;
    150         if (family.fNames.count() > 0) {
    151             cannonicalFamilyName = &family.fNames[0];
    152         }
    153         // TODO? make this lazy
    154         for (int i = 0; i < family.fFonts.count(); ++i) {
    155             const FontFileInfo& fontFile = family.fFonts[i];
    156 
    157             SkString pathName(family.fBasePath);
    158             pathName.append(fontFile.fFileName);
    159 
    160             std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(pathName.c_str());
    161             if (!stream) {
    162                 SkDEBUGF(("Requested font file %s does not exist or cannot be opened.\n",
    163                           pathName.c_str()));
    164                 continue;
    165             }
    166 
    167             const int ttcIndex = fontFile.fIndex;
    168             SkString familyName;
    169             SkFontStyle style;
    170             bool isFixedWidth;
    171             Scanner::AxisDefinitions axisDefinitions;
    172             if (!scanner.scanFont(stream.get(), ttcIndex,
    173                                   &familyName, &style, &isFixedWidth, &axisDefinitions))
    174             {
    175                 SkDEBUGF(("Requested font file %s exists, but is not a valid font.\n",
    176                           pathName.c_str()));
    177                 continue;
    178             }
    179 
    180             int weight = fontFile.fWeight != 0 ? fontFile.fWeight : style.weight();
    181             SkFontStyle::Slant slant = style.slant();
    182             switch (fontFile.fStyle) {
    183                 case FontFileInfo::Style::kAuto: slant = style.slant(); break;
    184                 case FontFileInfo::Style::kNormal: slant = SkFontStyle::kUpright_Slant; break;
    185                 case FontFileInfo::Style::kItalic: slant = SkFontStyle::kItalic_Slant; break;
    186                 default: SkASSERT(false); break;
    187             }
    188             style = SkFontStyle(weight, style.width(), slant);
    189 
    190             const SkLanguage& lang = family.fLanguage;
    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, lang, 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() && !face->fLang.getTag().startsWith(langTag.c_str())) {
    355                 continue;
    356             }
    357 
    358             if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
    359                 continue;
    360             }
    361 
    362             SkPaint paint;
    363             paint.setTypeface(face);
    364             paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
    365 
    366             uint16_t glyphID;
    367             paint.textToGlyphs(&character, sizeof(character), &glyphID);
    368             if (glyphID != 0) {
    369                 return face;
    370             }
    371         }
    372         return nullptr;
    373     }
    374 
    375     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
    376                                                     const SkFontStyle& style,
    377                                                     const char* bcp47[],
    378                                                     int bcp47Count,
    379                                                     SkUnichar character) const override
    380     {
    381         // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
    382         // The variant 'default' means 'compact and elegant'.
    383         // As a result, it is not possible to know the variant context from the font alone.
    384         // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
    385 
    386         // The first time match anything elegant, second time anything not elegant.
    387         for (int elegant = 2; elegant --> 0;) {
    388             for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
    389                 SkLanguage lang(bcp47[bcp47Index]);
    390                 while (!lang.getTag().isEmpty()) {
    391                     sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
    392                         find_family_style_character(fFallbackNameToFamilyMap,
    393                                                     style, SkToBool(elegant),
    394                                                     lang.getTag(), character);
    395                     if (matchingTypeface) {
    396                         return matchingTypeface.release();
    397                     }
    398 
    399                     lang = lang.getParent();
    400                 }
    401             }
    402             sk_sp<SkTypeface_AndroidSystem> matchingTypeface =
    403                 find_family_style_character(fFallbackNameToFamilyMap,
    404                                             style, SkToBool(elegant),
    405                                             SkString(), character);
    406             if (matchingTypeface) {
    407                 return matchingTypeface.release();
    408             }
    409         }
    410         return nullptr;
    411     }
    412 
    413     SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
    414         return this->createFromStream(new SkMemoryStream(sk_ref_sp(data)), ttcIndex);
    415     }
    416 
    417     SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
    418         std::unique_ptr<SkStreamAsset> stream = SkStream::MakeFromFile(path);
    419         return stream.get() ? this->createFromStream(stream.release(), ttcIndex) : nullptr;
    420     }
    421 
    422     SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
    423         std::unique_ptr<SkStreamAsset> stream(bareStream);
    424         bool isFixedPitch;
    425         SkFontStyle style;
    426         SkString name;
    427         if (!fScanner.scanFont(stream.get(), ttcIndex, &name, &style, &isFixedPitch, nullptr)) {
    428             return nullptr;
    429         }
    430         auto data = skstd::make_unique<SkFontData>(std::move(stream), ttcIndex, nullptr, 0);
    431         return new SkTypeface_AndroidStream(std::move(data), style, isFixedPitch, name);
    432     }
    433 
    434     SkTypeface* onCreateFromStream(SkStreamAsset* s, const SkFontArguments& args) const override {
    435         using Scanner = SkTypeface_FreeType::Scanner;
    436         std::unique_ptr<SkStreamAsset> stream(s);
    437         bool isFixedPitch;
    438         SkFontStyle style;
    439         SkString name;
    440         Scanner::AxisDefinitions axisDefinitions;
    441         if (!fScanner.scanFont(stream.get(), args.getCollectionIndex(),
    442                                &name, &style, &isFixedPitch, &axisDefinitions))
    443         {
    444             return nullptr;
    445         }
    446 
    447         SkAutoSTMalloc<4, SkFixed> axisValues(axisDefinitions.count());
    448         Scanner::computeAxisValues(axisDefinitions, args.getVariationDesignPosition(),
    449                                    axisValues, name);
    450 
    451         auto data = skstd::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
    452                                                    axisValues.get(), axisDefinitions.count());
    453         return new SkTypeface_AndroidStream(std::move(data), style, isFixedPitch, name);
    454     }
    455 
    456     SkTypeface* onCreateFromFontData(std::unique_ptr<SkFontData> data) const override {
    457         SkStreamAsset* stream(data->getStream());
    458         bool isFixedPitch;
    459         SkFontStyle style;
    460         SkString name;
    461         if (!fScanner.scanFont(stream, data->getIndex(), &name, &style, &isFixedPitch, nullptr)) {
    462             return nullptr;
    463         }
    464         return new SkTypeface_AndroidStream(std::move(data), style, isFixedPitch, name);
    465     }
    466 
    467     SkTypeface* onLegacyCreateTypeface(const char familyName[], SkFontStyle style) const override {
    468         if (familyName) {
    469             // On Android, we must return nullptr when we can't find the requested
    470             // named typeface so that the system/app can provide their own recovery
    471             // mechanism. On other platforms we'd provide a typeface from the
    472             // default family instead.
    473             return this->onMatchFamilyStyle(familyName, style);
    474         }
    475         return fDefaultStyleSet->matchStyle(style);
    476     }
    477 
    478 
    479 private:
    480 
    481     SkTypeface_FreeType::Scanner fScanner;
    482 
    483     SkTArray<sk_sp<SkFontStyleSet_Android>, true> fStyleSets;
    484     sk_sp<SkFontStyleSet> fDefaultStyleSet;
    485 
    486     SkTArray<NameToFamily, true> fNameToFamilyMap;
    487     SkTArray<NameToFamily, true> fFallbackNameToFamilyMap;
    488 
    489     void buildNameToFamilyMap(SkTDArray<FontFamily*> families, const bool isolated) {
    490         for (int i = 0; i < families.count(); i++) {
    491             FontFamily& family = *families[i];
    492 
    493             SkTArray<NameToFamily, true>* nameToFamily = &fNameToFamilyMap;
    494             if (family.fIsFallbackFont) {
    495                 nameToFamily = &fFallbackNameToFamilyMap;
    496 
    497                 if (0 == family.fNames.count()) {
    498                     SkString& fallbackName = family.fNames.push_back();
    499                     fallbackName.printf("%.2x##fallback", i);
    500                 }
    501             }
    502 
    503             sk_sp<SkFontStyleSet_Android> newSet =
    504                 sk_make_sp<SkFontStyleSet_Android>(family, fScanner, isolated);
    505             if (0 == newSet->count()) {
    506                 continue;
    507             }
    508 
    509             for (const SkString& name : family.fNames) {
    510                 nameToFamily->emplace_back(NameToFamily{name, newSet.get()});
    511             }
    512             fStyleSets.emplace_back(std::move(newSet));
    513         }
    514     }
    515 
    516     void findDefaultStyleSet() {
    517         SkASSERT(!fStyleSets.empty());
    518 
    519         static const char* defaultNames[] = { "sans-serif" };
    520         for (const char* defaultName : defaultNames) {
    521             fDefaultStyleSet.reset(this->onMatchFamily(defaultName));
    522             if (fDefaultStyleSet) {
    523                 break;
    524             }
    525         }
    526         if (nullptr == fDefaultStyleSet) {
    527             fDefaultStyleSet = fStyleSets[0];
    528         }
    529         SkASSERT(fDefaultStyleSet);
    530     }
    531 
    532     typedef SkFontMgr INHERITED;
    533 };
    534 
    535 #ifdef SK_DEBUG
    536 static char const * const gSystemFontUseStrings[] = {
    537     "OnlyCustom", "PreferCustom", "PreferSystem"
    538 };
    539 #endif
    540 
    541 sk_sp<SkFontMgr> SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom) {
    542     if (custom) {
    543         SkASSERT(0 <= custom->fSystemFontUse);
    544         SkASSERT(custom->fSystemFontUse < SK_ARRAY_COUNT(gSystemFontUseStrings));
    545         SkDEBUGF(("SystemFontUse: %s BasePath: %s Fonts: %s FallbackFonts: %s\n",
    546                   gSystemFontUseStrings[custom->fSystemFontUse],
    547                   custom->fBasePath,
    548                   custom->fFontsXml,
    549                   custom->fFallbackFontsXml));
    550     }
    551     return sk_make_sp<SkFontMgr_Android>(custom);
    552 }
    553