SkFontHost_linux.cpp revision b6896e72c773332552d94c27ccee5d30498de3aa
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontHost.h" 119714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com#include "SkFontDescriptor.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDescriptor.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMMapStream.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOSFile.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTSearch.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SK_FONT_FILE_PREFIX 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/msttcorefonts/" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 254dc686d75353235260c716242f4ed596b70beb95djsollen@google.combool find_name_and_attributes(SkStream* stream, SkString* name, 264dc686d75353235260c716242f4ed596b70beb95djsollen@google.com SkTypeface::Style* style, bool* isFixedWidth); 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void GetFullPathForSysFonts(SkString* full, const char name[]) 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com full->append(SK_FONT_FILE_PREFIX); 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com full->append(name); 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct FamilyRec; 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* This guy holds a mapping of a name -> family, used for looking up fonts. 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Since it is stored in a stretchy array that doesn't preserve object 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com semantics, we don't use constructor/destructors, but just have explicit 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com helpers to manage our internal bookkeeping. 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct NameFamilyPair { 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* fName; // we own this 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* fFamily; // we don't own this, we just reference it 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void construct(const char name[], FamilyRec* family) 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fName = strdup(name); 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFamily = family; // we don't own this, so just record the referene 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void destruct() 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com free((char*)fName); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we don't own family, so just ignore our reference 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// we use atomic_inc to grow this for each typeface we create 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int32_t gUniqueFontID; 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this is the mutex that protects these globals 631771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.comSK_DECLARE_STATIC_MUTEX(gFamilyMutex); 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic FamilyRec* gFamilyHead; 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTDArray<NameFamilyPair> gNameList; 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct FamilyRec { 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* fNext; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTypeface* fFaces[4]; 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec() 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNext = gFamilyHead; 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(fFaces, 0, sizeof(fFaces)); 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gFamilyHead = this; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTypeface* find_best_face(const FamilyRec* family, 801bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com SkTypeface::Style style) { 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTypeface* const* faces = family->fFaces; 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (faces[style] != NULL) { // exact match 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return faces[style]; 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for a matching bold 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (faces[style] != NULL) { 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return faces[style]; 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for the plain 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (faces[SkTypeface::kNormal] != NULL) { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return faces[SkTypeface::kNormal]; 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for anything 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 4; i++) { 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (faces[i] != NULL) { 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return faces[i]; 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // should never get here, since the faces list should not be empty 1020c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("faces list is empty"); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1061bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comstatic FamilyRec* find_family(const SkTypeface* member) { 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* curr = gFamilyHead; 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (curr != NULL) { 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 4; i++) { 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (curr->fFaces[i] == member) { 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return curr; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com curr = curr->fNext; 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 119f2afb67bab01062d2632543c1f004b166bf01e31reed@android.comstatic SkTypeface* find_from_uniqueID(uint32_t uniqueID) { 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* curr = gFamilyHead; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (curr != NULL) { 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 4; i++) { 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTypeface* face = curr->fFaces[i]; 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (face != NULL && face->uniqueID() == uniqueID) { 125f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com return face; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com curr = curr->fNext; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13017b78946096265d80215a6c946286ecaa35ea7edepoger@google.com return NULL; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Remove reference to this face from its family. If the resulting family 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com is empty (has no faces), return that family, otherwise return NULL 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1361bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comstatic FamilyRec* remove_from_family(const SkTypeface* face) { 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* family = find_family(face); 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(family->fFaces[face->style()] == face); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com family->fFaces[face->style()] = NULL; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 4; i++) { 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (family->fFaces[i] != NULL) { // family is non-empty 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return family; // return the empty family 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// maybe we should make FamilyRec be doubly-linked 1501bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comstatic void detach_and_delete_family(FamilyRec* family) { 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* curr = gFamilyHead; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* prev = NULL; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (curr != NULL) { 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* next = curr->fNext; 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (curr == family) { 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prev == NULL) { 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gFamilyHead = next; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fNext = next; 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(family); 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev = curr; 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com curr = next; 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1680c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1719714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.comstatic const char* find_family_name(const SkTypeface* familyMember) { 1729714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com const FamilyRec* familyRec = find_family(familyMember); 1739714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com for (int i = 0; i < gNameList.count(); i++) { 1749714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com if (gNameList[i].fFamily == familyRec) { 1759714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com return gNameList[i].fName; 1769714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com } 1779714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com } 1789714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com return NULL; 1799714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com} 1809714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic FamilyRec* find_familyrec(const char name[]) { 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const NameFamilyPair* list = gNameList.begin(); 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sizeof(list[0])); 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return index >= 0 ? list[index].fFamily : NULL; 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* rec = find_familyrec(name); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec ? find_best_face(rec, style) : NULL; 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTypeface* find_typeface(const SkTypeface* familyMember, 1941bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com SkTypeface::Style style) { 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const FamilyRec* family = find_family(familyMember); 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return family ? find_best_face(family, style) : NULL; 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1991bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comstatic void add_name(const char name[], FamilyRec* family) { 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoAsciiToLC tolc(name); 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com name = tolc.lc(); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NameFamilyPair* list = gNameList.begin(); 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = gNameList.count(); 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index < 0) { 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com list = gNameList.insert(~index); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com list->construct(name, family); 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2141bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comstatic void remove_from_names(FamilyRec* emptyFamily) { 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 4; i++) { 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(emptyFamily->fFaces[i] == NULL); 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<NameFamilyPair>& list = gNameList; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // must go backwards when removing 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = list.count() - 1; i >= 0; --i) { 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NameFamilyPair* pair = &list[i]; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (pair->fFamily == emptyFamily) { 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pair->destruct(); 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com list.remove(i); 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass FamilyTypeface : public SkTypeface { 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2373681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedWidth) 2383681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) { 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fIsSysFont = sysFont; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFamilyMutex); 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == family) { 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com family = SkNEW(FamilyRec); 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com family->fFaces[style] = this; 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFamilyRec = family; // just record it so we can return it if asked 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2501bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com virtual ~FamilyTypeface() { 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFamilyMutex); 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // remove us from our family. If the family is now empty, we return 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // that and then remove that family from the name list 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* family = remove_from_family(this); 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != family) { 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com remove_from_names(family); 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com detach_and_delete_family(family); 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isSysFont() const { return fIsSysFont; } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* getFamily() const { return fFamilyRec; } 26422dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com // openStream returns a SkStream that has been ref-ed 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual SkStream* openStream() = 0; 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual const char* getUniqueString() const = 0; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* fFamilyRec; // we don't own this, just point to it 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fIsSysFont; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkTypeface INHERITED; 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 277f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com/* This subclass is just a place holder for when we have no fonts available. 278f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com It exists so that our globals (e.g. gFamilyHead) that expect *something* 279f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com will not be null. 280f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com */ 281f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.comclass EmptyTypeface : public FamilyTypeface { 282f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.compublic: 2833681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {} 284f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com 285f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com // overrides 286f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com virtual SkStream* openStream() { return NULL; } 287f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com virtual const char* getUniqueString() const { return NULL; } 288f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com 289f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.comprivate: 290f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com typedef FamilyTypeface INHERITED; 291f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com}; 292f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass StreamTypeface : public FamilyTypeface { 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com StreamTypeface(Style style, bool sysFont, FamilyRec* family, 2963681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com SkStream* stream, bool isFixedWidth) 2973681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com : INHERITED(style, sysFont, family, isFixedWidth) { 2981c0c5a0a52d0d94653c6ca959a43226228a5ca08reed@android.com stream->ref(); 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStream = stream; 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3011bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com virtual ~StreamTypeface() { 3021c0c5a0a52d0d94653c6ca959a43226228a5ca08reed@android.com fStream->unref(); 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // overrides 30622dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com virtual SkStream* openStream() 30722dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com { 30822dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com // openStream returns a refed stream. 30922dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com fStream->ref(); 31022dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com return fStream; 31122dbaaf405e70da862a430f5e2558ce63ce17372reed@android.com } 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual const char* getUniqueString() const { return NULL; } 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkStream* fStream; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef FamilyTypeface INHERITED; 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass FileTypeface : public FamilyTypeface { 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FileTypeface(Style style, bool sysFont, FamilyRec* family, 3233681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com const char path[], bool isFixedWidth) 3243681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com : INHERITED(style, sysFont, family, isFixedWidth) { 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPath.set(path); 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // overrides 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual SkStream* openStream() 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for failure 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stream->getLength() <= 0) { 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(stream); 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // maybe MMAP isn't supported. try FILE 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stream->getLength() <= 0) { 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(stream); 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stream = NULL; 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return stream; 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 34551709c748e32bb115103b1468eb507f4ccaa7ee8reed@android.com 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual const char* getUniqueString() const { 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* str = strrchr(fPath.c_str(), '/'); 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (str) { 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com str += 1; // skip the '/' 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return str; 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString fPath; 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef FamilyTypeface INHERITED; 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool get_name_and_style(const char path[], SkString* name, 3643681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com SkTypeface::Style* style, bool* isFixedWidth) { 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMMAPStream stream(path); 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stream.getLength() > 0) { 3674dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return find_name_and_attributes(&stream, name, style, isFixedWidth); 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFILEStream stream(path); 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stream.getLength() > 0) { 3724dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return find_name_and_attributes(&stream, name, style, isFixedWidth); 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("---- failed to open <%s> as a font\n", path); 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// these globals are assigned (once) by load_system_fonts() 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTypeface* gFallBackTypeface; 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic FamilyRec* gDefaultFamily; 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTypeface* gDefaultNormal; 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3851bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comstatic void load_system_fonts() { 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we've already be called 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != gDefaultNormal) { 3886fb8f77abb561cec3eeb2d5c71ae9196770ddf00reed@google.com// printf("---- default font %p\n", gDefaultNormal); 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 391f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com 392f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com SkOSFile::Iter iter(SK_FONT_FILE_PREFIX, ".ttf"); 393f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com SkString name; 394f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com int count = 0; 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (iter.next(&name, false)) { 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString filename; 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com GetFullPathForSysFonts(&filename, name.c_str()); 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4003681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com bool isFixedWidth; 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString realname; 4026963af2327a9738d22716759dc39526a4935ecdereed@google.com SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4043681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedWidth)) { 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 408f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("font: <%s> %d <%s>\n", realname.c_str(), style, filename.c_str()); 410f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyRec* family = find_familyrec(realname.c_str()); 412887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com if (family && family->fFaces[style]) { 413887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com// SkDebugf("---- skipping duplicate typeface %s style %d\n", 414887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com// realname.c_str(), style); 415887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com continue; 416887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com } 417887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this constructor puts us into the global gFamilyHead llist 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (style, 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com true, // system-font (cannot delete) 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com family, // what family to join 4233681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com filename.c_str(), 4243681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com isFixedWidth) // filename 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ); 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == family) { 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com add_name(realname.c_str(), tf->getFamily()); 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 430f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com count += 1; 431f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com } 432f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com 433f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com if (0 == count) { 434f244f1b19f07b1c946f8d7e24decbe1809dda7f6reed@android.com SkNEW(EmptyTypeface); 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 436f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // do this after all fonts are loaded. This is our default font, and it 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // acts as a sentinel so we only execute load_system_fonts() once 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const char* gDefaultNames[] = { 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "Arial", "Verdana", "Times New Roman", NULL 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char** names = gDefaultNames; 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (*names) { 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (tf) { 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gDefaultNormal = tf; 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we found *something* 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == gDefaultNormal) { 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == gFamilyHead) { 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_throw(); 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 4; i++) { 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == gDefaultNormal) { 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_throw(); 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gFallBackTypeface = gDefaultNormal; 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gDefaultFamily = find_family(gDefaultNormal); 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("---- default %p head %p family %p\n", gDefaultNormal, gFamilyHead, gDefaultFamily); 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 4739714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 4749714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com SkFontDescriptor descriptor; 475b6896e72c773332552d94c27ccee5d30498de3aabungeman@google.com descriptor.setFamilyName(find_family_name(face)); 476b6896e72c773332552d94c27ccee5d30498de3aabungeman@google.com descriptor.setStyle(face->style()); 4779714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com descriptor.setFontFileName(((FamilyTypeface*)face)->getUniqueString()); 4789714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 4799714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com descriptor.serialize(stream); 4809714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 4819714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com const bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); 4829714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com if (isCustomFont) { 4839714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com // store the entire font in the fontData 4849714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); 4859714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com const uint32_t length = fontStream->getLength(); 4869714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 4879714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com stream->writePackedUInt(length); 4889714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com stream->writeStream(fontStream, length); 4899714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 4909714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com fontStream->unref(); 491e6488add7f8b1efa9b8b38d5737b98e7c63b3b79djsollen@google.com } else { 4929714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com stream->writePackedUInt(0); 493e6488add7f8b1efa9b8b38d5737b98e7c63b3b79djsollen@google.com } 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkTypeface* SkFontHost::Deserialize(SkStream* stream) { 4979714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com { 4989714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com SkAutoMutexAcquire ac(gFamilyMutex); 4999714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com load_system_fonts(); 500e6488add7f8b1efa9b8b38d5737b98e7c63b3b79djsollen@google.com } 5019714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 5029714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com SkFontDescriptor descriptor(stream); 503b6896e72c773332552d94c27ccee5d30498de3aabungeman@google.com const char* familyName = descriptor.getFamilyName(); 5049714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com const char* typefaceName = descriptor.getFontFileName(); 505b6896e72c773332552d94c27ccee5d30498de3aabungeman@google.com const SkTypeface::Style style = descriptor.getStyle(); 5069714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 5079714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com const uint32_t customFontDataLength = stream->readPackedUInt(); 5089714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com if (customFontDataLength > 0) { 5099714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 5109714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com // generate a new stream to store the custom typeface 5119714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com SkMemoryStream* fontStream = new SkMemoryStream(customFontDataLength - 1); 5129714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com stream->read((void*)fontStream->getMemoryBase(), customFontDataLength - 1); 5139714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 5149714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com SkTypeface* face = CreateTypefaceFromStream(fontStream); 5159714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 5169714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com fontStream->unref(); 5179714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com return face; 5189714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com } 5199714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com 5209714516a0db56fe1c59d5e831cb0c6d820102c30djsollen@google.com return SkFontHost::CreateTypeface(NULL, familyName, style); 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 525b1d9d2ef2803bd55fdc886d13033b48f8450dd14reed@android.comSkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 526b1d9d2ef2803bd55fdc886d13033b48f8450dd14reed@android.com const char familyName[], 527b1d9d2ef2803bd55fdc886d13033b48f8450dd14reed@android.com SkTypeface::Style style) { 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com load_system_fonts(); 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFamilyMutex); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clip to legal style bits 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTypeface* tf = NULL; 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != familyFace) { 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tf = find_typeface(familyFace, style); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (NULL != familyName) { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkDebugf("======= familyName <%s>\n", familyName); 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tf = find_typeface(familyName, style); 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == tf) { 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tf = find_best_face(gDefaultFamily, style); 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 547887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com 548887e4f325c2b9b306116a4eea37c5afad1db3346reed@android.com SkSafeRef(tf); 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return tf; 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5521bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comSkStream* SkFontHost::OpenStream(uint32_t fontID) { 553f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID); 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkStream* stream = tf ? tf->openStream() : NULL; 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5561c0c5a0a52d0d94653c6ca959a43226228a5ca08reed@android.com if (stream && stream->getLength() == 0) { 5571c0c5a0a52d0d94653c6ca959a43226228a5ca08reed@android.com stream->unref(); 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stream = NULL; 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return stream; 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 563ac98154faa0e786444bafcd093fd4842127fbf18reed@android.comsize_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, 564ac98154faa0e786444bafcd093fd4842127fbf18reed@android.com int32_t* index) { 565ac98154faa0e786444bafcd093fd4842127fbf18reed@android.com SkDebugf("SkFontHost::GetFileName unimplemented\n"); 566ac98154faa0e786444bafcd093fd4842127fbf18reed@android.com return 0; 567ac98154faa0e786444bafcd093fd4842127fbf18reed@android.com} 568ac98154faa0e786444bafcd093fd4842127fbf18reed@android.com 5697d26c590f6bc431a5ecf5c25619b64d058613a4dreed@google.comSkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { 570f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com return 0; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 575b1d9d2ef2803bd55fdc886d13033b48f8450dd14reed@android.comSkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == stream || stream->getLength() <= 0) { 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(stream); 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5803681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com 5813681276c7847594ff7b175c01dbd6b5d87e9d286reed@google.com bool isFixedWidth; 5824dc686d75353235260c716242f4ed596b70beb95djsollen@google.com SkTypeface::Style style; 5834dc686d75353235260c716242f4ed596b70beb95djsollen@google.com if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) { 5844dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth)); 5854dc686d75353235260c716242f4ed596b70beb95djsollen@google.com } else { 5864dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return NULL; 5874dc686d75353235260c716242f4ed596b70beb95djsollen@google.com } 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5901bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.comSkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 5911bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com SkTypeface* face = NULL; 5921bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path)); 5931bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com 5941bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com if (stream->isValid()) { 595f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com face = CreateTypefaceFromStream(stream); 5961bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com } 5971bfd0ca7804a082ce29fd56adb311c79fc11a99freed@android.com stream->unref(); 598f2afb67bab01062d2632543c1f004b166bf01e31reed@android.com return face; 5990becfc5b7608ba67a4c98721cd61939e89ac5653reed@android.com} 6000becfc5b7608ba67a4c98721cd61939e89ac5653reed@android.com 601