1bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
2bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com/*
3bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com * Copyright 2013 The Android Open Source Project
4bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com *
5bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com * Use of this source code is governed by a BSD-style license that can be
6bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com * found in the LICENSE file.
7bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com */
8bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
9bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkFontConfigInterface.h"
10bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkTypeface_android.h"
11bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
12bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkFontConfigParser_android.h"
13bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkFontConfigTypeface.h"
14bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkFontMgr.h"
15bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkGlyphCache.h"
16bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkPaint.h"
17bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkString.h"
18bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkStream.h"
19bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkThread.h"
20bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkTypefaceCache.h"
21bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkTArray.h"
22bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkTDict.h"
23bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include "SkTSearch.h"
24bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
25bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include <stdio.h>
26bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#include <string.h>
27bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
28bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#ifndef SK_DEBUG_FONTS
29bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    #define SK_DEBUG_FONTS 0
30bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#endif
31bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
32bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#if SK_DEBUG_FONTS
33bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    #define DEBUG_FONT(args) SkDebugf args
34bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#else
35bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    #define DEBUG_FONT(args)
36bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#endif
37bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
38bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
39bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
40bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com// For test only.
41bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic const char* gTestMainConfigFile = NULL;
42bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic const char* gTestFallbackConfigFile = NULL;
43bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic const char* gTestFontFilePrefix = NULL;
44bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
45bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
46bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
4740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comtypedef int32_t FontRecID;
4840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#define INVALID_FONT_REC_ID -1
4940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
5040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comtypedef int32_t FamilyRecID;
5140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#define INVALID_FAMILY_REC_ID -1
5240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
53bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com// used to record our notion of the pre-existing fonts
54bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstruct FontRec {
55bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkRefPtr<SkTypeface> fTypeface;
56bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkString fFileName;
57bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTypeface::Style fStyle;
58bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    bool fIsValid;
5940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    FamilyRecID fFamilyRecID;
60bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com};
61bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
62bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstruct FamilyRec {
63bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FamilyRec() {
64bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID));
65bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
66bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
67bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    static const int FONT_STYLE_COUNT = 4;
68bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FontRecID fFontRecID[FONT_STYLE_COUNT];
69b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    bool fIsFallbackFont;
7039a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    SkString fFallbackName;
71b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    SkPaintOptionsAndroid fPaintOptions;
72bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com};
73bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
74bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
75b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.comtypedef SkTDArray<FamilyRecID> FallbackFontList;
76bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
77bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comclass SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
78bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.compublic:
79bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies);
80bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    virtual ~SkFontConfigInterfaceAndroid();
81bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
82bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    virtual bool matchFamilyName(const char familyName[],
83bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                 SkTypeface::Style requested,
84bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                 FontIdentity* outFontIdentifier,
85bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                 SkString* outFamilyName,
86bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                 SkTypeface::Style* outStyle) SK_OVERRIDE;
87bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE;
88bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
89bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // new APIs
90bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    virtual SkDataTable* getFamilyNames() SK_OVERRIDE;
91bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    virtual bool matchFamilySet(const char inFamilyName[],
92bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                SkString* outFamilyName,
93bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                SkTArray<FontIdentity>*) SK_OVERRIDE;
94bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
95bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    /**
96bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com     *  Get the family name of the font in the default fallback font list that
97bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com     *  contains the specified chararacter. if no font is found, returns false.
98bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com     */
999902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com    bool getFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name);
100bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    /**
101bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com     *
102bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com     */
103bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style,
104bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                   SkPaintOptionsAndroid::FontVariant fontVariant);
105bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
106bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                    const SkPaintOptionsAndroid& options);
1075df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    SkTypeface* getTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface,
1085df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                      const SkPaintOptionsAndroid& options,
1095df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                      int* lowerBounds, int* upperBounds);
110bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
111bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comprivate:
112b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    void addFallbackFamily(FamilyRecID fontRecID);
11340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkTypeface* getTypefaceForFontRec(FontRecID fontRecID);
1149a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    FallbackFontList* getCurrentLocaleFallbackFontList();
11540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOriginal = true);
116bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
117bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTArray<FontRec> fFonts;
118bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTArray<FamilyRec> fFontFamilies;
119bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDict<FamilyRecID> fFamilyNameDict;
120bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FamilyRecID fDefaultFamilyRecID;
121bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
122bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // (SkLanguage)<->(fallback chain index) translation
123bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDict<FallbackFontList*> fFallbackFontDict;
12440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkTDict<FallbackFontList*> fFallbackFontAliasDict;
125bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FallbackFontList fDefaultFallbackList;
1269a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com
1279a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    // fallback info for current locale
1289a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    SkString fCachedLocale;
1299a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    FallbackFontList* fLocaleFallbackFontList;
130bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com};
131bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
132bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
133bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
134bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic SkFontConfigInterfaceAndroid* getSingletonInterface() {
135bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SK_DECLARE_STATIC_MUTEX(gMutex);
136bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    static SkFontConfigInterfaceAndroid* gFontConfigInterface;
137bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
138bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkAutoMutexAcquire ac(gMutex);
139bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (NULL == gFontConfigInterface) {
140bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // load info from a configuration file that we can use to populate the
141bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // system/fallback font structures
142bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        SkTDArray<FontFamily*> fontFamilies;
143bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        if (!gTestMainConfigFile) {
144bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            SkFontConfigParser::GetFontFamilies(fontFamilies);
145bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        } else {
146bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            SkFontConfigParser::GetTestFontFamilies(fontFamilies, gTestMainConfigFile,
147bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                    gTestFallbackConfigFile);
148bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
149bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
150bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        gFontConfigInterface = new SkFontConfigInterfaceAndroid(fontFamilies);
151bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
152bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // cleanup the data we received from the parser
153bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fontFamilies.deleteAll();
154bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
155bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return gFontConfigInterface;
156bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
157bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
158bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
159bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return getSingletonInterface();
160bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
161bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
162bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
163bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
164bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic bool has_font(const SkTArray<FontRec>& array, const SkString& filename) {
165bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    for (int i = 0; i < array.count(); i++) {
166bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        if (array[i].fFileName == filename) {
167bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            return true;
168bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
169bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
170bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return false;
171bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
172bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
173bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#ifndef SK_FONT_FILE_PREFIX
174bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    #define SK_FONT_FILE_PREFIX          "/fonts/"
175bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com#endif
176bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
17731db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.orgstatic void get_path_for_sys_fonts(SkString* full, const SkString& name) {
178bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (gTestFontFilePrefix) {
179bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        full->set(gTestFontFilePrefix);
180bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    } else {
181bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        full->set(getenv("ANDROID_ROOT"));
182bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        full->append(SK_FONT_FILE_PREFIX);
183bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
184bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    full->append(name);
185bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
186bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
187bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic void insert_into_name_dict(SkTDict<FamilyRecID>& familyNameDict,
188bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                  const char* name, FamilyRecID familyRecID) {
189bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkAutoAsciiToLC tolc(name);
19092e3f08c916cf8febb07d120afc63b8c33df1389djsollen@google.com    if (familyNameDict.find(tolc.lc())) {
19192e3f08c916cf8febb07d120afc63b8c33df1389djsollen@google.com        SkDebugf("---- system font attempting to use a the same name [%s] for"
19292e3f08c916cf8febb07d120afc63b8c33df1389djsollen@google.com                 "multiple families. skipping subsequent occurrences", tolc.lc());
19392e3f08c916cf8febb07d120afc63b8c33df1389djsollen@google.com    } else {
19492e3f08c916cf8febb07d120afc63b8c33df1389djsollen@google.com        familyNameDict.set(tolc.lc(), familyRecID);
19592e3f08c916cf8febb07d120afc63b8c33df1389djsollen@google.com    }
196bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
197bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
198bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com// Defined in SkFontHost_FreeType.cpp
199bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.combool find_name_and_attributes(SkStream* stream, SkString* name,
200bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                              SkTypeface::Style* style, bool* isFixedWidth);
201bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
202bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
203bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
204bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies) :
205bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fFonts(fontFamilies.count()),
206bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT),
207bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fFamilyNameDict(1024),
208bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fDefaultFamilyRecID(INVALID_FAMILY_REC_ID),
20940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        fFallbackFontDict(128),
2109a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com        fFallbackFontAliasDict(128),
2119a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com        fLocaleFallbackFontList(NULL) {
212bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
213bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    for (int i = 0; i < fontFamilies.count(); ++i) {
214bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        FontFamily* family = fontFamilies[i];
215bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
216bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // defer initializing the familyRec until we can be sure that at least
217bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // one of it's children contains a valid font file
218bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        FamilyRec* familyRec = NULL;
219bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
220bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
221bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        for (int j = 0; j < family->fFontFiles.count(); ++j) {
222bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            SkString filename;
22331db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.org            get_path_for_sys_fonts(&filename, family->fFontFiles[j].fFileName);
224bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
225bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            if (has_font(fFonts, filename)) {
226bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                SkDebugf("---- system font and fallback font files specify a duplicate "
227bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                        "font %s, skipping the second occurrence", filename.c_str());
228bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                continue;
229bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
230bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
231bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            FontRec& fontRec = fFonts.push_back();
232bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            fontRec.fFileName = filename;
233bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            fontRec.fStyle = SkTypeface::kNormal;
234bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            fontRec.fIsValid = false;
23540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            fontRec.fFamilyRecID = familyRecID;
236bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
237bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            const FontRecID fontRecID = fFonts.count() - 1;
238bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
239bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
240bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            if (stream.get() != NULL) {
241bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                bool isFixedWidth;
242bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                SkString name;
243bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                fontRec.fIsValid = find_name_and_attributes(stream.get(), &name,
244bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                            &fontRec.fStyle, &isFixedWidth);
245bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            } else {
246b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com                if (!family->fIsFallbackFont) {
247bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                    SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
248bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                }
249bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
250bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
251bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            if (fontRec.fIsValid) {
252bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s",
2539902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com                           i, fFonts.count() - 1, family->fIsFallbackFont, filename.c_str()));
254bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            } else {
255bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVALID)",
2569902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com                           i, fFonts.count() - 1, family->fIsFallbackFont, filename.c_str()));
257bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                continue;
258bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
259bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
260bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            // create a familyRec now that we know that at least one font in
261bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            // the family is valid
262bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            if (familyRec == NULL) {
263bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                familyRec = &fFontFamilies.push_back();
264bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                familyRecID = fFontFamilies.count() - 1;
26540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com                fontRec.fFamilyRecID = familyRecID;
266b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com
267b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com                familyRec->fIsFallbackFont = family->fIsFallbackFont;
26831db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.org                familyRec->fPaintOptions = family->fFontFiles[j].fPaintOptions;
269b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com
27031db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.org            } else if (familyRec->fPaintOptions != family->fFontFiles[j].fPaintOptions) {
271b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com                SkDebugf("Every font file within a family must have identical"
272b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com                         "language and variant attributes");
273b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com                sk_throw();
274bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
275bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
276bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            // add this font to the current familyRec
277bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) {
278bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d)",
279bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                            fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle],
280bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                            fontRecID));
281bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
282bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            familyRec->fFontRecID[fontRec.fStyle] = fontRecID;
283bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
284bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
28539a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com        if (familyRec) {
28639a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com            if (familyRec->fIsFallbackFont) {
28739a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                // add the font to the appropriate fallback chains and also insert a
28839a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                // unique name into the familyNameDict for internal usage
28939a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                addFallbackFamily(familyRecID);
29039a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com            } else {
29139a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                // add the names that map to this family to the dictionary for easy lookup
29231db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.org                const SkTArray<SkString>& names = family->fNames;
29331db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.org                if (names.empty()) {
29439a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                    SkDEBUGFAIL("ERROR: non-fallback font with no name");
29539a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                    continue;
29639a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                }
297bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
29839a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                for (int i = 0; i < names.count(); i++) {
29931db71dd59b18ae0f36ca2686fba5fdcc6fe9439commit-bot@chromium.org                    insert_into_name_dict(fFamilyNameDict, names[i].c_str(), familyRecID);
30039a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com                }
301bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
302bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
303bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
304bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
305bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    DEBUG_FONT(("---- We have %d system fonts", fFonts.count()));
306bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
307bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (fFontFamilies.count() > 0) {
308bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fDefaultFamilyRecID = 0;
309bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
310bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
311bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // scans the default fallback font chain, adding every entry to every other
312bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // fallback font chain to which it does not belong. this results in every
313bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // language-specific fallback font chain having all of its fallback fonts at
314bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // the front of the chain, and everything else at the end.
315bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FallbackFontList* fallbackList;
316bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict);
317bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    const char* fallbackLang = iter.next(&fallbackList);
318bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    while(fallbackLang != NULL) {
319bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        for (int i = 0; i < fDefaultFallbackList.count(); i++) {
320b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com            FamilyRecID familyRecID = fDefaultFallbackList[i];
321b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com            const SkString& fontLang = fFontFamilies[familyRecID].fPaintOptions.getLanguage().getTag();
322bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            if (strcmp(fallbackLang, fontLang.c_str()) != 0) {
323b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com                fallbackList->push(familyRecID);
324bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            }
325bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
326bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // move to the next fallback list in the dictionary
327bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fallbackLang = iter.next(&fallbackList);
328bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
329bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
330bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
331bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkFontConfigInterfaceAndroid::~SkFontConfigInterfaceAndroid() {
332bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // iterate through and cleanup fFallbackFontDict
333bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict);
334bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FallbackFontList* fallbackList;
335bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    while(iter.next(&fallbackList) != NULL) {
336bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        SkDELETE(fallbackList);
337bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
338bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
339bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
340b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.comvoid SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) {
341b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    SkASSERT(familyRecID < fFontFamilies.count());
34239a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    FamilyRec& familyRec = fFontFamilies[familyRecID];
343b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    SkASSERT(familyRec.fIsFallbackFont);
344bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
34539a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    // add the fallback family to the name dictionary.  This is
34639a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    // needed by getFallbackFamilyNameForChar() so that fallback
34739a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    // families can be identified by a unique name. The unique
34839a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    // identifier that we've chosen is the familyID in hex (e.g. '0F##fallback').
34939a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    familyRec.fFallbackName.printf("%.2x##fallback", familyRecID);
35039a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com    insert_into_name_dict(fFamilyNameDict, familyRec.fFallbackName.c_str(), familyRecID);
35139a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com
352bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // add to the default fallback list
353b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    fDefaultFallbackList.push(familyRecID);
354bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
355bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // stop here if it is the default language tag
356b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    const SkString& languageTag = familyRec.fPaintOptions.getLanguage().getTag();
357bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (languageTag.isEmpty()) {
358bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return;
359bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
360bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
361bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // add to the appropriate language's custom fallback list
362bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FallbackFontList* customList = NULL;
363bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (!fFallbackFontDict.find(languageTag.c_str(), &customList)) {
364bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        DEBUG_FONT(("----  Created fallback list for \"%s\"", languageTag.c_str()));
365bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        customList = SkNEW(FallbackFontList);
366bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fFallbackFontDict.set(languageTag.c_str(), customList);
367bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
368bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkASSERT(customList != NULL);
369b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    customList->push(familyRecID);
370bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
371bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
372bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
373bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comstatic FontRecID find_best_style(const FamilyRec& family, SkTypeface::Style style) {
374bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
375bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    const FontRecID* fontRecIDs = family.fFontRecID;
376bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
377bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (fontRecIDs[style] != INVALID_FONT_REC_ID) { // exact match
378bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return fontRecIDs[style];
379bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
380bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // look for a matching bold
381bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
382bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (fontRecIDs[style] != INVALID_FONT_REC_ID) {
383bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return fontRecIDs[style];
384bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
385bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // look for the plain
386bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (fontRecIDs[SkTypeface::kNormal] != INVALID_FONT_REC_ID) {
387bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return fontRecIDs[SkTypeface::kNormal];
388bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
389bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // look for anything
390bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    for (int i = 0; i < FamilyRec::FONT_STYLE_COUNT; i++) {
391bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        if (fontRecIDs[i] != INVALID_FONT_REC_ID) {
392bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            return fontRecIDs[i];
393bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
394bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
395bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // should never get here, since the fontRecID list should not be empty
396bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkDEBUGFAIL("No valid fonts exist for this family");
397bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return -1;
398bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
399bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
400bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.combool SkFontConfigInterfaceAndroid::matchFamilyName(const char familyName[],
401bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                   SkTypeface::Style style,
402bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                   FontIdentity* outFontIdentifier,
403bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                   SkString* outFamilyName,
404b7457d0d3b25f1a3dcc46656dce4e787645730bdrobertphillips@google.com                                                   SkTypeface::Style* outStyle) {
405bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // clip to legal style bits
406bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
407bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
408bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    bool exactNameMatch = false;
409bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
410bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
411bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (NULL != familyName) {
4122e08f19943b69eace09ef2536d2028913ede7725djsollen@google.com        SkAutoAsciiToLC tolc(familyName);
4132e08f19943b69eace09ef2536d2028913ede7725djsollen@google.com        if (fFamilyNameDict.find(tolc.lc(), &familyRecID)) {
414bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            exactNameMatch = true;
415bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
416bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    } else {
417bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        familyRecID = fDefaultFamilyRecID;
418bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
419bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
420bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
4211f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com    // If no matching family name is found then return false. This allows clients
4221f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com    // to be able to search for other fonts instead of forcing them to use the
4231f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com    // default font.
424bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (INVALID_FAMILY_REC_ID == familyRecID) {
4251f584ed3f43037e85bae3019d48e793ae28ebbd5djsollen@google.com        return false;
426bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
427bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
428bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], style);
429bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FontRec& fontRec = fFonts[fontRecID];
430bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
431bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (NULL != outFontIdentifier) {
432bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        outFontIdentifier->fID = fontRecID;
433bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        outFontIdentifier->fTTCIndex = 0;
434bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        outFontIdentifier->fString.set(fontRec.fFileName);
435bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com//        outFontIdentifier->fStyle = fontRec.fStyle;
436bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
437bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
438bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (NULL != outFamilyName) {
439bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        if (exactNameMatch) {
440bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            outFamilyName->set(familyName);
441bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        } else {
442bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            // find familyName from list of names
443bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            const char* familyName = NULL;
444ab6eeb9d8405ade57d251f93b0788f75ec83ed54djsollen@google.com            SkAssertResult(fFamilyNameDict.findKey(familyRecID, &familyName));
445ab6eeb9d8405ade57d251f93b0788f75ec83ed54djsollen@google.com            SkASSERT(familyName);
446bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            outFamilyName->set(familyName);
447bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
448bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
449bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
450bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (NULL != outStyle) {
451bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        *outStyle = fontRec.fStyle;
452bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
453bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
454bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return true;
455bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
456bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
457b7457d0d3b25f1a3dcc46656dce4e787645730bdrobertphillips@google.comSkStream* SkFontConfigInterfaceAndroid::openStream(const FontIdentity& identity) {
458bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return SkStream::NewFromFile(identity.fString.c_str());
459bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
460bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
461b7457d0d3b25f1a3dcc46656dce4e787645730bdrobertphillips@google.comSkDataTable* SkFontConfigInterfaceAndroid::getFamilyNames() {
462bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDArray<const char*> names;
463bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDArray<size_t> sizes;
464bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
465bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTDict<FamilyRecID>::Iter iter(fFamilyNameDict);
466bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    const char* familyName = iter.next(NULL);
467bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    while(familyName != NULL) {
468bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        *names.append() = familyName;
469bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        *sizes.append() = strlen(familyName) + 1;
470bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
471bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // move to the next familyName in the dictionary
472bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        familyName = iter.next(NULL);
473bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
474bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
475bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
476bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                      sizes.begin(), names.count());
477bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
478bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
479bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.combool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[],
480bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                  SkString* outFamilyName,
481b7457d0d3b25f1a3dcc46656dce4e787645730bdrobertphillips@google.com                                                  SkTArray<FontIdentity>*) {
482bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return false;
483bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
484bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
48540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstatic bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
48640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    const FontRecID* fontRecID = (const FontRecID*)ctx;
48740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    FontRecID currFontRecID = ((FontConfigTypeface*)face)->getIdentity().fID;
48840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    return currFontRecID == *fontRecID;
48940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com}
49040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
49140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comSkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRecID) {
49240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    FontRec& fontRec = fFonts[fontRecID];
493bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTypeface* face = fontRec.fTypeface.get();
494bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (!face) {
49540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        // look for it in the typeface cache
49640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        face = SkTypefaceCache::FindByProcAndRef(find_proc, &fontRecID);
497bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
498bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // if it is not in the cache then create it
49940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        if (!face) {
50040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            const char* familyName = NULL;
50140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            SkAssertResult(fFamilyNameDict.findKey(fontRec.fFamilyRecID, &familyName));
50240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            SkASSERT(familyName);
50340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            face = SkTypeface::CreateFromName(familyName, fontRec.fStyle);
50440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        }
505bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
506bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        // store the result for subsequent lookups
507bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        fontRec.fTypeface = face;
508bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
509bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkASSERT(face);
510bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return face;
511bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
512bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
5139902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.combool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni,
5149902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com                                                                const char* lang,
5159902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com                                                                SkString* name) {
516c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org    FallbackFontList* fallbackFontList = NULL;
517c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org    const SkString langTag(lang);
518c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org    if (langTag.isEmpty()) {
519c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org        fallbackFontList = this->getCurrentLocaleFallbackFontList();
520c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org    } else {
521c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org        fallbackFontList = this->findFallbackFontList(langTag);
522c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org    }
523c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org
5249a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    for (int i = 0; i < fallbackFontList->count(); i++) {
525b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com        FamilyRecID familyRecID = fallbackFontList->getAt(i);
5269902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com
5279902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com        // if it is not one of the accepted variants then move to the next family
5289902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com        int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant |
5299902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com                                   SkPaintOptionsAndroid::kElegant_Variant;
5309902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com        if (!(fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants)) {
5319902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com            continue;
5329902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com        }
5339902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com
534b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com        FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkTypeface::kNormal);
53540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
536bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
537bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        SkPaint paint;
538bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        paint.setTypeface(face);
539bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
540bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
541bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        uint16_t glyphID;
542bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        paint.textToGlyphs(&uni, sizeof(uni), &glyphID);
543bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        if (glyphID != 0) {
54439a7c7035b2978e2483cca67c2a9f8b201fb5fbbdjsollen@google.com            name->set(fFontFamilies[familyRecID].fFallbackName);
545bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            return true;
546bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
547bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
548bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return false;
549bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
550bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
551bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni,
552bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                             SkTypeface::Style style,
553bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                             SkPaintOptionsAndroid::FontVariant fontVariant) {
554bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], style);
55540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
556bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
557bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkPaintOptionsAndroid paintOptions;
558bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    paintOptions.setFontVariant(fontVariant);
559bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    paintOptions.setUseFontFallbacks(true);
560bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
561bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkPaint paint;
562bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    paint.setTypeface(face);
563bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
564bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    paint.setPaintOptionsAndroid(paintOptions);
565bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
566bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkAutoGlyphCache autoCache(paint, NULL, NULL);
567bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkGlyphCache*    cache = autoCache.getCache();
568bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
569bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkScalerContext* ctx = cache->getScalerContext();
570bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (ctx) {
571bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        SkFontID fontID = ctx->findTypefaceIdForChar(uni);
572bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return SkTypefaceCache::FindByID(fontID);
573bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
574bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return NULL;
575bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
576bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
5779a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.comFallbackFontList* SkFontConfigInterfaceAndroid::getCurrentLocaleFallbackFontList() {
5789a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    SkString locale = SkFontConfigParser::GetLocale();
5799a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    if (NULL == fLocaleFallbackFontList || locale != fCachedLocale) {
5809a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com        fCachedLocale = locale;
5819a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com        fLocaleFallbackFontList = this->findFallbackFontList(locale);
5829a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    }
5839a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com    return fLocaleFallbackFontList;
5849a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com}
5859a70f347c9f279bf7b4ad8f24e78e3e524767ed5djsollen@google.com
58640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comFallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLanguage& lang,
58740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com                                                                     bool isOriginal) {
588bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    const SkString& langTag = lang.getTag();
589bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (langTag.isEmpty()) {
590bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return &fDefaultFallbackList;
591bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
592bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
593bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FallbackFontList* fallbackFontList;
59440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontList) ||
59540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        fFallbackFontAliasDict.find(langTag.c_str(), langTag.size(), &fallbackFontList)) {
596bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return fallbackFontList;
597bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
598bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
599bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // attempt a recursive fuzzy match
600bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkLanguage parent = lang.getParent();
60140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    fallbackFontList = findFallbackFontList(parent, false);
60240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
60340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    // cache the original lang so we don't have to do the recursion again.
60440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if (isOriginal) {
60540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        DEBUG_FONT(("----  Created fallback list alias for \"%s\"", langTag.c_str()));
60640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        fFallbackFontAliasDict.set(langTag.c_str(), fallbackFontList);
60740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
60840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    return fallbackFontList;
609bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
610bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
611bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontID,
612bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                              SkFontID origFontID,
613bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                                              const SkPaintOptionsAndroid& opts) {
614bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // Skia does not support font fallback by default. This enables clients such
615bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // as WebKit to customize their font selection. In any case, clients can use
616bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // GetFallbackFamilyNameForChar() to get the fallback font for individual
617bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // characters.
618bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (!opts.isUsingFontFallbacks()) {
619bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return NULL;
620bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
621bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
622bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
623bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkASSERT(currentFallbackList);
624bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
625b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    SkTypeface::Style origStyle = SkTypeface::kNormal;
626b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID);
627b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    if (NULL != origTypeface) {
628b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com        origStyle = origTypeface->style();
629b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    }
630b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com
631bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // we must convert currTypeface into a FontRecID
632e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    FontRecID currFontRecID = INVALID_FONT_REC_ID;
633e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
634e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    // non-system fonts are not in the font cache so if we are asked to fallback
635e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    // for a non-system font we will start at the front of the chain.
63694da31dd3b1b240f649cde30b767247681b7724bcommit-bot@chromium.org    if (NULL != currTypeface) {
637e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com        currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity().fID;
638e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com        SkASSERT(INVALID_FONT_REC_ID != currFontRecID);
639e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    }
640bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
641b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    FamilyRecID currFamilyRecID = INVALID_FAMILY_REC_ID;
642b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    if (INVALID_FONT_REC_ID != currFontRecID) {
643b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com        currFamilyRecID = fFonts[currFontRecID].fFamilyRecID;
644b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    }
645b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com
646e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    // lookup the index next font in the chain
647b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com    int currFallbackFontIndex = currentFallbackList->find(currFamilyRecID);
648e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    // We add 1 to the returned index for 2 reasons: (1) if find succeeds it moves
649e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    // our index to the next entry in the list; (2) if find() fails it returns
650e47e7d17a6444e0f44aece3e6d2a842f64aadadadjsollen@google.com    // -1 and incrementing it will set our starting index to 0 (the head of the list)
651bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    int nextFallbackFontIndex = currFallbackFontIndex + 1;
652bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
65340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if(nextFallbackFontIndex >= currentFallbackList->count()) {
654bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        return NULL;
655bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
656bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
657bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // If a rec object is set to prefer "kDefault_Variant" it means they have no preference
658bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    // In this case, we set the value to "kCompact_Variant"
659bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant();
660bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    if (variant == SkPaintOptionsAndroid::kDefault_Variant) {
661bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        variant = SkPaintOptionsAndroid::kCompact_Variant;
662bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
663bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
664bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
665bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
666bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkTypeface* nextLogicalTypeface = 0;
667bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    while (nextFallbackFontIndex < currentFallbackList->count()) {
668b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com        FamilyRecID familyRecID = currentFallbackList->getAt(nextFallbackFontIndex);
669b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com        if ((fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) {
670b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com            FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle);
671b27eba7c28c7a52e6af91743ab51c266ed96dccddjsollen@google.com            nextLogicalTypeface = this->getTypefaceForFontRec(matchedFont);
672bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com            break;
673bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        }
674bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com        nextFallbackFontIndex++;
675bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    }
676bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
677bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=%d, "
67840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com                "lang=%s, variant=%d, nextFallbackIndex[%d,%d] => nextLogicalTypeface=%d",
679bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                currFontID, origFontID, currFontRecID, opts.getLanguage().getTag().c_str(),
68040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com                variant, nextFallbackFontIndex, currentFallbackList->getAt(nextFallbackFontIndex),
681bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0));
682bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return SkSafeRef(nextLogicalTypeface);
683bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
684bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
6855df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.comSkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForGlyphID(uint16_t glyphID,
6865df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                                                const SkTypeface* origTypeface,
6875df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                                                const SkPaintOptionsAndroid& opts,
6885df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                                                int* lBounds, int* uBounds) {
6895df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    // If we aren't using fallbacks then we shouldn't be calling this
6905df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    SkASSERT(opts.isUsingFontFallbacks());
6915df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    SkASSERT(origTypeface);
6925df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
6935df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    SkTypeface* currentTypeface = NULL;
6945df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    int lowerBounds = 0; //inclusive
6955df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    int upperBounds = origTypeface->countGlyphs(); //exclusive
6965df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
6975df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    // check to see if the glyph is in the bounds of the origTypeface
6985df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    if (glyphID < upperBounds) {
6995df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        currentTypeface = const_cast<SkTypeface*>(origTypeface);
7005df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    } else {
7015df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
7025df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        SkASSERT(currentFallbackList);
7035df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
7045df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        // If an object is set to prefer "kDefault_Variant" it means they have no preference
7055df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        // In this case, we set the value to "kCompact_Variant"
7065df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant();
7075df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        if (variant == SkPaintOptionsAndroid::kDefault_Variant) {
7085df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            variant = SkPaintOptionsAndroid::kCompact_Variant;
7095df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        }
7105df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
7115df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
7125df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        SkTypeface::Style origStyle = origTypeface->style();
7135df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
7145df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        for (int x = 0; x < currentFallbackList->count(); ++x) {
7155df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            const FamilyRecID familyRecID = currentFallbackList->getAt(x);
7165df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            const SkPaintOptionsAndroid& familyOptions = fFontFamilies[familyRecID].fPaintOptions;
7175df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            if ((familyOptions.getFontVariant() & acceptedVariants) != 0) {
7185df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle);
7195df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                currentTypeface = this->getTypefaceForFontRec(matchedFont);
7205df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                lowerBounds = upperBounds;
7215df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                upperBounds += currentTypeface->countGlyphs();
7225df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                if (glyphID < upperBounds) {
7235df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                    break;
7245df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                }
7255df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            }
7265df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        }
7275df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    }
7285df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
7295df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    if (NULL != currentTypeface) {
7305df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        if (lBounds) {
7315df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            *lBounds = lowerBounds;
7325df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        }
7335df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        if (uBounds) {
7345df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com            *uBounds = upperBounds;
7355df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com        }
7365df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    }
7375df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    return currentTypeface;
7385df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com}
7395df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
740bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
741bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
742bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.combool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
7439902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com    SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
744c0445fec1983465a2c985a2c88e796678585d68acommit-bot@chromium.org    return fontConfig->getFallbackFamilyNameForChar(uni, NULL, name);
7459902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com}
7469902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com
7479902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.combool SkGetFallbackFamilyNameForChar(SkUnichar uni, const char* lang, SkString* name) {
748bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
7499902c38f4802aad589177c069f792eeeabb1a29bdjsollen@google.com    return fontConfig->getFallbackFamilyNameForChar(uni, lang, name);
750bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
751bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
752bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comvoid SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
753bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                             const char* fontsdir) {
754bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    gTestMainConfigFile = mainconf;
755bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    gTestFallbackConfigFile = fallbackconf;
756bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    gTestFontFilePrefix = fontsdir;
757bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkASSERT(gTestMainConfigFile);
758bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkASSERT(gTestFallbackConfigFile);
759bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkASSERT(gTestFontFilePrefix);
760bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
761bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com              gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
762bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
763bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
764bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
765bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com                                         const SkPaintOptionsAndroid& options) {
766bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
767bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com    return fontConfig->nextLogicalTypeface(currFontID, origFontID, options);
768bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
769bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
770bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
7715df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.comSkTypeface* SkGetTypefaceForGlyphID(uint16_t glyphID, const SkTypeface* origTypeface,
7725df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                    const SkPaintOptionsAndroid& options,
7735df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                    int* lowerBounds, int* upperBounds) {
7745df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
7755df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com    return fontConfig->getTypefaceForGlyphID(glyphID, origTypeface, options,
7765df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com                                             lowerBounds, upperBounds);
7775df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com}
7785df5e6126d43f65d47092d682e7a7dd64a77ace3djsollen@google.com
779bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com///////////////////////////////////////////////////////////////////////////////
780bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com
78140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
78240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
78340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstruct HB_UnicodeMapping {
78440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    hb_script_t script;
78540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    const SkUnichar unicode;
78640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com};
78740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
78840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com/*
78940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * The following scripts are not complex fonts and we do not expect them to be parsed by this table
79040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * HB_SCRIPT_COMMON,
79140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * HB_SCRIPT_GREEK,
79240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * HB_SCRIPT_CYRILLIC,
79340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * HB_SCRIPT_HANGUL
79440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * HB_SCRIPT_INHERITED
79540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com */
79640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
79740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com/* Harfbuzz (old) is missing a number of scripts in its table. For these,
79840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * we include a value which can never happen. We won't get complex script
79940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * shaping in these cases, but the library wouldn't know how to shape
80040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com * them anyway. */
80140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#define HB_Script_Unknown HB_ScriptCount
80240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
80340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstatic HB_UnicodeMapping HB_UnicodeMappingArray[] = {
80498000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_ARMENIAN,    0x0531},
80598000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_HEBREW,      0x0591},
80698000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_ARABIC,      0x0600},
80798000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_SYRIAC,      0x0710},
80898000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_THAANA,      0x0780},
80998000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_NKO,         0x07C0},
81098000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_DEVANAGARI,  0x0901},
81198000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_BENGALI,     0x0981},
81298000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_GURMUKHI,    0x0A10},
81398000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_GUJARATI,    0x0A90},
81498000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_ORIYA,       0x0B10},
81598000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_TAMIL,       0x0B82},
81698000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_TELUGU,      0x0C10},
81798000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_KANNADA,     0x0C90},
81898000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_MALAYALAM,   0x0D10},
81998000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_SINHALA,     0x0D90},
82098000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_THAI,        0x0E01},
82198000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_LAO,         0x0E81},
82298000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_TIBETAN,     0x0F00},
82398000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_MYANMAR,     0x1000},
82498000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_GEORGIAN,    0x10A0},
82598000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_ETHIOPIC,    0x1200},
82698000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_CHEROKEE,    0x13A0},
82798000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_OGHAM,       0x1680},
82898000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_RUNIC,       0x16A0},
82998000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_KHMER,       0x1780},
83098000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_TAI_LE,      0x1950},
83198000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_NEW_TAI_LUE, 0x1980},
83298000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_TAI_THAM,    0x1A20},
83398000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org    {HB_SCRIPT_CHAM,        0xAA00},
83440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com};
83540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
83640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com// returns 0 for "Not Found"
83740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstatic SkUnichar getUnicodeFromHBScript(hb_script_t script) {
83840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkUnichar unichar = 0;
83940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping);
84040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    for (int i = 0; i < numSupportedFonts; i++) {
84140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        if (script == HB_UnicodeMappingArray[i].script) {
84240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            unichar = HB_UnicodeMappingArray[i].unicode;
84340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            break;
84440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        }
84540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
84640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    return unichar;
84740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com}
84840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
84940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstruct TypefaceLookupStruct {
85040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    hb_script_t script;
85140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkTypeface::Style style;
85240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkPaintOptionsAndroid::FontVariant fontVariant;
85340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkTypeface* typeface;
85440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com};
85540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
85640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comSK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex);  // This is the mutex for gTypefaceTable
85740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstatic SkTDArray<TypefaceLookupStruct> gTypefaceTable;  // This is protected by gTypefaceTableMutex
85840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
85940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.comstatic int typefaceLookupCompare(const TypefaceLookupStruct& first,
86040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com                                 const TypefaceLookupStruct& second) {
86140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if (first.script != second.script) {
86240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        return (first.script > second.script) ? 1 : -1;
86340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
86440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if (first.style != second.style) {
86540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        return (first.style > second.style) ? 1 : -1;
86640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
86740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if (first.fontVariant != second.fontVariant) {
86840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        return (first.fontVariant > second.fontVariant) ? 1 : -1;
86940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
87040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    return 0;
87140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com}
87240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
87398000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.orgSkTypeface* SkCreateTypefaceForScript(hb_script_t script, SkTypeface::Style style,
87498000efa59ef82eaee8df04e4dd0c328439719a7commit-bot@chromium.org                                      SkPaintOptionsAndroid::FontVariant fontVariant) {
87540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkAutoMutexAcquire ac(gTypefaceTableMutex);
87640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
87740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    TypefaceLookupStruct key;
87840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    key.script = script;
87940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    key.style = style;
88040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    key.fontVariant = fontVariant;
88140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
88240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    int index = SkTSearch<TypefaceLookupStruct>(
88340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            (const TypefaceLookupStruct*) gTypefaceTable.begin(),
88440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct),
88540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            typefaceLookupCompare);
88640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
88740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    SkTypeface* retTypeface = NULL;
88840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    if (index >= 0) {
88940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        retTypeface = gTypefaceTable[index].typeface;
89040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
89140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    else {
89240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        SkUnichar unichar = getUnicodeFromHBScript(script);
89340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        if (!unichar) {
89440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com            return NULL;
89540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        }
89640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
89740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
89840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        retTypeface = fontConfig->getTypefaceForChar(unichar, style, fontVariant);
89940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
90040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        // add to the lookup table
90140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        key.typeface = retTypeface;
90240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com        *gTypefaceTable.insert(~index) = key;
90340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    }
90440078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
90540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    // we ref(), the caller is expected to unref when they are done
90640078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    return SkSafeRef(retTypeface);
90740078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com}
90840078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
90940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#endif
91040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
91140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com///////////////////////////////////////////////////////////////////////////////
91240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
913bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.comSkFontMgr* SkFontMgr::Factory() {
914451b5962c906be9517cc99b80deecf525e85ee89bungeman@google.com    return NULL;
915bfae9d373ccc9cf47fd70757092962c7850fadf4djsollen@google.com}
916