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