SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, const char familyName[], SkTypeface::Style style) { SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); load_system_fonts(); // clip to legal style bits style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); SkTypeface* tf = NULL; if (NULL != familyFace) { tf = find_typeface(familyFace, style); } else if (NULL != familyName) { // SkDebugf("======= familyName <%s>\n", familyName); tf = find_typeface(familyName, style); } if (NULL == tf) { tf = find_best_face(gDefaultFamily, style); } // we ref(), since the semantic is to return a new instance tf->ref(); return tf; }
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, const char familyName[], SkTypeface::Style style) { load_system_fonts(); SkAutoMutexAcquire ac(gFamilyMutex); // clip to legal style bits style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); SkTypeface* tf = NULL; if (NULL != familyFace) { tf = find_typeface(familyFace, style); } else if (NULL != familyName) { // SkDebugf("======= familyName <%s>\n", familyName); tf = find_typeface(familyName, style); } if (NULL == tf) { tf = find_best_face(gDefaultFamily, style); } SkSafeRef(tf); return tf; }
// this function can't be called if the gFamilyHeadAndNameListMutex is already locked static SkFontID findFallbackFontIDForChar(SkUnichar uni, SkTypeface::Style style) { const SkTypeface* tf = findFallbackTypefaceForChar(uni); if (!tf) { return 0; } return find_typeface(tf, style)->uniqueID(); }
SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { #ifdef SK_BUILD_FOR_ANDROID_NDK // Skia does not support font fallback for ndk applications in order to // enable clients such as WebKit to customize their font selection. // Clients can use GetFallbackFamilyNameForChar() to get the fallback // font for individual characters. return 0; #else SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); load_system_fonts(); const SkTypeface* origTypeface = find_from_uniqueID(origFontID); const SkTypeface* currTypeface = find_from_uniqueID(currFontID); SkASSERT(origTypeface != 0); SkASSERT(currTypeface != 0); SkASSERT(gFallbackFonts); // Our fallback list always stores the id of the plain in each fallback // family, so we transform currFontID to its plain equivalent. currFontID = find_typeface(currTypeface, SkTypeface::kNormal)->uniqueID(); /* First see if fontID is already one of our fallbacks. If so, return its successor. If fontID is not in our list, then return the first one in our list. Note: list is zero-terminated, and returning zero means we have no more fonts to use for fallbacks. */ const uint32_t* list = gFallbackFonts; for (int i = 0; list[i] != 0; i++) { if (list[i] == currFontID) { if (list[i+1] == 0) return 0; const SkTypeface* nextTypeface = find_from_uniqueID(list[i+1]); return find_typeface(nextTypeface, origTypeface->style())->uniqueID(); } } // If we get here, currFontID was not a fallback, so we start at the // beginning of our list. Assuming there is at least one fallback font, // i.e. gFallbackFonts[0] != 0. const SkTypeface* firstTypeface = find_from_uniqueID(list[0]); return find_typeface(firstTypeface, origTypeface->style())->uniqueID(); #endif }
static void load_system_fonts() { // check if we've already be called if (NULL != gDefaultNormal) { return; } SkString baseDirectory(SK_FONT_FILE_PREFIX); unsigned int count = 0; load_directory_fonts(baseDirectory, &count); if (0 == count) { SkNEW(EmptyTypeface); } // do this after all fonts are loaded. This is our default font, and it // acts as a sentinel so we only execute load_system_fonts() once static const char* gDefaultNames[] = { #if defined(__LB_SHELL__) "Droid Sans", // our preferred default #endif "Arial", "Verdana", "Times New Roman", NULL }; const char** names = gDefaultNames; while (*names) { SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); if (tf) { gDefaultNormal = tf; break; } } // check if we found *something* if (NULL == gDefaultNormal) { if (NULL == gFamilyHead) { sk_throw(); } for (int i = 0; i < 4; i++) { if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { break; } } } if (NULL == gDefaultNormal) { sk_throw(); } gFallBackTypeface = gDefaultNormal; gDefaultFamily = find_family(gDefaultNormal); }
SkTypeface* SkCreateFallbackTypefaceForChar(SkUnichar uni, SkTypeface::Style style) { { SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); load_system_fonts(); } SkTypeface* tf = findFallbackTypefaceForChar(uni); if (!tf) { return NULL; } SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); tf = find_typeface(tf, style); // we ref(), since the semantic is to return a new instance tf->ref(); return tf; }
static void load_system_fonts() { // check if we've already be called if (NULL != gDefaultNormal) { // printf("---- default font %p\n", gDefaultNormal); return; } SkOSFile::Iter iter(SK_FONT_FILE_PREFIX, ".ttf"); SkString name; int count = 0; while (iter.next(&name, false)) { SkString filename; GetFullPathForSysFonts(&filename, name.c_str()); bool isFixedWidth; SkString realname; SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedWidth)) { SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); continue; } // SkDebugf("font: <%s> %d <%s>\n", realname.c_str(), style, filename.c_str()); FamilyRec* family = find_familyrec(realname.c_str()); if (family && family->fFaces[style]) { // SkDebugf("---- skipping duplicate typeface %s style %d\n", // realname.c_str(), style); continue; } // this constructor puts us into the global gFamilyHead llist FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, (style, true, // system-font (cannot delete) family, // what family to join filename.c_str(), isFixedWidth) // filename ); if (NULL == family) { add_name(realname.c_str(), tf->getFamily()); } count += 1; } if (0 == count) { SkNEW(EmptyTypeface); } // do this after all fonts are loaded. This is our default font, and it // acts as a sentinel so we only execute load_system_fonts() once static const char* gDefaultNames[] = { "Arial", "Verdana", "Times New Roman", NULL }; const char** names = gDefaultNames; while (*names) { SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); if (tf) { gDefaultNormal = tf; break; } } // check if we found *something* if (NULL == gDefaultNormal) { if (NULL == gFamilyHead) { sk_throw(); } for (int i = 0; i < 4; i++) { if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { break; } } } if (NULL == gDefaultNormal) { sk_throw(); } gFallBackTypeface = gDefaultNormal; gDefaultFamily = find_family(gDefaultNormal); // SkDebugf("---- default %p head %p family %p\n", gDefaultNormal, gFamilyHead, gDefaultFamily); }