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

mercurial