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

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
« no previous file with comments | « src/ports/SkFontHost_fontconfig.cpp ('k') | src/ports/SkFontHost_mac.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1
2 /* 1 /*
3 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
4 * 3 *
5 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
8 7
9
10 #include "SkFontHost.h" 8 #include "SkFontHost.h"
11 #include "SkFontHost_FreeType_common.h" 9 #include "SkFontHost_FreeType_common.h"
12 #include "SkFontDescriptor.h" 10 #include "SkFontDescriptor.h"
11 #include "SkFontMgr.h"
13 #include "SkDescriptor.h" 12 #include "SkDescriptor.h"
14 #include "SkOSFile.h" 13 #include "SkOSFile.h"
15 #include "SkPaint.h" 14 #include "SkPaint.h"
16 #include "SkString.h" 15 #include "SkString.h"
17 #include "SkStream.h" 16 #include "SkStream.h"
18 #include "SkThread.h" 17 #include "SkThread.h"
19 #include "SkTSearch.h" 18 #include "SkTSearch.h"
19 #include "SkTypefaceCache.h"
20 #include "SkTArray.h"
21
22 #include <limits>
20 23
21 #ifndef SK_FONT_FILE_PREFIX 24 #ifndef SK_FONT_FILE_PREFIX
22 #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" 25 # define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/"
23 #endif 26 #endif
24 #ifndef SK_FONT_FILE_DIR_SEPERATOR 27 #ifndef SK_FONT_FILE_DIR_SEPERATOR
25 #define SK_FONT_FILE_DIR_SEPERATOR "/" 28 # define SK_FONT_FILE_DIR_SEPERATOR "/"
26 #endif 29 #endif
27 30
28 bool find_name_and_attributes(SkStream* stream, SkString* name, 31 bool find_name_and_attributes(SkStream* stream, SkString* name,
29 SkTypeface::Style* style, bool* isFixedPitch); 32 SkTypeface::Style* style, bool* isFixedPitch);
30 33
31 /////////////////////////////////////////////////////////////////////////////// 34 ///////////////////////////////////////////////////////////////////////////////
32 35
33 struct FamilyRec; 36 /** The base SkTypeface implementation for the custom font manager. */
34 37 class SkTypeface_Custom : public SkTypeface_FreeType {
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 {
219 public: 38 public:
220 FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedPit ch) 39 SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkStri ng familyName)
221 : INHERITED(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedPitch) { 40 : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch)
222 fIsSysFont = sysFont; 41 , fIsSysFont(sysFont), fFamilyName(familyName)
223 42 { }
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 43
245 bool isSysFont() const { return fIsSysFont; } 44 bool isSysFont() const { return fIsSysFont; }
246 FamilyRec* getFamily() const { return fFamilyRec; }
247 45
248 virtual const char* getUniqueString() const = 0; 46 virtual const char* getUniqueString() const = 0;
249 47
250 protected: 48 protected:
251 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE ; 49 virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) cons t SK_OVERRIDE {
252 virtual SkTypeface* onRefMatchingStyle(Style styleBits) const SK_OVERRIDE; 50 desc->setFamilyName(fFamilyName.c_str());
51 desc->setFontFileName(this->getUniqueString());
52 *isLocal = !this->isSysFont();
53 }
253 54
254 private: 55 private:
255 FamilyRec* fFamilyRec; // we don't own this, just point to it 56 bool fIsSysFont;
256 bool fIsSysFont; 57 SkString fFamilyName;
257 58
258 typedef SkTypeface_FreeType INHERITED; 59 typedef SkTypeface_FreeType INHERITED;
259 }; 60 };
260 61
261 /////////////////////////////////////////////////////////////////////////////// 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()) {}
262 68
263 /* This subclass is just a place holder for when we have no fonts available. 69 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
264 It exists so that our globals (e.g. gFamilyHead) that expect *something*
265 will not be null.
266 */
267 class EmptyTypeface : public FamilyTypeface {
268 public:
269 EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {}
270
271 virtual const char* getUniqueString() SK_OVERRIDE const { return NULL; }
272 70
273 protected: 71 protected:
274 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } 72 virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; }
275 73
276 private: 74 private:
277 typedef FamilyTypeface INHERITED; 75 typedef SkTypeface_Custom INHERITED;
278 }; 76 };
279 77
280 class StreamTypeface : public FamilyTypeface { 78 /** The stream SkTypeface implementation for the custom font manager. */
79 class SkTypeface_Stream : public SkTypeface_Custom {
281 public: 80 public:
282 StreamTypeface(Style style, bool sysFont, FamilyRec* family, 81 SkTypeface_Stream(Style style, bool sysFont, SkStream* stream,
283 SkStream* stream, bool isFixedPitch) 82 bool isFixedPitch, const SkString familyName)
284 : INHERITED(style, sysFont, family, isFixedPitch) { 83 : INHERITED(style, sysFont, isFixedPitch, familyName)
285 stream->ref(); 84 , fStream(SkRef(stream))
286 fStream = stream; 85 { }
287 }
288 virtual ~StreamTypeface() {
289 fStream->unref();
290 }
291 86
292 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } 87 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; }
293 88
294 protected: 89 protected:
295 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 90 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
296 *ttcIndex = 0; 91 *ttcIndex = 0;
297 fStream->ref(); 92 return SkRef(fStream.get());
298 return fStream;
299 } 93 }
300 94
301 private: 95 private:
302 SkStream* fStream; 96 SkAutoTUnref<SkStream> fStream;
303 97
304 typedef FamilyTypeface INHERITED; 98 typedef SkTypeface_Custom INHERITED;
305 }; 99 };
306 100
307 class FileTypeface : public FamilyTypeface { 101 /** The file SkTypeface implementation for the custom font manager. */
102 class SkTypeface_File : public SkTypeface_Custom {
308 public: 103 public:
309 FileTypeface(Style style, bool sysFont, FamilyRec* family, 104 SkTypeface_File(Style style, bool sysFont, const char path[],
310 const char path[], bool isFixedPitch) 105 bool isFixedPitch, const SkString familyName)
311 : INHERITED(style, sysFont, family, isFixedPitch) { 106 : INHERITED(style, sysFont, isFixedPitch, familyName)
312 fPath.set(path); 107 , fPath(path)
313 } 108 { }
314 109
315 virtual const char* getUniqueString() const SK_OVERRIDE { 110 virtual const char* getUniqueString() const SK_OVERRIDE {
316 const char* str = strrchr(fPath.c_str(), '/'); 111 const char* str = strrchr(fPath.c_str(), '/');
317 if (str) { 112 if (str) {
318 str += 1; // skip the '/' 113 str += 1; // skip the '/'
319 } 114 }
320 return str; 115 return str;
321 } 116 }
322 117
323 protected: 118 protected:
324 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 119 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
325 *ttcIndex = 0; 120 *ttcIndex = 0;
326 return SkStream::NewFromFile(fPath.c_str()); 121 return SkStream::NewFromFile(fPath.c_str());
327 } 122 }
328 123
329 private: 124 private:
330 SkString fPath; 125 SkString fPath;
331 126
332 typedef FamilyTypeface INHERITED; 127 typedef SkTypeface_Custom INHERITED;
333 }; 128 };
334 129
335 /////////////////////////////////////////////////////////////////////////////// 130 ///////////////////////////////////////////////////////////////////////////////
336 /////////////////////////////////////////////////////////////////////////////// 131
337 132 /**
338 static bool get_name_and_style(const char path[], SkString* name, 133 * SkFontStyleSet_Custom
339 SkTypeface::Style* style, bool* isFixedPitch) { 134 *
340 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 135 * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families.
341 if (stream.get()) { 136 */
342 return find_name_and_attributes(stream, name, style, isFixedPitch); 137 class SkFontStyleSet_Custom : public SkFontStyleSet {
343 } else { 138 public:
344 SkDebugf("---- failed to open <%s> as a font\n", path); 139 SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { }
345 return false; 140
346 } 141 virtual int count() SK_OVERRIDE {
347 } 142 return fStyles.count();
348 143 }
349 // these globals are assigned (once) by load_system_fonts() 144
350 static SkTypeface* gFallBackTypeface; 145 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE {
351 static FamilyRec* gDefaultFamily; 146 SkASSERT(index < fStyles.count());
352 static SkTypeface* gDefaultNormal; 147 bool bold = fStyles[index]->isBold();
353 148 bool italic = fStyles[index]->isItalic();
354 static void load_directory_fonts(const SkString& directory, unsigned int* count) { 149 *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNo rmal_Weight,
355 SkOSFile::Iter iter(directory.c_str(), ".ttf"); 150 SkFontStyle::kNormal_Width,
356 SkString name; 151 italic ? SkFontStyle::kItalic_Slant : SkFontStyle:: kUpright_Slant);
357 152 name->reset();
358 while (iter.next(&name, false)) { 153 }
359 SkString filename(directory); 154
360 filename.append(name); 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& candid ate) {
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 SkFontMgr_Custom(const char* dir) {
214 this->load_system_fonts(dir);
215 }
216
217 protected:
218 virtual int onCountFamilies() SK_OVERRIDE {
219 return fFamilies.count();
220 }
221
222 virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
223 SkASSERT(index < fFamilies.count());
224 familyName->set(fFamilies[index]->fFamilyName);
225 }
226
227 virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) SK_OVERRIDE {
228 SkASSERT(index < fFamilies.count());
229 return SkRef(fFamilies[index].get());
230 }
231
232 virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) SK_OVE RRIDE {
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) SK_OVER RIDE
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) SK_OVERRI DE
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) 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) SK_OV ERRIDE {
267 if (NULL == stream || stream->getLength() <= 0) {
268 SkDELETE(stream);
269 return NULL;
270 }
361 271
362 bool isFixedPitch; 272 bool isFixedPitch;
363 SkString realname; 273 SkTypeface::Style style;
364 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized wa rning 274 SkString name;
365 275 if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) {
366 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPit ch)) { 276 return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedP itch, name));
367 SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); 277 } else {
368 continue; 278 return NULL;
369 } 279 }
370 280 }
371 FamilyRec* family = find_familyrec(realname.c_str()); 281
372 if (family && family->fFaces[style]) { 282 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVE RRIDE {
373 continue; 283 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
374 } 284 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
375 285 }
376 // this constructor puts us into the global gFamilyHead llist 286
377 FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, 287 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
378 (style, 288 unsigned styleBits) SK_OVERRIDE
379 true, // system-font (cannot delete) 289 {
380 family, // what family to join 290 SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits;
381 filename.c_str(), 291 SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold
382 isFixedPitch) // filename 292 ? SkFontStyle::kBold_Weight
383 ); 293 : SkFontStyle::kNormal_Weight,
384 294 SkFontStyle::kNormal_Width,
385 if (NULL == family) { 295 oldStyle & SkTypeface::kItalic
386 add_name(realname.c_str(), tf->getFamily()); 296 ? SkFontStyle::kItalic_Slant
387 } 297 : SkFontStyle::kUpright_Slant);
388 *count += 1; 298 SkTypeface* tf = NULL;
389 } 299
390 300 if (NULL != familyName) {
391 SkOSFile::Iter dirIter(directory.c_str()); 301 tf = this->onMatchFamilyStyle(familyName, style);
392 while (dirIter.next(&name, true)) { 302 }
393 if (name.startsWith(".")) { 303
394 continue; 304 if (NULL == tf) {
395 } 305 tf = gDefaultFamily->matchStyle(style);
396 SkString dirname(directory); 306 }
397 dirname.append(name); 307
398 dirname.append(SK_FONT_FILE_DIR_SEPERATOR); 308 return SkSafeRef(tf);
399 load_directory_fonts(dirname, count); 309 }
400 } 310
401 } 311 private:
402 312
403 static void load_system_fonts() { 313 static bool get_name_and_style(const char path[], SkString* name,
404 // check if we've already be called 314 SkTypeface::Style* style, bool* isFixedPitch) {
405 if (NULL != gDefaultNormal) { 315 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
406 return; 316 if (stream.get()) {
407 } 317 return find_name_and_attributes(stream, name, style, isFixedPitch);
408 318 } else {
409 SkString baseDirectory(SK_FONT_FILE_PREFIX); 319 SkDebugf("---- failed to open <%s> as a font\n", path);
410 unsigned int count = 0; 320 return false;
411 load_directory_fonts(baseDirectory, &count); 321 }
412 322 }
413 if (0 == count) { 323
414 SkNEW(EmptyTypeface); 324 void load_directory_fonts(const SkString& directory) {
415 } 325 SkOSFile::Iter iter(directory.c_str(), ".ttf");
416 326 SkString name;
417 // do this after all fonts are loaded. This is our default font, and it 327
418 // acts as a sentinel so we only execute load_system_fonts() once 328 while (iter.next(&name, false)) {
419 static const char* gDefaultNames[] = { 329 SkString filename(directory);
420 "Arial", "Verdana", "Times New Roman", NULL 330 filename.append(name);
421 }; 331
422 const char** names = gDefaultNames; 332 bool isFixedPitch;
423 while (*names) { 333 SkString realname;
424 SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); 334 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialize d warning
425 if (tf) { 335
336 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixe dPitch)) {
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 de lete)
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_We ight,
389 SkFontStyle::kNormal_Wi dth,
390 SkFontStyle::kUpright_S lant));
391 if (NULL == tf) {
392 continue;
393 }
394
395 gDefaultFamily = set;
426 gDefaultNormal = tf; 396 gDefaultNormal = tf;
427 break; 397 break;
428 } 398 }
429 } 399 if (NULL == gDefaultNormal) {
430 // check if we found *something* 400 gDefaultFamily = fFamilies[0];
431 if (NULL == gDefaultNormal) { 401 gDefaultNormal = gDefaultFamily->fStyles[0];
432 if (NULL == gFamilyHead) { 402 }
433 sk_throw(); 403 }
434 } 404
435 for (int i = 0; i < 4; i++) { 405 SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies;
436 if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { 406 SkFontStyleSet_Custom* gDefaultFamily;
437 break; 407 SkTypeface* gDefaultNormal;
438 } 408 };
439 } 409
440 } 410 SkFontMgr* SkFontMgr::Factory() {
441 if (NULL == gDefaultNormal) { 411 return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX);
442 sk_throw();
443 }
444 gFallBackTypeface = gDefaultNormal;
445 gDefaultFamily = find_family(gDefaultNormal);
446 } 412 }
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
« no previous file with comments | « src/ports/SkFontHost_fontconfig.cpp ('k') | src/ports/SkFontHost_mac.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698