Chromium Code Reviews| Index: src/ports/SkFontMgr_android.cpp |
| diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp |
| index 1facb537096b53d7c50b7f4e7bcf51d732a8ed5d..9447032ffa923ce808e5b866c35e57a0c746aa55 100644 |
| --- a/src/ports/SkFontMgr_android.cpp |
| +++ b/src/ports/SkFontMgr_android.cpp |
| @@ -33,6 +33,10 @@ |
| # define DEBUG_FONT(args) |
| #endif |
| +//SkTypeface* SkAndroidNextLogicalTypeface(SkFontID, SkFontID, SkPaintOptionsAndroid const&) { |
| +// return NULL; |
| +//} |
|
bungeman-skia
2014/07/30 17:00:07
I'll remove this block soon. I've commented out th
|
| + |
| class SkTypeface_Android : public SkTypeface_FreeType { |
| public: |
| SkTypeface_Android(int index, |
| @@ -59,9 +63,14 @@ public: |
| int index, |
| Style style, |
| bool isFixedPitch, |
| - const SkString familyName) |
| + const SkString familyName, |
| + const SkLanguage& lang, |
| + bool useInFallback) |
|
tomhudson
2014/07/30 17:54:58
You pass "is accepted fallback variant" to "use in
bungeman-skia
2014/07/30 23:03:28
Removed.
|
| : INHERITED(index, style, isFixedPitch, familyName) |
| - , fPathName(pathName) { } |
| + , fPathName(pathName) |
| + , fLang(lang) |
| + , fUseInFallback(useInFallback) |
|
bungeman-skia
2014/07/30 17:00:07
For the moment I'm sticking this on the typeface s
|
| + { } |
|
tomhudson
2014/07/30 17:54:58
Nit: Skia style?
bungeman-skia
2014/07/30 23:03:28
Hmm, we do this in a number of other places, Skia
|
| virtual void onGetFontDescriptor(SkFontDescriptor* desc, |
| bool* serialize) const SK_OVERRIDE { |
| @@ -77,8 +86,13 @@ public: |
| } |
| private: |
| - SkString fPathName; |
| + const SkString fPathName; |
| + |
| +public: |
|
djsollen
2014/07/30 17:31:43
seems like having 2 getters makes more sense than
tomhudson
2014/07/30 17:54:58
Acknowledged.
bungeman-skia
2014/07/30 23:03:28
You Java people and your gratuitous setters and ge
|
| + const SkLanguage fLang; |
| + const bool fUseInFallback; |
| +private: |
| typedef SkTypeface_Android INHERITED; |
| }; |
| @@ -120,7 +134,7 @@ void get_path_for_sys_fonts(SkString* full, const SkString& name) { |
| class SkFontStyleSet_Android : public SkFontStyleSet { |
| public: |
| - explicit SkFontStyleSet_Android(FontFamily* family) : fFontFamily(family) { |
| + explicit SkFontStyleSet_Android(FontFamily* family, SkString* name) { |
| // TODO? make this lazy |
| for (int i = 0; i < family->fFontFiles.count(); ++i) { |
| const SkString& fileName = family->fFontFiles[i].fFileName; |
| @@ -134,18 +148,31 @@ public: |
| continue; |
| } |
| + int ttcIndex = family->fFontFiles[i].fIndex; |
|
djsollen
2014/07/30 17:31:43
const int
bungeman-skia
2014/07/30 23:03:28
Done.
|
| SkString fontName; |
| SkTypeface::Style style; |
| bool isFixedWidth; |
| - if (!SkTypeface_FreeType::ScanFont(stream.get(), family->fFontFiles[i].fIndex, |
| + if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex, |
| &fontName, &style, &isFixedWidth)) { |
| DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, fileName.c_str())); |
| continue; |
| } |
| + static int32_t acceptedVariants = SkPaintOptionsAndroid::kDefault_Variant | |
|
djsollen
2014/07/30 17:31:43
let's document why we do this.
The compact varian
tomhudson
2014/07/30 17:54:58
Acknowledged.
bungeman-skia
2014/07/30 23:03:28
Moved all the way over to the parser.
|
| + SkPaintOptionsAndroid::kElegant_Variant; |
| + bool isAcceptedFallbackVariant = SkToBool( |
| + family->fFontFiles[i].fPaintOptions.getFontVariant() & acceptedVariants); |
| + |
| + const SkLanguage& lang = family->fFontFiles[i].fPaintOptions.getLanguage(); |
| + |
| + if (name != NULL) { |
| + fontName = *name; |
| + } |
| + |
| fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, |
| - (pathName, 0, |
| - style, isFixedWidth, fontName))); |
| + (pathName, ttcIndex, |
| + style, isFixedWidth, fontName, |
| + lang, isAcceptedFallbackVariant))); |
| } |
| } |
| @@ -163,7 +190,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; |
| } |
| @@ -174,11 +201,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,8 +240,7 @@ private: |
| } |
| - FontFamily* fFontFamily; |
| - SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles; |
| + SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles; |
| friend struct NameToFamily; |
| friend class SkFontMgr_Android; |
| @@ -274,6 +300,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; |
| } |
| @@ -295,6 +327,37 @@ protected: |
| return NULL; |
| } |
| + virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], |
| + const SkFontStyle& style, |
| + const char bpc47[], |
| + uint32_t character) const SK_OVERRIDE |
| + { |
| + 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 (!face->fUseInFallback || |
| + (!langTag.isEmpty() && langTag != face->fLang.getTag())) { |
| + 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); |
| @@ -329,20 +392,15 @@ protected: |
| oldStyle & SkTypeface::kItalic |
| ? SkFontStyle::kItalic_Slant |
| : SkFontStyle::kUpright_Slant); |
| - SkTypeface* tf = NULL; |
| if (NULL != familyName) { |
| // On Android, we must return NULL when we can't find the requested |
| // named typeface so that the system/app can provide their own recovery |
| // mechanism. On other platforms we'd provide a typeface from the |
| // default family instead. |
| - tf = this->onMatchFamilyStyle(familyName, style); |
| - } else { |
| - tf = fDefaultFamily->matchStyle(style); |
| + return this->onMatchFamilyStyle(familyName, style); |
| } |
| - |
| - // TODO: double ref? qv matchStyle() |
| - return SkSafeRef(tf); |
| + return fDefaultFamily->matchStyle(style); |
| } |
| @@ -353,15 +411,29 @@ 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(); |
| + if (families[i]->fIsFallbackFont) { |
|
djsollen
2014/07/30 17:31:43
in general this if/else block is very dense and ha
tomhudson
2014/07/30 17:54:58
Acknowledged.
bungeman-skia
2014/07/30 23:03:28
Made it much different now.
|
| + SkString fallbackName; |
| + fallbackName.printf("%.2x##fallback", i); |
| + NameToFamily* nextEntry = fFallbackNameToFamilyMap.append(); |
| + SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (fallbackName)); |
| + nextEntry->styleSet = fFontStyleSets.push_back().reset( |
| + SkNEW_ARGS(SkFontStyleSet_Android, (families[i], &fallbackName))); |
| + } else { |
| + SkString* cannonicalName = NULL; |
| + if (families[i]->fNames.count() > 0) { |
| + cannonicalName = &families[i]->fNames[0]; |
| + } |
| + SkFontStyleSet_Android* newSet = fFontStyleSets.push_back().reset( |
| + SkNEW_ARGS(SkFontStyleSet_Android, (families[i], cannonicalName))); |
| + 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 = newSet; |
| + } |
| } |
| } |
| } |