1From 0d730a94e9f6676d5cde45f955fe025a4549817e Mon Sep 17 00:00:00 2001
2From: George Wright <gw@gwright.org.uk>
3Date: Thu, 23 Aug 2012 16:45:38 -0400
4Subject: [PATCH 4/9] Bug 777614 - Re-apply bug 719872 - Fix crash on Android
5 by reverting to older FontHost r=nrc
6
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
11
12diff --git a/gfx/skia/src/ports/SkFontHost_android_old.cpp b/gfx/skia/src/ports/SkFontHost_android_old.cpp
13new file mode 100644
14index 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--
6831.7.11.4
684
685