Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/ports/SkFontHost_linux.cpp

Issue 66783003: Remove SK_FONTHOST_USES_FONTMGR. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698