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