gfx/skia/patches/archive/0007-Bug-719872-Old-Android-FontHost.patch

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

mercurial