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; |
+ } |
} |
} |
} |