1 /* libs/graphics/ports/SkFontHost_android.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkFontHost.h"
19 #include "SkGraphics.h"
20 #include "SkDescriptor.h"
21 #include "SkMMapStream.h"
22 #include "SkPaint.h"
23 #include "SkString.h"
24 #include "SkStream.h"
25 #include "SkThread.h"
26 #include "SkTSearch.h"
27 #include "FontHostConfiguration_android.h"
28 #include <stdio.h>
29 #include <string.h>
30
31 //#define SkDEBUGF(args ) SkDebugf args
32
33 #ifndef SK_FONT_FILE_PREFIX
34 #define SK_FONT_FILE_PREFIX "/fonts/"
35 #endif
36
37 // Defined in SkFontHost_FreeType.cpp
38 bool find_name_and_attributes(SkStream* stream, SkString* name,
39 SkTypeface::Style* style, bool* isFixedWidth);
40
getFullPathForSysFonts(SkString * full,const char name[])41 static void getFullPathForSysFonts(SkString* full, const char name[]) {
42 full->set(getenv("ANDROID_ROOT"));
43 full->append(SK_FONT_FILE_PREFIX);
44 full->append(name);
45 }
46
getNameAndStyle(const char path[],SkString * name,SkTypeface::Style * style,bool * isFixedWidth,bool isExpected)47 static bool getNameAndStyle(const char path[], SkString* name,
48 SkTypeface::Style* style,
49 bool* isFixedWidth, bool isExpected) {
50 SkString fullpath;
51 getFullPathForSysFonts(&fullpath, path);
52
53 SkMMAPStream stream(fullpath.c_str());
54 if (stream.getLength() > 0) {
55 return find_name_and_attributes(&stream, name, style, isFixedWidth);
56 }
57 else {
58 SkFILEStream stream(fullpath.c_str());
59 if (stream.getLength() > 0) {
60 return find_name_and_attributes(&stream, name, style, isFixedWidth);
61 }
62 }
63
64 if (isExpected) {
65 SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
66 }
67 return false;
68 }
69
70 static SkTypeface* deserializeLocked(SkStream* stream);
71 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace,
72 const char familyName[], const void* data, size_t bytelength,
73 SkTypeface::Style style);
74 static SkStream* openStreamLocked(uint32_t fontID);
75 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index);
76 static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID);
77 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream);
78
79 ///////////////////////////////////////////////////////////////////////////////
80
81 struct FamilyRec;
82
83 /* This guy holds a mapping of a name -> family, used for looking up fonts.
84 Since it is stored in a stretchy array that doesn't preserve object
85 semantics, we don't use constructor/destructors, but just have explicit
86 helpers to manage our internal bookkeeping.
87 */
88 struct NameFamilyPair {
89 const char* fName; // we own this
90 FamilyRec* fFamily; // we don't own this, we just reference it
91
constructNameFamilyPair92 void construct(const char name[], FamilyRec* family) {
93 fName = strdup(name);
94 fFamily = family; // we don't own this, so just record the reference
95 }
96
destructNameFamilyPair97 void destruct() {
98 free((char*)fName);
99 // we don't own family, so just ignore our reference
100 }
101 };
102 typedef SkTDArray<NameFamilyPair> NameFamilyPairList;
103
104 // we use atomic_inc to grow this for each typeface we create
105 static int32_t gUniqueFontID;
106
107 // this is the mutex that protects all of the global data structures in this module
108 // functions with the Locked() suffix must be called while holding this mutex
109 SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex);
110 static FamilyRec* gFamilyHead = NULL;
111 static SkTDArray<NameFamilyPair> gFallbackFilenameList;
112 static NameFamilyPairList gNameList;
113
114 struct FamilyRec {
115 FamilyRec* fNext;
116 SkTypeface* fFaces[4];
117
FamilyRecFamilyRec118 FamilyRec() : fNext(NULL) {
119 memset(fFaces, 0, sizeof(fFaces));
120 }
121 };
122
findBestFaceLocked(const FamilyRec * family,SkTypeface::Style style)123 static SkTypeface* findBestFaceLocked(const FamilyRec* family,
124 SkTypeface::Style style) {
125 SkTypeface* const* faces = family->fFaces;
126
127 if (faces[style] != NULL) { // exact match
128 return faces[style];
129 }
130 // look for a matching bold
131 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
132 if (faces[style] != NULL) {
133 return faces[style];
134 }
135 // look for the plain
136 if (faces[SkTypeface::kNormal] != NULL) {
137 return faces[SkTypeface::kNormal];
138 }
139 // look for anything
140 for (int i = 0; i < 4; i++) {
141 if (faces[i] != NULL) {
142 return faces[i];
143 }
144 }
145 // should never get here, since the faces list should not be empty
146 SkDEBUGFAIL("faces list is empty");
147 return NULL;
148 }
149
findFamilyLocked(const SkTypeface * member)150 static FamilyRec* findFamilyLocked(const SkTypeface* member) {
151 FamilyRec* curr = gFamilyHead;
152 while (curr != NULL) {
153 for (int i = 0; i < 4; i++) {
154 if (curr->fFaces[i] == member) {
155 return curr;
156 }
157 }
158 curr = curr->fNext;
159 }
160 return NULL;
161 }
162
163 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt
164 is not modified.
165 */
findFromUniqueIDLocked(uint32_t uniqueID)166 static SkTypeface* findFromUniqueIDLocked(uint32_t uniqueID) {
167 FamilyRec* curr = gFamilyHead;
168 while (curr != NULL) {
169 for (int i = 0; i < 4; i++) {
170 SkTypeface* face = curr->fFaces[i];
171 if (face != NULL && face->uniqueID() == uniqueID) {
172 return face;
173 }
174 }
175 curr = curr->fNext;
176 }
177 return NULL;
178 }
179
180 /* Remove reference to this face from its family. If the resulting family
181 is empty (has no faces), return that family, otherwise return NULL
182 */
removeFromFamilyLocked(const SkTypeface * face)183 static FamilyRec* removeFromFamilyLocked(const SkTypeface* face) {
184 FamilyRec* family = findFamilyLocked(face);
185 if (family) {
186 SkASSERT(family->fFaces[face->style()] == face);
187 family->fFaces[face->style()] = NULL;
188
189 for (int i = 0; i < 4; i++) {
190 if (family->fFaces[i] != NULL) { // family is non-empty
191 return NULL;
192 }
193 }
194 } else {
195 // SkDebugf("removeFromFamilyLocked(%p) face not found", face);
196 }
197 return family; // return the empty family
198 }
199
200 // maybe we should make FamilyRec be doubly-linked
detachAndDeleteFamilyLocked(FamilyRec * family)201 static void detachAndDeleteFamilyLocked(FamilyRec* family) {
202 FamilyRec* curr = gFamilyHead;
203 FamilyRec* prev = NULL;
204
205 while (curr != NULL) {
206 FamilyRec* next = curr->fNext;
207 if (curr == family) {
208 if (prev == NULL) {
209 gFamilyHead = next;
210 } else {
211 prev->fNext = next;
212 }
213 SkDELETE(family);
214 return;
215 }
216 prev = curr;
217 curr = next;
218 }
219 SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
220 }
221
findTypefaceLocked(const char name[],SkTypeface::Style style)222 static SkTypeface* findTypefaceLocked(const char name[], SkTypeface::Style style) {
223 int count = gNameList.count();
224 NameFamilyPair* list = gNameList.begin();
225 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
226 if (index >= 0) {
227 return findBestFaceLocked(list[index].fFamily, style);
228 }
229 return NULL;
230 }
231
findTypefaceLocked(const SkTypeface * familyMember,SkTypeface::Style style)232 static SkTypeface* findTypefaceLocked(const SkTypeface* familyMember,
233 SkTypeface::Style style) {
234 const FamilyRec* family = findFamilyLocked(familyMember);
235 return family ? findBestFaceLocked(family, style) : NULL;
236 }
237
addNameLocked(const char name[],FamilyRec * family)238 static void addNameLocked(const char name[], FamilyRec* family) {
239 SkAutoAsciiToLC tolc(name);
240 name = tolc.lc();
241
242 int count = gNameList.count();
243 NameFamilyPair* list = gNameList.begin();
244 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
245 if (index < 0) {
246 list = gNameList.insert(~index);
247 list->construct(name, family);
248 }
249 }
250
removeFromNamesLocked(FamilyRec * emptyFamily)251 static void removeFromNamesLocked(FamilyRec* emptyFamily) {
252 #ifdef SK_DEBUG
253 for (int i = 0; i < 4; i++) {
254 SkASSERT(emptyFamily->fFaces[i] == NULL);
255 }
256 #endif
257
258 // must go backwards when removing
259 for (int i = gNameList.count() - 1; i >= 0; --i) {
260 NameFamilyPair& pair = gNameList[i];
261 if (pair.fFamily == emptyFamily) {
262 pair.destruct();
263 gNameList.remove(i);
264 }
265 }
266 }
267
addTypefaceLocked(SkTypeface * typeface,SkTypeface * familyMember)268 static void addTypefaceLocked(SkTypeface* typeface, SkTypeface* familyMember) {
269 FamilyRec* rec = NULL;
270 if (familyMember) {
271 rec = findFamilyLocked(familyMember);
272 SkASSERT(rec);
273 } else {
274 rec = SkNEW(FamilyRec);
275 rec->fNext = gFamilyHead;
276 gFamilyHead = rec;
277 }
278 rec->fFaces[typeface->style()] = typeface;
279 }
280
removeTypeface(SkTypeface * typeface)281 static void removeTypeface(SkTypeface* typeface) {
282 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
283
284 // remove us from our family. If the family is now empty, we return
285 // that and then remove that family from the name list
286 FamilyRec* family = removeFromFamilyLocked(typeface);
287 if (NULL != family) {
288 removeFromNamesLocked(family);
289 detachAndDeleteFamilyLocked(family);
290 }
291 }
292
293 ///////////////////////////////////////////////////////////////////////////////
294
295 class FamilyTypeface : public SkTypeface {
296 protected:
FamilyTypeface(Style style,bool sysFont,bool isFixedWidth)297 FamilyTypeface(Style style, bool sysFont, bool isFixedWidth)
298 : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
299 fIsSysFont = sysFont;
300 }
301
302 public:
~FamilyTypeface()303 virtual ~FamilyTypeface() {
304 removeTypeface(this);
305 }
306
isSysFont() const307 bool isSysFont() const { return fIsSysFont; }
308
309 virtual SkStream* openStream() = 0;
310 virtual const char* getUniqueString() const = 0;
311 virtual const char* getFilePath() const = 0;
312
313 private:
314 bool fIsSysFont;
315
316 typedef SkTypeface INHERITED;
317 };
318
319 ///////////////////////////////////////////////////////////////////////////////
320
321 class StreamTypeface : public FamilyTypeface {
322 public:
StreamTypeface(Style style,bool sysFont,SkStream * stream,bool isFixedWidth)323 StreamTypeface(Style style, bool sysFont, SkStream* stream, bool isFixedWidth)
324 : INHERITED(style, sysFont, isFixedWidth) {
325 SkASSERT(stream);
326 stream->ref();
327 fStream = stream;
328 }
329
~StreamTypeface()330 virtual ~StreamTypeface() {
331 fStream->unref();
332 }
333
334 // overrides
openStream()335 virtual SkStream* openStream() {
336 // we just ref our existing stream, since the caller will call unref()
337 // when they are through
338 fStream->ref();
339 // must rewind each time, since the caller assumes a "new" stream
340 fStream->rewind();
341 return fStream;
342 }
getUniqueString() const343 virtual const char* getUniqueString() const { return NULL; }
getFilePath() const344 virtual const char* getFilePath() const { return NULL; }
345
346 private:
347 SkStream* fStream;
348
349 typedef FamilyTypeface INHERITED;
350 };
351
352 class FileTypeface : public FamilyTypeface {
353 public:
FileTypeface(Style style,bool sysFont,const char path[],bool isFixedWidth)354 FileTypeface(Style style, bool sysFont, const char path[], bool isFixedWidth)
355 : INHERITED(style, sysFont, isFixedWidth) {
356 fPath.set(path);
357 }
358
359 // overrides
openStream()360 virtual SkStream* openStream() {
361 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
362
363 // check for failure
364 if (stream->getLength() <= 0) {
365 SkDELETE(stream);
366 // maybe MMAP isn't supported. try FILE
367 stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
368 if (stream->getLength() <= 0) {
369 SkDELETE(stream);
370 stream = NULL;
371 }
372 }
373 return stream;
374 }
getUniqueString() const375 virtual const char* getUniqueString() const {
376 const char* str = strrchr(fPath.c_str(), '/');
377 if (str) {
378 str += 1; // skip the '/'
379 }
380 return str;
381 }
getFilePath() const382 virtual const char* getFilePath() const {
383 return fPath.c_str();
384 }
385
386 private:
387 SkString fPath;
388
389 typedef FamilyTypeface INHERITED;
390 };
391
392 ///////////////////////////////////////////////////////////////////////////////
393 ///////////////////////////////////////////////////////////////////////////////
394
395 // used to record our notion of the pre-existing fonts
396 struct FontInitRec {
397 const char* fFileName;
398 const char* const* fNames; // null-terminated list
399 };
400
401 // deliberately empty, but we use the address to identify fallback fonts
402 static const char* gFBNames[] = { NULL };
403
404
405 /* Fonts are grouped by family, with the first font in a family having the
406 list of names (even if that list is empty), and the following members having
407 null for the list. The names list must be NULL-terminated.
408 */
409 static SkTDArray<FontInitRec> gSystemFonts;
410 static SkTDArray<SkFontID> gFallbackFonts;
411
412 // these globals are assigned (once) by loadSystemFontsLocked()
413 static FamilyRec* gDefaultFamily = NULL;
414 static SkTypeface* gDefaultNormal = NULL;
415 static char** gDefaultNames = NULL;
416
dumpGlobalsLocked()417 static void dumpGlobalsLocked() {
418 SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal,
419 gDefaultNormal ? gDefaultNormal->uniqueID() : 0,
420 gDefaultNormal ? gDefaultNormal->getRefCnt() : 0);
421
422 if (gDefaultFamily) {
423 SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
424 gDefaultFamily,
425 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0,
426 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0,
427 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0,
428 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0,
429 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0,
430 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0,
431 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0,
432 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0);
433 } else {
434 SkDebugf("gDefaultFamily=%p", gDefaultFamily);
435 }
436
437 SkDebugf("gSystemFonts.count()=%d gFallbackFonts.count()=%d",
438 gSystemFonts.count(), gFallbackFonts.count());
439
440 for (int i = 0; i < gSystemFonts.count(); ++i) {
441 SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName);
442 size_t namesIndex = 0;
443 if (gSystemFonts[i].fNames)
444 for (const char* fontName = gSystemFonts[i].fNames[namesIndex];
445 fontName != 0;
446 fontName = gSystemFonts[i].fNames[++namesIndex]) {
447 SkDebugf(" name[%u]=%s", namesIndex, fontName);
448 }
449 }
450
451 if (gFamilyHead) {
452 FamilyRec* rec = gFamilyHead;
453 int i=0;
454 while (rec) {
455 SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}",
456 i++, rec,
457 rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0,
458 rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0,
459 rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0,
460 rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0,
461 rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0,
462 rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0,
463 rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0,
464 rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0);
465 rec = rec->fNext;
466 }
467 } else {
468 SkDebugf("gFamilyHead=%p", gFamilyHead);
469 }
470
471 }
472
473
haveSystemFont(const char * filename)474 static bool haveSystemFont(const char* filename) {
475 for (int i = 0; i < gSystemFonts.count(); i++) {
476 if (strcmp(gSystemFonts[i].fFileName, filename) == 0) {
477 return true;
478 }
479 }
480 return false;
481 }
482
483 /* Load info from a configuration file that populates the system/fallback font structures
484 */
loadFontInfoLocked()485 static void loadFontInfoLocked() {
486 SkTDArray<FontFamily*> fontFamilies;
487 getFontFamilies(fontFamilies);
488
489 gSystemFonts.reset();
490
491 for (int i = 0; i < fontFamilies.count(); ++i) {
492 FontFamily *family = fontFamilies[i];
493 for (int j = 0; j < family->fFileNames.count(); ++j) {
494 const char* filename = family->fFileNames[j];
495 if (haveSystemFont(filename)) {
496 SkDebugf("---- system font and fallback font files specify a duplicate "
497 "font %s, skipping the second occurrence", filename);
498 continue;
499 }
500
501 FontInitRec fontInfoRecord;
502 fontInfoRecord.fFileName = filename;
503 if (j == 0) {
504 if (family->fNames.count() == 0) {
505 // Fallback font
506 fontInfoRecord.fNames = (char **)gFBNames;
507 } else {
508 SkTDArray<const char*> names = family->fNames;
509 const char **nameList = (const char**)
510 malloc((names.count() + 1) * sizeof(char*));
511 if (nameList == NULL) {
512 // shouldn't get here
513 break;
514 }
515 if (gDefaultNames == NULL) {
516 gDefaultNames = (char**) nameList;
517 }
518 for (int i = 0; i < names.count(); ++i) {
519 nameList[i] = names[i];
520 }
521 nameList[names.count()] = NULL;
522 fontInfoRecord.fNames = nameList;
523 }
524 } else {
525 fontInfoRecord.fNames = NULL;
526 }
527 *gSystemFonts.append() = fontInfoRecord;
528 }
529 }
530 fontFamilies.deleteAll();
531
532 SkDEBUGF(("---- We have %d system fonts", gSystemFonts.count()));
533 for (int i = 0; i < gSystemFonts.count(); ++i) {
534 SkDEBUGF(("---- gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName));
535 }
536 }
537
538
539 /*
540 * Called once (ensured by the sentinel check at the beginning of our body).
541 * Initializes all the globals, and register the system fonts.
542 */
initSystemFontsLocked()543 static void initSystemFontsLocked() {
544 // check if we've already been called
545 if (gDefaultNormal) {
546 return;
547 }
548
549 SkASSERT(gUniqueFontID == 0);
550
551 loadFontInfoLocked();
552
553 gFallbackFonts.reset();
554
555 SkTypeface* firstInFamily = NULL;
556 for (int i = 0; i < gSystemFonts.count(); i++) {
557 // if we're the first in a new family, clear firstInFamily
558 const char* const* names = gSystemFonts[i].fNames;
559 if (names != NULL) {
560 firstInFamily = NULL;
561 }
562
563 bool isFixedWidth;
564 SkString name;
565 SkTypeface::Style style;
566
567 // we expect all the fonts, except the "fallback" fonts
568 bool isExpected = (names != gFBNames);
569 if (!getNameAndStyle(gSystemFonts[i].fFileName, &name, &style,
570 &isFixedWidth, isExpected)) {
571 // We need to increase gUniqueFontID here so that the unique id of
572 // each font matches its index in gSystemFonts array, as expected
573 // by findUniqueIDLocked.
574 sk_atomic_inc(&gUniqueFontID);
575 continue;
576 }
577
578 SkString fullpath;
579 getFullPathForSysFonts(&fullpath, gSystemFonts[i].fFileName);
580
581 SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style,
582 true, // system-font (cannot delete)
583 fullpath.c_str(), // filename
584 isFixedWidth));
585 addTypefaceLocked(tf, firstInFamily);
586
587 SkDEBUGF(("---- SkTypeface[%d] %s fontID %d\n",
588 i, gSystemFonts[i].fFileName, tf->uniqueID()));
589
590 if (names != NULL) {
591 // see if this is one of our fallback fonts
592 if (names == gFBNames) {
593 SkDEBUGF(("---- adding %s as fallback[%d] fontID %d\n",
594 gSystemFonts[i].fFileName, gFallbackFonts.count(), tf->uniqueID()));
595 *gFallbackFonts.append() = tf->uniqueID();
596 }
597
598 firstInFamily = tf;
599 FamilyRec* family = findFamilyLocked(tf);
600
601 // record the default family if this is it
602 if (names == gDefaultNames) {
603 gDefaultFamily = family;
604 }
605 // add the names to map to this family
606 while (*names) {
607 addNameLocked(*names, family);
608 names += 1;
609 }
610 }
611 }
612
613 // do this after all fonts are loaded. This is our default font, and it
614 // acts as a sentinel so we only execute loadSystemFontsLocked() once
615 gDefaultNormal = findBestFaceLocked(gDefaultFamily, SkTypeface::kNormal);
616
617 SkDEBUGCODE(dumpGlobalsLocked());
618 }
619
findUniqueIDLocked(const char * filename)620 static SkFontID findUniqueIDLocked(const char* filename) {
621 // uniqueID is the index, offset by one, of the associated element in
622 // gSystemFonts[] (assumes system fonts are loaded before external fonts)
623 // return 0 if not found
624 for (int i = 0; i < gSystemFonts.count(); i++) {
625 if (strcmp(gSystemFonts[i].fFileName, filename) == 0) {
626 return i + 1; // assume unique id of i'th system font is i + 1
627 }
628 }
629 return 0;
630 }
631
findFallbackFontIndex(SkFontID fontId)632 static int findFallbackFontIndex(SkFontID fontId) {
633 for (int i = 0; i < gFallbackFonts.count(); i++) {
634 if (gFallbackFonts[i] == fontId) {
635 return i;
636 }
637 }
638 return -1;
639 }
640
reloadFallbackFontsLocked()641 static void reloadFallbackFontsLocked() {
642 SkGraphics::PurgeFontCache();
643
644 SkTDArray<FontFamily*> fallbackFamilies;
645 getFallbackFontFamilies(fallbackFamilies);
646
647 gFallbackFonts.reset();
648
649 for (int i = 0; i < fallbackFamilies.count(); ++i) {
650 FontFamily *family = fallbackFamilies[i];
651
652 for (int j = 0; j < family->fFileNames.count(); ++j) {
653 const char* filename = family->fFileNames[j];
654 if (filename) {
655 if (!haveSystemFont(filename)) {
656 SkDebugf("---- skipping fallback font %s because it was not "
657 "previously loaded as a system font", filename);
658 continue;
659 }
660
661 // ensure the fallback font exists before adding it to the list
662 bool isFixedWidth;
663 SkString name;
664 SkTypeface::Style style;
665 if (!getNameAndStyle(filename, &name, &style,
666 &isFixedWidth, false)) {
667 continue;
668 }
669
670 SkFontID uniqueID = findUniqueIDLocked(filename);
671 SkASSERT(uniqueID != 0);
672 if (findFallbackFontIndex(uniqueID) >= 0) {
673 SkDebugf("---- system font and fallback font files specify a duplicate "
674 "font %s, skipping the second occurrence", filename);
675 continue;
676 }
677
678 SkDEBUGF(("---- reload %s as fallback[%d] fontID %d\n",
679 filename, gFallbackFonts.count(), uniqueID));
680
681 *gFallbackFonts.append() = uniqueID;
682 break; // The fallback set contains only the first font of each family
683 }
684 }
685 }
686
687 fallbackFamilies.deleteAll();
688 }
689
loadSystemFontsLocked()690 static void loadSystemFontsLocked() {
691 #if !defined(SK_BUILD_FOR_ANDROID_NDK)
692 static char prevLanguage[3];
693 static char prevRegion[3];
694 char language[3] = "";
695 char region[3] = "";
696
697 getLocale(language, region);
698
699 if (!gDefaultNormal) {
700 strncpy(prevLanguage, language, 2);
701 strncpy(prevRegion, region, 2);
702 initSystemFontsLocked();
703 } else if (strncmp(language, prevLanguage, 2) || strncmp(region, prevRegion, 2)) {
704 strncpy(prevLanguage, language, 2);
705 strncpy(prevRegion, region, 2);
706 reloadFallbackFontsLocked();
707 }
708 #else
709 if (!gDefaultNormal) {
710 initSystemFontsLocked();
711 reloadFallbackFontsLocked();
712 }
713 #endif
714 }
715
716 ///////////////////////////////////////////////////////////////////////////////
717
Serialize(const SkTypeface * face,SkWStream * stream)718 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
719 // lookup and record if the font is custom (i.e. not a system font)
720 bool isCustomFont = !((FamilyTypeface*)face)->isSysFont();
721 stream->writeBool(isCustomFont);
722
723 if (isCustomFont) {
724 SkStream* fontStream = ((FamilyTypeface*)face)->openStream();
725
726 // store the length of the custom font
727 uint32_t len = fontStream->getLength();
728 stream->write32(len);
729
730 // store the entire font in the serialized stream
731 void* fontData = malloc(len);
732
733 fontStream->read(fontData, len);
734 stream->write(fontData, len);
735
736 fontStream->unref();
737 free(fontData);
738 // SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len);
739
740 } else {
741 const char* name = ((FamilyTypeface*)face)->getUniqueString();
742
743 stream->write8((uint8_t)face->style());
744
745 if (NULL == name || 0 == *name) {
746 stream->writePackedUInt(0);
747 // SkDebugf("--- fonthost serialize null\n");
748 } else {
749 uint32_t len = strlen(name);
750 stream->writePackedUInt(len);
751 stream->write(name, len);
752 // SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
753 }
754 }
755 }
756
Deserialize(SkStream * stream)757 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
758 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
759 return deserializeLocked(stream);
760 }
761
deserializeLocked(SkStream * stream)762 static SkTypeface* deserializeLocked(SkStream* stream) {
763 loadSystemFontsLocked();
764
765 // check if the font is a custom or system font
766 bool isCustomFont = stream->readBool();
767
768 if (isCustomFont) {
769
770 // read the length of the custom font from the stream
771 uint32_t len = stream->readU32();
772
773 // generate a new stream to store the custom typeface
774 SkMemoryStream* fontStream = new SkMemoryStream(len);
775 stream->read((void*)fontStream->getMemoryBase(), len);
776
777 SkTypeface* face = createTypefaceFromStreamLocked(fontStream);
778
779 fontStream->unref();
780
781 // SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len);
782 return face;
783
784 } else {
785 int style = stream->readU8();
786
787 int len = stream->readPackedUInt();
788 if (len > 0) {
789 SkString str;
790 str.resize(len);
791 stream->read(str.writable_str(), len);
792
793 for (int i = 0; i < gSystemFonts.count(); i++) {
794 if (strcmp(gSystemFonts[i].fFileName, str.c_str()) == 0) {
795 // backup until we hit the fNames
796 for (int j = i; j >= 0; --j) {
797 if (gSystemFonts[j].fNames != NULL) {
798 return createTypefaceLocked(NULL,
799 gSystemFonts[j].fNames[0], NULL, 0,
800 (SkTypeface::Style)style);
801 }
802 }
803 }
804 }
805 }
806 }
807 return NULL;
808 }
809
810 ///////////////////////////////////////////////////////////////////////////////
811
CreateTypeface(const SkTypeface * familyFace,const char familyName[],const void * data,size_t bytelength,SkTypeface::Style style)812 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
813 const char familyName[],
814 const void* data, size_t bytelength,
815 SkTypeface::Style style) {
816 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
817 return createTypefaceLocked(familyFace, familyName, data, bytelength, style);
818 }
819
createTypefaceLocked(const SkTypeface * familyFace,const char familyName[],const void * data,size_t bytelength,SkTypeface::Style style)820 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace,
821 const char familyName[], const void* data, size_t bytelength,
822 SkTypeface::Style style) {
823 loadSystemFontsLocked();
824
825 // clip to legal style bits
826 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
827
828 SkTypeface* tf = NULL;
829
830 if (NULL != familyFace) {
831 tf = findTypefaceLocked(familyFace, style);
832 } else if (NULL != familyName) {
833 // SkDebugf("======= familyName <%s>\n", familyName);
834 tf = findTypefaceLocked(familyName, style);
835 }
836
837 if (NULL == tf) {
838 tf = findBestFaceLocked(gDefaultFamily, style);
839 }
840
841 // we ref(), since the semantic is to return a new instance
842 tf->ref();
843 return tf;
844 }
845
OpenStream(uint32_t fontID)846 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
847 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
848 return openStreamLocked(fontID);
849 }
850
openStreamLocked(uint32_t fontID)851 static SkStream* openStreamLocked(uint32_t fontID) {
852 FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID);
853 SkStream* stream = tf ? tf->openStream() : NULL;
854
855 if (stream && stream->getLength() == 0) {
856 stream->unref();
857 stream = NULL;
858 }
859 return stream;
860 }
861
GetFileName(SkFontID fontID,char path[],size_t length,int32_t * index)862 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
863 int32_t* index) {
864 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
865 return getFileNameLocked(fontID, path, length, index);
866 }
867
getFileNameLocked(SkFontID fontID,char path[],size_t length,int32_t * index)868 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index) {
869 FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID);
870 const char* src = tf ? tf->getFilePath() : NULL;
871
872 if (src) {
873 size_t size = strlen(src);
874 if (path) {
875 memcpy(path, src, SkMin32(size, length));
876 }
877 if (index) {
878 *index = 0; // we don't have collections (yet)
879 }
880 return size;
881 } else {
882 return 0;
883 }
884 }
885
NextLogicalFont(SkFontID currFontID,SkFontID origFontID)886 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
887 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
888 return nextLogicalFontLocked(currFontID, origFontID);
889 }
890
nextLogicalFontLocked(SkFontID currFontID,SkFontID origFontID)891 static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID) {
892 loadSystemFontsLocked();
893
894 const SkTypeface* origTypeface = findFromUniqueIDLocked(origFontID);
895 const SkTypeface* currTypeface = findFromUniqueIDLocked(currFontID);
896
897 SkASSERT(origTypeface != 0);
898 SkASSERT(currTypeface != 0);
899
900 // Our fallback list always stores the id of the plain in each fallback
901 // family, so we transform currFontID to its plain equivalent.
902 SkFontID plainFontID = findTypefaceLocked(currTypeface, SkTypeface::kNormal)->uniqueID();
903
904 /* First see if fontID is already one of our fallbacks. If so, return
905 its successor. If fontID is not in our list, then return the first one
906 in our list. Note: list is zero-terminated, and returning zero means
907 we have no more fonts to use for fallbacks.
908 */
909 int plainFallbackFontIndex = findFallbackFontIndex(plainFontID);
910 int nextFallbackFontIndex = plainFallbackFontIndex + 1;
911 SkFontID nextFontID;
912 if (nextFallbackFontIndex == gFallbackFonts.count()) {
913 nextFontID = 0; // no more fallbacks
914 } else {
915 const SkTypeface* nextTypeface = findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex]);
916 nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID();
917 }
918
919 SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, "
920 "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d "
921 "=> nextFontID=%d", currFontID, origFontID, plainFontID,
922 plainFallbackFontIndex, nextFallbackFontIndex, nextFontID));
923 return nextFontID;
924 }
925
926 ///////////////////////////////////////////////////////////////////////////////
927
CreateTypefaceFromStream(SkStream * stream)928 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
929 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex);
930 return createTypefaceFromStreamLocked(stream);
931 }
932
createTypefaceFromStreamLocked(SkStream * stream)933 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream) {
934 if (NULL == stream || stream->getLength() <= 0) {
935 return NULL;
936 }
937
938 // Make sure system fonts are loaded first to comply with the assumption
939 // that the font's uniqueID can be found using the findUniqueIDLocked method.
940 loadSystemFontsLocked();
941
942 bool isFixedWidth;
943 SkTypeface::Style style;
944
945 if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) {
946 SkTypeface* typeface = SkNEW_ARGS(StreamTypeface, (style, false, stream, isFixedWidth));
947 addTypefaceLocked(typeface, NULL);
948 return typeface;
949 } else {
950 return NULL;
951 }
952 }
953
CreateTypefaceFromFile(const char path[])954 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
955 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
956 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
957 // since we created the stream, we let go of our ref() here
958 stream->unref();
959 return face;
960 }
961