gfx/skia/patches/archive/0004-Bug-777614-Re-apply-bug-719872-Fix-crash-on-Android-.patch

changeset 0
6474c204b198
     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 +

mercurial