1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontHost.h"
90fc17c33f144956bb75650f991226a14e555f189reed@google.com#include "SkFontHost_FreeType_common.h"
109714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com#include "SkFontDescriptor.h"
11b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include "SkFontMgr.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDescriptor.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOSFile.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTSearch.h"
19b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include "SkTypefaceCache.h"
20b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include "SkTArray.h"
21b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
22b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#include <limits>
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SK_FONT_FILE_PREFIX
25b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com#    define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/"
262cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com#endif
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
284dc686d75353235260c716242f4ed596b70beb95djsollen@google.combool find_name_and_attributes(SkStream* stream, SkString* name,
29fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com                              SkTypeface::Style* style, bool* isFixedPitch);
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The base SkTypeface implementation for the custom font manager. */
34b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_Custom : public SkTypeface_FreeType {
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
36b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkString familyName)
37b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
38b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        , fIsSysFont(sysFont), fFamilyName(familyName)
39b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    { }
40ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool isSysFont() const { return fIsSysFont; }
42292b1d4903a770a77282508054917b48fb989d49reed@google.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual const char* getUniqueString() const = 0;
44ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
455526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.comprotected:
46b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE {
47b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        desc->setFamilyName(fFamilyName.c_str());
48b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        desc->setFontFileName(this->getUniqueString());
49b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        *isLocal = !this->isSysFont();
50b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
515526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
53b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    bool fIsSysFont;
54b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkString fFamilyName;
55ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
56032fbb8ebff7816793b077b6113de702e48713c1reed@google.com    typedef SkTypeface_FreeType INHERITED;
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
59b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The empty SkTypeface implementation for the custom font manager.
60b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  Used as the last resort fallback typeface.
61f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com */
62b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_Empty : public SkTypeface_Custom {
63f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.compublic:
64b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, true, false, SkString()) {}
65ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
66b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
67ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
68292b1d4903a770a77282508054917b48fb989d49reed@google.comprotected:
69292b1d4903a770a77282508054917b48fb989d49reed@google.com    virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
70292b1d4903a770a77282508054917b48fb989d49reed@google.com
71f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.comprivate:
72b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    typedef SkTypeface_Custom INHERITED;
73f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com};
74f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com
75b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The stream SkTypeface implementation for the custom font manager. */
76b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_Stream : public SkTypeface_Custom {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
78b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTypeface_Stream(Style style, bool sysFont, SkStream* stream,
79b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                      bool isFixedPitch, const SkString familyName)
80b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        : INHERITED(style, sysFont, isFixedPitch, familyName)
81b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        , fStream(SkRef(stream))
82b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    { }
83ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
84e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
85ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
86292b1d4903a770a77282508054917b48fb989d49reed@google.comprotected:
87292b1d4903a770a77282508054917b48fb989d49reed@google.com    virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
88292b1d4903a770a77282508054917b48fb989d49reed@google.com        *ttcIndex = 0;
89a2b44dc5882856b6ed3670f370819ab39998ada8commit-bot@chromium.org        return fStream->duplicate();
90292b1d4903a770a77282508054917b48fb989d49reed@google.com    }
91292b1d4903a770a77282508054917b48fb989d49reed@google.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
93b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkAutoTUnref<SkStream> fStream;
94ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
95b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    typedef SkTypeface_Custom INHERITED;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
98b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/** The file SkTypeface implementation for the custom font manager. */
99b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkTypeface_File : public SkTypeface_Custom {
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
101b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTypeface_File(Style style, bool sysFont, const char path[],
102b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                    bool isFixedPitch, const SkString familyName)
103b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        : INHERITED(style, sysFont, isFixedPitch, familyName)
104b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        , fPath(path)
105b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    { }
106ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
107e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    virtual const char* getUniqueString() const SK_OVERRIDE {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const char* str = strrchr(fPath.c_str(), '/');
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (str) {
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            str += 1;   // skip the '/'
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return str;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
114ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
115292b1d4903a770a77282508054917b48fb989d49reed@google.comprotected:
116292b1d4903a770a77282508054917b48fb989d49reed@google.com    virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
117292b1d4903a770a77282508054917b48fb989d49reed@google.com        *ttcIndex = 0;
118292b1d4903a770a77282508054917b48fb989d49reed@google.com        return SkStream::NewFromFile(fPath.c_str());
119292b1d4903a770a77282508054917b48fb989d49reed@google.com    }
120292b1d4903a770a77282508054917b48fb989d49reed@google.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkString fPath;
123ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
124b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    typedef SkTypeface_Custom INHERITED;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
129b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/**
130b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  SkFontStyleSet_Custom
131b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *
132b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
133b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com */
134b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkFontStyleSet_Custom : public SkFontStyleSet {
135b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.compublic:
136b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual int count() SK_OVERRIDE {
139b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return fStyles.count();
140b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
142b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
143b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkASSERT(index < fStyles.count());
144b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        bool bold = fStyles[index]->isBold();
145b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        bool italic = fStyles[index]->isItalic();
146b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
147b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                             SkFontStyle::kNormal_Width,
148b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                             italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
149b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        name->reset();
150b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
152b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
153b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkASSERT(index < fStyles.count());
154b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return SkRef(fStyles[index].get());
155b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
157b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
158b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        int score = 0;
159b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        score += (pattern.width() - candidate.width()) * 100;
160b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
161b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        score += pattern.weight() - candidate.weight();
162b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return score;
163b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
164ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
165b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
166b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (0 == fStyles.count()) {
167b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            return NULL;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
169f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com
170b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkTypeface_Custom* closest = fStyles[0];
171b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        int minScore = std::numeric_limits<int>::max();
172b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        for (int i = 0; i < fStyles.count(); ++i) {
173b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            bool bold = fStyles[i]->isBold();
174b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            bool italic = fStyles[i]->isItalic();
175b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
176b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                 : SkFontStyle::kNormal_Weight,
177b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                            SkFontStyle::kNormal_Width,
178b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                            italic ? SkFontStyle::kItalic_Slant
179b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                   : SkFontStyle::kUpright_Slant);
180b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
181b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            int score = match_score(pattern, style);
182b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (score < minScore) {
183b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                closest = fStyles[i];
184b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                minScore = score;
185b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
186887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com        }
187b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return SkRef(closest);
188b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
189887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com
190b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comprivate:
191b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
192b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkString fFamilyName;
193b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
194b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    void appendTypeface(SkTypeface_Custom* typeface) {
195b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        fStyles.push_back().reset(typeface);
196f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com    }
197f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com
198b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    friend class SkFontMgr_Custom;
199b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com};
200b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
201b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com/**
202b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  SkFontMgr_Custom
203b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *
204b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  This class is essentially a collection of SkFontStyleSet_Custom,
205b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  one SkFontStyleSet_Custom for each family. This class may be modified
206b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com *  to load fonts from any source by changing the initialization.
207b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com */
208b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comclass SkFontMgr_Custom : public SkFontMgr {
209b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.compublic:
210b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    explicit SkFontMgr_Custom(const char* dir) {
211b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        this->load_system_fonts(dir);
2122cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com    }
2132cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com
214b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comprotected:
215967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual int onCountFamilies() const SK_OVERRIDE {
216b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return fFamilies.count();
2172cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com    }
2182cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com
219967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
220b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkASSERT(index < fFamilies.count());
221b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        familyName->set(fFamilies[index]->fFamilyName);
222b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
2232cf84ec1e15fe69ca8840eab9e32708b81b95c90bungeman@google.com
224967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) const SK_OVERRIDE {
225b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkASSERT(index < fFamilies.count());
226b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return SkRef(fFamilies[index].get());
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
228f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com
229967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
230b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        for (int i = 0; i < fFamilies.count(); ++i) {
231b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (fFamilies[i]->fFamilyName.equals(familyName)) {
232b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                return SkRef(fFamilies[i].get());
233b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
235b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return NULL;
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
237b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
238b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
239967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org                                           const SkFontStyle& fontStyle) const SK_OVERRIDE
240b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    {
241b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
242b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return sset->matchStyle(fontStyle);
243b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
244b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
245b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
246967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org                                         const SkFontStyle& fontStyle) const SK_OVERRIDE
247b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    {
248b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        for (int i = 0; i < fFamilies.count(); ++i) {
249b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
250b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                if (fFamilies[i]->fStyles[j] == familyMember) {
251b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                    return fFamilies[i]->matchStyle(fontStyle);
252b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                }
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
255b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return NULL;
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
259b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
260b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return this->createFromStream(stream, ttcIndex);
261b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
263967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
264b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (NULL == stream || stream->getLength() <= 0) {
265b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkDELETE(stream);
266b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            return NULL;
267b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
269b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        bool isFixedPitch;
270b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkTypeface::Style style;
271b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkString name;
272b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) {
273b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedPitch, name));
274b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        } else {
275b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            return NULL;
276b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
277b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
278ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
279967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org    virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
280b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
281b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
282b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
283ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
284b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
285967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org                                               unsigned styleBits) const SK_OVERRIDE
286b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    {
287b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
288b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
289b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                 ? SkFontStyle::kBold_Weight
290b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                 : SkFontStyle::kNormal_Weight,
291b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                        SkFontStyle::kNormal_Width,
292b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                        oldStyle & SkTypeface::kItalic
293b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                 ? SkFontStyle::kItalic_Slant
294b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                 : SkFontStyle::kUpright_Slant);
295b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkTypeface* tf = NULL;
296b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
297b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (NULL != familyName) {
298b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            tf = this->onMatchFamilyStyle(familyName, style);
299b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
300ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
301b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (NULL == tf) {
302b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            tf = gDefaultFamily->matchStyle(style);
303b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
304ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
305b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        return SkSafeRef(tf);
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
307ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
308b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.comprivate:
309b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
310b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    static bool get_name_and_style(const char path[], SkString* name,
311b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                   SkTypeface::Style* style, bool* isFixedPitch) {
312b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
313b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (stream.get()) {
314b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            return find_name_and_attributes(stream, name, style, isFixedPitch);
315b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        } else {
316b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkDebugf("---- failed to open <%s> as a font\n", path);
317b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            return false;
318b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
320ada448040f04bb4c8fae82fe839807ba45a85d61chudy@google.com
321b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    void load_directory_fonts(const SkString& directory) {
322b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkOSFile::Iter iter(directory.c_str(), ".ttf");
323b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkString name;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
325b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        while (iter.next(&name, false)) {
326ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org            SkString filename(
327ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org                SkOSPath::SkPathJoin(directory.c_str(), name.c_str()));
328febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com
329b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            bool isFixedPitch;
330b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkString realname;
331b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning
332febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com
333b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) {
334b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                SkDebugf("------ can't load <%s> as a font\n", filename.c_str());
335b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                continue;
336b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
337febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com
338b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
339b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                style,
340b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                true,  // system-font (cannot delete)
341b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                filename.c_str(),
342b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                isFixedPitch,
343b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                realname));
344b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
345b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
346b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (NULL == addTo) {
347b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                addTo = new SkFontStyleSet_Custom(realname);
348b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                fFamilies.push_back().reset(addTo);
349b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
350b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            addTo->appendTypeface(tf);
351b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
352febfd70d26dce3eb30da5384e36d740576a56161bungeman@google.com
353b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkOSFile::Iter dirIter(directory.c_str());
354b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        while (dirIter.next(&name, true)) {
355b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (name.startsWith(".")) {
356b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                continue;
357b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
358ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org            SkString dirname(
359ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org                SkOSPath::SkPathJoin(directory.c_str(), name.c_str()));
360b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            load_directory_fonts(dirname);
361b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3633681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com
364b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    void load_system_fonts(const char* dir) {
365b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        SkString baseDirectory(dir);
366b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        load_directory_fonts(baseDirectory);
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
368b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (fFamilies.empty()) {
369b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
370b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            fFamilies.push_back().reset(family);
371b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            family->appendTypeface(SkNEW(SkTypeface_Empty));
372b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
373070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com
374b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        // Try to pick a default font.
375b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        static const char* gDefaultNames[] = {
376ea163cc3a708fc634ace369ce6c5b7b9da7fe9cccommit-bot@chromium.org            "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL
377b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        };
378b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
379b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
380b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (NULL == set) {
381b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                continue;
382b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
383ab44a17f376039cdcaba74f9fb8f282ea4caa63creed@google.com
384b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
385b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                         SkFontStyle::kNormal_Width,
386b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                                                         SkFontStyle::kUpright_Slant));
387b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            if (NULL == tf) {
388b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com                continue;
389b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            }
390070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com
391b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            gDefaultFamily = set;
392b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            gDefaultNormal = tf;
393b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            break;
394b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
395b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        if (NULL == gDefaultNormal) {
396b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            gDefaultFamily = fFamilies[0];
397b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com            gDefaultNormal = gDefaultFamily->fStyles[0];
398b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com        }
399b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    }
400b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com
401b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
402b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkFontStyleSet_Custom* gDefaultFamily;
403b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    SkTypeface* gDefaultNormal;
404b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com};
405070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com
406070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.comSkFontMgr* SkFontMgr::Factory() {
407b3d154de5e4c318f88e4c4ad15fe626054365997bungeman@google.com    return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);
408070da5edcb1c6e9b9507f06a5e2c270e1c1fd796reed@google.com}
409