gfx/skia/trunk/src/ports/SkFontHost_android_old.cpp

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

mercurial