1e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman/*
2e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman * Copyright 2015 Google Inc.
3e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman *
4e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman * Use of this source code is governed by a BSD-style license that can be
5e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman * found in the LICENSE file.
6e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman */
7e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
841868fe5625fc3bd70daa3f461c881b5db6a9265bungeman#include "SkFontDescriptor.h"
9e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman#include "SkFontMgr.h"
10ffa4a9213b4e754adc210fa02a3c4b1ae8d3b6d0mtklein#include "SkOnce.h"
11a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo#include "SkStream.h"
12e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman#include "SkTypes.h"
13e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
14e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanclass SkFontStyle;
15e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanclass SkTypeface;
16e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
17e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanclass SkEmptyFontStyleSet : public SkFontStyleSet {
18e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanpublic:
1936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    int count() override { return 0; }
2036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void getStyle(int, SkFontStyle*, SkString*) override {
21e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        SkDEBUGFAIL("SkFontStyleSet::getStyle called on empty set");
22e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
2336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* createTypeface(int index) override {
24e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        SkDEBUGFAIL("SkFontStyleSet::createTypeface called on empty set");
2596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
26e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
2736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkTypeface* matchStyle(const SkFontStyle&) override {
2896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
29e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
30e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman};
31e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
32385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanarySkFontStyleSet* SkFontStyleSet::CreateEmpty() { return new SkEmptyFontStyleSet; }
33e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
34e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman///////////////////////////////////////////////////////////////////////////////
35e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
36e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanclass SkEmptyFontMgr : public SkFontMgr {
37e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanprotected:
3836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    int onCountFamilies() const override {
39e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        return 0;
40e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
4136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onGetFamilyName(int index, SkString* familyName) const override {
42e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        SkDEBUGFAIL("onGetFamilyName called with bad index");
43e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
4436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkFontStyleSet* onCreateStyleSet(int index) const override {
45e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        SkDEBUGFAIL("onCreateStyleSet called with bad index");
4696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
47e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
4836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    SkFontStyleSet* onMatchFamily(const char[]) const override {
49e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        return SkFontStyleSet::CreateEmpty();
50e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
51e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
52592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    SkTypeface* onMatchFamilyStyle(const char[], const SkFontStyle&) const override {
5396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
54e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
55592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
56592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                            const SkFontStyle& style,
57592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                            const char* bcp47[],
58592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                            int bcp47Count,
59592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                            SkUnichar character) const override {
6096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
61e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
62592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    SkTypeface* onMatchFaceStyle(const SkTypeface*, const SkFontStyle&) const override {
6396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
64e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
65592273965a7fc7fc403252e420d15f6555b8f25dMike Reed
66592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int) const override {
67592273965a7fc7fc403252e420d15f6555b8f25dMike Reed        return nullptr;
68592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    }
69592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>, int) const override {
70592273965a7fc7fc403252e420d15f6555b8f25dMike Reed        return nullptr;
71592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    }
72592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
73592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                           const SkFontArguments&) const override {
7496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
75e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
76592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override {
7796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
78e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
79592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> onMakeFromFile(const char[], int) const override {
8096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
81e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
82592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    sk_sp<SkTypeface> onLegacyMakeTypeface(const char [], SkFontStyle) const override {
8396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
84e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
85e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman};
86e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
87e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanstatic SkFontStyleSet* emptyOnNull(SkFontStyleSet* fsset) {
8896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fsset) {
89e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman        fsset = SkFontStyleSet::CreateEmpty();
90e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
91e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return fsset;
92e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
93e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
94e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanint SkFontMgr::countFamilies() const {
95e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return this->onCountFamilies();
96e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
97e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
98e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanvoid SkFontMgr::getFamilyName(int index, SkString* familyName) const {
99e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    this->onGetFamilyName(index, familyName);
100e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
101e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
102e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanSkFontStyleSet* SkFontMgr::createStyleSet(int index) const {
103e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return emptyOnNull(this->onCreateStyleSet(index));
104e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
105e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
106e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanSkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) const {
107e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return emptyOnNull(this->onMatchFamily(familyName));
108e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
109e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
110e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanSkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
111e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman                                        const SkFontStyle& fs) const {
112e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return this->onMatchFamilyStyle(familyName, fs);
113e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
114e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
115e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanSkTypeface* SkFontMgr::matchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style,
116e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman                                                 const char* bcp47[], int bcp47Count,
117e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman                                                 SkUnichar character) const {
118e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return this->onMatchFamilyStyleCharacter(familyName, style, bcp47, bcp47Count, character);
119e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
120e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
121e1a828c555223e75ebf83d0674daa2e6fd5889a3bungemanSkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face,
122e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman                                      const SkFontStyle& fs) const {
123e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    return this->onMatchFaceStyle(face, fs);
124e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
125e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
126592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::makeFromData(sk_sp<SkData> data, int ttcIndex) const {
12796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == data) {
12896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
129e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
130592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->onMakeFromData(std::move(data), ttcIndex);
131e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
132e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
133592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::makeFromStream(std::unique_ptr<SkStreamAsset> stream,
134592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                            int ttcIndex) const {
13596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == stream) {
13696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
137e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman    }
138592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->onMakeFromStreamIndex(std::move(stream), ttcIndex);
139e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
140e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
141592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::makeFromStream(std::unique_ptr<SkStreamAsset> stream,
142592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                            const SkFontArguments& args) const {
143f6c7107d0385cc2b556802354b93b7dcff61570dbungeman    if (nullptr == stream) {
144f6c7107d0385cc2b556802354b93b7dcff61570dbungeman        return nullptr;
145f6c7107d0385cc2b556802354b93b7dcff61570dbungeman    }
146592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->onMakeFromStreamArgs(std::move(stream), args);
147f6c7107d0385cc2b556802354b93b7dcff61570dbungeman}
148f6c7107d0385cc2b556802354b93b7dcff61570dbungeman
149592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::makeFromFontData(std::unique_ptr<SkFontData> data) const {
15096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == data) {
15196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
15241868fe5625fc3bd70daa3f461c881b5db6a9265bungeman    }
153592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->onMakeFromFontData(std::move(data));
15441868fe5625fc3bd70daa3f461c881b5db6a9265bungeman}
15541868fe5625fc3bd70daa3f461c881b5db6a9265bungeman
156592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::makeFromFile(const char path[], int ttcIndex) const {
157592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    if (nullptr == path) {
158592273965a7fc7fc403252e420d15f6555b8f25dMike Reed        return nullptr;
159592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    }
160592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->onMakeFromFile(path, ttcIndex);
161f6c7107d0385cc2b556802354b93b7dcff61570dbungeman}
162f6c7107d0385cc2b556802354b93b7dcff61570dbungeman
163592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::legacyMakeTypeface(const char familyName[], SkFontStyle style) const {
164592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->onLegacyMakeTypeface(familyName, style);
16541868fe5625fc3bd70daa3f461c881b5db6a9265bungeman}
16641868fe5625fc3bd70daa3f461c881b5db6a9265bungeman
167592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
168592273965a7fc7fc403252e420d15f6555b8f25dMike Reed                                                  const SkFontArguments& args) const {
169592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->makeFromStream(std::move(stream), args.getCollectionIndex());
170592273965a7fc7fc403252e420d15f6555b8f25dMike Reed}
171592273965a7fc7fc403252e420d15f6555b8f25dMike Reedsk_sp<SkTypeface> SkFontMgr::onMakeFromFontData(std::unique_ptr<SkFontData> data) const {
172592273965a7fc7fc403252e420d15f6555b8f25dMike Reed    return this->makeFromStream(data->detachStream(), data->getIndex());
173e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman}
174e1a828c555223e75ebf83d0674daa2e6fd5889a3bungeman
1753186821c7e4448c4b586dde590760e22b46cf166Mike Klein// A global function pointer that's not declared, but can be overriden at startup by test tools.
1763186821c7e4448c4b586dde590760e22b46cf166Mike Kleinsk_sp<SkFontMgr> (*gSkFontMgr_DefaultFactory)() = nullptr;
1773186821c7e4448c4b586dde590760e22b46cf166Mike Klein
1783546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagnersk_sp<SkFontMgr> SkFontMgr::RefDefault() {
1793546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner    static SkOnce once;
1803546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner    static sk_sp<SkFontMgr> singleton;
1813546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner
1823546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner    once([]{
1833186821c7e4448c4b586dde590760e22b46cf166Mike Klein        sk_sp<SkFontMgr> fm = gSkFontMgr_DefaultFactory ? gSkFontMgr_DefaultFactory()
1843186821c7e4448c4b586dde590760e22b46cf166Mike Klein                                                        : SkFontMgr::Factory();
1853546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner        singleton = fm ? std::move(fm) : sk_make_sp<SkEmptyFontMgr>();
1863546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner    });
1873546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner    return singleton;
1883546ff10c2e1e91f5afe1efaab4e5e14f71689d1Ben Wagner}
189147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman
190147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman/**
191147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* Width has the greatest priority.
192147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If the value of pattern.width is 5 (normal) or less,
193147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*    narrower width values are checked first, then wider values.
194147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If the value of pattern.width is greater than 5 (normal),
195147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*    wider values are checked first, followed by narrower values.
196147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*
197147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* Italic/Oblique has the next highest priority.
198147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If italic requested and there is some italic font, use it.
199147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If oblique requested and there is some oblique font, use it.
200147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If italic requested and there is some oblique font, use it.
201147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If oblique requested and there is some italic font, use it.
202147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*
203147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* Exact match.
204147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If pattern.weight < 400, weights below pattern.weight are checked
205147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*   in descending order followed by weights above pattern.weight
206147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*   in ascending order until a match is found.
207147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If pattern.weight > 500, weights above pattern.weight are checked
208147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*   in ascending order followed by weights below pattern.weight
209147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*   in descending order until a match is found.
210147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If pattern.weight is 400, 500 is checked first
211147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*   and then the rule for pattern.weight < 400 is used.
212147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman* If pattern.weight is 500, 400 is checked first
213147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*   and then the rule for pattern.weight < 400 is used.
214147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman*/
215147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungemanSkTypeface* SkFontStyleSet::matchStyleCSS3(const SkFontStyle& pattern) {
216147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    int count = this->count();
217147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    if (0 == count) {
218147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        return nullptr;
219147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    }
220147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman
221147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    struct Score {
222147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        int score;
223147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        int index;
224b4bb7d825566042ed64697be49457dbac060e6c4bungeman        Score& operator +=(int rhs) { this->score += rhs; return *this; }
225b4bb7d825566042ed64697be49457dbac060e6c4bungeman        Score& operator <<=(int rhs) { this->score <<= rhs; return *this; }
226b4bb7d825566042ed64697be49457dbac060e6c4bungeman        bool operator <(const Score& that) { return this->score < that.score; }
227147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    };
228147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman
229147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    Score maxScore = { 0, 0 };
230147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    for (int i = 0; i < count; ++i) {
231147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        SkFontStyle current;
232147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        this->getStyle(i, &current, nullptr);
233147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        Score currentScore = { 0, i };
234147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman
235b4bb7d825566042ed64697be49457dbac060e6c4bungeman        // CSS stretch / SkFontStyle::Width
236b4bb7d825566042ed64697be49457dbac060e6c4bungeman        // Takes priority over everything else.
237147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        if (pattern.width() <= SkFontStyle::kNormal_Width) {
238147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            if (current.width() <= pattern.width()) {
239b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += 10 - pattern.width() + current.width();
240147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            } else {
241b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += 10 - current.width();
242147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            }
243147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        } else {
244147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            if (current.width() > pattern.width()) {
245b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += 10 + pattern.width() - current.width();
246147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            } else {
247b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += current.width();
248147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            }
249147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        }
250b4bb7d825566042ed64697be49457dbac060e6c4bungeman        currentScore <<= 8;
251b4bb7d825566042ed64697be49457dbac060e6c4bungeman
252b4bb7d825566042ed64697be49457dbac060e6c4bungeman        // CSS style (normal, italic, oblique) / SkFontStyle::Slant (upright, italic, oblique)
253b4bb7d825566042ed64697be49457dbac060e6c4bungeman        // Takes priority over all valid weights.
254b4bb7d825566042ed64697be49457dbac060e6c4bungeman        static_assert(SkFontStyle::kUpright_Slant == 0 &&
255b4bb7d825566042ed64697be49457dbac060e6c4bungeman                      SkFontStyle::kItalic_Slant  == 1 &&
256b4bb7d825566042ed64697be49457dbac060e6c4bungeman                      SkFontStyle::kOblique_Slant == 2,
257b4bb7d825566042ed64697be49457dbac060e6c4bungeman                      "SkFontStyle::Slant values not as required.");
258b4bb7d825566042ed64697be49457dbac060e6c4bungeman        SkASSERT(0 <= pattern.slant() && pattern.slant() <= 2 &&
259b4bb7d825566042ed64697be49457dbac060e6c4bungeman                 0 <= current.slant() && current.slant() <= 2);
260b4bb7d825566042ed64697be49457dbac060e6c4bungeman        static const int score[3][3] = {
261b4bb7d825566042ed64697be49457dbac060e6c4bungeman            /*               Upright Italic Oblique  [current]*/
262b4bb7d825566042ed64697be49457dbac060e6c4bungeman            /*   Upright */ {   3   ,  1   ,   2   },
263b4bb7d825566042ed64697be49457dbac060e6c4bungeman            /*   Italic  */ {   1   ,  3   ,   2   },
264b4bb7d825566042ed64697be49457dbac060e6c4bungeman            /*   Oblique */ {   1   ,  2   ,   3   },
265b4bb7d825566042ed64697be49457dbac060e6c4bungeman            /* [pattern] */
266b4bb7d825566042ed64697be49457dbac060e6c4bungeman        };
267b4bb7d825566042ed64697be49457dbac060e6c4bungeman        currentScore += score[pattern.slant()][current.slant()];
268b4bb7d825566042ed64697be49457dbac060e6c4bungeman        currentScore <<= 8;
269b4bb7d825566042ed64697be49457dbac060e6c4bungeman
270b4bb7d825566042ed64697be49457dbac060e6c4bungeman        // Synthetics (weight, style) [no stretch synthetic?]
271b4bb7d825566042ed64697be49457dbac060e6c4bungeman
272b4bb7d825566042ed64697be49457dbac060e6c4bungeman        // CSS weight / SkFontStyle::Weight
273147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        // The 'closer' to the target weight, the higher the score.
274147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        // 1000 is the 'heaviest' recognized weight
275147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        if (pattern.weight() == current.weight()) {
276b4bb7d825566042ed64697be49457dbac060e6c4bungeman            currentScore += 1000;
277147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        } else if (pattern.weight() <= 500) {
278147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            if (400 <= pattern.weight() && pattern.weight() < 450) {
279147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman                if (450 <= current.weight() && current.weight() <= 500) {
280147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman                    // Artificially boost the 500 weight.
281147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman                    // TODO: determine correct number to use.
282b4bb7d825566042ed64697be49457dbac060e6c4bungeman                    currentScore += 500;
283147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman                }
284147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            }
285147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            if (current.weight() <= pattern.weight()) {
286b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += 1000 - pattern.weight() + current.weight();
287147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            } else {
288b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += 1000 - current.weight();
289147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            }
290147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        } else if (pattern.weight() > 500) {
291147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            if (current.weight() > pattern.weight()) {
292b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += 1000 + pattern.weight() - current.weight();
293147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            } else {
294b4bb7d825566042ed64697be49457dbac060e6c4bungeman                currentScore += current.weight();
295147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            }
296147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        }
297147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman
298b4bb7d825566042ed64697be49457dbac060e6c4bungeman        if (maxScore < currentScore) {
299147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman            maxScore = currentScore;
300147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman        }
301147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    }
302147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman
303147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman    return this->createTypeface(maxScore.index);
304147ea2fb7ad9adeeb52fe5549f7ba20953296f6fbungeman}
305