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