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.
24static const char* gTestFontsXml = NULL;
25static const char* gTestFallbackFontsXml = NULL;
26static const char* gTestBasePath = NULL;
27
28class SkTypeface_Android : public SkTypeface_FreeType {
29public:
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
38protected:
39    void onGetFamilyName(SkString* familyName) const override {
40        *familyName = fFamilyName;
41    }
42
43    int fIndex;
44    SkString fFamilyName;
45
46private:
47    typedef SkTypeface_FreeType INHERITED;
48};
49
50class SkTypeface_AndroidSystem : public SkTypeface_Android {
51public:
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
84class SkTypeface_AndroidStream : public SkTypeface_Android {
85public:
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
107private:
108    SkAutoTDelete<SkStreamAsset> fStream;
109
110    typedef SkTypeface_Android INHERITED;
111};
112
113class SkFontStyleSet_Android : public SkFontStyleSet {
114public:
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
218private:
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 */
243struct NameToFamily {
244    SkString name;
245    SkFontStyleSet_Android* styleSet;
246};
247
248class SkFontMgr_Android : public SkFontMgr {
249public:
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
272protected:
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
437private:
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
508static char const * const gSystemFontUseStrings[] = {
509    "OnlyCustom", "PreferCustom", "PreferSystem"
510};
511#endif
512SkFontMgr* 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
526SkFontMgr* 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
542void 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