aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports/SkFontConfigInterface_android.cpp
diff options
context:
space:
mode:
authorGravatar djsollen@google.com <djsollen@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-21 16:53:50 +0000
committerGravatar djsollen@google.com <djsollen@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-05-21 16:53:50 +0000
commitbfae9d373ccc9cf47fd70757092962c7850fadf4 (patch)
treebb2dae453daf82743682a8323d273af418d1a145 /src/ports/SkFontConfigInterface_android.cpp
parent7768751b8bec9e50fcbdad67b82e1962e71c3eb9 (diff)
Add a fontConfig interface for android.
The contents of this CL are based on the SkFontHost_android.cpp found in the android repository. BUG= R=reed@google.com Review URL: https://codereview.chromium.org/14731025 git-svn-id: http://skia.googlecode.com/svn/trunk@9219 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/ports/SkFontConfigInterface_android.cpp')
-rw-r--r--src/ports/SkFontConfigInterface_android.cpp623
1 files changed, 623 insertions, 0 deletions
diff --git a/src/ports/SkFontConfigInterface_android.cpp b/src/ports/SkFontConfigInterface_android.cpp
new file mode 100644
index 0000000000..850d902ba4
--- /dev/null
+++ b/src/ports/SkFontConfigInterface_android.cpp
@@ -0,0 +1,623 @@
+
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFontConfigInterface.h"
+#include "SkTypeface_android.h"
+
+#include "SkFontConfigParser_android.h"
+#include "SkFontConfigTypeface.h"
+#include "SkFontMgr.h"
+#include "SkGlyphCache.h"
+#include "SkPaint.h"
+#include "SkPaintOptionsAndroid.h"
+#include "SkString.h"
+#include "SkStream.h"
+#include "SkThread.h"
+#include "SkTypefaceCache.h"
+#include "SkTArray.h"
+#include "SkTDict.h"
+#include "SkTSearch.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef SK_DEBUG_FONTS
+ #define SK_DEBUG_FONTS 0
+#endif
+
+#if SK_DEBUG_FONTS
+ #define DEBUG_FONT(args) SkDebugf args
+#else
+ #define DEBUG_FONT(args)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+// For test only.
+static const char* gTestMainConfigFile = NULL;
+static const char* gTestFallbackConfigFile = NULL;
+static const char* gTestFontFilePrefix = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+
+// used to record our notion of the pre-existing fonts
+struct FontRec {
+ SkRefPtr<SkTypeface> fTypeface;
+ SkString fFileName;
+ SkTypeface::Style fStyle;
+ SkPaintOptionsAndroid fPaintOptions;
+ bool fIsFallbackFont;
+ bool fIsValid;
+};
+
+typedef int32_t FontRecID;
+#define INVALID_FONT_REC_ID -1
+
+struct FamilyRec {
+ FamilyRec() {
+ memset(fFontRecID, INVALID_FONT_REC_ID, sizeof(fFontRecID));
+ }
+
+ static const int FONT_STYLE_COUNT = 4;
+ FontRecID fFontRecID[FONT_STYLE_COUNT];
+};
+
+typedef int32_t FamilyRecID;
+#define INVALID_FAMILY_REC_ID -1
+
+typedef SkTDArray<FontRecID> FallbackFontList;
+
+class SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
+public:
+ SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies);
+ virtual ~SkFontConfigInterfaceAndroid();
+
+ virtual bool matchFamilyName(const char familyName[],
+ SkTypeface::Style requested,
+ FontIdentity* outFontIdentifier,
+ SkString* outFamilyName,
+ SkTypeface::Style* outStyle) SK_OVERRIDE;
+ virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE;
+
+ // new APIs
+ virtual SkDataTable* getFamilyNames() SK_OVERRIDE;
+ virtual bool matchFamilySet(const char inFamilyName[],
+ SkString* outFamilyName,
+ SkTArray<FontIdentity>*) SK_OVERRIDE;
+
+ /**
+ * Get the family name of the font in the default fallback font list that
+ * contains the specified chararacter. if no font is found, returns false.
+ */
+ bool getFallbackFamilyNameForChar(SkUnichar uni, SkString* name);
+ /**
+ *
+ */
+ SkTypeface* getTypefaceForChar(SkUnichar uni, SkTypeface::Style style,
+ SkPaintOptionsAndroid::FontVariant fontVariant);
+ SkTypeface* nextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
+ const SkPaintOptionsAndroid& options);
+
+private:
+ void addFallbackFont(FontRecID fontRecID);
+ FallbackFontList* findFallbackFontList(const SkLanguage& lang);
+
+ SkTArray<FontRec> fFonts;
+ SkTArray<FamilyRec> fFontFamilies;
+ SkTDict<FamilyRecID> fFamilyNameDict;
+ FamilyRecID fDefaultFamilyRecID;
+
+ // (SkLanguage)<->(fallback chain index) translation
+ SkTDict<FallbackFontList*> fFallbackFontDict;
+ FallbackFontList fDefaultFallbackList;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static SkFontConfigInterfaceAndroid* getSingletonInterface() {
+ SK_DECLARE_STATIC_MUTEX(gMutex);
+ static SkFontConfigInterfaceAndroid* gFontConfigInterface;
+
+ SkAutoMutexAcquire ac(gMutex);
+ if (NULL == gFontConfigInterface) {
+ // load info from a configuration file that we can use to populate the
+ // system/fallback font structures
+ SkTDArray<FontFamily*> fontFamilies;
+ if (!gTestMainConfigFile) {
+ SkFontConfigParser::GetFontFamilies(fontFamilies);
+ } else {
+ SkFontConfigParser::GetTestFontFamilies(fontFamilies, gTestMainConfigFile,
+ gTestFallbackConfigFile);
+ }
+
+ gFontConfigInterface = new SkFontConfigInterfaceAndroid(fontFamilies);
+
+ // cleanup the data we received from the parser
+ fontFamilies.deleteAll();
+ }
+ return gFontConfigInterface;
+}
+
+SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
+ return getSingletonInterface();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool has_font(const SkTArray<FontRec>& array, const SkString& filename) {
+ for (int i = 0; i < array.count(); i++) {
+ if (array[i].fFileName == filename) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifndef SK_FONT_FILE_PREFIX
+ #define SK_FONT_FILE_PREFIX "/fonts/"
+#endif
+
+static void get_path_for_sys_fonts(SkString* full, const char name[]) {
+ if (gTestFontFilePrefix) {
+ full->set(gTestFontFilePrefix);
+ } else {
+ full->set(getenv("ANDROID_ROOT"));
+ full->append(SK_FONT_FILE_PREFIX);
+ }
+ full->append(name);
+}
+
+static void insert_into_name_dict(SkTDict<FamilyRecID>& familyNameDict,
+ const char* name, FamilyRecID familyRecID) {
+ SkAutoAsciiToLC tolc(name);
+ familyNameDict.set(tolc.lc(), familyRecID);
+}
+
+// Defined in SkFontHost_FreeType.cpp
+bool find_name_and_attributes(SkStream* stream, SkString* name,
+ SkTypeface::Style* style, bool* isFixedWidth);
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*>& fontFamilies) :
+ fFonts(fontFamilies.count()),
+ fFontFamilies(fontFamilies.count() / FamilyRec::FONT_STYLE_COUNT),
+ fFamilyNameDict(1024),
+ fDefaultFamilyRecID(INVALID_FAMILY_REC_ID),
+ fFallbackFontDict(128) {
+
+ for (int i = 0; i < fontFamilies.count(); ++i) {
+ FontFamily* family = fontFamilies[i];
+
+ // defer initializing the familyRec until we can be sure that at least
+ // one of it's children contains a valid font file
+ FamilyRec* familyRec = NULL;
+ FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
+
+ for (int j = 0; j < family->fFontFiles.count(); ++j) {
+ SkString filename;
+ get_path_for_sys_fonts(&filename, family->fFontFiles[j]->fFileName);
+
+ if (has_font(fFonts, filename)) {
+ SkDebugf("---- system font and fallback font files specify a duplicate "
+ "font %s, skipping the second occurrence", filename.c_str());
+ continue;
+ }
+
+ FontRec& fontRec = fFonts.push_back();
+ fontRec.fFileName = filename;
+ fontRec.fStyle = SkTypeface::kNormal;
+ fontRec.fPaintOptions = family->fFontFiles[j]->fPaintOptions;
+ fontRec.fIsFallbackFont = family->fIsFallbackFont;
+ fontRec.fIsValid = false;
+
+ const FontRecID fontRecID = fFonts.count() - 1;
+
+ SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
+ if (stream.get() != NULL) {
+ bool isFixedWidth;
+ SkString name;
+ fontRec.fIsValid = find_name_and_attributes(stream.get(), &name,
+ &fontRec.fStyle, &isFixedWidth);
+ } else {
+ if (!fontRec.fIsFallbackFont) {
+ SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
+ }
+ }
+
+ if (fontRec.fIsValid) {
+ DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s",
+ i, fFonts.count() - 1, fontRec.fIsFallbackFont, filename.c_str()));
+ } else {
+ DEBUG_FONT(("---- SystemFonts[%d][%d] fallback=%d file=%s (INVALID)",
+ i, fFonts.count() - 1, fontRec.fIsFallbackFont, filename.c_str()));
+ continue;
+ }
+
+ // create a familyRec now that we know that at least one font in
+ // the family is valid
+ if (familyRec == NULL) {
+ familyRec = &fFontFamilies.push_back();
+ familyRecID = fFontFamilies.count() - 1;
+ }
+
+ // add this font to the current familyRec
+ if (INVALID_FONT_REC_ID != familyRec->fFontRecID[fontRec.fStyle]) {
+ DEBUG_FONT(("Overwriting familyRec for style[%d] old,new:(%d,%d)",
+ fontRec.fStyle, familyRec->fFontRecID[fontRec.fStyle],
+ fontRecID));
+ }
+ familyRec->fFontRecID[fontRec.fStyle] = fontRecID;
+
+ // if this is a fallback font then add it to the appropriate fallback chains
+ if (fontRec.fIsFallbackFont) {
+ addFallbackFont(fontRecID);
+ }
+
+ // add the fallback file name to the name dictionary. This is needed
+ // by getFallbackFamilyNameForChar() so that fallback families can be
+ // requested by the filenames of the fonts they contain.
+ if (family->fIsFallbackFont && familyRec) {
+ insert_into_name_dict(fFamilyNameDict, fontRec.fFileName.c_str(), familyRecID);
+ }
+ }
+
+ // add the names that map to this family to the dictionary for easy lookup
+ if (familyRec && !family->fIsFallbackFont) {
+ SkTDArray<const char*> names = family->fNames;
+ if (names.isEmpty()) {
+ SkDEBUGFAIL("ERROR: non-fallback font with no name");
+ continue;
+ }
+
+ for (int i = 0; i < names.count(); i++) {
+ insert_into_name_dict(fFamilyNameDict, names[i], familyRecID);
+ }
+ }
+
+ }
+
+ DEBUG_FONT(("---- We have %d system fonts", fFonts.count()));
+
+ if (fFontFamilies.count() > 0) {
+ fDefaultFamilyRecID = 0;
+ }
+
+ // scans the default fallback font chain, adding every entry to every other
+ // fallback font chain to which it does not belong. this results in every
+ // language-specific fallback font chain having all of its fallback fonts at
+ // the front of the chain, and everything else at the end.
+ FallbackFontList* fallbackList;
+ SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict);
+ const char* fallbackLang = iter.next(&fallbackList);
+ while(fallbackLang != NULL) {
+ for (int i = 0; i < fDefaultFallbackList.count(); i++) {
+ FontRecID fontRecID = fDefaultFallbackList[i];
+ const SkString& fontLang = fFonts[fontRecID].fPaintOptions.getLanguage().getTag();
+ if (strcmp(fallbackLang, fontLang.c_str()) != 0) {
+ fallbackList->push(fontRecID);
+ }
+ }
+ // move to the next fallback list in the dictionary
+ fallbackLang = iter.next(&fallbackList);
+ }
+}
+
+SkFontConfigInterfaceAndroid::~SkFontConfigInterfaceAndroid() {
+ // iterate through and cleanup fFallbackFontDict
+ SkTDict<FallbackFontList*>::Iter iter(fFallbackFontDict);
+ FallbackFontList* fallbackList;
+ while(iter.next(&fallbackList) != NULL) {
+ SkDELETE(fallbackList);
+ }
+}
+
+void SkFontConfigInterfaceAndroid::addFallbackFont(FontRecID fontRecID) {
+ SkASSERT(fontRecID < fFonts.count());
+ const FontRec& fontRec = fFonts[fontRecID];
+ SkASSERT(fontRec.fIsFallbackFont);
+
+ // add to the default fallback list
+ fDefaultFallbackList.push(fontRecID);
+
+ // stop here if it is the default language tag
+ const SkString& languageTag = fontRec.fPaintOptions.getLanguage().getTag();
+ if (languageTag.isEmpty()) {
+ return;
+ }
+
+ // add to the appropriate language's custom fallback list
+ FallbackFontList* customList = NULL;
+ if (!fFallbackFontDict.find(languageTag.c_str(), &customList)) {
+ DEBUG_FONT(("---- Created fallback list for \"%s\"", languageTag.c_str()));
+ customList = SkNEW(FallbackFontList);
+ fFallbackFontDict.set(languageTag.c_str(), customList);
+ }
+ SkASSERT(customList != NULL);
+ customList->push(fontRecID);
+}
+
+
+static FontRecID find_best_style(const FamilyRec& family, SkTypeface::Style style) {
+
+ const FontRecID* fontRecIDs = family.fFontRecID;
+
+ if (fontRecIDs[style] != INVALID_FONT_REC_ID) { // exact match
+ return fontRecIDs[style];
+ }
+ // look for a matching bold
+ style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
+ if (fontRecIDs[style] != INVALID_FONT_REC_ID) {
+ return fontRecIDs[style];
+ }
+ // look for the plain
+ if (fontRecIDs[SkTypeface::kNormal] != INVALID_FONT_REC_ID) {
+ return fontRecIDs[SkTypeface::kNormal];
+ }
+ // look for anything
+ for (int i = 0; i < FamilyRec::FONT_STYLE_COUNT; i++) {
+ if (fontRecIDs[i] != INVALID_FONT_REC_ID) {
+ return fontRecIDs[i];
+ }
+ }
+ // should never get here, since the fontRecID list should not be empty
+ SkDEBUGFAIL("No valid fonts exist for this family");
+ return -1;
+}
+
+bool SkFontConfigInterfaceAndroid::matchFamilyName(const char familyName[],
+ SkTypeface::Style style,
+ FontIdentity* outFontIdentifier,
+ SkString* outFamilyName,
+ SkTypeface::Style* outStyle) SK_OVERRIDE {
+ // clip to legal style bits
+ style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
+
+ bool exactNameMatch = false;
+
+ FamilyRecID familyRecID = INVALID_FAMILY_REC_ID;
+ if (NULL != familyName) {
+ if (fFamilyNameDict.find(familyName, &familyRecID)) {
+ exactNameMatch = true;
+ }
+ } else {
+ familyRecID = fDefaultFamilyRecID;
+
+ }
+
+ if (INVALID_FAMILY_REC_ID == familyRecID) {
+ //TODO this ensures that we always return something
+ familyRecID = fDefaultFamilyRecID;
+ //return false;
+ }
+
+ FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], style);
+ FontRec& fontRec = fFonts[fontRecID];
+
+ if (NULL != outFontIdentifier) {
+ outFontIdentifier->fID = fontRecID;
+ outFontIdentifier->fTTCIndex = 0;
+ outFontIdentifier->fString.set(fontRec.fFileName);
+// outFontIdentifier->fStyle = fontRec.fStyle;
+ }
+
+ if (NULL != outFamilyName) {
+ if (exactNameMatch) {
+ outFamilyName->set(familyName);
+ } else {
+ // find familyName from list of names
+ const char* familyName = NULL;
+ bool found = fFamilyNameDict.findKey(familyRecID, &familyName);
+ SkASSERT(found && familyName);
+ outFamilyName->set(familyName);
+ }
+ }
+
+ if (NULL != outStyle) {
+ *outStyle = fontRec.fStyle;
+ }
+
+ return true;
+}
+
+SkStream* SkFontConfigInterfaceAndroid::openStream(const FontIdentity& identity) SK_OVERRIDE {
+ return SkStream::NewFromFile(identity.fString.c_str());
+}
+
+SkDataTable* SkFontConfigInterfaceAndroid::getFamilyNames() SK_OVERRIDE {
+ SkTDArray<const char*> names;
+ SkTDArray<size_t> sizes;
+
+ SkTDict<FamilyRecID>::Iter iter(fFamilyNameDict);
+ const char* familyName = iter.next(NULL);
+ while(familyName != NULL) {
+ *names.append() = familyName;
+ *sizes.append() = strlen(familyName) + 1;
+
+ // move to the next familyName in the dictionary
+ familyName = iter.next(NULL);
+ }
+
+ return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
+ sizes.begin(), names.count());
+}
+
+bool SkFontConfigInterfaceAndroid::matchFamilySet(const char inFamilyName[],
+ SkString* outFamilyName,
+ SkTArray<FontIdentity>*) SK_OVERRIDE {
+ return false;
+}
+
+static SkTypeface* get_typeface_for_rec(FontRec& fontRec) {
+ SkTypeface* face = fontRec.fTypeface.get();
+ if (!face) {
+ // TODO look for it in the typeface cache
+
+ // if it is not in the cache then create it
+ face = SkTypeface::CreateFromFile(fontRec.fFileName.c_str());
+
+ // store the result for subsequent lookups
+ fontRec.fTypeface = face;
+ }
+ SkASSERT(face);
+ return face;
+}
+
+bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
+ for (int i = 0; i < fDefaultFallbackList.count(); i++) {
+ FontRecID fontRecID = fDefaultFallbackList[i];
+ SkTypeface* face = get_typeface_for_rec(fFonts[fontRecID]);
+
+ SkPaint paint;
+ paint.setTypeface(face);
+ paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
+
+ uint16_t glyphID;
+ paint.textToGlyphs(&uni, sizeof(uni), &glyphID);
+ if (glyphID != 0) {
+ name->set(fFonts[fontRecID].fFileName);
+ return true;
+ }
+ }
+ return false;
+}
+
+SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForChar(SkUnichar uni,
+ SkTypeface::Style style,
+ SkPaintOptionsAndroid::FontVariant fontVariant) {
+ FontRecID fontRecID = find_best_style(fFontFamilies[fDefaultFamilyRecID], style);
+ SkTypeface* face = get_typeface_for_rec(fFonts[fontRecID]);
+
+ SkPaintOptionsAndroid paintOptions;
+ paintOptions.setFontVariant(fontVariant);
+ paintOptions.setUseFontFallbacks(true);
+
+ SkPaint paint;
+ paint.setTypeface(face);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ paint.setPaintOptionsAndroid(paintOptions);
+
+ SkAutoGlyphCache autoCache(paint, NULL, NULL);
+ SkGlyphCache* cache = autoCache.getCache();
+
+ SkScalerContext* ctx = cache->getScalerContext();
+ if (ctx) {
+ SkFontID fontID = ctx->findTypefaceIdForChar(uni);
+ return SkTypefaceCache::FindByID(fontID);
+ }
+ return NULL;
+}
+
+FallbackFontList* SkFontConfigInterfaceAndroid::findFallbackFontList(const SkLanguage& lang) {
+ const SkString& langTag = lang.getTag();
+ if (langTag.isEmpty()) {
+ return &fDefaultFallbackList;
+ }
+
+ FallbackFontList* fallbackFontList;
+ if (fFallbackFontDict.find(langTag.c_str(), langTag.size(), &fallbackFontList)) {
+ return fallbackFontList;
+ }
+
+ // attempt a recursive fuzzy match
+ // TODO we could cache the intermediate parent so that we don't have to do
+ // the recursion again.
+ SkLanguage parent = lang.getParent();
+ return findFallbackFontList(parent);
+}
+
+SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontID,
+ SkFontID origFontID,
+ const SkPaintOptionsAndroid& opts) {
+ // Skia does not support font fallback by default. This enables clients such
+ // as WebKit to customize their font selection. In any case, clients can use
+ // GetFallbackFamilyNameForChar() to get the fallback font for individual
+ // characters.
+ if (!opts.isUsingFontFallbacks()) {
+ return NULL;
+ }
+
+ const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID);
+ const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
+
+ FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
+ SkASSERT(currentFallbackList);
+
+ SkASSERT(origTypeface != 0);
+ SkASSERT(currTypeface != 0);
+
+ // we must convert currTypeface into a FontRecID
+ FontRecID currFontRecID = ((FontConfigTypeface*)currTypeface)->getIdentity().fID;
+
+ // TODO lookup the index next font in the chain
+ int currFallbackFontIndex = currentFallbackList->find(currFontRecID);
+ int nextFallbackFontIndex = currFallbackFontIndex + 1;
+ SkASSERT(-1 == nextFallbackFontIndex);
+
+ if(nextFallbackFontIndex >= currentFallbackList->count() && -1 == currFallbackFontIndex) {
+ return NULL;
+ }
+
+ // If a rec object is set to prefer "kDefault_Variant" it means they have no preference
+ // In this case, we set the value to "kCompact_Variant"
+ SkPaintOptionsAndroid::FontVariant variant = opts.getFontVariant();
+ if (variant == SkPaintOptionsAndroid::kDefault_Variant) {
+ variant = SkPaintOptionsAndroid::kCompact_Variant;
+ }
+
+ int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | variant;
+
+ SkTypeface* nextLogicalTypeface = 0;
+ while (nextFallbackFontIndex < currentFallbackList->count()) {
+ FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex);
+ if (fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants) {
+ nextLogicalTypeface = get_typeface_for_rec(fFonts[fontRecID]);
+ break;
+ }
+ nextFallbackFontIndex++;
+ }
+
+ DEBUG_FONT(("---- nextLogicalFont: currFontID=%d, origFontID=%d, currRecID=%d, "
+ "lang=%s, variant=%d, nextFallbackIndex=%d => nextLogicalTypeface=%d",
+ currFontID, origFontID, currFontRecID, opts.getLanguage().getTag().c_str(),
+ variant, nextFallbackFontIndex,
+ (nextLogicalTypeface) ? nextLogicalTypeface->uniqueID() : 0));
+ return SkSafeRef(nextLogicalTypeface);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool SkGetFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
+ SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
+ return fontConfig->getFallbackFamilyNameForChar(uni, name);
+}
+
+void SkUseTestFontConfigFile(const char* mainconf, const char* fallbackconf,
+ const char* fontsdir) {
+ gTestMainConfigFile = mainconf;
+ gTestFallbackConfigFile = fallbackconf;
+ gTestFontFilePrefix = fontsdir;
+ SkASSERT(gTestMainConfigFile);
+ SkASSERT(gTestFallbackConfigFile);
+ SkASSERT(gTestFontFilePrefix);
+ SkDEBUGF(("Use Test Config File Main %s, Fallback %s, Font Dir %s",
+ gTestMainConfigFile, gTestFallbackConfigFile, gTestFontFilePrefix));
+}
+
+SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
+ const SkPaintOptionsAndroid& options) {
+ SkFontConfigInterfaceAndroid* fontConfig = getSingletonInterface();
+ return fontConfig->nextLogicalTypeface(currFontID, origFontID, options);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkFontMgr* SkFontMgr::Factory() {
+ return NULL;
+}