| Index: src/ports/SkFontConfigInterface_android.cpp
|
| diff --git a/src/ports/SkFontConfigInterface_android.cpp b/src/ports/SkFontConfigInterface_android.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..850d902ba4489b1d5afdd7c8ff8867890ec853ce
|
| --- /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;
|
| +}
|
|
|