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