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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 From 0d730a94e9f6676d5cde45f955fe025a4549817e Mon Sep 17 00:00:00 2001
     2 From: George Wright <gw@gwright.org.uk>
     3 Date: Thu, 23 Aug 2012 16:45:38 -0400
     4 Subject: [PATCH 4/9] Bug 777614 - Re-apply bug 719872 - Fix crash on Android
     5  by reverting to older FontHost r=nrc
     7 ---
     8  gfx/skia/src/ports/SkFontHost_android_old.cpp | 664 ++++++++++++++++++++++++++
     9  1 file changed, 664 insertions(+)
    10  create mode 100644 gfx/skia/src/ports/SkFontHost_android_old.cpp
    12 diff --git a/gfx/skia/src/ports/SkFontHost_android_old.cpp b/gfx/skia/src/ports/SkFontHost_android_old.cpp
    13 new file mode 100644
    14 index 0000000..b5c4f3c
    15 --- /dev/null
    16 +++ b/gfx/skia/src/ports/SkFontHost_android_old.cpp
    17 @@ -0,0 +1,664 @@
    18 +
    19 +/*
    20 + * Copyright 2006 The Android Open Source Project
    21 + *
    22 + * Use of this source code is governed by a BSD-style license that can be
    23 + * found in the LICENSE file.
    24 + */
    25 +
    26 +
    27 +#include "SkFontHost.h"
    28 +#include "SkDescriptor.h"
    29 +#include "SkMMapStream.h"
    30 +#include "SkPaint.h"
    31 +#include "SkString.h"
    32 +#include "SkStream.h"
    33 +#include "SkThread.h"
    34 +#include "SkTSearch.h"
    35 +#include <stdio.h>
    36 +
    37 +#define FONT_CACHE_MEMORY_BUDGET    (768 * 1024)
    38 +
    39 +#ifndef SK_FONT_FILE_PREFIX
    40 +    #define SK_FONT_FILE_PREFIX          "/fonts/"
    41 +#endif
    42 +
    43 +bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style,
    44 +                                           bool* isFixedWidth);
    45 +
    46 +static void GetFullPathForSysFonts(SkString* full, const char name[]) {
    47 +    full->set(getenv("ANDROID_ROOT"));
    48 +    full->append(SK_FONT_FILE_PREFIX);
    49 +    full->append(name);
    50 +}
    51 +
    52 +///////////////////////////////////////////////////////////////////////////////
    53 +
    54 +struct FamilyRec;
    55 +
    56 +/*  This guy holds a mapping of a name -> family, used for looking up fonts.
    57 +    Since it is stored in a stretchy array that doesn't preserve object
    58 +    semantics, we don't use constructor/destructors, but just have explicit
    59 +    helpers to manage our internal bookkeeping.
    60 +*/
    61 +struct NameFamilyPair {
    62 +    const char* fName;      // we own this
    63 +    FamilyRec*  fFamily;    // we don't own this, we just reference it
    64 +
    65 +    void construct(const char name[], FamilyRec* family) {
    66 +        fName = strdup(name);
    67 +        fFamily = family;   // we don't own this, so just record the referene
    68 +    }
    69 +
    70 +    void destruct() {
    71 +        free((char*)fName);
    72 +        // we don't own family, so just ignore our reference
    73 +    }
    74 +};
    75 +
    76 +// we use atomic_inc to grow this for each typeface we create
    77 +static int32_t gUniqueFontID;
    78 +
    79 +// this is the mutex that protects these globals
    80 +static SkMutex gFamilyMutex;
    81 +static FamilyRec* gFamilyHead;
    82 +static SkTDArray<NameFamilyPair> gNameList;
    83 +
    84 +struct FamilyRec {
    85 +    FamilyRec*  fNext;
    86 +    SkTypeface* fFaces[4];
    87 +
    88 +    FamilyRec()
    89 +    {
    90 +        fNext = gFamilyHead;
    91 +        memset(fFaces, 0, sizeof(fFaces));
    92 +        gFamilyHead = this;
    93 +    }
    94 +};
    95 +
    96 +static SkTypeface* find_best_face(const FamilyRec* family,
    97 +                                  SkTypeface::Style style) {
    98 +    SkTypeface* const* faces = family->fFaces;
    99 +
   100 +    if (faces[style] != NULL) { // exact match
   101 +        return faces[style];
   102 +    }
   103 +    // look for a matching bold
   104 +    style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
   105 +    if (faces[style] != NULL) {
   106 +        return faces[style];
   107 +    }
   108 +    // look for the plain
   109 +    if (faces[SkTypeface::kNormal] != NULL) {
   110 +        return faces[SkTypeface::kNormal];
   111 +    }
   112 +    // look for anything
   113 +    for (int i = 0; i < 4; i++) {
   114 +        if (faces[i] != NULL) {
   115 +            return faces[i];
   116 +        }
   117 +    }
   118 +    // should never get here, since the faces list should not be empty
   119 +    SkASSERT(!"faces list is empty");
   120 +    return NULL;
   121 +}
   122 +
   123 +static FamilyRec* find_family(const SkTypeface* member) {
   124 +    FamilyRec* curr = gFamilyHead;
   125 +    while (curr != NULL) {
   126 +        for (int i = 0; i < 4; i++) {
   127 +            if (curr->fFaces[i] == member) {
   128 +                return curr;
   129 +            }
   130 +        }
   131 +        curr = curr->fNext;
   132 +    }
   133 +    return NULL;
   134 +}
   135 +
   136 +/*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
   137 +    is not modified.
   138 + */
   139 +static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
   140 +    FamilyRec* curr = gFamilyHead;
   141 +    while (curr != NULL) {
   142 +        for (int i = 0; i < 4; i++) {
   143 +            SkTypeface* face = curr->fFaces[i];
   144 +            if (face != NULL && face->uniqueID() == uniqueID) {
   145 +                return face;
   146 +            }
   147 +        }
   148 +        curr = curr->fNext;
   149 +    }
   150 +    return NULL;
   151 +}
   152 +
   153 +/*  Remove reference to this face from its family. If the resulting family
   154 +    is empty (has no faces), return that family, otherwise return NULL
   155 +*/
   156 +static FamilyRec* remove_from_family(const SkTypeface* face) {
   157 +    FamilyRec* family = find_family(face);
   158 +    SkASSERT(family->fFaces[face->style()] == face);
   159 +    family->fFaces[face->style()] = NULL;
   160 +
   161 +    for (int i = 0; i < 4; i++) {
   162 +        if (family->fFaces[i] != NULL) {    // family is non-empty
   163 +            return NULL;
   164 +        }
   165 +    }
   166 +    return family;  // return the empty family
   167 +}
   168 +
   169 +// maybe we should make FamilyRec be doubly-linked
   170 +static void detach_and_delete_family(FamilyRec* family) {
   171 +    FamilyRec* curr = gFamilyHead;
   172 +    FamilyRec* prev = NULL;
   173 +
   174 +    while (curr != NULL) {
   175 +        FamilyRec* next = curr->fNext;
   176 +        if (curr == family) {
   177 +            if (prev == NULL) {
   178 +                gFamilyHead = next;
   179 +            } else {
   180 +                prev->fNext = next;
   181 +            }
   182 +            SkDELETE(family);
   183 +            return;
   184 +        }
   185 +        prev = curr;
   186 +        curr = next;
   187 +    }
   188 +    SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
   189 +}
   190 +
   191 +static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
   192 +    NameFamilyPair* list = gNameList.begin();
   193 +    int             count = gNameList.count();
   194 +
   195 +    int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
   196 +
   197 +    if (index >= 0) {
   198 +        return find_best_face(list[index].fFamily, style);
   199 +    }
   200 +    return NULL;
   201 +}
   202 +
   203 +static SkTypeface* find_typeface(const SkTypeface* familyMember,
   204 +                                 SkTypeface::Style style) {
   205 +    const FamilyRec* family = find_family(familyMember);
   206 +    return family ? find_best_face(family, style) : NULL;
   207 +}
   208 +
   209 +static void add_name(const char name[], FamilyRec* family) {
   210 +    SkAutoAsciiToLC tolc(name);
   211 +    name = tolc.lc();
   212 +
   213 +    NameFamilyPair* list = gNameList.begin();
   214 +    int             count = gNameList.count();
   215 +
   216 +    int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
   217 +
   218 +    if (index < 0) {
   219 +        list = gNameList.insert(~index);
   220 +        list->construct(name, family);
   221 +    }
   222 +}
   223 +
   224 +static void remove_from_names(FamilyRec* emptyFamily)
   225 +{
   226 +#ifdef SK_DEBUG
   227 +    for (int i = 0; i < 4; i++) {
   228 +        SkASSERT(emptyFamily->fFaces[i] == NULL);
   229 +    }
   230 +#endif
   231 +
   232 +    SkTDArray<NameFamilyPair>& list = gNameList;
   233 +
   234 +    // must go backwards when removing
   235 +    for (int i = list.count() - 1; i >= 0; --i) {
   236 +        NameFamilyPair* pair = &list[i];
   237 +        if (pair->fFamily == emptyFamily) {
   238 +            pair->destruct();
   239 +            list.remove(i);
   240 +        }
   241 +    }
   242 +}
   243 +
   244 +///////////////////////////////////////////////////////////////////////////////
   245 +
   246 +class FamilyTypeface : public SkTypeface {
   247 +public:
   248 +    FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember,
   249 +                   bool isFixedWidth)
   250 +    : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
   251 +        fIsSysFont = sysFont;
   252 +
   253 +        SkAutoMutexAcquire  ac(gFamilyMutex);
   254 +
   255 +        FamilyRec* rec = NULL;
   256 +        if (familyMember) {
   257 +            rec = find_family(familyMember);
   258 +            SkASSERT(rec);
   259 +        } else {
   260 +            rec = SkNEW(FamilyRec);
   261 +        }
   262 +        rec->fFaces[style] = this;
   263 +    }
   264 +
   265 +    virtual ~FamilyTypeface() {
   266 +        SkAutoMutexAcquire  ac(gFamilyMutex);
   267 +
   268 +        // remove us from our family. If the family is now empty, we return
   269 +        // that and then remove that family from the name list
   270 +        FamilyRec* family = remove_from_family(this);
   271 +        if (NULL != family) {
   272 +            remove_from_names(family);
   273 +            detach_and_delete_family(family);
   274 +        }
   275 +    }
   276 +
   277 +    bool isSysFont() const { return fIsSysFont; }
   278 +
   279 +    virtual SkStream* openStream() = 0;
   280 +    virtual const char* getUniqueString() const = 0;
   281 +    virtual const char* getFilePath() const = 0;
   282 +
   283 +private:
   284 +    bool    fIsSysFont;
   285 +
   286 +    typedef SkTypeface INHERITED;
   287 +};
   288 +
   289 +///////////////////////////////////////////////////////////////////////////////
   290 +
   291 +class StreamTypeface : public FamilyTypeface {
   292 +public:
   293 +    StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
   294 +                   SkStream* stream, bool isFixedWidth)
   295 +    : INHERITED(style, sysFont, familyMember, isFixedWidth) {
   296 +        SkASSERT(stream);
   297 +        stream->ref();
   298 +        fStream = stream;
   299 +    }
   300 +    virtual ~StreamTypeface() {
   301 +        fStream->unref();
   302 +    }
   303 +
   304 +    // overrides
   305 +    virtual SkStream* openStream() {
   306 +        // we just ref our existing stream, since the caller will call unref()
   307 +        // when they are through
   308 +        fStream->ref();
   309 +        // must rewind each time, since the caller assumes a "new" stream
   310 +        fStream->rewind();
   311 +        return fStream;
   312 +    }
   313 +    virtual const char* getUniqueString() const { return NULL; }
   314 +    virtual const char* getFilePath() const { return NULL; }
   315 +
   316 +private:
   317 +    SkStream* fStream;
   318 +
   319 +    typedef FamilyTypeface INHERITED;
   320 +};
   321 +
   322 +class FileTypeface : public FamilyTypeface {
   323 +public:
   324 +    FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
   325 +                 const char path[], bool isFixedWidth)
   326 +    : INHERITED(style, sysFont, familyMember, isFixedWidth) {
   327 +        SkString fullpath;
   328 +
   329 +        if (sysFont) {
   330 +            GetFullPathForSysFonts(&fullpath, path);
   331 +            path = fullpath.c_str();
   332 +        }
   333 +        fPath.set(path);
   334 +    }
   335 +
   336 +    // overrides
   337 +    virtual SkStream* openStream() {
   338 +        SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
   339 +
   340 +        // check for failure
   341 +        if (stream->getLength() <= 0) {
   342 +            SkDELETE(stream);
   343 +            // maybe MMAP isn't supported. try FILE
   344 +            stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
   345 +            if (stream->getLength() <= 0) {
   346 +                SkDELETE(stream);
   347 +                stream = NULL;
   348 +            }
   349 +        }
   350 +        return stream;
   351 +    }
   352 +    virtual const char* getUniqueString() const {
   353 +        const char* str = strrchr(fPath.c_str(), '/');
   354 +        if (str) {
   355 +            str += 1;   // skip the '/'
   356 +        }
   357 +        return str;
   358 +    }
   359 +    virtual const char* getFilePath() const {
   360 +        return fPath.c_str();
   361 +    }
   362 +
   363 +private:
   364 +    SkString fPath;
   365 +
   366 +    typedef FamilyTypeface INHERITED;
   367 +};
   368 +
   369 +///////////////////////////////////////////////////////////////////////////////
   370 +///////////////////////////////////////////////////////////////////////////////
   371 +
   372 +static bool get_name_and_style(const char path[], SkString* name,
   373 +                               SkTypeface::Style* style,
   374 +                               bool* isFixedWidth, bool isExpected) {
   375 +    SkString        fullpath;
   376 +    GetFullPathForSysFonts(&fullpath, path);
   377 +
   378 +    SkMMAPStream stream(fullpath.c_str());
   379 +    if (stream.getLength() > 0) {
   380 +        find_name_and_attributes(&stream, name, style, isFixedWidth);
   381 +        return true;
   382 +    }
   383 +    else {
   384 +        SkFILEStream stream(fullpath.c_str());
   385 +        if (stream.getLength() > 0) {
   386 +            find_name_and_attributes(&stream, name, style, isFixedWidth);
   387 +            return true;
   388 +        }
   389 +    }
   390 +
   391 +    if (isExpected) {
   392 +        SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
   393 +    }
   394 +    return false;
   395 +}
   396 +
   397 +// used to record our notion of the pre-existing fonts
   398 +struct FontInitRec {
   399 +    const char*         fFileName;
   400 +    const char* const*  fNames;     // null-terminated list
   401 +};
   402 +
   403 +static const char* gSansNames[] = {
   404 +    "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
   405 +};
   406 +
   407 +static const char* gSerifNames[] = {
   408 +    "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
   409 +    "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
   410 +};
   411 +
   412 +static const char* gMonoNames[] = {
   413 +    "monospace", "courier", "courier new", "monaco", NULL
   414 +};
   415 +
   416 +// deliberately empty, but we use the address to identify fallback fonts
   417 +static const char* gFBNames[] = { NULL };
   418 +
   419 +/*  Fonts must be grouped by family, with the first font in a family having the
   420 +    list of names (even if that list is empty), and the following members having
   421 +    null for the list. The names list must be NULL-terminated
   422 +*/
   423 +static const FontInitRec gSystemFonts[] = {
   424 +    { "DroidSans.ttf",              gSansNames  },
   425 +    { "DroidSans-Bold.ttf",         NULL        },
   426 +    { "DroidSerif-Regular.ttf",     gSerifNames },
   427 +    { "DroidSerif-Bold.ttf",        NULL        },
   428 +    { "DroidSerif-Italic.ttf",      NULL        },
   429 +    { "DroidSerif-BoldItalic.ttf",  NULL        },
   430 +    { "DroidSansMono.ttf",          gMonoNames  },
   431 +    /*  These are optional, and can be ignored if not found in the file system.
   432 +        These are appended to gFallbackFonts[] as they are seen, so we list
   433 +        them in the order we want them to be accessed by NextLogicalFont().
   434 +     */
   435 +    { "DroidSansArabic.ttf",        gFBNames    },
   436 +    { "DroidSansHebrew.ttf",        gFBNames    },
   437 +    { "DroidSansThai.ttf",          gFBNames    },
   438 +    { "MTLmr3m.ttf",                gFBNames    }, // Motoya Japanese Font
   439 +    { "MTLc3m.ttf",                 gFBNames    }, // Motoya Japanese Font
   440 +    { "DroidSansJapanese.ttf",      gFBNames    },
   441 +    { "DroidSansFallback.ttf",      gFBNames    }
   442 +};
   443 +
   444 +#define DEFAULT_NAMES   gSansNames
   445 +
   446 +// these globals are assigned (once) by load_system_fonts()
   447 +static FamilyRec* gDefaultFamily;
   448 +static SkTypeface* gDefaultNormal;
   449 +
   450 +/*  This is sized conservatively, assuming that it will never be a size issue.
   451 +    It will be initialized in load_system_fonts(), and will be filled with the
   452 +    fontIDs that can be used for fallback consideration, in sorted order (sorted
   453 +    meaning element[0] should be used first, then element[1], etc. When we hit
   454 +    a fontID==0 in the array, the list is done, hence our allocation size is
   455 +    +1 the total number of possible system fonts. Also see NextLogicalFont().
   456 + */
   457 +static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
   458 +
   459 +/*  Called once (ensured by the sentinel check at the beginning of our body).
   460 +    Initializes all the globals, and register the system fonts.
   461 + */
   462 +static void load_system_fonts() {
   463 +    // check if we've already be called
   464 +    if (NULL != gDefaultNormal) {
   465 +        return;
   466 +    }
   467 +
   468 +    const FontInitRec* rec = gSystemFonts;
   469 +    SkTypeface* firstInFamily = NULL;
   470 +    int fallbackCount = 0;
   471 +
   472 +    for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
   473 +        // if we're the first in a new family, clear firstInFamily
   474 +        if (rec[i].fNames != NULL) {
   475 +            firstInFamily = NULL;
   476 +        }
   477 +
   478 +        bool isFixedWidth;
   479 +        SkString name;
   480 +        SkTypeface::Style style;
   481 +
   482 +        // we expect all the fonts, except the "fallback" fonts
   483 +        bool isExpected = (rec[i].fNames != gFBNames);
   484 +        if (!get_name_and_style(rec[i].fFileName, &name, &style,
   485 +                                &isFixedWidth, isExpected)) {
   486 +            continue;
   487 +        }
   488 +
   489 +        SkTypeface* tf = SkNEW_ARGS(FileTypeface,
   490 +                                    (style,
   491 +                                     true,  // system-font (cannot delete)
   492 +                                     firstInFamily, // what family to join
   493 +                                     rec[i].fFileName,
   494 +                                     isFixedWidth) // filename
   495 +                                    );
   496 +
   497 +        if (rec[i].fNames != NULL) {
   498 +            // see if this is one of our fallback fonts
   499 +            if (rec[i].fNames == gFBNames) {
   500 +            //    SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
   501 +            //             rec[i].fFileName, fallbackCount, tf->uniqueID());
   502 +                gFallbackFonts[fallbackCount++] = tf->uniqueID();
   503 +            }
   504 +
   505 +            firstInFamily = tf;
   506 +            FamilyRec* family = find_family(tf);
   507 +            const char* const* names = rec[i].fNames;
   508 +
   509 +            // record the default family if this is it
   510 +            if (names == DEFAULT_NAMES) {
   511 +                gDefaultFamily = family;
   512 +            }
   513 +            // add the names to map to this family
   514 +            while (*names) {
   515 +                add_name(*names, family);
   516 +                names += 1;
   517 +            }
   518 +        }
   519 +    }
   520 +
   521 +    // do this after all fonts are loaded. This is our default font, and it
   522 +    // acts as a sentinel so we only execute load_system_fonts() once
   523 +    gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
   524 +    // now terminate our fallback list with the sentinel value
   525 +    gFallbackFonts[fallbackCount] = 0;
   526 +}
   527 +
   528 +///////////////////////////////////////////////////////////////////////////////
   529 +
   530 +void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
   531 +    const char* name = ((FamilyTypeface*)face)->getUniqueString();
   532 +
   533 +    stream->write8((uint8_t)face->style());
   534 +
   535 +    if (NULL == name || 0 == *name) {
   536 +        stream->writePackedUInt(0);
   537 +//        SkDebugf("--- fonthost serialize null\n");
   538 +    } else {
   539 +        uint32_t len = strlen(name);
   540 +        stream->writePackedUInt(len);
   541 +        stream->write(name, len);
   542 +//      SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style());
   543 +    }
   544 +}
   545 +
   546 +SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
   547 +    load_system_fonts();
   548 +
   549 +    int style = stream->readU8();
   550 +
   551 +    int len = stream->readPackedUInt();
   552 +    if (len > 0) {
   553 +        SkString str;
   554 +        str.resize(len);
   555 +        stream->read(str.writable_str(), len);
   556 +
   557 +        const FontInitRec* rec = gSystemFonts;
   558 +        for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
   559 +            if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
   560 +                // backup until we hit the fNames
   561 +                for (int j = i; j >= 0; --j) {
   562 +                    if (rec[j].fNames != NULL) {
   563 +                        return SkFontHost::CreateTypeface(NULL,
   564 +                                    rec[j].fNames[0], (SkTypeface::Style)style);
   565 +                    }
   566 +                }
   567 +            }
   568 +        }
   569 +    }
   570 +    return NULL;
   571 +}
   572 +
   573 +///////////////////////////////////////////////////////////////////////////////
   574 +
   575 +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
   576 +                                       const char familyName[],
   577 +                                       SkTypeface::Style style) {
   578 +    load_system_fonts();
   579 +
   580 +    SkAutoMutexAcquire  ac(gFamilyMutex);
   581 +
   582 +    // clip to legal style bits
   583 +    style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
   584 +
   585 +    SkTypeface* tf = NULL;
   586 +
   587 +    if (NULL != familyFace) {
   588 +        tf = find_typeface(familyFace, style);
   589 +    } else if (NULL != familyName) {
   590 +//        SkDebugf("======= familyName <%s>\n", familyName);
   591 +        tf = find_typeface(familyName, style);
   592 +    }
   593 +
   594 +    if (NULL == tf) {
   595 +        tf = find_best_face(gDefaultFamily, style);
   596 +    }
   597 +
   598 +    // we ref(), since the symantic is to return a new instance
   599 +    tf->ref();
   600 +    return tf;
   601 +}
   602 +
   603 +SkStream* SkFontHost::OpenStream(uint32_t fontID) {
   604 +    SkAutoMutexAcquire  ac(gFamilyMutex);
   605 +
   606 +    FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
   607 +    SkStream* stream = tf ? tf->openStream() : NULL;
   608 +
   609 +    if (stream && stream->getLength() == 0) {
   610 +        stream->unref();
   611 +        stream = NULL;
   612 +    }
   613 +    return stream;
   614 +}
   615 +
   616 +size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
   617 +                               int32_t* index) {
   618 +    SkAutoMutexAcquire  ac(gFamilyMutex);
   619 +
   620 +    FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
   621 +    const char* src = tf ? tf->getFilePath() : NULL;
   622 +
   623 +    if (src) {
   624 +        size_t size = strlen(src);
   625 +        if (path) {
   626 +            memcpy(path, src, SkMin32(size, length));
   627 +        }
   628 +        if (index) {
   629 +            *index = 0; // we don't have collections (yet)
   630 +        }
   631 +        return size;
   632 +    } else {
   633 +        return 0;
   634 +    }
   635 +}
   636 +
   637 +SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
   638 +    load_system_fonts();
   639 +
   640 +    /*  First see if fontID is already one of our fallbacks. If so, return
   641 +        its successor. If fontID is not in our list, then return the first one
   642 +        in our list. Note: list is zero-terminated, and returning zero means
   643 +        we have no more fonts to use for fallbacks.
   644 +     */
   645 +    const uint32_t* list = gFallbackFonts;
   646 +    for (int i = 0; list[i] != 0; i++) {
   647 +        if (list[i] == currFontID) {
   648 +            return list[i+1];
   649 +        }
   650 +    }
   651 +    return list[0];
   652 +}
   653 +
   654 +///////////////////////////////////////////////////////////////////////////////
   655 +
   656 +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
   657 +    if (NULL == stream || stream->getLength() <= 0) {
   658 +        return NULL;
   659 +    }
   660 +
   661 +    bool isFixedWidth;
   662 +    SkString name;
   663 +    SkTypeface::Style style;
   664 +    find_name_and_attributes(stream, &name, &style, &isFixedWidth);
   665 +
   666 +    if (!name.isEmpty()) {
   667 +        return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
   668 +    } else {
   669 +        return NULL;
   670 +    }
   671 +}
   672 +
   673 +SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
   674 +    SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
   675 +    SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
   676 +    // since we created the stream, we let go of our ref() here
   677 +    stream->unref();
   678 +    return face;
   679 +}
   680 +
   681 +///////////////////////////////////////////////////////////////////////////////
   682 -- 
   683 1.7.11.4

mercurial