Index: src/ports/SkFontMgr_android.cpp |
diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp |
index 2bae9ca0e51a62409f61c51839ddccc3c0368316..616ff22076b9ad32bf0938bbc28605e88e7ec31a 100644 |
--- a/src/ports/SkFontMgr_android.cpp |
+++ b/src/ports/SkFontMgr_android.cpp |
@@ -59,9 +59,13 @@ public: |
int index, |
Style style, |
bool isFixedPitch, |
- const SkString familyName) |
+ const SkString familyName, |
+ const SkLanguage& lang, |
+ SkPaintOptionsAndroid::FontVariant variant) |
: INHERITED(index, style, isFixedPitch, familyName) |
- , fPathName(pathName) { } |
+ , fPathName(pathName) |
+ , fLang(lang) |
+ , fVariant(variant) { } |
virtual void onGetFontDescriptor(SkFontDescriptor* desc, |
bool* serialize) const SK_OVERRIDE { |
@@ -76,8 +80,9 @@ public: |
return SkStream::NewFromFile(fPathName.c_str()); |
} |
-private: |
- SkString fPathName; |
+ const SkString fPathName; |
+ const SkLanguage fLang; |
+ const SkPaintOptionsAndroid::FontVariant fVariant; |
typedef SkTypeface_Android INHERITED; |
}; |
@@ -120,33 +125,48 @@ void get_path_for_sys_fonts(SkString* full, const SkString& name) { |
class SkFontStyleSet_Android : public SkFontStyleSet { |
public: |
- explicit SkFontStyleSet_Android(FontFamily* family) { |
+ explicit SkFontStyleSet_Android(const FontFamily& family) { |
+ const SkString* cannonicalFamilyName = NULL; |
+ if (family.fNames.count() > 0) { |
+ cannonicalFamilyName = &family.fNames[0]; |
+ } |
// TODO? make this lazy |
- for (int i = 0; i < family->fFontFiles.count(); ++i) { |
- const SkString& fileName = family->fFontFiles[i].fFileName; |
+ for (int i = 0; i < family.fFontFiles.count(); ++i) { |
+ const FontFileInfo& fontFile = family.fFontFiles[i]; |
SkString pathName; |
- get_path_for_sys_fonts(&pathName, fileName); |
+ get_path_for_sys_fonts(&pathName, fontFile.fFileName); |
SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str())); |
if (!stream.get()) { |
- DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, fileName.c_str())); |
+ DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathName.c_str())); |
continue; |
} |
- const int ttcIndex = family->fFontFiles[i].fIndex; |
- SkString fontName; |
+ const int ttcIndex = fontFile.fIndex; |
+ SkString familyName; |
SkTypeface::Style style; |
bool isFixedWidth; |
if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex, |
- &fontName, &style, &isFixedWidth)) { |
- DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, fileName.c_str())); |
+ &familyName, &style, &isFixedWidth)) { |
+ DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathName.c_str())); |
continue; |
} |
+ const SkLanguage& lang = fontFile.fPaintOptions.getLanguage(); |
+ SkPaintOptionsAndroid::FontVariant variant = fontFile.fPaintOptions.getFontVariant(); |
+ |
+ // The first specified family name overrides the family name found in the font. |
+ // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return |
+ // all of the specified family names in addition to the names found in the font. |
+ if (cannonicalFamilyName != NULL) { |
+ familyName = *cannonicalFamilyName; |
+ } |
+ |
fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, |
(pathName, ttcIndex, |
- style, isFixedWidth, fontName))); |
+ style, isFixedWidth, familyName, |
+ lang, variant))); |
} |
} |
@@ -164,7 +184,7 @@ public: |
name->reset(); |
} |
} |
- virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { |
+ virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE { |
if (index < 0 || fStyles.count() <= index) { |
return NULL; |
} |
@@ -175,11 +195,11 @@ public: |
* TODO: consider replacing with SkStyleSet_Indirect::matchStyle(); |
* this simpler version using match_score() passes all our tests. |
*/ |
- virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { |
+ virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { |
if (0 == fStyles.count()) { |
return NULL; |
} |
- SkTypeface* closest = fStyles[0]; |
+ SkTypeface_AndroidSystem* closest = fStyles[0]; |
int minScore = std::numeric_limits<int>::max(); |
for (int i = 0; i < fStyles.count(); ++i) { |
SkFontStyle style = this->style(i); |
@@ -213,7 +233,7 @@ private: |
return score; |
} |
- SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles; |
+ SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles; |
friend struct NameToFamily; |
friend class SkFontMgr_Android; |
@@ -273,6 +293,12 @@ protected: |
return SkRef(fNameToFamilyMap[i].styleSet); |
} |
} |
+ // TODO: eventually we should not need to name fallback families. |
+ for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) { |
+ if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) { |
+ return SkRef(fFallbackNameToFamilyMap[i].styleSet); |
+ } |
+ } |
return NULL; |
} |
@@ -294,6 +320,60 @@ protected: |
return NULL; |
} |
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], |
+ const SkFontStyle& style, |
+ const char bpc47[], |
+ uint32_t character) const SK_OVERRIDE |
+ { |
+ // If the familyName maps to a family, then match the style and get the variant. |
+ // Otherwise "elegant" unless the family name ends in "compact". |
+ bool isCompact = false; |
+ if (familyName) { |
+ size_t familyNameLen = strlen(familyName); |
+ static const char compactLiteral[] = "compact"; |
+ static const size_t compactLiteralLen = SK_ARRAY_COUNT(compactLiteral); |
+ if (compactLiteralLen <= familyNameLen) { |
djsollen
2014/08/01 20:24:04
should this be < or would a font with the name "co
bungeman-skia
2014/08/04 19:24:20
So, when I wrote this I was under the impression f
|
+ const char* familyNameEnd = familyName + familyNameLen - compactLiteralLen; |
+ isCompact = SkToBool(strcmp(familyNameEnd, compactLiteral)); |
+ } |
+ } |
+ |
+ uint32_t ignoredVariantMask = SkPaintOptionsAndroid::kCompact_Variant; |
+ if (isCompact) { |
+ ignoredVariantMask = ~SkPaintOptionsAndroid::kCompact_Variant; |
+ } |
+ |
+ for (int i = 0; i < 2; ++i, ignoredVariantMask = ~ignoredVariantMask) { |
djsollen
2014/08/01 20:24:04
document that the second time through the loop loo
bungeman-skia
2014/08/04 19:24:20
Changed the logic to make this more obvious and ad
|
+ SkLanguage lang(bpc47); |
+ do { |
+ const SkString& langTag = lang.getTag(); |
+ for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) { |
+ SkFontStyleSet_Android* family = fFallbackNameToFamilyMap[i].styleSet; |
+ SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style)); |
+ |
+ if (!langTag.isEmpty() && langTag != face->fLang.getTag()) { |
+ continue; |
+ } |
+ |
+ if (SkToBool(face->fVariant & ignoredVariantMask)) { |
+ continue; |
+ } |
+ |
+ SkPaint paint; |
+ paint.setTypeface(face); |
+ paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); |
+ |
+ uint16_t glyphID; |
+ paint.textToGlyphs(&character, sizeof(character), &glyphID); |
+ if (glyphID != 0) { |
+ return face.detach(); |
+ } |
+ } |
+ } while (!lang.getTag().isEmpty() && (lang = lang.getParent(), true)); |
djsollen
2014/08/01 20:24:04
At first glance it is not clear that the last run
bungeman-skia
2014/08/04 19:24:20
Documented.
|
+ } |
+ return NULL; |
+ } |
+ |
virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE { |
SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); |
return this->createFromStream(stream, ttcIndex); |
@@ -347,15 +427,33 @@ private: |
SkTypeface* fDefaultTypeface; |
SkTDArray<NameToFamily> fNameToFamilyMap; |
+ SkTDArray<NameToFamily> fFallbackNameToFamilyMap; |
void buildNameToFamilyMap(SkTDArray<FontFamily*> families) { |
for (int i = 0; i < families.count(); i++) { |
- fFontStyleSets.push_back().reset( |
- SkNEW_ARGS(SkFontStyleSet_Android, (families[i]))); |
- for (int j = 0; j < families[i]->fNames.count(); j++) { |
- NameToFamily* nextEntry = fNameToFamilyMap.append(); |
- SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (families[i]->fNames[j])); |
- nextEntry->styleSet = fFontStyleSets.back().get(); |
+ FontFamily& family = *families[i]; |
+ |
+ SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap; |
+ if (family.fIsFallbackFont) { |
+ nameToFamily = &fFallbackNameToFamilyMap; |
+ |
+ if (0 == family.fNames.count()) { |
+ SkString& fallbackName = family.fNames.push_back(); |
+ fallbackName.printf("%.2x##fallback", i); |
+ } |
+ } |
+ |
+ SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family)); |
+ if (0 == newSet->count()) { |
+ SkDELETE(newSet); |
+ continue; |
+ } |
+ fFontStyleSets.push_back().reset(newSet); |
+ |
+ for (int j = 0; j < family.fNames.count(); j++) { |
+ NameToFamily* nextEntry = nameToFamily->append(); |
+ SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[j])); |
+ nextEntry->styleSet = newSet; |
} |
} |
} |