gfx/skia/trunk/src/ports/SkFontHost_android_old.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:150de64e47ec
1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkFontDescriptor.h"
11 #include "SkFontHost.h"
12 #include "SkFontHost_FreeType_common.h"
13 #include "SkDescriptor.h"
14 #include "SkStream.h"
15 #include "SkPaint.h"
16 #include "SkString.h"
17 #include "SkStream.h"
18 #include "SkThread.h"
19 #include "SkTSearch.h"
20 #include <stdio.h>
21
22 #define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
23
24 #ifndef SK_FONT_FILE_PREFIX
25 #define SK_FONT_FILE_PREFIX "/fonts/"
26 #endif
27
28 bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style,
29 bool* isFixedWidth);
30
31 static void GetFullPathForSysFonts(SkString* full, const char name[]) {
32 full->set(getenv("ANDROID_ROOT"));
33 full->append(SK_FONT_FILE_PREFIX);
34 full->append(name);
35 }
36
37 ///////////////////////////////////////////////////////////////////////////////
38
39 struct FamilyRec;
40
41 /* This guy holds a mapping of a name -> family, used for looking up fonts.
42 Since it is stored in a stretchy array that doesn't preserve object
43 semantics, we don't use constructor/destructors, but just have explicit
44 helpers to manage our internal bookkeeping.
45 */
46 struct NameFamilyPair {
47 const char* fName; // we own this
48 FamilyRec* fFamily; // we don't own this, we just reference it
49
50 void construct(const char name[], FamilyRec* family) {
51 fName = strdup(name);
52 fFamily = family; // we don't own this, so just record the referene
53 }
54
55 void destruct() {
56 free((char*)fName);
57 // we don't own family, so just ignore our reference
58 }
59 };
60
61 // we use atomic_inc to grow this for each typeface we create
62 static int32_t gUniqueFontID;
63
64 // this is the mutex that protects these globals
65 static SkMutex gFamilyMutex;
66 static FamilyRec* gFamilyHead;
67 static SkTDArray<NameFamilyPair> gNameList;
68
69 struct FamilyRec {
70 FamilyRec* fNext;
71 SkTypeface* fFaces[4];
72
73 FamilyRec()
74 {
75 fNext = gFamilyHead;
76 memset(fFaces, 0, sizeof(fFaces));
77 gFamilyHead = this;
78 }
79 };
80
81 static SkTypeface* find_best_face(const FamilyRec* family,
82 SkTypeface::Style style) {
83 SkTypeface* const* faces = family->fFaces;
84
85 if (faces[style] != NULL) { // exact match
86 return faces[style];
87 }
88 // look for a matching bold
89 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
90 if (faces[style] != NULL) {
91 return faces[style];
92 }
93 // look for the plain
94 if (faces[SkTypeface::kNormal] != NULL) {
95 return faces[SkTypeface::kNormal];
96 }
97 // look for anything
98 for (int i = 0; i < 4; i++) {
99 if (faces[i] != NULL) {
100 return faces[i];
101 }
102 }
103 // should never get here, since the faces list should not be empty
104 SkASSERT(!"faces list is empty");
105 return NULL;
106 }
107
108 static FamilyRec* find_family(const SkTypeface* member) {
109 FamilyRec* curr = gFamilyHead;
110 while (curr != NULL) {
111 for (int i = 0; i < 4; i++) {
112 if (curr->fFaces[i] == member) {
113 return curr;
114 }
115 }
116 curr = curr->fNext;
117 }
118 return NULL;
119 }
120
121 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt
122 is not modified.
123 */
124 static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
125 FamilyRec* curr = gFamilyHead;
126 while (curr != NULL) {
127 for (int i = 0; i < 4; i++) {
128 SkTypeface* face = curr->fFaces[i];
129 if (face != NULL && face->uniqueID() == uniqueID) {
130 return face;
131 }
132 }
133 curr = curr->fNext;
134 }
135 return NULL;
136 }
137
138 /* Remove reference to this face from its family. If the resulting family
139 is empty (has no faces), return that family, otherwise return NULL
140 */
141 static FamilyRec* remove_from_family(const SkTypeface* face) {
142 FamilyRec* family = find_family(face);
143 SkASSERT(family->fFaces[face->style()] == face);
144 family->fFaces[face->style()] = NULL;
145
146 for (int i = 0; i < 4; i++) {
147 if (family->fFaces[i] != NULL) { // family is non-empty
148 return NULL;
149 }
150 }
151 return family; // return the empty family
152 }
153
154 // maybe we should make FamilyRec be doubly-linked
155 static void detach_and_delete_family(FamilyRec* family) {
156 FamilyRec* curr = gFamilyHead;
157 FamilyRec* prev = NULL;
158
159 while (curr != NULL) {
160 FamilyRec* next = curr->fNext;
161 if (curr == family) {
162 if (prev == NULL) {
163 gFamilyHead = next;
164 } else {
165 prev->fNext = next;
166 }
167 SkDELETE(family);
168 return;
169 }
170 prev = curr;
171 curr = next;
172 }
173 SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
174 }
175
176 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
177 NameFamilyPair* list = gNameList.begin();
178 int count = gNameList.count();
179
180 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
181
182 if (index >= 0) {
183 return find_best_face(list[index].fFamily, style);
184 }
185 return NULL;
186 }
187
188 static SkTypeface* find_typeface(const SkTypeface* familyMember,
189 SkTypeface::Style style) {
190 const FamilyRec* family = find_family(familyMember);
191 return family ? find_best_face(family, style) : NULL;
192 }
193
194 static void add_name(const char name[], FamilyRec* family) {
195 SkAutoAsciiToLC tolc(name);
196 name = tolc.lc();
197
198 NameFamilyPair* list = gNameList.begin();
199 int count = gNameList.count();
200
201 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
202
203 if (index < 0) {
204 list = gNameList.insert(~index);
205 list->construct(name, family);
206 }
207 }
208
209 static void remove_from_names(FamilyRec* emptyFamily)
210 {
211 #ifdef SK_DEBUG
212 for (int i = 0; i < 4; i++) {
213 SkASSERT(emptyFamily->fFaces[i] == NULL);
214 }
215 #endif
216
217 SkTDArray<NameFamilyPair>& list = gNameList;
218
219 // must go backwards when removing
220 for (int i = list.count() - 1; i >= 0; --i) {
221 NameFamilyPair* pair = &list[i];
222 if (pair->fFamily == emptyFamily) {
223 pair->destruct();
224 list.remove(i);
225 }
226 }
227 }
228
229 ///////////////////////////////////////////////////////////////////////////////
230
231 class FamilyTypeface : public SkTypeface_FreeType {
232 public:
233 FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember,
234 bool isFixedWidth)
235 : SkTypeface_FreeType(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
236 fIsSysFont = sysFont;
237
238 SkAutoMutexAcquire ac(gFamilyMutex);
239
240 FamilyRec* rec = NULL;
241 if (familyMember) {
242 rec = find_family(familyMember);
243 SkASSERT(rec);
244 } else {
245 rec = SkNEW(FamilyRec);
246 }
247 rec->fFaces[style] = this;
248 }
249
250 virtual ~FamilyTypeface() {
251 SkAutoMutexAcquire ac(gFamilyMutex);
252
253 // remove us from our family. If the family is now empty, we return
254 // that and then remove that family from the name list
255 FamilyRec* family = remove_from_family(this);
256 if (NULL != family) {
257 remove_from_names(family);
258 detach_and_delete_family(family);
259 }
260 }
261
262 bool isSysFont() const { return fIsSysFont; }
263
264 virtual const char* getUniqueString() const = 0;
265 virtual const char* getFilePath() const = 0;
266
267 protected:
268 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
269
270 private:
271 bool fIsSysFont;
272
273 typedef SkTypeface INHERITED;
274 };
275
276 ///////////////////////////////////////////////////////////////////////////////
277
278 class StreamTypeface : public FamilyTypeface {
279 public:
280 StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
281 SkStream* stream, bool isFixedWidth)
282 : INHERITED(style, sysFont, familyMember, isFixedWidth) {
283 SkASSERT(stream);
284 stream->ref();
285 fStream = stream;
286 }
287 virtual ~StreamTypeface() {
288 fStream->unref();
289 }
290
291 // overrides
292 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
293 *ttcIndex = 0;
294 // we just ref our existing stream, since the caller will call unref()
295 // when they are through
296 fStream->ref();
297 // must rewind each time, since the caller assumes a "new" stream
298 fStream->rewind();
299 return fStream;
300 }
301 virtual const char* getUniqueString() const { return NULL; }
302 virtual const char* getFilePath() const { return NULL; }
303
304 private:
305 SkStream* fStream;
306
307 typedef FamilyTypeface INHERITED;
308 };
309
310 class FileTypeface : public FamilyTypeface {
311 public:
312 FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
313 const char path[], bool isFixedWidth)
314 : INHERITED(style, sysFont, familyMember, isFixedWidth) {
315 SkString fullpath;
316
317 if (sysFont) {
318 GetFullPathForSysFonts(&fullpath, path);
319 path = fullpath.c_str();
320 }
321 fPath.set(path);
322 }
323
324 // overrides
325 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
326 *ttcIndex = 0;
327 SkStream* stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
328
329 // check for failure
330 if (stream->getLength() <= 0) {
331 SkDELETE(stream);
332 stream = NULL;
333 }
334 return stream;
335 }
336 virtual const char* getUniqueString() const {
337 const char* str = strrchr(fPath.c_str(), '/');
338 if (str) {
339 str += 1; // skip the '/'
340 }
341 return str;
342 }
343 virtual const char* getFilePath() const {
344 return fPath.c_str();
345 }
346
347 private:
348 SkString fPath;
349
350 typedef FamilyTypeface INHERITED;
351 };
352
353 ///////////////////////////////////////////////////////////////////////////////
354 ///////////////////////////////////////////////////////////////////////////////
355
356 static bool get_name_and_style(const char path[], SkString* name,
357 SkTypeface::Style* style,
358 bool* isFixedWidth, bool isExpected) {
359 SkString fullpath;
360 GetFullPathForSysFonts(&fullpath, path);
361
362 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(fullpath.c_str()));
363 if (stream.get()) {
364 find_name_and_attributes(stream, name, style, isFixedWidth);
365 return true;
366 }
367
368 if (isExpected) {
369 SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
370 }
371 return false;
372 }
373
374 // used to record our notion of the pre-existing fonts
375 struct FontInitRec {
376 const char* fFileName;
377 const char* const* fNames; // null-terminated list
378 };
379
380 static const char* gSansNames[] = {
381 "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
382 };
383
384 static const char* gSerifNames[] = {
385 "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
386 "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
387 };
388
389 static const char* gMonoNames[] = {
390 "monospace", "courier", "courier new", "monaco", NULL
391 };
392
393 // deliberately empty, but we use the address to identify fallback fonts
394 static const char* gFBNames[] = { NULL };
395
396 /* Fonts must be grouped by family, with the first font in a family having the
397 list of names (even if that list is empty), and the following members having
398 null for the list. The names list must be NULL-terminated
399 */
400 static const FontInitRec gSystemFonts[] = {
401 { "DroidSans.ttf", gSansNames },
402 { "DroidSans-Bold.ttf", NULL },
403 { "DroidSerif-Regular.ttf", gSerifNames },
404 { "DroidSerif-Bold.ttf", NULL },
405 { "DroidSerif-Italic.ttf", NULL },
406 { "DroidSerif-BoldItalic.ttf", NULL },
407 { "DroidSansMono.ttf", gMonoNames },
408 /* These are optional, and can be ignored if not found in the file system.
409 These are appended to gFallbackFonts[] as they are seen, so we list
410 them in the order we want them to be accessed by NextLogicalFont().
411 */
412 { "DroidSansArabic.ttf", gFBNames },
413 { "DroidSansHebrew.ttf", gFBNames },
414 { "DroidSansThai.ttf", gFBNames },
415 { "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font
416 { "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font
417 { "DroidSansJapanese.ttf", gFBNames },
418 { "DroidSansFallback.ttf", gFBNames }
419 };
420
421 #define DEFAULT_NAMES gSansNames
422
423 // these globals are assigned (once) by load_system_fonts()
424 static FamilyRec* gDefaultFamily;
425 static SkTypeface* gDefaultNormal;
426
427 /* This is sized conservatively, assuming that it will never be a size issue.
428 It will be initialized in load_system_fonts(), and will be filled with the
429 fontIDs that can be used for fallback consideration, in sorted order (sorted
430 meaning element[0] should be used first, then element[1], etc. When we hit
431 a fontID==0 in the array, the list is done, hence our allocation size is
432 +1 the total number of possible system fonts. Also see NextLogicalFont().
433 */
434 static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
435
436 /* Called once (ensured by the sentinel check at the beginning of our body).
437 Initializes all the globals, and register the system fonts.
438 */
439 static void load_system_fonts() {
440 // check if we've already be called
441 if (NULL != gDefaultNormal) {
442 return;
443 }
444
445 const FontInitRec* rec = gSystemFonts;
446 SkTypeface* firstInFamily = NULL;
447 int fallbackCount = 0;
448
449 for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
450 // if we're the first in a new family, clear firstInFamily
451 if (rec[i].fNames != NULL) {
452 firstInFamily = NULL;
453 }
454
455 bool isFixedWidth;
456 SkString name;
457 SkTypeface::Style style;
458
459 // we expect all the fonts, except the "fallback" fonts
460 bool isExpected = (rec[i].fNames != gFBNames);
461 if (!get_name_and_style(rec[i].fFileName, &name, &style,
462 &isFixedWidth, isExpected)) {
463 continue;
464 }
465
466 SkTypeface* tf = SkNEW_ARGS(FileTypeface,
467 (style,
468 true, // system-font (cannot delete)
469 firstInFamily, // what family to join
470 rec[i].fFileName,
471 isFixedWidth) // filename
472 );
473
474 if (rec[i].fNames != NULL) {
475 // see if this is one of our fallback fonts
476 if (rec[i].fNames == gFBNames) {
477 // SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
478 // rec[i].fFileName, fallbackCount, tf->uniqueID());
479 gFallbackFonts[fallbackCount++] = tf->uniqueID();
480 }
481
482 firstInFamily = tf;
483 FamilyRec* family = find_family(tf);
484 const char* const* names = rec[i].fNames;
485
486 // record the default family if this is it
487 if (names == DEFAULT_NAMES) {
488 gDefaultFamily = family;
489 }
490 // add the names to map to this family
491 while (*names) {
492 add_name(*names, family);
493 names += 1;
494 }
495 }
496 }
497
498 // do this after all fonts are loaded. This is our default font, and it
499 // acts as a sentinel so we only execute load_system_fonts() once
500 gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
501 // now terminate our fallback list with the sentinel value
502 gFallbackFonts[fallbackCount] = 0;
503 }
504
505 void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
506 bool* isLocalStream) const {
507 {
508 SkAutoMutexAcquire ac(gFamilyMutex);
509 //desc->setFamilyName(find_family_name(this));
510 desc->setFontFileName(this->getUniqueString());
511 }
512 *isLocalStream = !this->isSysFont();
513 }
514
515 ///////////////////////////////////////////////////////////////////////////////
516
517 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
518 const char familyName[],
519 SkTypeface::Style style) {
520 load_system_fonts();
521
522 SkAutoMutexAcquire ac(gFamilyMutex);
523
524 // clip to legal style bits
525 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
526
527 SkTypeface* tf = NULL;
528
529 if (NULL != familyFace) {
530 tf = find_typeface(familyFace, style);
531 } else if (NULL != familyName) {
532 // SkDebugf("======= familyName <%s>\n", familyName);
533 tf = find_typeface(familyName, style);
534 }
535
536 if (NULL == tf) {
537 tf = find_best_face(gDefaultFamily, style);
538 }
539
540 // we ref(), since the symantic is to return a new instance
541 tf->ref();
542 return tf;
543 }
544
545 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
546 const SkPaintOptionsAndroid& options) {
547 load_system_fonts();
548
549 /* First see if fontID is already one of our fallbacks. If so, return
550 its successor. If fontID is not in our list, then return the first one
551 in our list. Note: list is zero-terminated, and returning zero means
552 we have no more fonts to use for fallbacks.
553 */
554 const uint32_t* list = gFallbackFonts;
555 for (int i = 0; list[i] != 0; i++) {
556 if (list[i] == currFontID) {
557 return find_from_uniqueID(list[i+1]);
558 }
559 }
560 return find_from_uniqueID(list[0]);
561 }
562
563 ///////////////////////////////////////////////////////////////////////////////
564
565 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
566 if (NULL == stream || stream->getLength() <= 0) {
567 return NULL;
568 }
569
570 bool isFixedWidth;
571 SkString name;
572 SkTypeface::Style style;
573 find_name_and_attributes(stream, &name, &style, &isFixedWidth);
574
575 if (!name.isEmpty()) {
576 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
577 } else {
578 return NULL;
579 }
580 }
581
582 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
583 SkStream* stream = SkNEW_ARGS(SkFILEStream, (path));
584 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
585 // since we created the stream, we let go of our ref() here
586 stream->unref();
587 return face;
588 }
589

mercurial