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 #include "SkGlyphCache.h" 31 #include "SkLanguage.h" 32 #include "SkTypeface_android.h" 33 #include "SkTArray.h" 34 #include "SkTDict.h" 35 #include "SkTSearch.h" 36 37 //#define SkDEBUGF(args ) SkDebugf args 38 39 #ifndef SK_FONT_FILE_PREFIX 40 #define SK_FONT_FILE_PREFIX "/fonts/" 41 #endif 42 43 // Defined in SkFontHost_FreeType.cpp 44 bool find_name_and_attributes(SkStream* stream, SkString* name, 45 SkTypeface::Style* style, bool* isFixedWidth); 46 47 static void getFullPathForSysFonts(SkString* full, const char name[]) { 48 full->set(getenv("ANDROID_ROOT")); 49 full->append(SK_FONT_FILE_PREFIX); 50 full->append(name); 51 } 52 53 static bool getNameAndStyle(const char path[], SkString* name, 54 SkTypeface::Style* style, 55 bool* isFixedWidth, bool isExpected) { 56 SkString fullpath; 57 getFullPathForSysFonts(&fullpath, path); 58 59 SkMMAPStream stream(fullpath.c_str()); 60 if (stream.getLength() > 0) { 61 return find_name_and_attributes(&stream, name, style, isFixedWidth); 62 } 63 else { 64 SkFILEStream stream(fullpath.c_str()); 65 if (stream.getLength() > 0) { 66 return find_name_and_attributes(&stream, name, style, isFixedWidth); 67 } 68 } 69 70 if (isExpected) { 71 SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str()); 72 } 73 return false; 74 } 75 76 static SkTypeface* deserializeLocked(SkStream* stream); 77 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace, 78 const char familyName[], const void* data, size_t bytelength, 79 SkTypeface::Style style); 80 static SkStream* openStreamLocked(uint32_t fontID); 81 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index); 82 static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec); 83 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream); 84 85 86 /////////////////////////////////////////////////////////////////////////////// 87 88 struct FamilyRec; 89 90 /* This guy holds a mapping of a name -> family, used for looking up fonts. 91 Since it is stored in a stretchy array that doesn't preserve object 92 semantics, we don't use constructor/destructors, but just have explicit 93 helpers to manage our internal bookkeeping. 94 */ 95 struct NameFamilyPair { 96 const char* fName; // we own this 97 FamilyRec* fFamily; // we don't own this, we just reference it 98 99 void construct(const char name[], FamilyRec* family) { 100 fName = strdup(name); 101 fFamily = family; // we don't own this, so just record the reference 102 } 103 104 void destruct() { 105 free((char*)fName); 106 // we don't own family, so just ignore our reference 107 } 108 }; 109 typedef SkTDArray<NameFamilyPair> NameFamilyPairList; 110 111 // we use atomic_inc to grow this for each typeface we create 112 static int32_t gUniqueFontID; 113 114 // this is the mutex that protects all of the global data structures in this module 115 // functions with the Locked() suffix must be called while holding this mutex 116 SK_DECLARE_STATIC_MUTEX(gFamilyHeadAndNameListMutex); 117 static FamilyRec* gFamilyHead = NULL; 118 static SkTDArray<NameFamilyPair> gFallbackFilenameList; 119 static NameFamilyPairList gNameList; 120 121 struct FamilyRec { 122 FamilyRec* fNext; 123 SkTypeface* fFaces[4]; 124 125 FamilyRec() : fNext(NULL) { 126 memset(fFaces, 0, sizeof(fFaces)); 127 } 128 }; 129 130 static SkTypeface* findBestFaceLocked(const FamilyRec* family, 131 SkTypeface::Style style) { 132 SkTypeface* const* faces = family->fFaces; 133 134 if (faces[style] != NULL) { // exact match 135 return faces[style]; 136 } 137 // look for a matching bold 138 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 139 if (faces[style] != NULL) { 140 return faces[style]; 141 } 142 // look for the plain 143 if (faces[SkTypeface::kNormal] != NULL) { 144 return faces[SkTypeface::kNormal]; 145 } 146 // look for anything 147 for (int i = 0; i < 4; i++) { 148 if (faces[i] != NULL) { 149 return faces[i]; 150 } 151 } 152 // should never get here, since the faces list should not be empty 153 SkDEBUGFAIL("faces list is empty"); 154 return NULL; 155 } 156 157 static SkTypeface* FindBestFace(const FamilyRec* family, 158 SkTypeface::Style style) { 159 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 160 return findBestFaceLocked(family, style); 161 } 162 163 static FamilyRec* findFamilyLocked(const SkTypeface* member) { 164 FamilyRec* curr = gFamilyHead; 165 while (curr != NULL) { 166 for (int i = 0; i < 4; i++) { 167 if (curr->fFaces[i] == member) { 168 return curr; 169 } 170 } 171 curr = curr->fNext; 172 } 173 return NULL; 174 } 175 176 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt 177 is not modified. 178 */ 179 static SkTypeface* findFromUniqueIDLocked(uint32_t uniqueID) { 180 FamilyRec* curr = gFamilyHead; 181 while (curr != NULL) { 182 for (int i = 0; i < 4; i++) { 183 SkTypeface* face = curr->fFaces[i]; 184 if (face != NULL && face->uniqueID() == uniqueID) { 185 return face; 186 } 187 } 188 curr = curr->fNext; 189 } 190 return NULL; 191 } 192 193 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt 194 is not modified. 195 */ 196 static SkTypeface* FindFromUniqueID(uint32_t uniqueID) { 197 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 198 return findFromUniqueIDLocked(uniqueID); 199 } 200 201 /* Remove reference to this face from its family. If the resulting family 202 is empty (has no faces), return that family, otherwise return NULL 203 */ 204 static FamilyRec* removeFromFamilyLocked(const SkTypeface* face) { 205 FamilyRec* family = findFamilyLocked(face); 206 if (family) { 207 SkASSERT(family->fFaces[face->style()] == face); 208 family->fFaces[face->style()] = NULL; 209 210 for (int i = 0; i < 4; i++) { 211 if (family->fFaces[i] != NULL) { // family is non-empty 212 return NULL; 213 } 214 } 215 } else { 216 // SkDebugf("removeFromFamilyLocked(%p) face not found", face); 217 } 218 return family; // return the empty family 219 } 220 221 // maybe we should make FamilyRec be doubly-linked 222 static void detachAndDeleteFamilyLocked(FamilyRec* family) { 223 FamilyRec* curr = gFamilyHead; 224 FamilyRec* prev = NULL; 225 226 while (curr != NULL) { 227 FamilyRec* next = curr->fNext; 228 if (curr == family) { 229 if (prev == NULL) { 230 gFamilyHead = next; 231 } else { 232 prev->fNext = next; 233 } 234 SkDELETE(family); 235 return; 236 } 237 prev = curr; 238 curr = next; 239 } 240 SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); 241 } 242 243 static SkTypeface* findTypefaceLocked(const char name[], SkTypeface::Style style) { 244 int count = gNameList.count(); 245 NameFamilyPair* list = gNameList.begin(); 246 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 247 if (index >= 0) { 248 return findBestFaceLocked(list[index].fFamily, style); 249 } 250 return NULL; 251 } 252 253 static SkTypeface* findTypefaceLocked(const SkTypeface* familyMember, 254 SkTypeface::Style style) { 255 const FamilyRec* family = findFamilyLocked(familyMember); 256 return family ? findBestFaceLocked(family, style) : NULL; 257 } 258 259 static void addNameLocked(const char name[], FamilyRec* family) { 260 SkAutoAsciiToLC tolc(name); 261 name = tolc.lc(); 262 263 int count = gNameList.count(); 264 NameFamilyPair* list = gNameList.begin(); 265 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 266 if (index < 0) { 267 list = gNameList.insert(~index); 268 list->construct(name, family); 269 } 270 } 271 272 static void removeFromNamesLocked(FamilyRec* emptyFamily) { 273 #ifdef SK_DEBUG 274 for (int i = 0; i < 4; i++) { 275 SkASSERT(emptyFamily->fFaces[i] == NULL); 276 } 277 #endif 278 279 // must go backwards when removing 280 for (int i = gNameList.count() - 1; i >= 0; --i) { 281 NameFamilyPair& pair = gNameList[i]; 282 if (pair.fFamily == emptyFamily) { 283 pair.destruct(); 284 gNameList.remove(i); 285 } 286 } 287 } 288 289 static void addTypefaceLocked(SkTypeface* typeface, SkTypeface* familyMember) { 290 FamilyRec* rec = NULL; 291 if (familyMember) { 292 rec = findFamilyLocked(familyMember); 293 SkASSERT(rec); 294 } else { 295 rec = SkNEW(FamilyRec); 296 rec->fNext = gFamilyHead; 297 gFamilyHead = rec; 298 } 299 rec->fFaces[typeface->style()] = typeface; 300 } 301 302 static void removeTypeface(SkTypeface* typeface) { 303 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 304 305 // remove us from our family. If the family is now empty, we return 306 // that and then remove that family from the name list 307 FamilyRec* family = removeFromFamilyLocked(typeface); 308 if (NULL != family) { 309 removeFromNamesLocked(family); 310 detachAndDeleteFamilyLocked(family); 311 } 312 } 313 314 /////////////////////////////////////////////////////////////////////////////// 315 316 class FamilyTypeface : public SkTypeface { 317 protected: 318 FamilyTypeface(Style style, bool sysFont, bool isFixedWidth) 319 : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) { 320 fIsSysFont = sysFont; 321 } 322 323 public: 324 virtual ~FamilyTypeface() { 325 removeTypeface(this); 326 } 327 328 bool isSysFont() const { return fIsSysFont; } 329 330 virtual SkStream* openStream() = 0; 331 virtual const char* getUniqueString() const = 0; 332 virtual const char* getFilePath() const = 0; 333 334 private: 335 bool fIsSysFont; 336 337 typedef SkTypeface INHERITED; 338 }; 339 340 /////////////////////////////////////////////////////////////////////////////// 341 342 class StreamTypeface : public FamilyTypeface { 343 public: 344 StreamTypeface(Style style, bool sysFont, SkStream* stream, bool isFixedWidth) 345 : INHERITED(style, sysFont, isFixedWidth) { 346 SkASSERT(stream); 347 stream->ref(); 348 fStream = stream; 349 } 350 351 virtual ~StreamTypeface() { 352 fStream->unref(); 353 } 354 355 // overrides 356 virtual SkStream* openStream() { 357 // we just ref our existing stream, since the caller will call unref() 358 // when they are through 359 fStream->ref(); 360 // must rewind each time, since the caller assumes a "new" stream 361 fStream->rewind(); 362 return fStream; 363 } 364 virtual const char* getUniqueString() const { return NULL; } 365 virtual const char* getFilePath() const { return NULL; } 366 367 private: 368 SkStream* fStream; 369 370 typedef FamilyTypeface INHERITED; 371 }; 372 373 class FileTypeface : public FamilyTypeface { 374 public: 375 FileTypeface(Style style, bool sysFont, const char path[], bool isFixedWidth) 376 : INHERITED(style, sysFont, isFixedWidth) { 377 fPath.set(path); 378 } 379 380 // overrides 381 virtual SkStream* openStream() { 382 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); 383 384 // check for failure 385 if (stream->getLength() <= 0) { 386 SkDELETE(stream); 387 // maybe MMAP isn't supported. try FILE 388 stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); 389 if (stream->getLength() <= 0) { 390 SkDELETE(stream); 391 stream = NULL; 392 } 393 } 394 return stream; 395 } 396 virtual const char* getUniqueString() const { 397 const char* str = strrchr(fPath.c_str(), '/'); 398 if (str) { 399 str += 1; // skip the '/' 400 } 401 return str; 402 } 403 virtual const char* getFilePath() const { 404 return fPath.c_str(); 405 } 406 407 private: 408 SkString fPath; 409 410 typedef FamilyTypeface INHERITED; 411 }; 412 413 /////////////////////////////////////////////////////////////////////////////// 414 /////////////////////////////////////////////////////////////////////////////// 415 416 // used to record our notion of the pre-existing fonts 417 struct FontInitRec { 418 const char* fFileName; 419 const char* const* fNames; // null-terminated list 420 SkPaint::FontVariant fVariant; 421 SkLanguage fLanguage; 422 }; 423 424 //used to record information about the fallback fonts 425 struct FallbackFontRec { 426 SkFontID fFontID; 427 SkPaint::FontVariant fVariant; 428 }; 429 430 struct FallbackFontList { 431 FallbackFontList(const SkLanguage& language) : fLanguage(language) { } 432 SkTDArray<FallbackFontRec> fList; 433 SkLanguage fLanguage; 434 }; 435 436 // deliberately empty, but we use the address to identify fallback fonts 437 static const char* gFBNames[] = { NULL }; 438 439 /* Fonts are grouped by family, with the first font in a family having the 440 list of names (even if that list is empty), and the following members having 441 null for the list. The names list must be NULL-terminated. 442 */ 443 static SkTArray<FontInitRec> gSystemFonts; 444 static SkTDArray<FallbackFontList*> gFallbackFontLists; 445 446 // these globals are assigned (once) by loadSystemFontsLocked() 447 static FamilyRec* gDefaultFamily = NULL; 448 static SkTypeface* gDefaultNormal = NULL; 449 static char** gDefaultNames = NULL; 450 451 static FallbackFontList* getFallbackFontListLocked(const SkLanguage& lang); 452 static void dumpGlobalsLocked() { 453 SkDebugf("gDefaultNormal=%p id=%u refCnt=%d", gDefaultNormal, 454 gDefaultNormal ? gDefaultNormal->uniqueID() : 0, 455 gDefaultNormal ? gDefaultNormal->getRefCnt() : 0); 456 457 if (gDefaultFamily) { 458 SkDebugf("gDefaultFamily=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", 459 gDefaultFamily, 460 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->uniqueID() : 0, 461 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->uniqueID() : 0, 462 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->uniqueID() : 0, 463 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->uniqueID() : 0, 464 gDefaultFamily->fFaces[0] ? gDefaultFamily->fFaces[0]->getRefCnt() : 0, 465 gDefaultFamily->fFaces[1] ? gDefaultFamily->fFaces[1]->getRefCnt() : 0, 466 gDefaultFamily->fFaces[2] ? gDefaultFamily->fFaces[2]->getRefCnt() : 0, 467 gDefaultFamily->fFaces[3] ? gDefaultFamily->fFaces[3]->getRefCnt() : 0); 468 } else { 469 SkDebugf("gDefaultFamily=%p", gDefaultFamily); 470 } 471 472 FallbackFontList* defaultFallbackList = 473 getFallbackFontListLocked(SkLanguage()); 474 SkASSERT(defaultFallbackList != NULL); 475 SkDebugf("gSystemFonts.count()=%d defaultFallbackList->fList.count()=%d", 476 gSystemFonts.count(), defaultFallbackList->fList.count()); 477 478 for (int i = 0; i < gSystemFonts.count(); ++i) { 479 SkDebugf("gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName); 480 size_t namesIndex = 0; 481 if (gSystemFonts[i].fNames) 482 for (const char* fontName = gSystemFonts[i].fNames[namesIndex]; 483 fontName != 0; 484 fontName = gSystemFonts[i].fNames[++namesIndex]) { 485 SkDebugf(" name[%u]=%s", namesIndex, fontName); 486 } 487 } 488 489 if (gFamilyHead) { 490 FamilyRec* rec = gFamilyHead; 491 int i=0; 492 while (rec) { 493 SkDebugf("gFamilyHead[%d]=%p fFaces={%u,%u,%u,%u} refCnt={%d,%d,%d,%d}", 494 i++, rec, 495 rec->fFaces[0] ? rec->fFaces[0]->uniqueID() : 0, 496 rec->fFaces[1] ? rec->fFaces[1]->uniqueID() : 0, 497 rec->fFaces[2] ? rec->fFaces[2]->uniqueID() : 0, 498 rec->fFaces[3] ? rec->fFaces[3]->uniqueID() : 0, 499 rec->fFaces[0] ? rec->fFaces[0]->getRefCnt() : 0, 500 rec->fFaces[1] ? rec->fFaces[1]->getRefCnt() : 0, 501 rec->fFaces[2] ? rec->fFaces[2]->getRefCnt() : 0, 502 rec->fFaces[3] ? rec->fFaces[3]->getRefCnt() : 0); 503 rec = rec->fNext; 504 } 505 } else { 506 SkDebugf("gFamilyHead=%p", gFamilyHead); 507 } 508 509 } 510 511 512 static bool haveSystemFont(const char* filename) { 513 for (int i = 0; i < gSystemFonts.count(); i++) { 514 if (strcmp(gSystemFonts[i].fFileName, filename) == 0) { 515 return true; 516 } 517 } 518 return false; 519 } 520 521 // (SkLanguage)<->(fallback chain index) translation 522 static const size_t kLangDictSize = 128; 523 static SkTDict<FallbackFontList*> gLangTagToFallbackFontList(kLangDictSize); 524 static bool gIsOKToUseFallbackFontListCache = false; 525 526 // crawl fallback font lists by hand looking for a specific language 527 static FallbackFontList* getFallbackFontListNoCacheLocked( 528 const SkLanguage& lang) { 529 unsigned int numLists = gFallbackFontLists.count(); 530 for (unsigned int listIdx = 0; listIdx < numLists; ++listIdx) { 531 FallbackFontList* list = gFallbackFontLists[listIdx]; 532 SkASSERT(list != NULL); 533 if (list->fLanguage == lang) { 534 return list; 535 } 536 } 537 return NULL; 538 } 539 540 // perform fancy fuzzy-matching memoized query for a fallback font list. 541 // should only be called after fallback font lists are fully loaded. 542 static FallbackFontList* getFallbackFontListLocked(const SkLanguage& lang) { 543 SkASSERT(gIsOKToUseFallbackFontListCache); 544 const SkString& langTag = lang.getTag(); 545 FallbackFontList* fallbackFontList; 546 if (gLangTagToFallbackFontList.find(langTag.c_str(), langTag.size(), 547 &fallbackFontList)) { 548 // cache hit! 549 return fallbackFontList; 550 } 551 552 // try again without the cache 553 fallbackFontList = getFallbackFontListNoCacheLocked(lang); 554 if (fallbackFontList != NULL) { 555 // found it - cache and return 556 gLangTagToFallbackFontList.set(langTag.c_str(), langTag.size(), 557 fallbackFontList); 558 SkDEBUGF(("new fallback cache entry: \"%s\"", langTag.c_str())); 559 return fallbackFontList; 560 } 561 562 // no hit - can we fuzzy-match? 563 if (lang.getTag().isEmpty()) { 564 // nope! this happens if attempting to direct match with no default 565 return NULL; 566 } 567 568 // attempt fuzzy match 569 SkLanguage parent = lang.getParent(); 570 fallbackFontList = getFallbackFontListLocked(parent); 571 if (fallbackFontList != NULL) { 572 // found it - cache and return 573 gLangTagToFallbackFontList.set(langTag.c_str(), langTag.size(), 574 fallbackFontList); 575 SkDEBUGF(("new fallback cache entry: \"%s\" -> \"%s\"", langTag.c_str(), 576 fallbackFontList->fLanguage.getTag().c_str())); 577 return fallbackFontList; 578 } 579 580 // utter failure. this happens if attempting to fuzzy-match with no default 581 SkASSERT(fallbackFontList != NULL); 582 return NULL; 583 } 584 585 // creates a new fallback font list for the specified language 586 static FallbackFontList* createFallbackFontListLocked(const SkLanguage& lang) { 587 SkASSERT(!gIsOKToUseFallbackFontListCache); 588 SkDEBUGF(("new fallback list: \"%s\"", lang.getTag().c_str())); 589 FallbackFontList* fallbackFontList = new FallbackFontList(lang); 590 gFallbackFontLists.push(fallbackFontList); 591 return fallbackFontList; 592 } 593 594 // adds a fallback font record to both the default fallback chain and the 595 // language-specific fallback chain to which it belongs, if any 596 static void addFallbackFontLocked(const FallbackFontRec& fallbackRec, 597 const SkLanguage& lang) { 598 SkASSERT(!gIsOKToUseFallbackFontListCache); 599 SkDEBUGF(("new fallback font: %d, in \"%s\"", fallbackRec.fFontID, 600 lang.getTag().c_str())); 601 // add to the default fallback list 602 FallbackFontList* fallbackList = 603 getFallbackFontListNoCacheLocked(SkLanguage()); 604 if (fallbackList == NULL) { 605 // oops! no default list yet. create one. 606 fallbackList = createFallbackFontListLocked(SkLanguage()); 607 } 608 SkASSERT(fallbackList != NULL); 609 fallbackList->fList.push(fallbackRec); 610 if (lang.getTag().isEmpty()) { 611 return; 612 } 613 // also add to the appropriate language's fallback list 614 fallbackList = getFallbackFontListNoCacheLocked(lang); 615 if (fallbackList == NULL) { 616 // first entry for this list! 617 fallbackList = createFallbackFontListLocked(lang); 618 } 619 SkASSERT(fallbackList != NULL); 620 fallbackList->fList.push(fallbackRec); 621 } 622 623 static int getSystemFontIndexForFontID(SkFontID fontID) { 624 // font unique id = one-based index in system font table 625 SkASSERT(fontID - 1 < gSystemFonts.count()); 626 return fontID - 1; 627 } 628 629 // scans the default fallback font chain, adding every entry to every other 630 // fallback font chain to which it does not belong. this results in every 631 // language-specific fallback font chain having all of its fallback fonts at 632 // the front of the chain, and everything else at the end. after this has been 633 // run, it is ok to use the fallback font chain lookup table. 634 static void finaliseFallbackFontListsLocked() { 635 SkASSERT(!gIsOKToUseFallbackFontListCache); 636 // if we have more than one list, we need to finalise non-default lists 637 unsigned int numLists = gFallbackFontLists.count(); 638 if (numLists > 1) { 639 // pull fonts off of the default list... 640 FallbackFontList* defaultList = getFallbackFontListNoCacheLocked( 641 SkLanguage()); 642 SkASSERT(defaultList != NULL); 643 int numDefaultFonts = defaultList->fList.count(); 644 for (int fontIdx = 0; fontIdx < numDefaultFonts; ++fontIdx) { 645 // figure out which language they represent 646 SkFontID fontID = defaultList->fList[fontIdx].fFontID; 647 int sysFontIdx = getSystemFontIndexForFontID(fontID); 648 const SkLanguage& lang = gSystemFonts[sysFontIdx].fLanguage; 649 for (unsigned int listIdx = 0; listIdx < numLists; ++listIdx) { 650 // and add them to every other language's list 651 FallbackFontList* thisList = gFallbackFontLists[listIdx]; 652 SkASSERT(thisList != NULL); 653 if (thisList != defaultList && thisList->fLanguage != lang) { 654 thisList->fList.push(defaultList->fList[fontIdx]); 655 } 656 } 657 } 658 } 659 gIsOKToUseFallbackFontListCache = true; 660 } 661 662 static void resetFallbackFontListsLocked() { 663 // clear cache 664 gLangTagToFallbackFontList.reset(); 665 // clear the data it pointed at 666 int numFallbackLists = gFallbackFontLists.count(); 667 for (int fallbackIdx = 0; fallbackIdx < numFallbackLists; ++fallbackIdx) { 668 delete gFallbackFontLists[fallbackIdx]; 669 } 670 gFallbackFontLists.reset(); 671 gIsOKToUseFallbackFontListCache = false; 672 } 673 674 /* Load info from a configuration file that populates the system/fallback font structures 675 */ 676 static void loadFontInfoLocked() { 677 resetFallbackFontListsLocked(); 678 679 SkTDArray<FontFamily*> fontFamilies; 680 getFontFamilies(fontFamilies); 681 682 gSystemFonts.reset(); 683 684 for (int i = 0; i < fontFamilies.count(); ++i) { 685 FontFamily *family = fontFamilies[i]; 686 for (int j = 0; j < family->fFontFileArray.count(); ++j) { 687 const char* filename = family->fFontFileArray[j]->fFileName; 688 if (haveSystemFont(filename)) { 689 SkDebugf("---- system font and fallback font files specify a duplicate " 690 "font %s, skipping the second occurrence", filename); 691 continue; 692 } 693 694 FontInitRec fontInfoRecord; 695 fontInfoRecord.fFileName = filename; 696 fontInfoRecord.fVariant = family->fFontFileArray[j]->fVariant; 697 fontInfoRecord.fLanguage = family->fFontFileArray[j]->fLanguage; 698 if (j == 0) { 699 if (family->fNames.count() == 0) { 700 // Fallback font 701 fontInfoRecord.fNames = (char **)gFBNames; 702 } else { 703 SkTDArray<const char*> names = family->fNames; 704 const char **nameList = (const char**) 705 malloc((names.count() + 1) * sizeof(char*)); 706 if (nameList == NULL) { 707 // shouldn't get here 708 break; 709 } 710 if (gDefaultNames == NULL) { 711 gDefaultNames = (char**) nameList; 712 } 713 for (int i = 0; i < names.count(); ++i) { 714 nameList[i] = names[i]; 715 } 716 nameList[names.count()] = NULL; 717 fontInfoRecord.fNames = nameList; 718 } 719 } else { 720 fontInfoRecord.fNames = NULL; 721 } 722 gSystemFonts.push_back(fontInfoRecord); 723 } 724 } 725 fontFamilies.deleteAll(); 726 727 SkDEBUGF(("---- We have %d system fonts", gSystemFonts.count())); 728 for (int i = 0; i < gSystemFonts.count(); ++i) { 729 SkDEBUGF(("---- gSystemFonts[%d] fileName=%s", i, gSystemFonts[i].fFileName)); 730 } 731 } 732 733 /* 734 * Called once (ensured by the sentinel check at the beginning of our body). 735 * Initializes all the globals, and register the system fonts. 736 */ 737 static void initSystemFontsLocked() { 738 // check if we've already been called 739 if (gDefaultNormal) { 740 return; 741 } 742 743 SkASSERT(gUniqueFontID == 0); 744 745 loadFontInfoLocked(); 746 747 SkTypeface* firstInFamily = NULL; 748 for (int i = 0; i < gSystemFonts.count(); i++) { 749 // if we're the first in a new family, clear firstInFamily 750 const char* const* names = gSystemFonts[i].fNames; 751 if (names != NULL) { 752 firstInFamily = NULL; 753 } 754 755 bool isFixedWidth; 756 SkString name; 757 SkTypeface::Style style; 758 759 // we expect all the fonts, except the "fallback" fonts 760 bool isExpected = (names != gFBNames); 761 if (!getNameAndStyle(gSystemFonts[i].fFileName, &name, &style, 762 &isFixedWidth, isExpected)) { 763 // We need to increase gUniqueFontID here so that the unique id of 764 // each font matches its index in gSystemFonts array, as expected 765 // by findUniqueIDLocked. 766 sk_atomic_inc(&gUniqueFontID); 767 continue; 768 } 769 770 SkString fullpath; 771 getFullPathForSysFonts(&fullpath, gSystemFonts[i].fFileName); 772 773 SkTypeface* tf = SkNEW_ARGS(FileTypeface, (style, 774 true, // system-font (cannot delete) 775 fullpath.c_str(), // filename 776 isFixedWidth)); 777 addTypefaceLocked(tf, firstInFamily); 778 779 SkDEBUGF(("---- SkTypeface[%d] %s fontID %d\n", 780 i, gSystemFonts[i].fFileName, tf->uniqueID())); 781 782 if (names != NULL) { 783 // see if this is one of our fallback fonts 784 if (names == gFBNames) { 785 // add to appropriate fallback chains 786 FallbackFontRec fallbackRec; 787 fallbackRec.fFontID = tf->uniqueID(); 788 fallbackRec.fVariant = gSystemFonts[i].fVariant; 789 addFallbackFontLocked(fallbackRec, gSystemFonts[i].fLanguage); 790 } 791 792 firstInFamily = tf; 793 FamilyRec* family = findFamilyLocked(tf); 794 795 // record the default family if this is it 796 if (names == gDefaultNames) { 797 gDefaultFamily = family; 798 } 799 // add the names to map to this family 800 while (*names) { 801 addNameLocked(*names, family); 802 names += 1; 803 } 804 } 805 } 806 finaliseFallbackFontListsLocked(); 807 808 // do this after all fonts are loaded. This is our default font, and it 809 // acts as a sentinel so we only execute loadSystemFontsLocked() once 810 gDefaultNormal = findBestFaceLocked(gDefaultFamily, SkTypeface::kNormal); 811 812 SkDEBUGCODE(dumpGlobalsLocked()); 813 } 814 815 static int findFallbackFontIndex(SkFontID fontId, FallbackFontList* currentFallbackList) { 816 for (int i = 0; i < currentFallbackList->fList.count(); i++) { 817 if (currentFallbackList->fList[i].fFontID == fontId) { 818 return i; 819 } 820 } 821 return -1; 822 } 823 824 static void loadSystemFontsLocked() { 825 if (!gDefaultNormal) { 826 initSystemFontsLocked(); 827 } 828 } 829 830 /////////////////////////////////////////////////////////////////////////////// 831 832 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 833 // lookup and record if the font is custom (i.e. not a system font) 834 bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); 835 stream->writeBool(isCustomFont); 836 837 if (isCustomFont) { 838 SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); 839 840 // store the length of the custom font 841 uint32_t len = fontStream->getLength(); 842 stream->write32(len); 843 844 // store the entire font in the serialized stream 845 void* fontData = malloc(len); 846 847 fontStream->read(fontData, len); 848 stream->write(fontData, len); 849 850 fontStream->unref(); 851 free(fontData); 852 // SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len); 853 854 } else { 855 const char* name = ((FamilyTypeface*)face)->getUniqueString(); 856 857 stream->write8((uint8_t)face->style()); 858 859 if (NULL == name || 0 == *name) { 860 stream->writePackedUInt(0); 861 // SkDebugf("--- fonthost serialize null\n"); 862 } else { 863 uint32_t len = strlen(name); 864 stream->writePackedUInt(len); 865 stream->write(name, len); 866 // SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style()); 867 } 868 } 869 } 870 871 SkTypeface* SkFontHost::Deserialize(SkStream* stream) { 872 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 873 return deserializeLocked(stream); 874 } 875 876 static SkTypeface* deserializeLocked(SkStream* stream) { 877 loadSystemFontsLocked(); 878 879 // check if the font is a custom or system font 880 bool isCustomFont = stream->readBool(); 881 882 if (isCustomFont) { 883 884 // read the length of the custom font from the stream 885 uint32_t len = stream->readU32(); 886 887 // generate a new stream to store the custom typeface 888 SkMemoryStream* fontStream = new SkMemoryStream(len); 889 stream->read((void*)fontStream->getMemoryBase(), len); 890 891 SkTypeface* face = createTypefaceFromStreamLocked(fontStream); 892 893 fontStream->unref(); 894 895 // SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len); 896 return face; 897 898 } else { 899 int style = stream->readU8(); 900 901 int len = stream->readPackedUInt(); 902 if (len > 0) { 903 SkString str; 904 str.resize(len); 905 stream->read(str.writable_str(), len); 906 907 for (int i = 0; i < gSystemFonts.count(); i++) { 908 if (strcmp(gSystemFonts[i].fFileName, str.c_str()) == 0) { 909 // backup until we hit the fNames 910 for (int j = i; j >= 0; --j) { 911 if (gSystemFonts[j].fNames != NULL) { 912 return createTypefaceLocked(NULL, 913 gSystemFonts[j].fNames[0], NULL, 0, 914 (SkTypeface::Style)style); 915 } 916 } 917 } 918 } 919 } 920 } 921 return NULL; 922 } 923 924 /////////////////////////////////////////////////////////////////////////////// 925 926 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 927 const char familyName[], 928 const void* data, size_t bytelength, 929 SkTypeface::Style style) { 930 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 931 return createTypefaceLocked(familyFace, familyName, data, bytelength, style); 932 } 933 934 static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace, 935 const char familyName[], const void* data, size_t bytelength, 936 SkTypeface::Style style) { 937 loadSystemFontsLocked(); 938 939 // clip to legal style bits 940 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 941 942 SkTypeface* tf = NULL; 943 944 if (NULL != familyFace) { 945 tf = findTypefaceLocked(familyFace, style); 946 } else if (NULL != familyName) { 947 // SkDebugf("======= familyName <%s>\n", familyName); 948 tf = findTypefaceLocked(familyName, style); 949 } 950 951 if (NULL == tf) { 952 tf = findBestFaceLocked(gDefaultFamily, style); 953 } 954 955 // we ref(), since the semantic is to return a new instance 956 tf->ref(); 957 return tf; 958 } 959 960 SkStream* SkFontHost::OpenStream(uint32_t fontID) { 961 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 962 return openStreamLocked(fontID); 963 } 964 965 static SkStream* openStreamLocked(uint32_t fontID) { 966 FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID); 967 SkStream* stream = tf ? tf->openStream() : NULL; 968 969 if (stream && stream->getLength() == 0) { 970 stream->unref(); 971 stream = NULL; 972 } 973 return stream; 974 } 975 976 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, 977 int32_t* index) { 978 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 979 return getFileNameLocked(fontID, path, length, index); 980 } 981 982 static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index) { 983 FamilyTypeface* tf = (FamilyTypeface*)findFromUniqueIDLocked(fontID); 984 const char* src = tf ? tf->getFilePath() : NULL; 985 986 if (src) { 987 size_t size = strlen(src); 988 if (path) { 989 memcpy(path, src, SkMin32(size, length)); 990 } 991 if (index) { 992 *index = 0; // we don't have collections (yet) 993 } 994 return size; 995 } else { 996 return 0; 997 } 998 } 999 1000 SkFontID SkFontHost::NextLogicalFont(const SkScalerContext::Rec& rec) { 1001 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 1002 return nextLogicalFontLocked(rec); 1003 } 1004 1005 static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec) { 1006 loadSystemFontsLocked(); 1007 1008 const SkTypeface* origTypeface = findFromUniqueIDLocked(rec.fOrigFontID); 1009 const SkTypeface* currTypeface = findFromUniqueIDLocked(rec.fFontID); 1010 1011 FallbackFontList* currentFallbackList = 1012 getFallbackFontListLocked(rec.fLanguage); 1013 SkASSERT(currentFallbackList); 1014 1015 SkASSERT(origTypeface != 0); 1016 SkASSERT(currTypeface != 0); 1017 1018 // Our fallback list always stores the id of the plain in each fallback 1019 // family, so we transform currFontID to its plain equivalent. 1020 SkFontID plainFontID = findTypefaceLocked(currTypeface, SkTypeface::kNormal)->uniqueID(); 1021 1022 /* First see if fontID is already one of our fallbacks. If so, return 1023 its successor. If fontID is not in our list, then return the first one 1024 in our list. Note: list is zero-terminated, and returning zero means 1025 we have no more fonts to use for fallbacks. 1026 */ 1027 int plainFallbackFontIndex = findFallbackFontIndex(plainFontID, currentFallbackList); 1028 int nextFallbackFontIndex = plainFallbackFontIndex + 1; 1029 1030 // If a rec object is set to prefer "kDefault_Variant" it means they have no preference 1031 // In this case, we set the value to "kCompact_Variant" 1032 SkPaint::FontVariant recPreference = rec.fFontVariant; 1033 if (recPreference == SkPaint::kDefault_Variant) { 1034 recPreference = SkPaint::kCompact_Variant; 1035 } 1036 SkFontID nextFontID = 0; 1037 while (nextFallbackFontIndex < currentFallbackList->fList.count()) { 1038 bool normalFont = 1039 (currentFallbackList->fList[nextFallbackFontIndex].fVariant == SkPaint::kDefault_Variant); 1040 bool fontChosen = (currentFallbackList->fList[nextFallbackFontIndex].fVariant == recPreference); 1041 if (normalFont || fontChosen) { 1042 const SkTypeface* nextTypeface = 1043 findFromUniqueIDLocked(currentFallbackList->fList[nextFallbackFontIndex].fFontID); 1044 nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID(); 1045 break; 1046 } 1047 nextFallbackFontIndex++; 1048 } 1049 1050 SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, " 1051 "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d " 1052 "=> nextFontID=%d", rec.fFontID, rec.fOrigFontID, plainFontID, 1053 plainFallbackFontIndex, nextFallbackFontIndex, nextFontID)); 1054 return nextFontID; 1055 } 1056 1057 /////////////////////////////////////////////////////////////////////////////// 1058 1059 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 1060 SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); 1061 return createTypefaceFromStreamLocked(stream); 1062 } 1063 1064 static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream) { 1065 if (NULL == stream || stream->getLength() <= 0) { 1066 return NULL; 1067 } 1068 1069 // Make sure system fonts are loaded first to comply with the assumption 1070 // that the font's uniqueID can be found using the findUniqueIDLocked method. 1071 loadSystemFontsLocked(); 1072 1073 bool isFixedWidth; 1074 SkTypeface::Style style; 1075 1076 if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) { 1077 SkTypeface* typeface = SkNEW_ARGS(StreamTypeface, (style, false, stream, isFixedWidth)); 1078 addTypefaceLocked(typeface, NULL); 1079 return typeface; 1080 } else { 1081 return NULL; 1082 } 1083 } 1084 1085 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 1086 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path)); 1087 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream); 1088 // since we created the stream, we let go of our ref() here 1089 stream->unref(); 1090 return face; 1091 } 1092 1093 /////////////////////////////////////////////////////////////////////////////// 1094 // Function from SkTypeface_android.h 1095 /////////////////////////////////////////////////////////////////////////////// 1096 1097 static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style, 1098 SkPaint::FontVariant fontVariant) { 1099 SkTypeface* face = FindBestFace(gDefaultFamily, style); 1100 if (!face) { 1101 return 0; 1102 } 1103 1104 SkPaint paint; 1105 paint.setTypeface(face); 1106 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 1107 paint.setFontVariant(fontVariant); 1108 1109 SkAutoGlyphCache autoCache(paint, NULL); 1110 SkGlyphCache* cache = autoCache.getCache(); 1111 SkFontID fontID = 0; 1112 1113 SkScalerContext* ctx = cache->getScalerContext(); 1114 if (ctx) { 1115 return ctx->findTypefaceIdForChar(uni); 1116 } 1117 return 0; 1118 } 1119 1120 struct HB_UnicodeMapping { 1121 HB_Script script; 1122 const SkUnichar unicode; 1123 }; 1124 1125 /* 1126 * The following scripts are not complex fonts and we do not expect them to be parsed by this table 1127 * HB_Script_Common, 1128 * HB_Script_Greek, 1129 * HB_Script_Cyrillic, 1130 * HB_Script_Hangul 1131 * HB_Script_Inherited 1132 */ 1133 1134 static HB_UnicodeMapping HB_UnicodeMappingArray[] { 1135 {HB_Script_Armenian, 0x0531}, 1136 {HB_Script_Hebrew, 0x0591}, 1137 {HB_Script_Arabic, 0x0600}, 1138 {HB_Script_Syriac, 0x0710}, 1139 {HB_Script_Thaana, 0x0780}, 1140 {HB_Script_Nko, 0x07C0}, 1141 {HB_Script_Devanagari, 0x0901}, 1142 {HB_Script_Bengali, 0x0981}, 1143 {HB_Script_Gurmukhi, 0x0A10}, 1144 {HB_Script_Gujarati, 0x0A90}, 1145 {HB_Script_Oriya, 0x0B10}, 1146 {HB_Script_Tamil, 0x0B82}, 1147 {HB_Script_Telugu, 0x0C10}, 1148 {HB_Script_Kannada, 0x0C90}, 1149 {HB_Script_Malayalam, 0x0D10}, 1150 {HB_Script_Sinhala, 0x0D90}, 1151 {HB_Script_Thai, 0x0E01}, 1152 {HB_Script_Lao, 0x0E81}, 1153 {HB_Script_Tibetan, 0x0F00}, 1154 {HB_Script_Myanmar, 0x1000}, 1155 {HB_Script_Georgian, 0x10A0}, 1156 // we don't currently support HB_Script_Ethiopic, it is a placeholder for an upstream merge 1157 //{HB_Script_Ethiopic, 0x1200}, 1158 {HB_Script_Ogham, 0x1680}, 1159 {HB_Script_Runic, 0x16A0}, 1160 {HB_Script_Khmer, 0x1780}, 1161 }; 1162 1163 // returns 0 for "Not Found" 1164 static SkUnichar getUnicodeFromHBScript(HB_Script script) { 1165 SkUnichar unichar = 0; 1166 int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping); 1167 for (int i = 0; i < numSupportedFonts; i++) { 1168 if (script == HB_UnicodeMappingArray[i].script) { 1169 unichar = HB_UnicodeMappingArray[i].unicode; 1170 break; 1171 } 1172 } 1173 return unichar; 1174 } 1175 1176 struct TypefaceLookupStruct { 1177 HB_Script script; 1178 SkTypeface::Style style; 1179 SkPaint::FontVariant fontVariant; 1180 SkTypeface* typeface; 1181 }; 1182 1183 SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex); // This is the mutex for gTypefaceTable 1184 static SkTDArray<TypefaceLookupStruct> gTypefaceTable; // This is protected by gTypefaceTableMutex 1185 1186 static int typefaceLookupCompare(const TypefaceLookupStruct& first, 1187 const TypefaceLookupStruct& second) { 1188 if (first.script != second.script) { 1189 return (first.script > second.script) ? 1 : -1; 1190 } 1191 if (first.style != second.style) { 1192 return (first.style > second.style) ? 1 : -1; 1193 } 1194 if (first.fontVariant != second.fontVariant) { 1195 return (first.fontVariant > second.fontVariant) ? 1 : -1; 1196 } 1197 return 0; 1198 } 1199 1200 SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style, 1201 SkPaint::FontVariant fontVariant) { 1202 SkTypeface* retTypeface = NULL; 1203 1204 SkAutoMutexAcquire ac(gTypefaceTableMutex); // Note: NOT gFamilyHeadAndNameListMutex 1205 TypefaceLookupStruct key; 1206 key.script = script; 1207 key.style = style; 1208 key.fontVariant = fontVariant; 1209 int index = SkTSearch<TypefaceLookupStruct>( 1210 (const TypefaceLookupStruct*) gTypefaceTable.begin(), 1211 gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct), 1212 &typefaceLookupCompare); 1213 if (index >= 0) { 1214 retTypeface = gTypefaceTable[index].typeface; 1215 } 1216 else { 1217 SkUnichar unichar = getUnicodeFromHBScript(script); 1218 if (!unichar) { 1219 return NULL; 1220 } 1221 SkFontID newFontID = findFontIDForChar(unichar, style, fontVariant); 1222 // retrieve the typeface that corresponds to this fontID 1223 retTypeface = FindFromUniqueID(newFontID); 1224 key.typeface = retTypeface; 1225 index = ~index; 1226 *gTypefaceTable.insert(index) = key; 1227 } 1228 // we ref(), the caller is expected to unref when they are done 1229 SkSafeRef(retTypeface); 1230 return retTypeface; 1231 } 1232