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

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.

     2 /*
     3  * Copyright 2006 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
    10 #include "SkFontDescriptor.h"
    11 #include "SkFontHost.h"
    12 #include "SkFontHost_FreeType_common.h"
    13 #include "SkDescriptor.h"
    14 #include "SkStream.h"
    15 #include "SkPaint.h"
    16 #include "SkString.h"
    17 #include "SkStream.h"
    18 #include "SkThread.h"
    19 #include "SkTSearch.h"
    20 #include <stdio.h>
    22 #define FONT_CACHE_MEMORY_BUDGET    (768 * 1024)
    24 #ifndef SK_FONT_FILE_PREFIX
    25     #define SK_FONT_FILE_PREFIX          "/fonts/"
    26 #endif
    28 bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style,
    29                                            bool* isFixedWidth);
    31 static void GetFullPathForSysFonts(SkString* full, const char name[]) {
    32     full->set(getenv("ANDROID_ROOT"));
    33     full->append(SK_FONT_FILE_PREFIX);
    34     full->append(name);
    35 }
    37 ///////////////////////////////////////////////////////////////////////////////
    39 struct FamilyRec;
    41 /*  This guy holds a mapping of a name -> family, used for looking up fonts.
    42     Since it is stored in a stretchy array that doesn't preserve object
    43     semantics, we don't use constructor/destructors, but just have explicit
    44     helpers to manage our internal bookkeeping.
    45 */
    46 struct NameFamilyPair {
    47     const char* fName;      // we own this
    48     FamilyRec*  fFamily;    // we don't own this, we just reference it
    50     void construct(const char name[], FamilyRec* family) {
    51         fName = strdup(name);
    52         fFamily = family;   // we don't own this, so just record the referene
    53     }
    55     void destruct() {
    56         free((char*)fName);
    57         // we don't own family, so just ignore our reference
    58     }
    59 };
    61 // we use atomic_inc to grow this for each typeface we create
    62 static int32_t gUniqueFontID;
    64 // this is the mutex that protects these globals
    65 static SkMutex gFamilyMutex;
    66 static FamilyRec* gFamilyHead;
    67 static SkTDArray<NameFamilyPair> gNameList;
    69 struct FamilyRec {
    70     FamilyRec*  fNext;
    71     SkTypeface* fFaces[4];
    73     FamilyRec()
    74     {
    75         fNext = gFamilyHead;
    76         memset(fFaces, 0, sizeof(fFaces));
    77         gFamilyHead = this;
    78     }
    79 };
    81 static SkTypeface* find_best_face(const FamilyRec* family,
    82                                   SkTypeface::Style style) {
    83     SkTypeface* const* faces = family->fFaces;
    85     if (faces[style] != NULL) { // exact match
    86         return faces[style];
    87     }
    88     // look for a matching bold
    89     style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
    90     if (faces[style] != NULL) {
    91         return faces[style];
    92     }
    93     // look for the plain
    94     if (faces[SkTypeface::kNormal] != NULL) {
    95         return faces[SkTypeface::kNormal];
    96     }
    97     // look for anything
    98     for (int i = 0; i < 4; i++) {
    99         if (faces[i] != NULL) {
   100             return faces[i];
   101         }
   102     }
   103     // should never get here, since the faces list should not be empty
   104     SkASSERT(!"faces list is empty");
   105     return NULL;
   106 }
   108 static FamilyRec* find_family(const SkTypeface* member) {
   109     FamilyRec* curr = gFamilyHead;
   110     while (curr != NULL) {
   111         for (int i = 0; i < 4; i++) {
   112             if (curr->fFaces[i] == member) {
   113                 return curr;
   114             }
   115         }
   116         curr = curr->fNext;
   117     }
   118     return NULL;
   119 }
   121 /*  Returns the matching typeface, or NULL. If a typeface is found, its refcnt
   122     is not modified.
   123  */
   124 static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
   125     FamilyRec* curr = gFamilyHead;
   126     while (curr != NULL) {
   127         for (int i = 0; i < 4; i++) {
   128             SkTypeface* face = curr->fFaces[i];
   129             if (face != NULL && face->uniqueID() == uniqueID) {
   130                 return face;
   131             }
   132         }
   133         curr = curr->fNext;
   134     }
   135     return NULL;
   136 }
   138 /*  Remove reference to this face from its family. If the resulting family
   139     is empty (has no faces), return that family, otherwise return NULL
   140 */
   141 static FamilyRec* remove_from_family(const SkTypeface* face) {
   142     FamilyRec* family = find_family(face);
   143     SkASSERT(family->fFaces[face->style()] == face);
   144     family->fFaces[face->style()] = NULL;
   146     for (int i = 0; i < 4; i++) {
   147         if (family->fFaces[i] != NULL) {    // family is non-empty
   148             return NULL;
   149         }
   150     }
   151     return family;  // return the empty family
   152 }
   154 // maybe we should make FamilyRec be doubly-linked
   155 static void detach_and_delete_family(FamilyRec* family) {
   156     FamilyRec* curr = gFamilyHead;
   157     FamilyRec* prev = NULL;
   159     while (curr != NULL) {
   160         FamilyRec* next = curr->fNext;
   161         if (curr == family) {
   162             if (prev == NULL) {
   163                 gFamilyHead = next;
   164             } else {
   165                 prev->fNext = next;
   166             }
   167             SkDELETE(family);
   168             return;
   169         }
   170         prev = curr;
   171         curr = next;
   172     }
   173     SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
   174 }
   176 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
   177     NameFamilyPair* list = gNameList.begin();
   178     int             count = gNameList.count();
   180     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
   182     if (index >= 0) {
   183         return find_best_face(list[index].fFamily, style);
   184     }
   185     return NULL;
   186 }
   188 static SkTypeface* find_typeface(const SkTypeface* familyMember,
   189                                  SkTypeface::Style style) {
   190     const FamilyRec* family = find_family(familyMember);
   191     return family ? find_best_face(family, style) : NULL;
   192 }
   194 static void add_name(const char name[], FamilyRec* family) {
   195     SkAutoAsciiToLC tolc(name);
   196     name = tolc.lc();
   198     NameFamilyPair* list = gNameList.begin();
   199     int             count = gNameList.count();
   201     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
   203     if (index < 0) {
   204         list = gNameList.insert(~index);
   205         list->construct(name, family);
   206     }
   207 }
   209 static void remove_from_names(FamilyRec* emptyFamily)
   210 {
   211 #ifdef SK_DEBUG
   212     for (int i = 0; i < 4; i++) {
   213         SkASSERT(emptyFamily->fFaces[i] == NULL);
   214     }
   215 #endif
   217     SkTDArray<NameFamilyPair>& list = gNameList;
   219     // must go backwards when removing
   220     for (int i = list.count() - 1; i >= 0; --i) {
   221         NameFamilyPair* pair = &list[i];
   222         if (pair->fFamily == emptyFamily) {
   223             pair->destruct();
   224             list.remove(i);
   225         }
   226     }
   227 }
   229 ///////////////////////////////////////////////////////////////////////////////
   231 class FamilyTypeface : public SkTypeface_FreeType {
   232 public:
   233     FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember,
   234                    bool isFixedWidth)
   235     : SkTypeface_FreeType(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
   236         fIsSysFont = sysFont;
   238         SkAutoMutexAcquire  ac(gFamilyMutex);
   240         FamilyRec* rec = NULL;
   241         if (familyMember) {
   242             rec = find_family(familyMember);
   243             SkASSERT(rec);
   244         } else {
   245             rec = SkNEW(FamilyRec);
   246         }
   247         rec->fFaces[style] = this;
   248     }
   250     virtual ~FamilyTypeface() {
   251         SkAutoMutexAcquire  ac(gFamilyMutex);
   253         // remove us from our family. If the family is now empty, we return
   254         // that and then remove that family from the name list
   255         FamilyRec* family = remove_from_family(this);
   256         if (NULL != family) {
   257             remove_from_names(family);
   258             detach_and_delete_family(family);
   259         }
   260     }
   262     bool isSysFont() const { return fIsSysFont; }
   264     virtual const char* getUniqueString() const = 0;
   265     virtual const char* getFilePath() const = 0;
   267 protected:
   268     virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
   270 private:
   271     bool    fIsSysFont;
   273     typedef SkTypeface INHERITED;
   274 };
   276 ///////////////////////////////////////////////////////////////////////////////
   278 class StreamTypeface : public FamilyTypeface {
   279 public:
   280     StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
   281                    SkStream* stream, bool isFixedWidth)
   282     : INHERITED(style, sysFont, familyMember, isFixedWidth) {
   283         SkASSERT(stream);
   284         stream->ref();
   285         fStream = stream;
   286     }
   287     virtual ~StreamTypeface() {
   288         fStream->unref();
   289     }
   291     // overrides
   292     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
   293         *ttcIndex = 0;
   294         // we just ref our existing stream, since the caller will call unref()
   295         // when they are through
   296         fStream->ref();
   297         // must rewind each time, since the caller assumes a "new" stream
   298         fStream->rewind();
   299         return fStream;
   300     }
   301     virtual const char* getUniqueString() const { return NULL; }
   302     virtual const char* getFilePath() const { return NULL; }
   304 private:
   305     SkStream* fStream;
   307     typedef FamilyTypeface INHERITED;
   308 };
   310 class FileTypeface : public FamilyTypeface {
   311 public:
   312     FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
   313                  const char path[], bool isFixedWidth)
   314     : INHERITED(style, sysFont, familyMember, isFixedWidth) {
   315         SkString fullpath;
   317         if (sysFont) {
   318             GetFullPathForSysFonts(&fullpath, path);
   319             path = fullpath.c_str();
   320         }
   321         fPath.set(path);
   322     }
   324     // overrides
   325     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
   326         *ttcIndex = 0;
   327         SkStream* stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
   329         // check for failure
   330         if (stream->getLength() <= 0) {
   331             SkDELETE(stream);
   332             stream = NULL;
   333         }
   334         return stream;
   335     }
   336     virtual const char* getUniqueString() const {
   337         const char* str = strrchr(fPath.c_str(), '/');
   338         if (str) {
   339             str += 1;   // skip the '/'
   340         }
   341         return str;
   342     }
   343     virtual const char* getFilePath() const {
   344         return fPath.c_str();
   345     }
   347 private:
   348     SkString fPath;
   350     typedef FamilyTypeface INHERITED;
   351 };
   353 ///////////////////////////////////////////////////////////////////////////////
   354 ///////////////////////////////////////////////////////////////////////////////
   356 static bool get_name_and_style(const char path[], SkString* name,
   357                                SkTypeface::Style* style,
   358                                bool* isFixedWidth, bool isExpected) {
   359     SkString        fullpath;
   360     GetFullPathForSysFonts(&fullpath, path);
   362     SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(fullpath.c_str()));
   363     if (stream.get()) {
   364         find_name_and_attributes(stream, name, style, isFixedWidth);
   365         return true;
   366     }
   368     if (isExpected) {
   369         SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
   370     }
   371     return false;
   372 }
   374 // used to record our notion of the pre-existing fonts
   375 struct FontInitRec {
   376     const char*         fFileName;
   377     const char* const*  fNames;     // null-terminated list
   378 };
   380 static const char* gSansNames[] = {
   381     "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
   382 };
   384 static const char* gSerifNames[] = {
   385     "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
   386     "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
   387 };
   389 static const char* gMonoNames[] = {
   390     "monospace", "courier", "courier new", "monaco", NULL
   391 };
   393 // deliberately empty, but we use the address to identify fallback fonts
   394 static const char* gFBNames[] = { NULL };
   396 /*  Fonts must be grouped by family, with the first font in a family having the
   397     list of names (even if that list is empty), and the following members having
   398     null for the list. The names list must be NULL-terminated
   399 */
   400 static const FontInitRec gSystemFonts[] = {
   401     { "DroidSans.ttf",              gSansNames  },
   402     { "DroidSans-Bold.ttf",         NULL        },
   403     { "DroidSerif-Regular.ttf",     gSerifNames },
   404     { "DroidSerif-Bold.ttf",        NULL        },
   405     { "DroidSerif-Italic.ttf",      NULL        },
   406     { "DroidSerif-BoldItalic.ttf",  NULL        },
   407     { "DroidSansMono.ttf",          gMonoNames  },
   408     /*  These are optional, and can be ignored if not found in the file system.
   409         These are appended to gFallbackFonts[] as they are seen, so we list
   410         them in the order we want them to be accessed by NextLogicalFont().
   411      */
   412     { "DroidSansArabic.ttf",        gFBNames    },
   413     { "DroidSansHebrew.ttf",        gFBNames    },
   414     { "DroidSansThai.ttf",          gFBNames    },
   415     { "MTLmr3m.ttf",                gFBNames    }, // Motoya Japanese Font
   416     { "MTLc3m.ttf",                 gFBNames    }, // Motoya Japanese Font
   417     { "DroidSansJapanese.ttf",      gFBNames    },
   418     { "DroidSansFallback.ttf",      gFBNames    }
   419 };
   421 #define DEFAULT_NAMES   gSansNames
   423 // these globals are assigned (once) by load_system_fonts()
   424 static FamilyRec* gDefaultFamily;
   425 static SkTypeface* gDefaultNormal;
   427 /*  This is sized conservatively, assuming that it will never be a size issue.
   428     It will be initialized in load_system_fonts(), and will be filled with the
   429     fontIDs that can be used for fallback consideration, in sorted order (sorted
   430     meaning element[0] should be used first, then element[1], etc. When we hit
   431     a fontID==0 in the array, the list is done, hence our allocation size is
   432     +1 the total number of possible system fonts. Also see NextLogicalFont().
   433  */
   434 static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
   436 /*  Called once (ensured by the sentinel check at the beginning of our body).
   437     Initializes all the globals, and register the system fonts.
   438  */
   439 static void load_system_fonts() {
   440     // check if we've already be called
   441     if (NULL != gDefaultNormal) {
   442         return;
   443     }
   445     const FontInitRec* rec = gSystemFonts;
   446     SkTypeface* firstInFamily = NULL;
   447     int fallbackCount = 0;
   449     for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
   450         // if we're the first in a new family, clear firstInFamily
   451         if (rec[i].fNames != NULL) {
   452             firstInFamily = NULL;
   453         }
   455         bool isFixedWidth;
   456         SkString name;
   457         SkTypeface::Style style;
   459         // we expect all the fonts, except the "fallback" fonts
   460         bool isExpected = (rec[i].fNames != gFBNames);
   461         if (!get_name_and_style(rec[i].fFileName, &name, &style,
   462                                 &isFixedWidth, isExpected)) {
   463             continue;
   464         }
   466         SkTypeface* tf = SkNEW_ARGS(FileTypeface,
   467                                     (style,
   468                                      true,  // system-font (cannot delete)
   469                                      firstInFamily, // what family to join
   470                                      rec[i].fFileName,
   471                                      isFixedWidth) // filename
   472                                     );
   474         if (rec[i].fNames != NULL) {
   475             // see if this is one of our fallback fonts
   476             if (rec[i].fNames == gFBNames) {
   477             //    SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
   478             //             rec[i].fFileName, fallbackCount, tf->uniqueID());
   479                 gFallbackFonts[fallbackCount++] = tf->uniqueID();
   480             }
   482             firstInFamily = tf;
   483             FamilyRec* family = find_family(tf);
   484             const char* const* names = rec[i].fNames;
   486             // record the default family if this is it
   487             if (names == DEFAULT_NAMES) {
   488                 gDefaultFamily = family;
   489             }
   490             // add the names to map to this family
   491             while (*names) {
   492                 add_name(*names, family);
   493                 names += 1;
   494             }
   495         }
   496     }
   498     // do this after all fonts are loaded. This is our default font, and it
   499     // acts as a sentinel so we only execute load_system_fonts() once
   500     gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
   501     // now terminate our fallback list with the sentinel value
   502     gFallbackFonts[fallbackCount] = 0;
   503 }
   505 void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
   506                                          bool* isLocalStream) const {
   507     {
   508         SkAutoMutexAcquire ac(gFamilyMutex);
   509         //desc->setFamilyName(find_family_name(this));
   510         desc->setFontFileName(this->getUniqueString());
   511     }
   512     *isLocalStream = !this->isSysFont();
   513 }
   515 ///////////////////////////////////////////////////////////////////////////////
   517 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
   518                                        const char familyName[],
   519                                        SkTypeface::Style style) {
   520     load_system_fonts();
   522     SkAutoMutexAcquire  ac(gFamilyMutex);
   524     // clip to legal style bits
   525     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
   527     SkTypeface* tf = NULL;
   529     if (NULL != familyFace) {
   530         tf = find_typeface(familyFace, style);
   531     } else if (NULL != familyName) {
   532 //        SkDebugf("======= familyName <%s>\n", familyName);
   533         tf = find_typeface(familyName, style);
   534     }
   536     if (NULL == tf) {
   537         tf = find_best_face(gDefaultFamily, style);
   538     }
   540     // we ref(), since the symantic is to return a new instance
   541     tf->ref();
   542     return tf;
   543 }
   545 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
   546                                          const SkPaintOptionsAndroid& options) {
   547     load_system_fonts();
   549     /*  First see if fontID is already one of our fallbacks. If so, return
   550         its successor. If fontID is not in our list, then return the first one
   551         in our list. Note: list is zero-terminated, and returning zero means
   552         we have no more fonts to use for fallbacks.
   553      */
   554     const uint32_t* list = gFallbackFonts;
   555     for (int i = 0; list[i] != 0; i++) {
   556         if (list[i] == currFontID) {
   557             return find_from_uniqueID(list[i+1]);
   558         }
   559     }
   560     return find_from_uniqueID(list[0]);
   561 }
   563 ///////////////////////////////////////////////////////////////////////////////
   565 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
   566     if (NULL == stream || stream->getLength() <= 0) {
   567         return NULL;
   568     }
   570     bool isFixedWidth;
   571     SkString name;
   572     SkTypeface::Style style;
   573     find_name_and_attributes(stream, &name, &style, &isFixedWidth);
   575     if (!name.isEmpty()) {
   576         return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
   577     } else {
   578         return NULL;
   579     }
   580 }
   582 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
   583     SkStream* stream = SkNEW_ARGS(SkFILEStream, (path));
   584     SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
   585     // since we created the stream, we let go of our ref() here
   586     stream->unref();
   587     return face;
   588 }

mercurial