| Index: src/ports/SkFontMgr_android.cpp
|
| diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp
|
| index 2bae9ca0e51a62409f61c51839ddccc3c0368316..31b5346a10686a1e0955cfdc1183e3f7ba2f15a8 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,
|
| + uint32_t variantStyle)
|
| : INHERITED(index, style, isFixedPitch, familyName)
|
| - , fPathName(pathName) { }
|
| + , fPathName(pathName)
|
| + , fLang(lang)
|
| + , fVariantStyle(variantStyle) { }
|
|
|
| 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 uint32_t fVariantStyle;
|
|
|
| typedef SkTypeface_Android INHERITED;
|
| };
|
| @@ -120,33 +125,52 @@ 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();
|
| + uint32_t variant = fontFile.fPaintOptions.getFontVariant();
|
| + if (SkPaintOptionsAndroid::kDefault_Variant == variant) {
|
| + variant = SkPaintOptionsAndroid::kCompact_Variant |
|
| + SkPaintOptionsAndroid::kElegant_Variant;
|
| + }
|
| +
|
| + // 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 +188,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 +199,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 +237,7 @@ private:
|
| return score;
|
| }
|
|
|
| - SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles;
|
| + SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
|
|
|
| friend struct NameToFamily;
|
| friend class SkFontMgr_Android;
|
| @@ -273,6 +297,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 +324,54 @@ protected:
|
| return NULL;
|
| }
|
|
|
| + virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
|
| + const SkFontStyle& style,
|
| + const char bpc47[],
|
| + uint32_t character) const SK_OVERRIDE
|
| + {
|
| + // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascent/descent'.
|
| + // The variant 'default' means 'compact and elegant'.
|
| + // As a result, it is not possible to know the variant context from the font alone.
|
| + // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
|
| +
|
| + // For compatibility, try 'elegant' fonts first in fallback.
|
| + uint32_t variantMask = SkPaintOptionsAndroid::kElegant_Variant;
|
| +
|
| + // The first time match anything in the mask, second time anything not in the mask.
|
| + for (bool maskMatches = true; maskMatches != false; maskMatches = false) {
|
| + SkLanguage lang(bpc47);
|
| + // Match against the language, removing a segment each time.
|
| + // The last time through the loop, the language will be empty.
|
| + // The empty language is special, and matches all languages.
|
| + 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->fVariantStyle & variantMask) != maskMatches) {
|
| + 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));
|
| + }
|
| + 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 +425,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;
|
| }
|
| }
|
| }
|
|
|