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