1/*
2 * Copyright 2015 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 "SkFontDescriptor.h"
9#include "SkFontMgr.h"
10#include "SkOnce.h"
11#include "SkStream.h"
12#include "SkTypes.h"
13
14class SkFontStyle;
15class SkTypeface;
16
17class SkEmptyFontStyleSet : public SkFontStyleSet {
18public:
19    int count() override { return 0; }
20    void getStyle(int, SkFontStyle*, SkString*) override {
21        SkDEBUGFAIL("SkFontStyleSet::getStyle called on empty set");
22    }
23    SkTypeface* createTypeface(int index) override {
24        SkDEBUGFAIL("SkFontStyleSet::createTypeface called on empty set");
25        return nullptr;
26    }
27    SkTypeface* matchStyle(const SkFontStyle&) override {
28        return nullptr;
29    }
30};
31
32SkFontStyleSet* SkFontStyleSet::CreateEmpty() { return new SkEmptyFontStyleSet; }
33
34///////////////////////////////////////////////////////////////////////////////
35
36class SkEmptyFontMgr : public SkFontMgr {
37protected:
38    int onCountFamilies() const override {
39        return 0;
40    }
41    void onGetFamilyName(int index, SkString* familyName) const override {
42        SkDEBUGFAIL("onGetFamilyName called with bad index");
43    }
44    SkFontStyleSet* onCreateStyleSet(int index) const override {
45        SkDEBUGFAIL("onCreateStyleSet called with bad index");
46        return nullptr;
47    }
48    SkFontStyleSet* onMatchFamily(const char[]) const override {
49        return SkFontStyleSet::CreateEmpty();
50    }
51
52    SkTypeface* onMatchFamilyStyle(const char[], const SkFontStyle&) const override {
53        return nullptr;
54    }
55    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
56                                            const SkFontStyle& style,
57                                            const char* bcp47[],
58                                            int bcp47Count,
59                                            SkUnichar character) const override {
60        return nullptr;
61    }
62    SkTypeface* onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const override {
63        return nullptr;
64    }
65
66    sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int) const override {
67        return nullptr;
68    }
69    sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>, int) const override {
70        return nullptr;
71    }
72    sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
73                                           const SkFontArguments&) const override {
74        return nullptr;
75    }
76    sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override {
77        return nullptr;
78    }
79    sk_sp<SkTypeface> onMakeFromFile(const char[], int) const override {
80        return nullptr;
81    }
82    sk_sp<SkTypeface> onLegacyMakeTypeface(const char [], SkFontStyle) const override {
83        return nullptr;
84    }
85};
86
87static SkFontStyleSet* emptyOnNull(SkFontStyleSet* fsset) {
88    if (nullptr == fsset) {
89        fsset = SkFontStyleSet::CreateEmpty();
90    }
91    return fsset;
92}
93
94int SkFontMgr::countFamilies() const {
95    return this->onCountFamilies();
96}
97
98void SkFontMgr::getFamilyName(int index, SkString* familyName) const {
99    this->onGetFamilyName(index, familyName);
100}
101
102SkFontStyleSet* SkFontMgr::createStyleSet(int index) const {
103    return emptyOnNull(this->onCreateStyleSet(index));
104}
105
106SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) const {
107    return emptyOnNull(this->onMatchFamily(familyName));
108}
109
110SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
111                                        const SkFontStyle& fs) const {
112    return this->onMatchFamilyStyle(familyName, fs);
113}
114
115SkTypeface* SkFontMgr::matchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style,
116                                                 const char* bcp47[], int bcp47Count,
117                                                 SkUnichar character) const {
118    return this->onMatchFamilyStyleCharacter(familyName, style, bcp47, bcp47Count, character);
119}
120
121SkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face,
122                                      const SkFontStyle& fs) const {
123    return this->onMatchFaceStyle(face, fs);
124}
125
126sk_sp<SkTypeface> SkFontMgr::makeFromData(sk_sp<SkData> data, int ttcIndex) const {
127    if (nullptr == data) {
128        return nullptr;
129    }
130    return this->onMakeFromData(std::move(data), ttcIndex);
131}
132
133sk_sp<SkTypeface> SkFontMgr::makeFromStream(std::unique_ptr<SkStreamAsset> stream,
134                                            int ttcIndex) const {
135    if (nullptr == stream) {
136        return nullptr;
137    }
138    return this->onMakeFromStreamIndex(std::move(stream), ttcIndex);
139}
140
141sk_sp<SkTypeface> SkFontMgr::makeFromStream(std::unique_ptr<SkStreamAsset> stream,
142                                            const SkFontArguments& args) const {
143    if (nullptr == stream) {
144        return nullptr;
145    }
146    return this->onMakeFromStreamArgs(std::move(stream), args);
147}
148
149sk_sp<SkTypeface> SkFontMgr::makeFromFontData(std::unique_ptr<SkFontData> data) const {
150    if (nullptr == data) {
151        return nullptr;
152    }
153    return this->onMakeFromFontData(std::move(data));
154}
155
156sk_sp<SkTypeface> SkFontMgr::makeFromFile(const char path[], int ttcIndex) const {
157    if (nullptr == path) {
158        return nullptr;
159    }
160    return this->onMakeFromFile(path, ttcIndex);
161}
162
163sk_sp<SkTypeface> SkFontMgr::legacyMakeTypeface(const char familyName[], SkFontStyle style) const {
164    return this->onLegacyMakeTypeface(familyName, style);
165}
166
167sk_sp<SkTypeface> SkFontMgr::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
168                                                  const SkFontArguments& args) const {
169    return this->makeFromStream(std::move(stream), args.getCollectionIndex());
170}
171sk_sp<SkTypeface> SkFontMgr::onMakeFromFontData(std::unique_ptr<SkFontData> data) const {
172    return this->makeFromStream(data->detachStream(), data->getIndex());
173}
174
175// A global function pointer that's not declared, but can be overriden at startup by test tools.
176sk_sp<SkFontMgr> (*gSkFontMgr_DefaultFactory)() = nullptr;
177
178sk_sp<SkFontMgr> SkFontMgr::RefDefault() {
179    static SkOnce once;
180    static sk_sp<SkFontMgr> singleton;
181
182    once([]{
183        sk_sp<SkFontMgr> fm = gSkFontMgr_DefaultFactory ? gSkFontMgr_DefaultFactory()
184                                                        : SkFontMgr::Factory();
185        singleton = fm ? std::move(fm) : sk_make_sp<SkEmptyFontMgr>();
186    });
187    return singleton;
188}
189
190/**
191* Width has the greatest priority.
192* If the value of pattern.width is 5 (normal) or less,
193*    narrower width values are checked first, then wider values.
194* If the value of pattern.width is greater than 5 (normal),
195*    wider values are checked first, followed by narrower values.
196*
197* Italic/Oblique has the next highest priority.
198* If italic requested and there is some italic font, use it.
199* If oblique requested and there is some oblique font, use it.
200* If italic requested and there is some oblique font, use it.
201* If oblique requested and there is some italic font, use it.
202*
203* Exact match.
204* If pattern.weight < 400, weights below pattern.weight are checked
205*   in descending order followed by weights above pattern.weight
206*   in ascending order until a match is found.
207* If pattern.weight > 500, weights above pattern.weight are checked
208*   in ascending order followed by weights below pattern.weight
209*   in descending order until a match is found.
210* If pattern.weight is 400, 500 is checked first
211*   and then the rule for pattern.weight < 400 is used.
212* If pattern.weight is 500, 400 is checked first
213*   and then the rule for pattern.weight < 400 is used.
214*/
215SkTypeface* SkFontStyleSet::matchStyleCSS3(const SkFontStyle& pattern) {
216    int count = this->count();
217    if (0 == count) {
218        return nullptr;
219    }
220
221    struct Score {
222        int score;
223        int index;
224        Score& operator +=(int rhs) { this->score += rhs; return *this; }
225        Score& operator <<=(int rhs) { this->score <<= rhs; return *this; }
226        bool operator <(const Score& that) { return this->score < that.score; }
227    };
228
229    Score maxScore = { 0, 0 };
230    for (int i = 0; i < count; ++i) {
231        SkFontStyle current;
232        this->getStyle(i, &current, nullptr);
233        Score currentScore = { 0, i };
234
235        // CSS stretch / SkFontStyle::Width
236        // Takes priority over everything else.
237        if (pattern.width() <= SkFontStyle::kNormal_Width) {
238            if (current.width() <= pattern.width()) {
239                currentScore += 10 - pattern.width() + current.width();
240            } else {
241                currentScore += 10 - current.width();
242            }
243        } else {
244            if (current.width() > pattern.width()) {
245                currentScore += 10 + pattern.width() - current.width();
246            } else {
247                currentScore += current.width();
248            }
249        }
250        currentScore <<= 8;
251
252        // CSS style (normal, italic, oblique) / SkFontStyle::Slant (upright, italic, oblique)
253        // Takes priority over all valid weights.
254        static_assert(SkFontStyle::kUpright_Slant == 0 &&
255                      SkFontStyle::kItalic_Slant  == 1 &&
256                      SkFontStyle::kOblique_Slant == 2,
257                      "SkFontStyle::Slant values not as required.");
258        SkASSERT(0 <= pattern.slant() && pattern.slant() <= 2 &&
259                 0 <= current.slant() && current.slant() <= 2);
260        static const int score[3][3] = {
261            /*               Upright Italic Oblique  [current]*/
262            /*   Upright */ {   3   ,  1   ,   2   },
263            /*   Italic  */ {   1   ,  3   ,   2   },
264            /*   Oblique */ {   1   ,  2   ,   3   },
265            /* [pattern] */
266        };
267        currentScore += score[pattern.slant()][current.slant()];
268        currentScore <<= 8;
269
270        // Synthetics (weight, style) [no stretch synthetic?]
271
272        // CSS weight / SkFontStyle::Weight
273        // The 'closer' to the target weight, the higher the score.
274        // 1000 is the 'heaviest' recognized weight
275        if (pattern.weight() == current.weight()) {
276            currentScore += 1000;
277        } else if (pattern.weight() <= 500) {
278            if (400 <= pattern.weight() && pattern.weight() < 450) {
279                if (450 <= current.weight() && current.weight() <= 500) {
280                    // Artificially boost the 500 weight.
281                    // TODO: determine correct number to use.
282                    currentScore += 500;
283                }
284            }
285            if (current.weight() <= pattern.weight()) {
286                currentScore += 1000 - pattern.weight() + current.weight();
287            } else {
288                currentScore += 1000 - current.weight();
289            }
290        } else if (pattern.weight() > 500) {
291            if (current.weight() > pattern.weight()) {
292                currentScore += 1000 + pattern.weight() - current.weight();
293            } else {
294                currentScore += current.weight();
295            }
296        }
297
298        if (maxScore < currentScore) {
299            maxScore = currentScore;
300        }
301    }
302
303    return this->createTypeface(maxScore.index);
304}
305