OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkFontHost.h" | 10 #include "SkFontHost.h" |
11 #include "SkFontHost_FreeType_common.h" | 11 #include "SkFontHost_FreeType_common.h" |
12 #include "SkFontDescriptor.h" | 12 #include "SkFontDescriptor.h" |
13 #include "SkFontMgr.h" | |
bungeman-skia
2013/11/08 20:55:55
This file hasn't been updated in a long time, so I
| |
13 #include "SkDescriptor.h" | 14 #include "SkDescriptor.h" |
14 #include "SkOSFile.h" | 15 #include "SkOSFile.h" |
15 #include "SkPaint.h" | 16 #include "SkPaint.h" |
16 #include "SkString.h" | 17 #include "SkString.h" |
17 #include "SkStream.h" | 18 #include "SkStream.h" |
18 #include "SkThread.h" | 19 #include "SkThread.h" |
19 #include "SkTSearch.h" | 20 #include "SkTSearch.h" |
21 #include "SkTypefaceCache.h" | |
22 #include "SkTArray.h" | |
23 | |
24 #include <limits> | |
20 | 25 |
21 #ifndef SK_FONT_FILE_PREFIX | 26 #ifndef SK_FONT_FILE_PREFIX |
22 #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" | 27 #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" |
23 #endif | 28 #endif |
24 #ifndef SK_FONT_FILE_DIR_SEPERATOR | 29 #ifndef SK_FONT_FILE_DIR_SEPERATOR |
25 #define SK_FONT_FILE_DIR_SEPERATOR "/" | 30 #define SK_FONT_FILE_DIR_SEPERATOR "/" |
26 #endif | 31 #endif |
27 | 32 |
28 bool find_name_and_attributes(SkStream* stream, SkString* name, | 33 bool find_name_and_attributes(SkStream* stream, SkString* name, |
29 SkTypeface::Style* style, bool* isFixedPitch); | 34 SkTypeface::Style* style, bool* isFixedPitch); |
30 | 35 |
31 /////////////////////////////////////////////////////////////////////////////// | 36 /////////////////////////////////////////////////////////////////////////////// |
32 | 37 |
33 struct FamilyRec; | |
34 | |
35 /* This guy holds a mapping of a name -> family, used for looking up fonts. | |
36 Since it is stored in a stretchy array that doesn't preserve object | |
37 semantics, we don't use constructor/destructors, but just have explicit | |
38 helpers to manage our internal bookkeeping. | |
39 */ | |
40 struct NameFamilyPair { | |
41 const char* fName; // we own this | |
42 FamilyRec* fFamily; // we don't own this, we just reference it | |
43 | |
44 void construct(const char name[], FamilyRec* family) | |
45 { | |
46 fName = strdup(name); | |
47 fFamily = family; // we don't own this, so just record the referene | |
48 } | |
49 void destruct() | |
50 { | |
51 free((char*)fName); | |
52 // we don't own family, so just ignore our reference | |
53 } | |
54 }; | |
55 | |
56 // we use atomic_inc to grow this for each typeface we create | |
57 static int32_t gUniqueFontID; | |
58 | |
59 // this is the mutex that protects these globals | |
60 SK_DECLARE_STATIC_MUTEX(gFamilyMutex); | |
61 static FamilyRec* gFamilyHead; | |
62 static SkTDArray<NameFamilyPair> gNameList; | |
63 | |
64 struct FamilyRec { | |
65 FamilyRec* fNext; | |
66 SkTypeface* fFaces[4]; | |
67 | |
68 FamilyRec() | |
69 { | |
70 fNext = gFamilyHead; | |
71 memset(fFaces, 0, sizeof(fFaces)); | |
72 gFamilyHead = this; | |
73 } | |
74 }; | |
75 | |
76 static SkTypeface* find_best_face(const FamilyRec* family, | |
77 SkTypeface::Style style) { | |
78 SkTypeface* const* faces = family->fFaces; | |
79 | |
80 if (faces[style] != NULL) { // exact match | |
81 return faces[style]; | |
82 } | |
83 // look for a matching bold | |
84 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); | |
85 if (faces[style] != NULL) { | |
86 return faces[style]; | |
87 } | |
88 // look for the plain | |
89 if (faces[SkTypeface::kNormal] != NULL) { | |
90 return faces[SkTypeface::kNormal]; | |
91 } | |
92 // look for anything | |
93 for (int i = 0; i < 4; i++) { | |
94 if (faces[i] != NULL) { | |
95 return faces[i]; | |
96 } | |
97 } | |
98 // should never get here, since the faces list should not be empty | |
99 SkDEBUGFAIL("faces list is empty"); | |
100 return NULL; | |
101 } | |
102 | |
103 static FamilyRec* find_family(const SkTypeface* member) { | |
104 FamilyRec* curr = gFamilyHead; | |
105 while (curr != NULL) { | |
106 for (int i = 0; i < 4; i++) { | |
107 if (curr->fFaces[i] == member) { | |
108 return curr; | |
109 } | |
110 } | |
111 curr = curr->fNext; | |
112 } | |
113 return NULL; | |
114 } | |
115 | |
116 /* Remove reference to this face from its family. If the resulting family | |
117 is empty (has no faces), return that family, otherwise return NULL | |
118 */ | |
119 static FamilyRec* remove_from_family(const SkTypeface* face) { | |
120 FamilyRec* family = find_family(face); | |
121 SkASSERT(family->fFaces[face->style()] == face); | |
122 family->fFaces[face->style()] = NULL; | |
123 | |
124 for (int i = 0; i < 4; i++) { | |
125 if (family->fFaces[i] != NULL) { // family is non-empty | |
126 return NULL; | |
127 } | |
128 } | |
129 return family; // return the empty family | |
130 } | |
131 | |
132 // maybe we should make FamilyRec be doubly-linked | |
133 static void detach_and_delete_family(FamilyRec* family) { | |
134 FamilyRec* curr = gFamilyHead; | |
135 FamilyRec* prev = NULL; | |
136 | |
137 while (curr != NULL) { | |
138 FamilyRec* next = curr->fNext; | |
139 if (curr == family) { | |
140 if (prev == NULL) { | |
141 gFamilyHead = next; | |
142 } else { | |
143 prev->fNext = next; | |
144 } | |
145 SkDELETE(family); | |
146 return; | |
147 } | |
148 prev = curr; | |
149 curr = next; | |
150 } | |
151 SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); | |
152 } | |
153 | |
154 static const char* find_family_name(const SkTypeface* familyMember) { | |
155 const FamilyRec* familyRec = find_family(familyMember); | |
156 for (int i = 0; i < gNameList.count(); i++) { | |
157 if (gNameList[i].fFamily == familyRec) { | |
158 return gNameList[i].fName; | |
159 } | |
160 } | |
161 return NULL; | |
162 } | |
163 | |
164 static FamilyRec* find_familyrec(const char name[]) { | |
165 const NameFamilyPair* list = gNameList.begin(); | |
166 int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, | |
167 sizeof(list[0])); | |
168 return index >= 0 ? list[index].fFamily : NULL; | |
169 } | |
170 | |
171 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { | |
172 FamilyRec* rec = find_familyrec(name); | |
173 return rec ? find_best_face(rec, style) : NULL; | |
174 } | |
175 | |
176 static SkTypeface* find_typeface(const SkTypeface* familyMember, | |
177 SkTypeface::Style style) { | |
178 const FamilyRec* family = find_family(familyMember); | |
179 return family ? find_best_face(family, style) : NULL; | |
180 } | |
181 | |
182 static void add_name(const char name[], FamilyRec* family) { | |
183 SkAutoAsciiToLC tolc(name); | |
184 name = tolc.lc(); | |
185 | |
186 NameFamilyPair* list = gNameList.begin(); | |
187 int count = gNameList.count(); | |
188 | |
189 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); | |
190 | |
191 if (index < 0) { | |
192 list = gNameList.insert(~index); | |
193 list->construct(name, family); | |
194 } | |
195 } | |
196 | |
197 static void remove_from_names(FamilyRec* emptyFamily) { | |
198 #ifdef SK_DEBUG | |
199 for (int i = 0; i < 4; i++) { | |
200 SkASSERT(emptyFamily->fFaces[i] == NULL); | |
201 } | |
202 #endif | |
203 | |
204 SkTDArray<NameFamilyPair>& list = gNameList; | |
205 | |
206 // must go backwards when removing | |
207 for (int i = list.count() - 1; i >= 0; --i) { | |
208 NameFamilyPair* pair = &list[i]; | |
209 if (pair->fFamily == emptyFamily) { | |
210 pair->destruct(); | |
211 list.remove(i); | |
212 } | |
213 } | |
214 } | |
215 | |
216 /////////////////////////////////////////////////////////////////////////////// | |
217 | |
218 class FamilyTypeface : public SkTypeface_FreeType { | 38 class FamilyTypeface : public SkTypeface_FreeType { |
219 public: | 39 public: |
220 FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedPit ch) | 40 FamilyTypeface(Style style, bool sysFont, bool isFixedPitch, const SkString familyName) |
221 : INHERITED(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedPitch) { | 41 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) |
222 fIsSysFont = sysFont; | 42 , fIsSysFont(sysFont), fFamilyName(familyName) |
223 | 43 { } |
224 SkAutoMutexAcquire ac(gFamilyMutex); | |
225 | |
226 if (NULL == family) { | |
227 family = SkNEW(FamilyRec); | |
228 } | |
229 family->fFaces[style] = this; | |
230 fFamilyRec = family; // just record it so we can return it if asked | |
231 } | |
232 | |
233 virtual ~FamilyTypeface() { | |
234 SkAutoMutexAcquire ac(gFamilyMutex); | |
235 | |
236 // remove us from our family. If the family is now empty, we return | |
237 // that and then remove that family from the name list | |
238 FamilyRec* family = remove_from_family(this); | |
239 if (NULL != family) { | |
240 remove_from_names(family); | |
241 detach_and_delete_family(family); | |
242 } | |
243 } | |
244 | 44 |
245 bool isSysFont() const { return fIsSysFont; } | 45 bool isSysFont() const { return fIsSysFont; } |
246 FamilyRec* getFamily() const { return fFamilyRec; } | |
247 | 46 |
248 virtual const char* getUniqueString() const = 0; | 47 virtual const char* getUniqueString() const = 0; |
249 | 48 |
250 protected: | 49 protected: |
251 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE ; | 50 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocalStream ) const SK_OVERRIDE { |
252 virtual SkTypeface* onRefMatchingStyle(Style styleBits) const SK_OVERRIDE; | 51 desc->setFamilyName(fFamilyName.c_str()); |
52 desc->setFontFileName(this->getUniqueString()); | |
53 *isLocalStream = !this->isSysFont(); | |
54 } | |
253 | 55 |
254 private: | 56 private: |
255 FamilyRec* fFamilyRec; // we don't own this, just point to it | 57 bool fIsSysFont; |
256 bool fIsSysFont; | 58 SkString fFamilyName; |
257 | 59 |
258 typedef SkTypeface_FreeType INHERITED; | 60 typedef SkTypeface_FreeType INHERITED; |
259 }; | 61 }; |
260 | 62 |
261 /////////////////////////////////////////////////////////////////////////////// | |
262 | |
263 /* This subclass is just a place holder for when we have no fonts available. | |
264 It exists so that our globals (e.g. gFamilyHead) that expect *something* | |
265 will not be null. | |
266 */ | |
267 class EmptyTypeface : public FamilyTypeface { | 63 class EmptyTypeface : public FamilyTypeface { |
268 public: | 64 public: |
269 EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {} | 65 EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, false, SkString()) {} |
270 | 66 |
271 virtual const char* getUniqueString() SK_OVERRIDE const { return NULL; } | 67 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } |
272 | 68 |
273 protected: | 69 protected: |
274 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } | 70 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } |
275 | 71 |
276 private: | 72 private: |
277 typedef FamilyTypeface INHERITED; | 73 typedef FamilyTypeface INHERITED; |
278 }; | 74 }; |
279 | 75 |
280 class StreamTypeface : public FamilyTypeface { | 76 class StreamTypeface : public FamilyTypeface { |
281 public: | 77 public: |
282 StreamTypeface(Style style, bool sysFont, FamilyRec* family, | 78 StreamTypeface(Style style, bool sysFont, SkStream* stream, bool isFixedPitc h, const SkString familyName) |
283 SkStream* stream, bool isFixedPitch) | 79 : INHERITED(style, sysFont, isFixedPitch, familyName) |
284 : INHERITED(style, sysFont, family, isFixedPitch) { | 80 , fStream(SkRef(stream)) |
285 stream->ref(); | 81 { } |
286 fStream = stream; | |
287 } | |
288 virtual ~StreamTypeface() { | |
289 fStream->unref(); | |
290 } | |
291 | 82 |
292 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } | 83 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } |
293 | 84 |
294 protected: | 85 protected: |
295 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | 86 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { |
296 *ttcIndex = 0; | 87 *ttcIndex = 0; |
297 fStream->ref(); | 88 return SkRef(fStream.get()); |
298 return fStream; | |
299 } | 89 } |
300 | 90 |
301 private: | 91 private: |
302 SkStream* fStream; | 92 SkAutoTUnref<SkStream> fStream; |
303 | 93 |
304 typedef FamilyTypeface INHERITED; | 94 typedef FamilyTypeface INHERITED; |
305 }; | 95 }; |
306 | 96 |
307 class FileTypeface : public FamilyTypeface { | 97 class FileTypeface : public FamilyTypeface { |
308 public: | 98 public: |
309 FileTypeface(Style style, bool sysFont, FamilyRec* family, | 99 FileTypeface(Style style, bool sysFont, const char path[], bool isFixedPitch , const SkString familyName) |
310 const char path[], bool isFixedPitch) | 100 : INHERITED(style, sysFont, isFixedPitch, familyName) |
311 : INHERITED(style, sysFont, family, isFixedPitch) { | 101 , fPath(path) |
312 fPath.set(path); | 102 { } |
313 } | |
314 | 103 |
315 virtual const char* getUniqueString() const SK_OVERRIDE { | 104 virtual const char* getUniqueString() const SK_OVERRIDE { |
316 const char* str = strrchr(fPath.c_str(), '/'); | 105 const char* str = strrchr(fPath.c_str(), '/'); |
317 if (str) { | 106 if (str) { |
318 str += 1; // skip the '/' | 107 str += 1; // skip the '/' |
319 } | 108 } |
320 return str; | 109 return str; |
321 } | 110 } |
322 | 111 |
323 protected: | 112 protected: |
324 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { | 113 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { |
325 *ttcIndex = 0; | 114 *ttcIndex = 0; |
326 return SkStream::NewFromFile(fPath.c_str()); | 115 return SkStream::NewFromFile(fPath.c_str()); |
327 } | 116 } |
328 | 117 |
329 private: | 118 private: |
330 SkString fPath; | 119 SkString fPath; |
331 | 120 |
332 typedef FamilyTypeface INHERITED; | 121 typedef FamilyTypeface INHERITED; |
333 }; | 122 }; |
334 | 123 |
335 /////////////////////////////////////////////////////////////////////////////// | 124 /////////////////////////////////////////////////////////////////////////////// |
336 /////////////////////////////////////////////////////////////////////////////// | 125 /////////////////////////////////////////////////////////////////////////////// |
337 | 126 |
338 static bool get_name_and_style(const char path[], SkString* name, | 127 class SkFontStyleSet_Custom : public SkFontStyleSet { |
reed1
2013/11/08 21:24:39
/*
* SkFontStyleSet_Custom
*
* ????
*/
bungeman-skia
2013/11/08 22:27:05
Added a number of comments. Done.
| |
339 SkTypeface::Style* style, bool* isFixedPitch) { | 128 public: |
340 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | 129 SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } |
341 if (stream.get()) { | 130 |
342 return find_name_and_attributes(stream, name, style, isFixedPitch); | 131 virtual int count() SK_OVERRIDE { |
343 } else { | 132 return fStyles.count(); |
344 SkDebugf("---- failed to open <%s> as a font\n", path); | 133 } |
345 return false; | 134 |
346 } | 135 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE { |
347 } | 136 SkASSERT(index < fStyles.count()); |
348 | 137 bool bold = fStyles[index]->isBold(); |
349 // these globals are assigned (once) by load_system_fonts() | 138 bool italic = fStyles[index]->isItalic(); |
350 static SkTypeface* gFallBackTypeface; | 139 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNo rmal_Weight, |
351 static FamilyRec* gDefaultFamily; | 140 SkFontStyle::kNormal_Width, |
352 static SkTypeface* gDefaultNormal; | 141 italic ? SkFontStyle::kItalic_Slant : SkFontStyle:: kUpright_Slant); |
353 | 142 name->reset(); |
354 static void load_directory_fonts(const SkString& directory, unsigned int* count) { | 143 } |
355 SkOSFile::Iter iter(directory.c_str(), ".ttf"); | 144 |
356 SkString name; | 145 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { |
357 | 146 SkASSERT(index < fStyles.count()); |
358 while (iter.next(&name, false)) { | 147 return SkRef(fStyles[index].get()); |
359 SkString filename(directory); | 148 } |
360 filename.append(name); | 149 |
150 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) { | |
151 int score = 0; | |
152 score += (pattern.width() - candidate.width()) * 100; | |
153 score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; | |
154 score += pattern.weight() - candidate.weight(); | |
155 return score; | |
156 } | |
157 | |
158 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { | |
159 if (0 == fStyles.count()) { | |
160 return NULL; | |
161 } | |
162 | |
163 FamilyTypeface* closest = fStyles[0]; | |
164 int minScore = std::numeric_limits<int>::max(); | |
165 for (int i = 0; i < fStyles.count(); ++i) { | |
166 bool bold = fStyles[i]->isBold(); | |
167 bool italic = fStyles[i]->isItalic(); | |
168 SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight | |
169 : SkFontStyle::kNormal_Weight, | |
170 SkFontStyle::kNormal_Width, | |
171 italic ? SkFontStyle::kItalic_Slant | |
172 : SkFontStyle::kUpright_Slant ); | |
173 | |
174 int score = match_score(pattern, style); | |
175 if (score < minScore) { | |
176 closest = fStyles[i]; | |
177 minScore = score; | |
178 } | |
179 } | |
180 return SkRef(closest); | |
181 } | |
182 | |
183 private: | |
184 SkTArray<SkAutoTUnref<FamilyTypeface>, true> fStyles; | |
185 SkString fFamilyName; | |
186 | |
187 void appendTypeface(FamilyTypeface* typeface) { | |
188 fStyles.push_back().reset(typeface); | |
189 } | |
190 | |
191 friend class SkFontMgr_Custom; | |
192 }; | |
193 | |
194 class SkFontMgr_Custom : public SkFontMgr { | |
195 public: | |
196 SkFontMgr_Custom(const char* dir) { | |
197 this->load_system_fonts(dir); | |
198 } | |
199 | |
200 protected: | |
201 virtual int onCountFamilies() SK_OVERRIDE { | |
202 return fFamily.count(); | |
203 } | |
204 | |
205 virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE { | |
206 SkASSERT(index < fFamily.count()); | |
207 familyName->set(fFamily[index]->fFamilyName); | |
208 } | |
209 | |
210 virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) SK_OVERRIDE { | |
211 SkASSERT(index < fFamily.count()); | |
212 return SkRef(fFamily[index].get()); | |
213 } | |
214 | |
215 virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) SK_OVE RRIDE { | |
216 for (int i = 0; i < fFamily.count(); ++i) { | |
217 if (fFamily[i]->fFamilyName.equals(familyName)) { | |
218 return SkRef(fFamily[i].get()); | |
219 } | |
220 } | |
221 return NULL; | |
222 } | |
223 | |
224 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], | |
225 const SkFontStyle& fontStyle) SK_OVER RIDE | |
226 { | |
227 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); | |
228 return sset->matchStyle(fontStyle); | |
229 } | |
230 | |
231 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, | |
232 const SkFontStyle& fontStyle) SK_OVERRI DE | |
233 { | |
234 for (int i = 0; i < fFamily.count(); ++i) { | |
235 for (int j = 0; j < fFamily[i]->fStyles.count(); ++j) { | |
236 if (fFamily[i]->fStyles[j] == familyMember) { | |
237 return fFamily[i]->matchStyle(fontStyle); | |
238 } | |
239 } | |
240 } | |
241 return NULL; | |
242 } | |
243 | |
244 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE { | |
245 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); | |
246 return this->createFromStream(stream, ttcIndex); | |
247 } | |
248 | |
249 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OV ERRIDE { | |
250 if (NULL == stream || stream->getLength() <= 0) { | |
251 SkDELETE(stream); | |
252 return NULL; | |
253 } | |
361 | 254 |
362 bool isFixedPitch; | 255 bool isFixedPitch; |
363 SkString realname; | 256 SkTypeface::Style style; |
364 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized wa rning | 257 SkString name; |
365 | 258 if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) { |
366 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPit ch)) { | 259 return SkNEW_ARGS(StreamTypeface, (style, false, stream, isFixedPitc h, name)); |
367 SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); | 260 } else { |
368 continue; | 261 return NULL; |
369 } | 262 } |
370 | 263 } |
371 FamilyRec* family = find_familyrec(realname.c_str()); | 264 |
372 if (family && family->fFaces[style]) { | 265 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVE RRIDE { |
373 continue; | 266 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
374 } | 267 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; |
375 | 268 } |
376 // this constructor puts us into the global gFamilyHead llist | 269 |
377 FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, | 270 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], |
378 (style, | 271 unsigned styleBits) SK_OVERRIDE |
379 true, // system-font (cannot delete) | 272 { |
380 family, // what family to join | 273 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; |
381 filename.c_str(), | 274 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold |
382 isFixedPitch) // filename | 275 ? SkFontStyle::kBold_Weight |
383 ); | 276 : SkFontStyle::kNormal_Weight, |
384 | 277 SkFontStyle::kNormal_Width, |
385 if (NULL == family) { | 278 oldStyle & SkTypeface::kItalic |
386 add_name(realname.c_str(), tf->getFamily()); | 279 ? SkFontStyle::kItalic_Slant |
387 } | 280 : SkFontStyle::kUpright_Slant); |
388 *count += 1; | 281 SkTypeface* tf = NULL; |
389 } | 282 |
390 | 283 if (NULL != familyName) { |
391 SkOSFile::Iter dirIter(directory.c_str()); | 284 tf = this->onMatchFamilyStyle(familyName, style); |
392 while (dirIter.next(&name, true)) { | 285 } |
393 if (name.startsWith(".")) { | 286 |
394 continue; | 287 if (NULL == tf) { |
395 } | 288 tf = gDefaultFamily->matchStyle(style); |
396 SkString dirname(directory); | 289 } |
397 dirname.append(name); | 290 |
398 dirname.append(SK_FONT_FILE_DIR_SEPERATOR); | 291 return SkSafeRef(tf); |
399 load_directory_fonts(dirname, count); | 292 } |
400 } | 293 |
401 } | 294 private: |
402 | 295 |
403 static void load_system_fonts() { | 296 static bool get_name_and_style(const char path[], SkString* name, |
404 // check if we've already be called | 297 SkTypeface::Style* style, bool* isFixedPitch) { |
405 if (NULL != gDefaultNormal) { | 298 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
406 return; | 299 if (stream.get()) { |
407 } | 300 return find_name_and_attributes(stream, name, style, isFixedPitch); |
408 | 301 } else { |
409 SkString baseDirectory(SK_FONT_FILE_PREFIX); | 302 SkDebugf("---- failed to open <%s> as a font\n", path); |
410 unsigned int count = 0; | 303 return false; |
411 load_directory_fonts(baseDirectory, &count); | 304 } |
412 | 305 } |
413 if (0 == count) { | 306 |
414 SkNEW(EmptyTypeface); | 307 void load_directory_fonts(const SkString& directory) { |
415 } | 308 SkOSFile::Iter iter(directory.c_str(), ".ttf"); |
416 | 309 SkString name; |
417 // do this after all fonts are loaded. This is our default font, and it | 310 |
418 // acts as a sentinel so we only execute load_system_fonts() once | 311 while (iter.next(&name, false)) { |
419 static const char* gDefaultNames[] = { | 312 SkString filename(directory); |
420 "Arial", "Verdana", "Times New Roman", NULL | 313 filename.append(name); |
421 }; | 314 |
422 const char** names = gDefaultNames; | 315 bool isFixedPitch; |
423 while (*names) { | 316 SkString realname; |
424 SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); | 317 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialize d warning |
425 if (tf) { | 318 |
319 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixe dPitch)) { | |
320 SkDebugf("------ can't load <%s> as a font\n", filename.c_str()) ; | |
321 continue; | |
322 } | |
323 | |
324 FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, ( | |
325 style, | |
326 true, // system-font (cannot de lete) | |
327 filename.c_str(), | |
328 isFixedPitch, | |
329 realname)); | |
330 | |
331 SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str()) ; | |
332 if (NULL == addTo) { | |
333 addTo = new SkFontStyleSet_Custom(realname); | |
334 fFamily.push_back().reset(addTo); | |
335 } | |
336 addTo->appendTypeface(tf); | |
337 } | |
338 | |
339 SkOSFile::Iter dirIter(directory.c_str()); | |
340 while (dirIter.next(&name, true)) { | |
341 if (name.startsWith(".")) { | |
342 continue; | |
343 } | |
344 SkString dirname(directory); | |
345 dirname.append(name); | |
346 dirname.append(SK_FONT_FILE_DIR_SEPERATOR); | |
347 load_directory_fonts(dirname); | |
348 } | |
349 } | |
350 | |
351 void load_system_fonts(const char* dir) { | |
352 SkString baseDirectory(dir); | |
353 load_directory_fonts(baseDirectory); | |
354 | |
355 if (fFamily.empty()) { | |
356 SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString() ); | |
357 fFamily.push_back().reset(family); | |
358 family->appendTypeface(SkNEW(EmptyTypeface)); | |
359 } | |
360 | |
361 // Try to pick a default font. | |
362 static const char* gDefaultNames[] = { | |
363 "Arial", "Verdana", "Times New Roman", NULL | |
364 }; | |
365 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { | |
366 SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]); | |
367 if (NULL == set) { | |
368 continue; | |
369 } | |
370 | |
371 SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_We ight, | |
372 SkFontStyle::kNormal_Wi dth, | |
373 SkFontStyle::kUpright_S lant)); | |
374 if (NULL == tf) { | |
375 continue; | |
376 } | |
377 | |
378 gDefaultFamily = set; | |
426 gDefaultNormal = tf; | 379 gDefaultNormal = tf; |
427 break; | 380 break; |
428 } | 381 } |
429 } | 382 if (NULL == gDefaultNormal) { |
430 // check if we found *something* | 383 gDefaultFamily = fFamily[0]; |
431 if (NULL == gDefaultNormal) { | 384 gDefaultNormal = gDefaultFamily->fStyles[0]; |
432 if (NULL == gFamilyHead) { | 385 } |
433 sk_throw(); | 386 } |
434 } | 387 |
435 for (int i = 0; i < 4; i++) { | 388 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamily; |
436 if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { | 389 SkFontStyleSet_Custom* gDefaultFamily; |
437 break; | 390 SkTypeface* gDefaultNormal; |
438 } | 391 }; |
439 } | 392 |
440 } | 393 SkFontMgr* SkFontMgr::Factory() { |
441 if (NULL == gDefaultNormal) { | 394 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX); |
442 sk_throw(); | |
443 } | |
444 gFallBackTypeface = gDefaultNormal; | |
445 gDefaultFamily = find_family(gDefaultNormal); | |
446 } | 395 } |
447 | |
448 /////////////////////////////////////////////////////////////////////////////// | |
449 | |
450 void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | |
451 bool* isLocalStream) const { | |
452 desc->setFamilyName(find_family_name(this)); | |
453 desc->setFontFileName(this->getUniqueString()); | |
454 *isLocalStream = !this->isSysFont(); | |
455 } | |
456 | |
457 static SkTypeface* create_typeface(const SkTypeface* familyFace, | |
458 const char familyName[], | |
459 SkTypeface::Style style) { | |
460 load_system_fonts(); | |
461 | |
462 SkAutoMutexAcquire ac(gFamilyMutex); | |
463 | |
464 // clip to legal style bits | |
465 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); | |
466 | |
467 SkTypeface* tf = NULL; | |
468 | |
469 if (NULL != familyFace) { | |
470 tf = find_typeface(familyFace, style); | |
471 } else if (NULL != familyName) { | |
472 // SkDebugf("======= familyName <%s>\n", familyName); | |
473 tf = find_typeface(familyName, style); | |
474 } | |
475 | |
476 if (NULL == tf) { | |
477 tf = find_best_face(gDefaultFamily, style); | |
478 } | |
479 | |
480 SkSafeRef(tf); | |
481 return tf; | |
482 } | |
483 | |
484 SkTypeface* FamilyTypeface::onRefMatchingStyle(Style style) const { | |
485 return create_typeface(this, NULL, style); | |
486 } | |
487 | |
488 /////////////////////////////////////////////////////////////////////////////// | |
489 | |
490 #ifndef SK_FONTHOST_USES_FONTMGR | |
491 | |
492 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, | |
493 const char familyName[], | |
494 SkTypeface::Style style) { | |
495 return create_typeface(familyFace, NULL, style); | |
496 } | |
497 | |
498 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { | |
499 if (NULL == stream || stream->getLength() <= 0) { | |
500 SkDELETE(stream); | |
501 return NULL; | |
502 } | |
503 | |
504 bool isFixedPitch; | |
505 SkTypeface::Style style; | |
506 if (find_name_and_attributes(stream, NULL, &style, &isFixedPitch)) { | |
507 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedPi tch)); | |
508 } else { | |
509 return NULL; | |
510 } | |
511 } | |
512 | |
513 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { | |
514 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | |
515 return stream.get() ? CreateTypefaceFromStream(stream) : NULL; | |
516 } | |
517 | |
518 #endif | |
519 | |
520 /////////////////////////////////////////////////////////////////////////////// | |
521 | |
522 #include "SkFontMgr.h" | |
523 | |
524 SkFontMgr* SkFontMgr::Factory() { | |
525 // todo | |
526 return NULL; | |
527 } | |
OLD | NEW |