SkFontHost_linux.cpp revision 4f7e846cd8b577fc40f30cce6d982d853763a3eb
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkFontHost.h" 11#include "SkFontDescriptor.h" 12#include "SkDescriptor.h" 13#include "SkOSFile.h" 14#include "SkPaint.h" 15#include "SkString.h" 16#include "SkStream.h" 17#include "SkThread.h" 18#include "SkTSearch.h" 19 20#ifndef SK_FONT_FILE_PREFIX 21 #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" 22#endif 23#ifndef SK_FONT_FILE_DIR_SEPERATOR 24 #define SK_FONT_FILE_DIR_SEPERATOR "/" 25#endif 26 27bool find_name_and_attributes(SkStream* stream, SkString* name, 28 SkTypeface::Style* style, bool* isFixedWidth); 29 30/////////////////////////////////////////////////////////////////////////////// 31 32struct FamilyRec; 33 34/* This guy holds a mapping of a name -> family, used for looking up fonts. 35 Since it is stored in a stretchy array that doesn't preserve object 36 semantics, we don't use constructor/destructors, but just have explicit 37 helpers to manage our internal bookkeeping. 38 */ 39struct NameFamilyPair { 40 const char* fName; // we own this 41 FamilyRec* fFamily; // we don't own this, we just reference it 42 43 void construct(const char name[], FamilyRec* family) 44 { 45 fName = strdup(name); 46 fFamily = family; // we don't own this, so just record the referene 47 } 48 void destruct() 49 { 50 free((char*)fName); 51 // we don't own family, so just ignore our reference 52 } 53}; 54 55// we use atomic_inc to grow this for each typeface we create 56static int32_t gUniqueFontID; 57 58// this is the mutex that protects these globals 59SK_DECLARE_STATIC_MUTEX(gFamilyMutex); 60static FamilyRec* gFamilyHead; 61static SkTDArray<NameFamilyPair> gNameList; 62 63struct FamilyRec { 64 FamilyRec* fNext; 65 SkTypeface* fFaces[4]; 66 67 FamilyRec() 68 { 69 fNext = gFamilyHead; 70 memset(fFaces, 0, sizeof(fFaces)); 71 gFamilyHead = this; 72 } 73}; 74 75static SkTypeface* find_best_face(const FamilyRec* family, 76 SkTypeface::Style style) { 77 SkTypeface* const* faces = family->fFaces; 78 79 if (faces[style] != NULL) { // exact match 80 return faces[style]; 81 } 82 // look for a matching bold 83 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 84 if (faces[style] != NULL) { 85 return faces[style]; 86 } 87 // look for the plain 88 if (faces[SkTypeface::kNormal] != NULL) { 89 return faces[SkTypeface::kNormal]; 90 } 91 // look for anything 92 for (int i = 0; i < 4; i++) { 93 if (faces[i] != NULL) { 94 return faces[i]; 95 } 96 } 97 // should never get here, since the faces list should not be empty 98 SkDEBUGFAIL("faces list is empty"); 99 return NULL; 100} 101 102static FamilyRec* find_family(const SkTypeface* member) { 103 FamilyRec* curr = gFamilyHead; 104 while (curr != NULL) { 105 for (int i = 0; i < 4; i++) { 106 if (curr->fFaces[i] == member) { 107 return curr; 108 } 109 } 110 curr = curr->fNext; 111 } 112 return NULL; 113} 114 115static SkTypeface* find_from_uniqueID(uint32_t uniqueID) { 116 FamilyRec* curr = gFamilyHead; 117 while (curr != NULL) { 118 for (int i = 0; i < 4; i++) { 119 SkTypeface* face = curr->fFaces[i]; 120 if (face != NULL && face->uniqueID() == uniqueID) { 121 return face; 122 } 123 } 124 curr = curr->fNext; 125 } 126 return NULL; 127} 128 129/* Remove reference to this face from its family. If the resulting family 130 is empty (has no faces), return that family, otherwise return NULL 131 */ 132static FamilyRec* remove_from_family(const SkTypeface* face) { 133 FamilyRec* family = find_family(face); 134 SkASSERT(family->fFaces[face->style()] == face); 135 family->fFaces[face->style()] = NULL; 136 137 for (int i = 0; i < 4; i++) { 138 if (family->fFaces[i] != NULL) { // family is non-empty 139 return NULL; 140 } 141 } 142 return family; // return the empty family 143} 144 145// maybe we should make FamilyRec be doubly-linked 146static void detach_and_delete_family(FamilyRec* family) { 147 FamilyRec* curr = gFamilyHead; 148 FamilyRec* prev = NULL; 149 150 while (curr != NULL) { 151 FamilyRec* next = curr->fNext; 152 if (curr == family) { 153 if (prev == NULL) { 154 gFamilyHead = next; 155 } else { 156 prev->fNext = next; 157 } 158 SkDELETE(family); 159 return; 160 } 161 prev = curr; 162 curr = next; 163 } 164 SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); 165} 166 167static const char* find_family_name(const SkTypeface* familyMember) { 168 const FamilyRec* familyRec = find_family(familyMember); 169 for (int i = 0; i < gNameList.count(); i++) { 170 if (gNameList[i].fFamily == familyRec) { 171 return gNameList[i].fName; 172 } 173 } 174 return NULL; 175} 176 177static FamilyRec* find_familyrec(const char name[]) { 178 const NameFamilyPair* list = gNameList.begin(); 179 int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, 180 sizeof(list[0])); 181 return index >= 0 ? list[index].fFamily : NULL; 182} 183 184static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { 185 FamilyRec* rec = find_familyrec(name); 186 return rec ? find_best_face(rec, style) : NULL; 187} 188 189static SkTypeface* find_typeface(const SkTypeface* familyMember, 190 SkTypeface::Style style) { 191 const FamilyRec* family = find_family(familyMember); 192 return family ? find_best_face(family, style) : NULL; 193} 194 195static void add_name(const char name[], FamilyRec* family) { 196 SkAutoAsciiToLC tolc(name); 197 name = tolc.lc(); 198 199 NameFamilyPair* list = gNameList.begin(); 200 int count = gNameList.count(); 201 202 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 203 204 if (index < 0) { 205 list = gNameList.insert(~index); 206 list->construct(name, family); 207 } 208} 209 210static void remove_from_names(FamilyRec* emptyFamily) { 211#ifdef SK_DEBUG 212 for (int i = 0; i < 4; i++) { 213 SkASSERT(emptyFamily->fFaces[i] == NULL); 214 } 215#endif 216 217 SkTDArray<NameFamilyPair>& list = gNameList; 218 219 // must go backwards when removing 220 for (int i = list.count() - 1; i >= 0; --i) { 221 NameFamilyPair* pair = &list[i]; 222 if (pair->fFamily == emptyFamily) { 223 pair->destruct(); 224 list.remove(i); 225 } 226 } 227} 228 229/////////////////////////////////////////////////////////////////////////////// 230 231class FamilyTypeface : public SkTypeface { 232public: 233 FamilyTypeface(Style style, bool sysFont, FamilyRec* family, bool isFixedWidth) 234 : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) { 235 fIsSysFont = sysFont; 236 237 SkAutoMutexAcquire ac(gFamilyMutex); 238 239 if (NULL == family) { 240 family = SkNEW(FamilyRec); 241 } 242 family->fFaces[style] = this; 243 fFamilyRec = family; // just record it so we can return it if asked 244 } 245 246 virtual ~FamilyTypeface() { 247 SkAutoMutexAcquire ac(gFamilyMutex); 248 249 // remove us from our family. If the family is now empty, we return 250 // that and then remove that family from the name list 251 FamilyRec* family = remove_from_family(this); 252 if (NULL != family) { 253 remove_from_names(family); 254 detach_and_delete_family(family); 255 } 256 } 257 258 bool isSysFont() const { return fIsSysFont; } 259 FamilyRec* getFamily() const { return fFamilyRec; } 260 // openStream returns a SkStream that has been ref-ed 261 virtual SkStream* openStream() = 0; 262 virtual const char* getUniqueString() const = 0; 263 264private: 265 FamilyRec* fFamilyRec; // we don't own this, just point to it 266 bool fIsSysFont; 267 268 typedef SkTypeface INHERITED; 269}; 270 271/////////////////////////////////////////////////////////////////////////////// 272 273/* This subclass is just a place holder for when we have no fonts available. 274 It exists so that our globals (e.g. gFamilyHead) that expect *something* 275 will not be null. 276 */ 277class EmptyTypeface : public FamilyTypeface { 278public: 279 EmptyTypeface() : INHERITED(SkTypeface::kNormal, true, NULL, false) {} 280 281 // overrides 282 virtual SkStream* openStream() SK_OVERRIDE { return NULL; } 283 virtual const char* getUniqueString() SK_OVERRIDE const { return NULL; } 284 285private: 286 typedef FamilyTypeface INHERITED; 287}; 288 289class StreamTypeface : public FamilyTypeface { 290public: 291 StreamTypeface(Style style, bool sysFont, FamilyRec* family, 292 SkStream* stream, bool isFixedWidth) 293 : INHERITED(style, sysFont, family, isFixedWidth) { 294 stream->ref(); 295 fStream = stream; 296 } 297 virtual ~StreamTypeface() { 298 fStream->unref(); 299 } 300 301 virtual SkStream* openStream() SK_OVERRIDE { 302 // openStream returns a refed stream. 303 fStream->ref(); 304 return fStream; 305 } 306 virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } 307 308private: 309 SkStream* fStream; 310 311 typedef FamilyTypeface INHERITED; 312}; 313 314class FileTypeface : public FamilyTypeface { 315public: 316 FileTypeface(Style style, bool sysFont, FamilyRec* family, 317 const char path[], bool isFixedWidth) 318 : INHERITED(style, sysFont, family, isFixedWidth) { 319 fPath.set(path); 320 } 321 322 virtual SkStream* openStream() SK_OVERRIDE { 323 return SkStream::NewFromFile(fPath.c_str()); 324 } 325 326 virtual const char* getUniqueString() const SK_OVERRIDE { 327 const char* str = strrchr(fPath.c_str(), '/'); 328 if (str) { 329 str += 1; // skip the '/' 330 } 331 return str; 332 } 333 334private: 335 SkString fPath; 336 337 typedef FamilyTypeface INHERITED; 338}; 339 340/////////////////////////////////////////////////////////////////////////////// 341/////////////////////////////////////////////////////////////////////////////// 342 343static bool get_name_and_style(const char path[], SkString* name, 344 SkTypeface::Style* style, bool* isFixedWidth) { 345 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 346 if (stream.get()) { 347 return find_name_and_attributes(stream, name, style, isFixedWidth); 348 } else { 349 SkDebugf("---- failed to open <%s> as a font\n", path); 350 return false; 351 } 352} 353 354// these globals are assigned (once) by load_system_fonts() 355static SkTypeface* gFallBackTypeface; 356static FamilyRec* gDefaultFamily; 357static SkTypeface* gDefaultNormal; 358 359static void load_directory_fonts(const SkString& directory, unsigned int* count) { 360 SkOSFile::Iter iter(directory.c_str(), ".ttf"); 361 SkString name; 362 363 while (iter.next(&name, false)) { 364 SkString filename(directory); 365 filename.append(name); 366 367 bool isFixedWidth; 368 SkString realname; 369 SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning 370 371 if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedWidth)) { 372 SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); 373 continue; 374 } 375 376 FamilyRec* family = find_familyrec(realname.c_str()); 377 if (family && family->fFaces[style]) { 378 continue; 379 } 380 381 // this constructor puts us into the global gFamilyHead llist 382 FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, 383 (style, 384 true, // system-font (cannot delete) 385 family, // what family to join 386 filename.c_str(), 387 isFixedWidth) // filename 388 ); 389 390 if (NULL == family) { 391 add_name(realname.c_str(), tf->getFamily()); 392 } 393 *count += 1; 394 } 395 396 SkOSFile::Iter dirIter(directory.c_str()); 397 while (dirIter.next(&name, true)) { 398 if (name.startsWith(".")) { 399 continue; 400 } 401 SkString dirname(directory); 402 dirname.append(name); 403 dirname.append(SK_FONT_FILE_DIR_SEPERATOR); 404 load_directory_fonts(dirname, count); 405 } 406} 407 408static void load_system_fonts() { 409 // check if we've already be called 410 if (NULL != gDefaultNormal) { 411 return; 412 } 413 414 SkString baseDirectory(SK_FONT_FILE_PREFIX); 415 unsigned int count = 0; 416 load_directory_fonts(baseDirectory, &count); 417 418 if (0 == count) { 419 SkNEW(EmptyTypeface); 420 } 421 422 // do this after all fonts are loaded. This is our default font, and it 423 // acts as a sentinel so we only execute load_system_fonts() once 424 static const char* gDefaultNames[] = { 425 "Arial", "Verdana", "Times New Roman", NULL 426 }; 427 const char** names = gDefaultNames; 428 while (*names) { 429 SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); 430 if (tf) { 431 gDefaultNormal = tf; 432 break; 433 } 434 } 435 // check if we found *something* 436 if (NULL == gDefaultNormal) { 437 if (NULL == gFamilyHead) { 438 sk_throw(); 439 } 440 for (int i = 0; i < 4; i++) { 441 if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { 442 break; 443 } 444 } 445 } 446 if (NULL == gDefaultNormal) { 447 sk_throw(); 448 } 449 gFallBackTypeface = gDefaultNormal; 450 gDefaultFamily = find_family(gDefaultNormal); 451} 452 453/////////////////////////////////////////////////////////////////////////////// 454 455void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 456 457 SkFontDescriptor descriptor; 458 descriptor.setFamilyName(find_family_name(face)); 459 descriptor.setStyle(face->style()); 460 descriptor.setFontFileName(((FamilyTypeface*)face)->getUniqueString()); 461 462 descriptor.serialize(stream); 463 464 const bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); 465 if (isCustomFont) { 466 // store the entire font in the fontData 467 SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); 468 const uint32_t length = fontStream->getLength(); 469 470 stream->writePackedUInt(length); 471 stream->writeStream(fontStream, length); 472 473 fontStream->unref(); 474 } else { 475 stream->writePackedUInt(0); 476 } 477} 478 479SkTypeface* SkFontHost::Deserialize(SkStream* stream) { 480 load_system_fonts(); 481 482 SkFontDescriptor descriptor(stream); 483 const char* familyName = descriptor.getFamilyName(); 484 const SkTypeface::Style style = descriptor.getStyle(); 485 486 const uint32_t customFontDataLength = stream->readPackedUInt(); 487 if (customFontDataLength > 0) { 488 489 // generate a new stream to store the custom typeface 490 SkMemoryStream* fontStream = new SkMemoryStream(customFontDataLength - 1); 491 stream->read((void*)fontStream->getMemoryBase(), customFontDataLength - 1); 492 493 SkTypeface* face = CreateTypefaceFromStream(fontStream); 494 495 fontStream->unref(); 496 return face; 497 } 498 499 return SkFontHost::CreateTypeface(NULL, familyName, style); 500} 501 502/////////////////////////////////////////////////////////////////////////////// 503 504SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 505 const char familyName[], 506 SkTypeface::Style style) { 507 load_system_fonts(); 508 509 SkAutoMutexAcquire ac(gFamilyMutex); 510 511 // clip to legal style bits 512 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 513 514 SkTypeface* tf = NULL; 515 516 if (NULL != familyFace) { 517 tf = find_typeface(familyFace, style); 518 } else if (NULL != familyName) { 519 // SkDebugf("======= familyName <%s>\n", familyName); 520 tf = find_typeface(familyName, style); 521 } 522 523 if (NULL == tf) { 524 tf = find_best_face(gDefaultFamily, style); 525 } 526 527 SkSafeRef(tf); 528 return tf; 529} 530 531SkStream* SkFontHost::OpenStream(uint32_t fontID) { 532 FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID); 533 SkStream* stream = tf ? tf->openStream() : NULL; 534 535 if (stream && stream->getLength() == 0) { 536 stream->unref(); 537 stream = NULL; 538 } 539 return stream; 540} 541 542size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, 543 int32_t* index) { 544// SkDebugf("SkFontHost::GetFileName unimplemented\n"); 545 return 0; 546} 547 548SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { 549 return 0; 550} 551 552/////////////////////////////////////////////////////////////////////////////// 553 554SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 555 if (NULL == stream || stream->getLength() <= 0) { 556 SkDELETE(stream); 557 return NULL; 558 } 559 560 bool isFixedWidth; 561 SkTypeface::Style style; 562 if (find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) { 563 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth)); 564 } else { 565 return NULL; 566 } 567} 568 569SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 570 SkTypeface* face = NULL; 571 SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path)); 572 573 if (stream->isValid()) { 574 face = CreateTypefaceFromStream(stream); 575 } 576 stream->unref(); 577 return face; 578} 579