Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / ports / SkFontHost_linux.cpp
1 /*
2  * Copyright 2006 The Android Open Source Project
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 "SkFontHost.h"
9 #include "SkFontHost_FreeType_common.h"
10 #include "SkFontDescriptor.h"
11 #include "SkFontMgr.h"
12 #include "SkDescriptor.h"
13 #include "SkOSFile.h"
14 #include "SkPaint.h"
15 #include "SkString.h"
16 #include "SkStream.h"
17 #include "SkThread.h"
18 #include "SkTSearch.h"
19 #include "SkTypefaceCache.h"
20 #include "SkTArray.h"
21
22 #include <limits>
23
24 #ifndef SK_FONT_FILE_PREFIX
25 #    define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/"
26 #endif
27 #ifndef SK_FONT_FILE_DIR_SEPERATOR
28 #    define SK_FONT_FILE_DIR_SEPERATOR "/"
29 #endif
30
31 bool find_name_and_attributes(SkStream* stream, SkString* name,
32                               SkTypeface::Style* style, bool* isFixedPitch);
33
34 ///////////////////////////////////////////////////////////////////////////////
35
36 /** The base SkTypeface implementation for the custom font manager. */
37 class SkTypeface_Custom : public SkTypeface_FreeType {
38 public:
39     SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkString familyName)
40         : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
41         , fIsSysFont(sysFont), fFamilyName(familyName)
42     { }
43
44     bool isSysFont() const { return fIsSysFont; }
45
46     virtual const char* getUniqueString() const = 0;
47
48 protected:
49     virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE {
50         desc->setFamilyName(fFamilyName.c_str());
51         desc->setFontFileName(this->getUniqueString());
52         *isLocal = !this->isSysFont();
53     }
54
55 private:
56     bool fIsSysFont;
57     SkString fFamilyName;
58
59     typedef SkTypeface_FreeType INHERITED;
60 };
61
62 /** The empty SkTypeface implementation for the custom font manager.
63  *  Used as the last resort fallback typeface.
64  */
65 class SkTypeface_Empty : public SkTypeface_Custom {
66 public:
67     SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, true, false, SkString()) {}
68
69     virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
70
71 protected:
72     virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
73
74 private:
75     typedef SkTypeface_Custom INHERITED;
76 };
77
78 /** The stream SkTypeface implementation for the custom font manager. */
79 class SkTypeface_Stream : public SkTypeface_Custom {
80 public:
81     SkTypeface_Stream(Style style, bool sysFont, SkStream* stream,
82                       bool isFixedPitch, const SkString familyName)
83         : INHERITED(style, sysFont, isFixedPitch, familyName)
84         , fStream(SkRef(stream))
85     { }
86
87     virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
88
89 protected:
90     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
91         *ttcIndex = 0;
92         return SkRef(fStream.get());
93     }
94
95 private:
96     SkAutoTUnref<SkStream> fStream;
97
98     typedef SkTypeface_Custom INHERITED;
99 };
100
101 /** The file SkTypeface implementation for the custom font manager. */
102 class SkTypeface_File : public SkTypeface_Custom {
103 public:
104     SkTypeface_File(Style style, bool sysFont, const char path[],
105                     bool isFixedPitch, const SkString familyName)
106         : INHERITED(style, sysFont, isFixedPitch, familyName)
107         , fPath(path)
108     { }
109
110     virtual const char* getUniqueString() const SK_OVERRIDE {
111         const char* str = strrchr(fPath.c_str(), '/');
112         if (str) {
113             str += 1;   // skip the '/'
114         }
115         return str;
116     }
117
118 protected:
119     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
120         *ttcIndex = 0;
121         return SkStream::NewFromFile(fPath.c_str());
122     }
123
124 private:
125     SkString fPath;
126
127     typedef SkTypeface_Custom INHERITED;
128 };
129
130 ///////////////////////////////////////////////////////////////////////////////
131
132 /**
133  *  SkFontStyleSet_Custom
134  *
135  *  This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
136  */
137 class SkFontStyleSet_Custom : public SkFontStyleSet {
138 public:
139     explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
140
141     virtual int count() SK_OVERRIDE {
142         return fStyles.count();
143     }
144
145     virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE {
146         SkASSERT(index < fStyles.count());
147         bool bold = fStyles[index]->isBold();
148         bool italic = fStyles[index]->isItalic();
149         *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
150                              SkFontStyle::kNormal_Width,
151                              italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
152         name->reset();
153     }
154
155     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
156         SkASSERT(index < fStyles.count());
157         return SkRef(fStyles[index].get());
158     }
159
160     static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) {
161         int score = 0;
162         score += (pattern.width() - candidate.width()) * 100;
163         score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000;
164         score += pattern.weight() - candidate.weight();
165         return score;
166     }
167
168     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
169         if (0 == fStyles.count()) {
170             return NULL;
171         }
172
173         SkTypeface_Custom* closest = fStyles[0];
174         int minScore = std::numeric_limits<int>::max();
175         for (int i = 0; i < fStyles.count(); ++i) {
176             bool bold = fStyles[i]->isBold();
177             bool italic = fStyles[i]->isItalic();
178             SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight
179                                                  : SkFontStyle::kNormal_Weight,
180                                             SkFontStyle::kNormal_Width,
181                                             italic ? SkFontStyle::kItalic_Slant
182                                                    : SkFontStyle::kUpright_Slant);
183
184             int score = match_score(pattern, style);
185             if (score < minScore) {
186                 closest = fStyles[i];
187                 minScore = score;
188             }
189         }
190         return SkRef(closest);
191     }
192
193 private:
194     SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles;
195     SkString fFamilyName;
196
197     void appendTypeface(SkTypeface_Custom* typeface) {
198         fStyles.push_back().reset(typeface);
199     }
200
201     friend class SkFontMgr_Custom;
202 };
203
204 /**
205  *  SkFontMgr_Custom
206  *
207  *  This class is essentially a collection of SkFontStyleSet_Custom,
208  *  one SkFontStyleSet_Custom for each family. This class may be modified
209  *  to load fonts from any source by changing the initialization.
210  */
211 class SkFontMgr_Custom : public SkFontMgr {
212 public:
213     explicit SkFontMgr_Custom(const char* dir) {
214         this->load_system_fonts(dir);
215     }
216
217 protected:
218     virtual int onCountFamilies() const SK_OVERRIDE {
219         return fFamilies.count();
220     }
221
222     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
223         SkASSERT(index < fFamilies.count());
224         familyName->set(fFamilies[index]->fFamilyName);
225     }
226
227     virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) const SK_OVERRIDE {
228         SkASSERT(index < fFamilies.count());
229         return SkRef(fFamilies[index].get());
230     }
231
232     virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
233         for (int i = 0; i < fFamilies.count(); ++i) {
234             if (fFamilies[i]->fFamilyName.equals(familyName)) {
235                 return SkRef(fFamilies[i].get());
236             }
237         }
238         return NULL;
239     }
240
241     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
242                                            const SkFontStyle& fontStyle) const SK_OVERRIDE
243     {
244         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
245         return sset->matchStyle(fontStyle);
246     }
247
248     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
249                                          const SkFontStyle& fontStyle) const SK_OVERRIDE
250     {
251         for (int i = 0; i < fFamilies.count(); ++i) {
252             for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) {
253                 if (fFamilies[i]->fStyles[j] == familyMember) {
254                     return fFamilies[i]->matchStyle(fontStyle);
255                 }
256             }
257         }
258         return NULL;
259     }
260
261     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
262         SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
263         return this->createFromStream(stream, ttcIndex);
264     }
265
266     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
267         if (NULL == stream || stream->getLength() <= 0) {
268             SkDELETE(stream);
269             return NULL;
270         }
271
272         bool isFixedPitch;
273         SkTypeface::Style style;
274         SkString name;
275         if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) {
276             return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedPitch, name));
277         } else {
278             return NULL;
279         }
280     }
281
282     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
283         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
284         return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
285     }
286
287     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
288                                                unsigned styleBits) const SK_OVERRIDE
289     {
290         SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
291         SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
292                                                  ? SkFontStyle::kBold_Weight
293                                                  : SkFontStyle::kNormal_Weight,
294                                         SkFontStyle::kNormal_Width,
295                                         oldStyle & SkTypeface::kItalic
296                                                  ? SkFontStyle::kItalic_Slant
297                                                  : SkFontStyle::kUpright_Slant);
298         SkTypeface* tf = NULL;
299
300         if (NULL != familyName) {
301             tf = this->onMatchFamilyStyle(familyName, style);
302         }
303
304         if (NULL == tf) {
305             tf = gDefaultFamily->matchStyle(style);
306         }
307
308         return SkSafeRef(tf);
309     }
310
311 private:
312
313     static bool get_name_and_style(const char path[], SkString* name,
314                                    SkTypeface::Style* style, bool* isFixedPitch) {
315         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
316         if (stream.get()) {
317             return find_name_and_attributes(stream, name, style, isFixedPitch);
318         } else {
319             SkDebugf("---- failed to open <%s> as a font\n", path);
320             return false;
321         }
322     }
323
324     void load_directory_fonts(const SkString& directory) {
325         SkOSFile::Iter iter(directory.c_str(), ".ttf");
326         SkString name;
327
328         while (iter.next(&name, false)) {
329             SkString filename(directory);
330             filename.append(name);
331
332             bool isFixedPitch;
333             SkString realname;
334             SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning
335
336             if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) {
337                 SkDebugf("------ can't load <%s> as a font\n", filename.c_str());
338                 continue;
339             }
340
341             SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, (
342                                                 style,
343                                                 true,  // system-font (cannot delete)
344                                                 filename.c_str(),
345                                                 isFixedPitch,
346                                                 realname));
347
348             SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str());
349             if (NULL == addTo) {
350                 addTo = new SkFontStyleSet_Custom(realname);
351                 fFamilies.push_back().reset(addTo);
352             }
353             addTo->appendTypeface(tf);
354         }
355
356         SkOSFile::Iter dirIter(directory.c_str());
357         while (dirIter.next(&name, true)) {
358             if (name.startsWith(".")) {
359                 continue;
360             }
361             SkString dirname(directory);
362             dirname.append(name);
363             dirname.append(SK_FONT_FILE_DIR_SEPERATOR);
364             load_directory_fonts(dirname);
365         }
366     }
367
368     void load_system_fonts(const char* dir) {
369         SkString baseDirectory(dir);
370         load_directory_fonts(baseDirectory);
371
372         if (fFamilies.empty()) {
373             SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString());
374             fFamilies.push_back().reset(family);
375             family->appendTypeface(SkNEW(SkTypeface_Empty));
376         }
377
378         // Try to pick a default font.
379         static const char* gDefaultNames[] = {
380             "Arial", "Verdana", "Times New Roman", NULL
381         };
382         for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
383             SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]);
384             if (NULL == set) {
385                 continue;
386             }
387
388             SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight,
389                                                          SkFontStyle::kNormal_Width,
390                                                          SkFontStyle::kUpright_Slant));
391             if (NULL == tf) {
392                 continue;
393             }
394
395             gDefaultFamily = set;
396             gDefaultNormal = tf;
397             break;
398         }
399         if (NULL == gDefaultNormal) {
400             gDefaultFamily = fFamilies[0];
401             gDefaultNormal = gDefaultFamily->fStyles[0];
402         }
403     }
404
405     SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
406     SkFontStyleSet_Custom* gDefaultFamily;
407     SkTypeface* gDefaultNormal;
408 };
409
410 SkFontMgr* SkFontMgr::Factory() {
411     return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);
412 }