1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/ports/SkFontHost_android_old.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,589 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkFontDescriptor.h" 1.14 +#include "SkFontHost.h" 1.15 +#include "SkFontHost_FreeType_common.h" 1.16 +#include "SkDescriptor.h" 1.17 +#include "SkStream.h" 1.18 +#include "SkPaint.h" 1.19 +#include "SkString.h" 1.20 +#include "SkStream.h" 1.21 +#include "SkThread.h" 1.22 +#include "SkTSearch.h" 1.23 +#include <stdio.h> 1.24 + 1.25 +#define FONT_CACHE_MEMORY_BUDGET (768 * 1024) 1.26 + 1.27 +#ifndef SK_FONT_FILE_PREFIX 1.28 + #define SK_FONT_FILE_PREFIX "/fonts/" 1.29 +#endif 1.30 + 1.31 +bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style, 1.32 + bool* isFixedWidth); 1.33 + 1.34 +static void GetFullPathForSysFonts(SkString* full, const char name[]) { 1.35 + full->set(getenv("ANDROID_ROOT")); 1.36 + full->append(SK_FONT_FILE_PREFIX); 1.37 + full->append(name); 1.38 +} 1.39 + 1.40 +/////////////////////////////////////////////////////////////////////////////// 1.41 + 1.42 +struct FamilyRec; 1.43 + 1.44 +/* This guy holds a mapping of a name -> family, used for looking up fonts. 1.45 + Since it is stored in a stretchy array that doesn't preserve object 1.46 + semantics, we don't use constructor/destructors, but just have explicit 1.47 + helpers to manage our internal bookkeeping. 1.48 +*/ 1.49 +struct NameFamilyPair { 1.50 + const char* fName; // we own this 1.51 + FamilyRec* fFamily; // we don't own this, we just reference it 1.52 + 1.53 + void construct(const char name[], FamilyRec* family) { 1.54 + fName = strdup(name); 1.55 + fFamily = family; // we don't own this, so just record the referene 1.56 + } 1.57 + 1.58 + void destruct() { 1.59 + free((char*)fName); 1.60 + // we don't own family, so just ignore our reference 1.61 + } 1.62 +}; 1.63 + 1.64 +// we use atomic_inc to grow this for each typeface we create 1.65 +static int32_t gUniqueFontID; 1.66 + 1.67 +// this is the mutex that protects these globals 1.68 +static SkMutex gFamilyMutex; 1.69 +static FamilyRec* gFamilyHead; 1.70 +static SkTDArray<NameFamilyPair> gNameList; 1.71 + 1.72 +struct FamilyRec { 1.73 + FamilyRec* fNext; 1.74 + SkTypeface* fFaces[4]; 1.75 + 1.76 + FamilyRec() 1.77 + { 1.78 + fNext = gFamilyHead; 1.79 + memset(fFaces, 0, sizeof(fFaces)); 1.80 + gFamilyHead = this; 1.81 + } 1.82 +}; 1.83 + 1.84 +static SkTypeface* find_best_face(const FamilyRec* family, 1.85 + SkTypeface::Style style) { 1.86 + SkTypeface* const* faces = family->fFaces; 1.87 + 1.88 + if (faces[style] != NULL) { // exact match 1.89 + return faces[style]; 1.90 + } 1.91 + // look for a matching bold 1.92 + style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); 1.93 + if (faces[style] != NULL) { 1.94 + return faces[style]; 1.95 + } 1.96 + // look for the plain 1.97 + if (faces[SkTypeface::kNormal] != NULL) { 1.98 + return faces[SkTypeface::kNormal]; 1.99 + } 1.100 + // look for anything 1.101 + for (int i = 0; i < 4; i++) { 1.102 + if (faces[i] != NULL) { 1.103 + return faces[i]; 1.104 + } 1.105 + } 1.106 + // should never get here, since the faces list should not be empty 1.107 + SkASSERT(!"faces list is empty"); 1.108 + return NULL; 1.109 +} 1.110 + 1.111 +static FamilyRec* find_family(const SkTypeface* member) { 1.112 + FamilyRec* curr = gFamilyHead; 1.113 + while (curr != NULL) { 1.114 + for (int i = 0; i < 4; i++) { 1.115 + if (curr->fFaces[i] == member) { 1.116 + return curr; 1.117 + } 1.118 + } 1.119 + curr = curr->fNext; 1.120 + } 1.121 + return NULL; 1.122 +} 1.123 + 1.124 +/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt 1.125 + is not modified. 1.126 + */ 1.127 +static SkTypeface* find_from_uniqueID(uint32_t uniqueID) { 1.128 + FamilyRec* curr = gFamilyHead; 1.129 + while (curr != NULL) { 1.130 + for (int i = 0; i < 4; i++) { 1.131 + SkTypeface* face = curr->fFaces[i]; 1.132 + if (face != NULL && face->uniqueID() == uniqueID) { 1.133 + return face; 1.134 + } 1.135 + } 1.136 + curr = curr->fNext; 1.137 + } 1.138 + return NULL; 1.139 +} 1.140 + 1.141 +/* Remove reference to this face from its family. If the resulting family 1.142 + is empty (has no faces), return that family, otherwise return NULL 1.143 +*/ 1.144 +static FamilyRec* remove_from_family(const SkTypeface* face) { 1.145 + FamilyRec* family = find_family(face); 1.146 + SkASSERT(family->fFaces[face->style()] == face); 1.147 + family->fFaces[face->style()] = NULL; 1.148 + 1.149 + for (int i = 0; i < 4; i++) { 1.150 + if (family->fFaces[i] != NULL) { // family is non-empty 1.151 + return NULL; 1.152 + } 1.153 + } 1.154 + return family; // return the empty family 1.155 +} 1.156 + 1.157 +// maybe we should make FamilyRec be doubly-linked 1.158 +static void detach_and_delete_family(FamilyRec* family) { 1.159 + FamilyRec* curr = gFamilyHead; 1.160 + FamilyRec* prev = NULL; 1.161 + 1.162 + while (curr != NULL) { 1.163 + FamilyRec* next = curr->fNext; 1.164 + if (curr == family) { 1.165 + if (prev == NULL) { 1.166 + gFamilyHead = next; 1.167 + } else { 1.168 + prev->fNext = next; 1.169 + } 1.170 + SkDELETE(family); 1.171 + return; 1.172 + } 1.173 + prev = curr; 1.174 + curr = next; 1.175 + } 1.176 + SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); 1.177 +} 1.178 + 1.179 +static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { 1.180 + NameFamilyPair* list = gNameList.begin(); 1.181 + int count = gNameList.count(); 1.182 + 1.183 + int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 1.184 + 1.185 + if (index >= 0) { 1.186 + return find_best_face(list[index].fFamily, style); 1.187 + } 1.188 + return NULL; 1.189 +} 1.190 + 1.191 +static SkTypeface* find_typeface(const SkTypeface* familyMember, 1.192 + SkTypeface::Style style) { 1.193 + const FamilyRec* family = find_family(familyMember); 1.194 + return family ? find_best_face(family, style) : NULL; 1.195 +} 1.196 + 1.197 +static void add_name(const char name[], FamilyRec* family) { 1.198 + SkAutoAsciiToLC tolc(name); 1.199 + name = tolc.lc(); 1.200 + 1.201 + NameFamilyPair* list = gNameList.begin(); 1.202 + int count = gNameList.count(); 1.203 + 1.204 + int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 1.205 + 1.206 + if (index < 0) { 1.207 + list = gNameList.insert(~index); 1.208 + list->construct(name, family); 1.209 + } 1.210 +} 1.211 + 1.212 +static void remove_from_names(FamilyRec* emptyFamily) 1.213 +{ 1.214 +#ifdef SK_DEBUG 1.215 + for (int i = 0; i < 4; i++) { 1.216 + SkASSERT(emptyFamily->fFaces[i] == NULL); 1.217 + } 1.218 +#endif 1.219 + 1.220 + SkTDArray<NameFamilyPair>& list = gNameList; 1.221 + 1.222 + // must go backwards when removing 1.223 + for (int i = list.count() - 1; i >= 0; --i) { 1.224 + NameFamilyPair* pair = &list[i]; 1.225 + if (pair->fFamily == emptyFamily) { 1.226 + pair->destruct(); 1.227 + list.remove(i); 1.228 + } 1.229 + } 1.230 +} 1.231 + 1.232 +/////////////////////////////////////////////////////////////////////////////// 1.233 + 1.234 +class FamilyTypeface : public SkTypeface_FreeType { 1.235 +public: 1.236 + FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember, 1.237 + bool isFixedWidth) 1.238 + : SkTypeface_FreeType(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) { 1.239 + fIsSysFont = sysFont; 1.240 + 1.241 + SkAutoMutexAcquire ac(gFamilyMutex); 1.242 + 1.243 + FamilyRec* rec = NULL; 1.244 + if (familyMember) { 1.245 + rec = find_family(familyMember); 1.246 + SkASSERT(rec); 1.247 + } else { 1.248 + rec = SkNEW(FamilyRec); 1.249 + } 1.250 + rec->fFaces[style] = this; 1.251 + } 1.252 + 1.253 + virtual ~FamilyTypeface() { 1.254 + SkAutoMutexAcquire ac(gFamilyMutex); 1.255 + 1.256 + // remove us from our family. If the family is now empty, we return 1.257 + // that and then remove that family from the name list 1.258 + FamilyRec* family = remove_from_family(this); 1.259 + if (NULL != family) { 1.260 + remove_from_names(family); 1.261 + detach_and_delete_family(family); 1.262 + } 1.263 + } 1.264 + 1.265 + bool isSysFont() const { return fIsSysFont; } 1.266 + 1.267 + virtual const char* getUniqueString() const = 0; 1.268 + virtual const char* getFilePath() const = 0; 1.269 + 1.270 +protected: 1.271 + virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; 1.272 + 1.273 +private: 1.274 + bool fIsSysFont; 1.275 + 1.276 + typedef SkTypeface INHERITED; 1.277 +}; 1.278 + 1.279 +/////////////////////////////////////////////////////////////////////////////// 1.280 + 1.281 +class StreamTypeface : public FamilyTypeface { 1.282 +public: 1.283 + StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember, 1.284 + SkStream* stream, bool isFixedWidth) 1.285 + : INHERITED(style, sysFont, familyMember, isFixedWidth) { 1.286 + SkASSERT(stream); 1.287 + stream->ref(); 1.288 + fStream = stream; 1.289 + } 1.290 + virtual ~StreamTypeface() { 1.291 + fStream->unref(); 1.292 + } 1.293 + 1.294 + // overrides 1.295 + virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 1.296 + *ttcIndex = 0; 1.297 + // we just ref our existing stream, since the caller will call unref() 1.298 + // when they are through 1.299 + fStream->ref(); 1.300 + // must rewind each time, since the caller assumes a "new" stream 1.301 + fStream->rewind(); 1.302 + return fStream; 1.303 + } 1.304 + virtual const char* getUniqueString() const { return NULL; } 1.305 + virtual const char* getFilePath() const { return NULL; } 1.306 + 1.307 +private: 1.308 + SkStream* fStream; 1.309 + 1.310 + typedef FamilyTypeface INHERITED; 1.311 +}; 1.312 + 1.313 +class FileTypeface : public FamilyTypeface { 1.314 +public: 1.315 + FileTypeface(Style style, bool sysFont, SkTypeface* familyMember, 1.316 + const char path[], bool isFixedWidth) 1.317 + : INHERITED(style, sysFont, familyMember, isFixedWidth) { 1.318 + SkString fullpath; 1.319 + 1.320 + if (sysFont) { 1.321 + GetFullPathForSysFonts(&fullpath, path); 1.322 + path = fullpath.c_str(); 1.323 + } 1.324 + fPath.set(path); 1.325 + } 1.326 + 1.327 + // overrides 1.328 + virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 1.329 + *ttcIndex = 0; 1.330 + SkStream* stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); 1.331 + 1.332 + // check for failure 1.333 + if (stream->getLength() <= 0) { 1.334 + SkDELETE(stream); 1.335 + stream = NULL; 1.336 + } 1.337 + return stream; 1.338 + } 1.339 + virtual const char* getUniqueString() const { 1.340 + const char* str = strrchr(fPath.c_str(), '/'); 1.341 + if (str) { 1.342 + str += 1; // skip the '/' 1.343 + } 1.344 + return str; 1.345 + } 1.346 + virtual const char* getFilePath() const { 1.347 + return fPath.c_str(); 1.348 + } 1.349 + 1.350 +private: 1.351 + SkString fPath; 1.352 + 1.353 + typedef FamilyTypeface INHERITED; 1.354 +}; 1.355 + 1.356 +/////////////////////////////////////////////////////////////////////////////// 1.357 +/////////////////////////////////////////////////////////////////////////////// 1.358 + 1.359 +static bool get_name_and_style(const char path[], SkString* name, 1.360 + SkTypeface::Style* style, 1.361 + bool* isFixedWidth, bool isExpected) { 1.362 + SkString fullpath; 1.363 + GetFullPathForSysFonts(&fullpath, path); 1.364 + 1.365 + SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(fullpath.c_str())); 1.366 + if (stream.get()) { 1.367 + find_name_and_attributes(stream, name, style, isFixedWidth); 1.368 + return true; 1.369 + } 1.370 + 1.371 + if (isExpected) { 1.372 + SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str()); 1.373 + } 1.374 + return false; 1.375 +} 1.376 + 1.377 +// used to record our notion of the pre-existing fonts 1.378 +struct FontInitRec { 1.379 + const char* fFileName; 1.380 + const char* const* fNames; // null-terminated list 1.381 +}; 1.382 + 1.383 +static const char* gSansNames[] = { 1.384 + "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL 1.385 +}; 1.386 + 1.387 +static const char* gSerifNames[] = { 1.388 + "serif", "times", "times new roman", "palatino", "georgia", "baskerville", 1.389 + "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL 1.390 +}; 1.391 + 1.392 +static const char* gMonoNames[] = { 1.393 + "monospace", "courier", "courier new", "monaco", NULL 1.394 +}; 1.395 + 1.396 +// deliberately empty, but we use the address to identify fallback fonts 1.397 +static const char* gFBNames[] = { NULL }; 1.398 + 1.399 +/* Fonts must be grouped by family, with the first font in a family having the 1.400 + list of names (even if that list is empty), and the following members having 1.401 + null for the list. The names list must be NULL-terminated 1.402 +*/ 1.403 +static const FontInitRec gSystemFonts[] = { 1.404 + { "DroidSans.ttf", gSansNames }, 1.405 + { "DroidSans-Bold.ttf", NULL }, 1.406 + { "DroidSerif-Regular.ttf", gSerifNames }, 1.407 + { "DroidSerif-Bold.ttf", NULL }, 1.408 + { "DroidSerif-Italic.ttf", NULL }, 1.409 + { "DroidSerif-BoldItalic.ttf", NULL }, 1.410 + { "DroidSansMono.ttf", gMonoNames }, 1.411 + /* These are optional, and can be ignored if not found in the file system. 1.412 + These are appended to gFallbackFonts[] as they are seen, so we list 1.413 + them in the order we want them to be accessed by NextLogicalFont(). 1.414 + */ 1.415 + { "DroidSansArabic.ttf", gFBNames }, 1.416 + { "DroidSansHebrew.ttf", gFBNames }, 1.417 + { "DroidSansThai.ttf", gFBNames }, 1.418 + { "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font 1.419 + { "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font 1.420 + { "DroidSansJapanese.ttf", gFBNames }, 1.421 + { "DroidSansFallback.ttf", gFBNames } 1.422 +}; 1.423 + 1.424 +#define DEFAULT_NAMES gSansNames 1.425 + 1.426 +// these globals are assigned (once) by load_system_fonts() 1.427 +static FamilyRec* gDefaultFamily; 1.428 +static SkTypeface* gDefaultNormal; 1.429 + 1.430 +/* This is sized conservatively, assuming that it will never be a size issue. 1.431 + It will be initialized in load_system_fonts(), and will be filled with the 1.432 + fontIDs that can be used for fallback consideration, in sorted order (sorted 1.433 + meaning element[0] should be used first, then element[1], etc. When we hit 1.434 + a fontID==0 in the array, the list is done, hence our allocation size is 1.435 + +1 the total number of possible system fonts. Also see NextLogicalFont(). 1.436 + */ 1.437 +static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1]; 1.438 + 1.439 +/* Called once (ensured by the sentinel check at the beginning of our body). 1.440 + Initializes all the globals, and register the system fonts. 1.441 + */ 1.442 +static void load_system_fonts() { 1.443 + // check if we've already be called 1.444 + if (NULL != gDefaultNormal) { 1.445 + return; 1.446 + } 1.447 + 1.448 + const FontInitRec* rec = gSystemFonts; 1.449 + SkTypeface* firstInFamily = NULL; 1.450 + int fallbackCount = 0; 1.451 + 1.452 + for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { 1.453 + // if we're the first in a new family, clear firstInFamily 1.454 + if (rec[i].fNames != NULL) { 1.455 + firstInFamily = NULL; 1.456 + } 1.457 + 1.458 + bool isFixedWidth; 1.459 + SkString name; 1.460 + SkTypeface::Style style; 1.461 + 1.462 + // we expect all the fonts, except the "fallback" fonts 1.463 + bool isExpected = (rec[i].fNames != gFBNames); 1.464 + if (!get_name_and_style(rec[i].fFileName, &name, &style, 1.465 + &isFixedWidth, isExpected)) { 1.466 + continue; 1.467 + } 1.468 + 1.469 + SkTypeface* tf = SkNEW_ARGS(FileTypeface, 1.470 + (style, 1.471 + true, // system-font (cannot delete) 1.472 + firstInFamily, // what family to join 1.473 + rec[i].fFileName, 1.474 + isFixedWidth) // filename 1.475 + ); 1.476 + 1.477 + if (rec[i].fNames != NULL) { 1.478 + // see if this is one of our fallback fonts 1.479 + if (rec[i].fNames == gFBNames) { 1.480 + // SkDebugf("---- adding %s as fallback[%d] fontID %d\n", 1.481 + // rec[i].fFileName, fallbackCount, tf->uniqueID()); 1.482 + gFallbackFonts[fallbackCount++] = tf->uniqueID(); 1.483 + } 1.484 + 1.485 + firstInFamily = tf; 1.486 + FamilyRec* family = find_family(tf); 1.487 + const char* const* names = rec[i].fNames; 1.488 + 1.489 + // record the default family if this is it 1.490 + if (names == DEFAULT_NAMES) { 1.491 + gDefaultFamily = family; 1.492 + } 1.493 + // add the names to map to this family 1.494 + while (*names) { 1.495 + add_name(*names, family); 1.496 + names += 1; 1.497 + } 1.498 + } 1.499 + } 1.500 + 1.501 + // do this after all fonts are loaded. This is our default font, and it 1.502 + // acts as a sentinel so we only execute load_system_fonts() once 1.503 + gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); 1.504 + // now terminate our fallback list with the sentinel value 1.505 + gFallbackFonts[fallbackCount] = 0; 1.506 +} 1.507 + 1.508 +void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 1.509 + bool* isLocalStream) const { 1.510 + { 1.511 + SkAutoMutexAcquire ac(gFamilyMutex); 1.512 + //desc->setFamilyName(find_family_name(this)); 1.513 + desc->setFontFileName(this->getUniqueString()); 1.514 + } 1.515 + *isLocalStream = !this->isSysFont(); 1.516 +} 1.517 + 1.518 +/////////////////////////////////////////////////////////////////////////////// 1.519 + 1.520 +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 1.521 + const char familyName[], 1.522 + SkTypeface::Style style) { 1.523 + load_system_fonts(); 1.524 + 1.525 + SkAutoMutexAcquire ac(gFamilyMutex); 1.526 + 1.527 + // clip to legal style bits 1.528 + style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); 1.529 + 1.530 + SkTypeface* tf = NULL; 1.531 + 1.532 + if (NULL != familyFace) { 1.533 + tf = find_typeface(familyFace, style); 1.534 + } else if (NULL != familyName) { 1.535 +// SkDebugf("======= familyName <%s>\n", familyName); 1.536 + tf = find_typeface(familyName, style); 1.537 + } 1.538 + 1.539 + if (NULL == tf) { 1.540 + tf = find_best_face(gDefaultFamily, style); 1.541 + } 1.542 + 1.543 + // we ref(), since the symantic is to return a new instance 1.544 + tf->ref(); 1.545 + return tf; 1.546 +} 1.547 + 1.548 +SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID, 1.549 + const SkPaintOptionsAndroid& options) { 1.550 + load_system_fonts(); 1.551 + 1.552 + /* First see if fontID is already one of our fallbacks. If so, return 1.553 + its successor. If fontID is not in our list, then return the first one 1.554 + in our list. Note: list is zero-terminated, and returning zero means 1.555 + we have no more fonts to use for fallbacks. 1.556 + */ 1.557 + const uint32_t* list = gFallbackFonts; 1.558 + for (int i = 0; list[i] != 0; i++) { 1.559 + if (list[i] == currFontID) { 1.560 + return find_from_uniqueID(list[i+1]); 1.561 + } 1.562 + } 1.563 + return find_from_uniqueID(list[0]); 1.564 +} 1.565 + 1.566 +/////////////////////////////////////////////////////////////////////////////// 1.567 + 1.568 +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 1.569 + if (NULL == stream || stream->getLength() <= 0) { 1.570 + return NULL; 1.571 + } 1.572 + 1.573 + bool isFixedWidth; 1.574 + SkString name; 1.575 + SkTypeface::Style style; 1.576 + find_name_and_attributes(stream, &name, &style, &isFixedWidth); 1.577 + 1.578 + if (!name.isEmpty()) { 1.579 + return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth)); 1.580 + } else { 1.581 + return NULL; 1.582 + } 1.583 +} 1.584 + 1.585 +SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 1.586 + SkStream* stream = SkNEW_ARGS(SkFILEStream, (path)); 1.587 + SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream); 1.588 + // since we created the stream, we let go of our ref() here 1.589 + stream->unref(); 1.590 + return face; 1.591 +} 1.592 +