aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bungeman <bungeman@google.com>2014-10-23 07:08:05 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-23 07:08:06 -0700
commitc20386e3937d3d398ac9b35f9c7d997e972ade98 (patch)
treea8c66e05bad1508b43b2689edf3773b2b9f34595
parent7fdffe41494cbd78a8ee2a6ef0509e46ec77039f (diff)
Update fontMgr to take list of bcp47 language tags.
This will enable clients to pass more than one bcp47 tag to ensure that the most appropriate font is selected. BUG=chromium:422180 Review URL: https://codereview.chromium.org/670243002
-rw-r--r--gm/fontmgr.cpp4
-rw-r--r--include/ports/SkFontMgr.h22
-rw-r--r--include/ports/SkFontMgr_indirect.h12
-rw-r--r--include/ports/SkRemotableFontMgr.h8
-rw-r--r--src/core/SkFontHost.cpp24
-rw-r--r--src/fonts/SkFontMgr_indirect.cpp18
-rw-r--r--src/ports/SkFontMgr_android.cpp95
-rw-r--r--src/ports/SkFontMgr_fontconfig.cpp22
-rw-r--r--src/ports/SkRemotableFontMgr_win_dw.cpp29
9 files changed, 175 insertions, 59 deletions
diff --git a/gm/fontmgr.cpp b/gm/fontmgr.cpp
index a1e7ff2a68..be2b11a272 100644
--- a/gm/fontmgr.cpp
+++ b/gm/fontmgr.cpp
@@ -38,7 +38,11 @@ static SkScalar drawCharacter(SkCanvas* canvas, uint32_t character, SkScalar x,
// find typeface containing the requested character and draw it
SkString ch;
ch.appendUnichar(character);
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
+ SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle, &bpc47, 1, character);
+#else
SkTypeface* typeface = fm->matchFamilyStyleCharacter(fontName, fontStyle, bpc47, character);
+#endif
SkSafeUnref(paint.setTypeface(typeface));
x = drawString(canvas, ch, x, y, paint) + 20;
diff --git a/include/ports/SkFontMgr.h b/include/ports/SkFontMgr.h
index 181fe9f6aa..721018124a 100644
--- a/include/ports/SkFontMgr.h
+++ b/include/ports/SkFontMgr.h
@@ -64,14 +64,24 @@ public:
/**
* Use the system fallback to find a typeface for the given character.
- * Note that bpc47 is a combination of ISO 639, 15924, and 3166-1 codes,
+ * Note that bcp47 is a combination of ISO 639, 15924, and 3166-1 codes,
* so it is fine to just pass a ISO 639 here.
*
* Will return NULL if no family can be found for the character
* in the system fallback.
+ *
+ * bcp47[0] is the least significant fallback, bcp47[bcp47Count-1] is the
+ * most significant. If no specified bcp47 codes match, any font with the
+ * requested character will be matched.
*/
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
+ SkTypeface* matchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const;
+#else
SkTypeface* matchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
- const char bpc47[], uint32_t character) const;
+ const char bcp47[], SkUnichar character) const;
+#endif
SkTypeface* matchFaceStyle(const SkTypeface*, const SkFontStyle&) const;
@@ -117,8 +127,14 @@ protected:
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
const SkFontStyle&) const = 0;
// TODO: pure virtual, implement on all impls.
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
- const char bpc47[], uint32_t character) const
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const
+#else
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+ const char bcp47[], SkUnichar character) const
+#endif
{ return NULL; }
virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
const SkFontStyle&) const = 0;
diff --git a/include/ports/SkFontMgr_indirect.h b/include/ports/SkFontMgr_indirect.h
index b9ce344a73..95a2355a1c 100644
--- a/include/ports/SkFontMgr_indirect.h
+++ b/include/ports/SkFontMgr_indirect.h
@@ -39,10 +39,18 @@ protected:
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
const SkFontStyle& fontStyle) const SK_OVERRIDE;
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle&,
- const char bpc47[],
- uint32_t character) const SK_OVERRIDE;
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const SK_OVERRIDE;
+#else
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle&,
+ const char bcp47[],
+ SkUnichar character) const SK_OVERRIDE;
+#endif
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
const SkFontStyle& fontStyle) const SK_OVERRIDE;
diff --git a/include/ports/SkRemotableFontMgr.h b/include/ports/SkRemotableFontMgr.h
index bf2459955f..5a0a1bc43b 100644
--- a/include/ports/SkRemotableFontMgr.h
+++ b/include/ports/SkRemotableFontMgr.h
@@ -134,8 +134,14 @@ public:
* Note that bpc47 is a combination of ISO 639, 15924, and 3166-1 codes,
* so it is fine to just pass a ISO 639 here.
*/
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
virtual SkFontIdentity matchNameStyleCharacter(const char familyName[], const SkFontStyle&,
- const char bpc47[], SkUnichar character) const=0;
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const=0;
+#else
+ virtual SkFontIdentity matchNameStyleCharacter(const char familyName[], const SkFontStyle&,
+ const char bcp47[], SkUnichar character) const=0;
+#endif
/**
* Returns the data for the given data id.
diff --git a/src/core/SkFontHost.cpp b/src/core/SkFontHost.cpp
index 77b80e8821..14cca5a6a5 100644
--- a/src/core/SkFontHost.cpp
+++ b/src/core/SkFontHost.cpp
@@ -119,10 +119,18 @@ protected:
const SkFontStyle&) const SK_OVERRIDE {
return NULL;
}
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle& style,
- const char bpc47[],
- uint32_t character) const SK_OVERRIDE {
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const SK_OVERRIDE {
+#else
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char bcp47[],
+ SkUnichar character) const SK_OVERRIDE {
+#endif
return NULL;
}
virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
@@ -171,10 +179,18 @@ SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
return this->onMatchFamilyStyle(familyName, fs);
}
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
+SkTypeface* SkFontMgr::matchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style,
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const {
+ return this->onMatchFamilyStyleCharacter(familyName, style, bcp47, bcp47Count, character);
+}
+#else
SkTypeface* SkFontMgr::matchFamilyStyleCharacter(const char familyName[], const SkFontStyle& style,
- const char bpc47[], uint32_t character) const {
- return this->onMatchFamilyStyleCharacter(familyName, style, bpc47, character);
+ const char bcp47[], SkUnichar character) const {
+ return this->onMatchFamilyStyleCharacter(familyName, style, bcp47, character);
}
+#endif
SkTypeface* SkFontMgr::matchFaceStyle(const SkTypeface* face,
const SkFontStyle& fs) const {
diff --git a/src/fonts/SkFontMgr_indirect.cpp b/src/fonts/SkFontMgr_indirect.cpp
index 54f2de8290..c9d30259c5 100644
--- a/src/fonts/SkFontMgr_indirect.cpp
+++ b/src/fonts/SkFontMgr_indirect.cpp
@@ -245,13 +245,25 @@ SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyle(const char familyName[],
return this->createTypefaceFromFontId(id);
}
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle& style,
- const char bpc47[],
- uint32_t character) const {
- SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bpc47, character);
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const {
+ SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47,
+ bcp47Count, character);
return this->createTypefaceFromFontId(id);
}
+#else
+SkTypeface* SkFontMgr_Indirect::onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char bcp47[],
+ SkUnichar character) const {
+ SkFontIdentity id = fProxy->matchNameStyleCharacter(familyName, style, bcp47, character);
+ return this->createTypefaceFromFontId(id);
+}
+#endif
SkTypeface* SkFontMgr_Indirect::onMatchFaceStyle(const SkTypeface* familyMember,
const SkFontStyle& fontStyle) const {
diff --git a/src/ports/SkFontMgr_android.cpp b/src/ports/SkFontMgr_android.cpp
index 15f1d3ed58..2865d800b7 100644
--- a/src/ports/SkFontMgr_android.cpp
+++ b/src/ports/SkFontMgr_android.cpp
@@ -344,50 +344,79 @@ protected:
return NULL;
}
+static SkTypeface_AndroidSystem* find_family_style_character(
+ const SkTDArray<NameToFamily>& fallbackNameToFamilyMap,
+ const SkFontStyle& style, bool elegant,
+ const SkString& langTag, SkUnichar character)
+{
+ for (int i = 0; i < fallbackNameToFamilyMap.count(); ++i) {
+ SkFontStyleSet_Android* family = fallbackNameToFamilyMap[i].styleSet;
+ SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchStyle(style));
+
+ if (!langTag.isEmpty() && langTag != face->fLang.getTag()) {
+ continue;
+ }
+
+ if (SkToBool(face->fVariantStyle & kElegant_FontVariant) != elegant) {
+ 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();
+ }
+ }
+ return NULL;
+}
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle& style,
- const char bpc47[],
- uint32_t character) const SK_OVERRIDE
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const SK_OVERRIDE
{
+#else
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char bcp47_val[],
+ SkUnichar character) const SK_OVERRIDE
+ {
+ const char** bcp47 = &bcp47_val;
+ int bcp47Count = bcp47_val ? 1 : 0;
+#endif
// 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 = kElegant_FontVariant;
-
- // 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;
+ // The first time match anything elegant, second time anything not elegant.
+ for (int elegant = 2; elegant --> 0;) {
+ for (int bcp47Index = bcp47Count; bcp47Index --> 0;) {
+ SkLanguage lang(bcp47[bcp47Index]);
+ while (!lang.getTag().isEmpty()) {
+ SkTypeface_AndroidSystem* matchingTypeface =
+ find_family_style_character(fFallbackNameToFamilyMap,
+ style, SkToBool(elegant),
+ lang.getTag(), character);
+ if (matchingTypeface) {
+ return matchingTypeface;
}
- 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();
- }
+ lang = lang.getParent();
}
- } while (!lang.getTag().isEmpty() && (lang = lang.getParent(), true));
+ }
+ SkTypeface_AndroidSystem* matchingTypeface =
+ find_family_style_character(fFallbackNameToFamilyMap,
+ style, SkToBool(elegant),
+ SkString(), character);
+ if (matchingTypeface) {
+ return matchingTypeface;
+ }
}
return NULL;
}
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp
index dbc64b6e47..6ec5604af4 100644
--- a/src/ports/SkFontMgr_fontconfig.cpp
+++ b/src/ports/SkFontMgr_fontconfig.cpp
@@ -762,11 +762,22 @@ protected:
return createTypefaceFromFcPattern(font);
}
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
const SkFontStyle& style,
- const char bpc47[],
- uint32_t character) const SK_OVERRIDE
+ const char* bcp47[],
+ int bcp47Count,
+ SkUnichar character) const SK_OVERRIDE
{
+#else
+ virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
+ const SkFontStyle& style,
+ const char bcp47_val[],
+ SkUnichar character) const SK_OVERRIDE
+ {
+ const char** bcp47 = &bcp47_val;
+ int bcp47Count = bcp47_val ? 1 : 0;
+#endif
FCLocker lock;
SkAutoFcPattern pattern;
@@ -777,9 +788,12 @@ protected:
FcCharSetAddChar(charSet, character);
FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
- if (bpc47) {
+ if (bcp47Count > 0) {
+ SkASSERT(bcp47);
SkAutoFcLangSet langSet;
- FcLangSetAdd(langSet, (const FcChar8*)bpc47);
+ for (int i = bcp47Count; i --> 0;) {
+ FcLangSetAdd(langSet, (const FcChar8*)bcp47[i]);
+ }
FcPatternAddLangSet(pattern, FC_LANG, langSet);
}
diff --git a/src/ports/SkRemotableFontMgr_win_dw.cpp b/src/ports/SkRemotableFontMgr_win_dw.cpp
index d979683273..9fef440d83 100644
--- a/src/ports/SkRemotableFontMgr_win_dw.cpp
+++ b/src/ports/SkRemotableFontMgr_win_dw.cpp
@@ -408,11 +408,21 @@ public:
SkFontIdentity fIdentity;
};
+#ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
+ virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
+ const SkFontStyle&, pattern
+ const char* bcp47[], int bcp47Count,
+ SkUnichar character) const SK_OVERRIDE
+ {
+#else
virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
const SkFontStyle& pattern,
- const char bpc47[],
- SkUnichar character) const SK_OVERRIDE
+ const char bcp47_val[],
+ SkUnichar character) const SK_OVERRIDE
{
+ const char** bcp47 = &bcp47_val;
+ int bcp47Count = bcp47_val ? 1 : 0;
+#endif
SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
IDWriteFactory* dwFactory = sk_get_dwrite_factory();
@@ -431,13 +441,14 @@ public:
HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, identity);
}
- const SkSMallocWCHAR* dwBpc47;
- SkSMallocWCHAR dwBpc47Local;
- if (NULL == bpc47) {
- dwBpc47 = &fLocaleName;
+ const SkSMallocWCHAR* dwBcp47;
+ SkSMallocWCHAR dwBcp47Local;
+ if (bcp47Count < 1) {
+ dwBcp47 = &fLocaleName;
} else {
- HR_GENERAL(sk_cstring_to_wchar(bpc47, &dwBpc47Local), NULL, identity);
- dwBpc47 = &dwBpc47Local;
+ //TODO: support fallback stack.
+ HR_GENERAL(sk_cstring_to_wchar(bcp47[bcp47Count-1], &dwBcp47Local), NULL, identity);
+ dwBcp47 = &dwBcp47Local;
}
SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
@@ -447,7 +458,7 @@ public:
dwStyle.fSlant,
dwStyle.fWidth,
72.0f,
- *dwBpc47,
+ *dwBcp47,
&fallbackFormat),
"Could not create text format.",
identity);