fix regression in fallback chain where we don't account for the original font style.

This CL also enforces that the language and variant are the same for all fonts
within a given fallback family.

R=reed@google.com

Review URL: https://codereview.chromium.org/23670009

git-svn-id: http://skia.googlecode.com/svn/trunk@11128 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
djsollen@google.com 2013-09-06 12:59:50 +00:00
parent e15d9ecef8
commit b27eba7c28

View File

@ -55,8 +55,6 @@ struct FontRec {
SkRefPtr<SkTypeface> fTypeface;
SkString fFileName;
SkTypeface::Style fStyle;
SkPaintOptionsAndroid fPaintOptions;
bool fIsFallbackFont;
bool fIsValid;
FamilyRecID fFamilyRecID;
};
@ -68,10 +66,12 @@ struct FamilyRec {
static const int FONT_STYLE_COUNT = 4;
FontRecID fFontRecID[FONT_STYLE_COUNT];
bool fIsFallbackFont;
SkPaintOptionsAndroid fPaintOptions;
};
typedef SkTDArray<FontRecID> FallbackFontList;
typedef SkTDArray<FamilyRecID> FallbackFontList;
class SkFontConfigInterfaceAndroid : public SkFontConfigInterface {
public:
@ -105,7 +105,7 @@ public:
const SkPaintOptionsAndroid& options);
private:
void addFallbackFont(FontRecID fontRecID);
void addFallbackFamily(FamilyRecID fontRecID);
SkTypeface* getTypefaceForFontRec(FontRecID fontRecID);
FallbackFontList* getCurrentLocaleFallbackFontList();
FallbackFontList* findFallbackFontList(const SkLanguage& lang, bool isOriginal = true);
@ -227,8 +227,6 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
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;
fontRec.fFamilyRecID = familyRecID;
@ -241,7 +239,7 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
fontRec.fIsValid = find_name_and_attributes(stream.get(), &name,
&fontRec.fStyle, &isFixedWidth);
} else {
if (!fontRec.fIsFallbackFont) {
if (!family->fIsFallbackFont) {
SkDebugf("---- failed to open <%s> as a font\n", filename.c_str());
}
}
@ -261,6 +259,18 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
familyRec = &fFontFamilies.push_back();
familyRecID = fFontFamilies.count() - 1;
fontRec.fFamilyRecID = familyRecID;
familyRec->fIsFallbackFont = family->fIsFallbackFont;
familyRec->fPaintOptions = family->fFontFiles[j]->fPaintOptions;
// if this is a fallback font then add it to the appropriate fallback chains
if (familyRec->fIsFallbackFont) {
addFallbackFamily(familyRecID);
}
} else if (familyRec->fPaintOptions != family->fFontFiles[j]->fPaintOptions) {
SkDebugf("Every font file within a family must have identical"
"language and variant attributes");
sk_throw();
}
// add this font to the current familyRec
@ -271,21 +281,16 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
}
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) {
if (familyRec && familyRec->fIsFallbackFont) {
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) {
if (familyRec && !familyRec->fIsFallbackFont) {
SkTDArray<const char*> names = family->fNames;
if (names.isEmpty()) {
SkDEBUGFAIL("ERROR: non-fallback font with no name");
@ -314,10 +319,10 @@ SkFontConfigInterfaceAndroid::SkFontConfigInterfaceAndroid(SkTDArray<FontFamily*
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();
FamilyRecID familyRecID = fDefaultFallbackList[i];
const SkString& fontLang = fFontFamilies[familyRecID].fPaintOptions.getLanguage().getTag();
if (strcmp(fallbackLang, fontLang.c_str()) != 0) {
fallbackList->push(fontRecID);
fallbackList->push(familyRecID);
}
}
// move to the next fallback list in the dictionary
@ -334,16 +339,16 @@ SkFontConfigInterfaceAndroid::~SkFontConfigInterfaceAndroid() {
}
}
void SkFontConfigInterfaceAndroid::addFallbackFont(FontRecID fontRecID) {
SkASSERT(fontRecID < fFonts.count());
const FontRec& fontRec = fFonts[fontRecID];
SkASSERT(fontRec.fIsFallbackFont);
void SkFontConfigInterfaceAndroid::addFallbackFamily(FamilyRecID familyRecID) {
SkASSERT(familyRecID < fFontFamilies.count());
const FamilyRec& familyRec = fFontFamilies[familyRecID];
SkASSERT(familyRec.fIsFallbackFont);
// add to the default fallback list
fDefaultFallbackList.push(fontRecID);
fDefaultFallbackList.push(familyRecID);
// stop here if it is the default language tag
const SkString& languageTag = fontRec.fPaintOptions.getLanguage().getTag();
const SkString& languageTag = familyRec.fPaintOptions.getLanguage().getTag();
if (languageTag.isEmpty()) {
return;
}
@ -356,7 +361,7 @@ void SkFontConfigInterfaceAndroid::addFallbackFont(FontRecID fontRecID) {
fFallbackFontDict.set(languageTag.c_str(), customList);
}
SkASSERT(customList != NULL);
customList->push(fontRecID);
customList->push(familyRecID);
}
@ -502,7 +507,8 @@ SkTypeface* SkFontConfigInterfaceAndroid::getTypefaceForFontRec(FontRecID fontRe
bool SkFontConfigInterfaceAndroid::getFallbackFamilyNameForChar(SkUnichar uni, SkString* name) {
FallbackFontList* fallbackFontList = this->getCurrentLocaleFallbackFontList();
for (int i = 0; i < fallbackFontList->count(); i++) {
FontRecID fontRecID = fallbackFontList->getAt(i);
FamilyRecID familyRecID = fallbackFontList->getAt(i);
FontRecID fontRecID = find_best_style(fFontFamilies[familyRecID], SkTypeface::kNormal);
SkTypeface* face = this->getTypefaceForFontRec(fontRecID);
SkPaint paint;
@ -593,6 +599,12 @@ SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI
FallbackFontList* currentFallbackList = findFallbackFontList(opts.getLanguage());
SkASSERT(currentFallbackList);
SkTypeface::Style origStyle = SkTypeface::kNormal;
const SkTypeface* origTypeface = SkTypefaceCache::FindByID(origFontID);
if (NULL != origTypeface) {
origStyle = origTypeface->style();
}
// we must convert currTypeface into a FontRecID
FontRecID currFontRecID = INVALID_FONT_REC_ID;
const SkTypeface* currTypeface = SkTypefaceCache::FindByID(currFontID);
@ -603,8 +615,13 @@ SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI
SkASSERT(INVALID_FONT_REC_ID != currFontRecID);
}
FamilyRecID currFamilyRecID = INVALID_FAMILY_REC_ID;
if (INVALID_FONT_REC_ID != currFontRecID) {
currFamilyRecID = fFonts[currFontRecID].fFamilyRecID;
}
// lookup the index next font in the chain
int currFallbackFontIndex = currentFallbackList->find(currFontRecID);
int currFallbackFontIndex = currentFallbackList->find(currFamilyRecID);
// We add 1 to the returned index for 2 reasons: (1) if find succeeds it moves
// our index to the next entry in the list; (2) if find() fails it returns
// -1 and incrementing it will set our starting index to 0 (the head of the list)
@ -625,9 +642,10 @@ SkTypeface* SkFontConfigInterfaceAndroid::nextLogicalTypeface(SkFontID currFontI
SkTypeface* nextLogicalTypeface = 0;
while (nextFallbackFontIndex < currentFallbackList->count()) {
FontRecID fontRecID = currentFallbackList->getAt(nextFallbackFontIndex);
if ((fFonts[fontRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) {
nextLogicalTypeface = this->getTypefaceForFontRec(fontRecID);
FamilyRecID familyRecID = currentFallbackList->getAt(nextFallbackFontIndex);
if ((fFontFamilies[familyRecID].fPaintOptions.getFontVariant() & acceptedVariants) != 0) {
FontRecID matchedFont = find_best_style(fFontFamilies[familyRecID], origStyle);
nextLogicalTypeface = this->getTypefaceForFontRec(matchedFont);
break;
}
nextFallbackFontIndex++;