Skip to content

Check the presence of glyphs when selecting font #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions third_party/txt/src/minikin/FontCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,27 @@ void FontCollection::itemize(const uint16_t* string,
}
start -= prevChLength;
}
result->push_back(
{family->getClosestMatch(style), static_cast<int>(start), 0});
result->push_back({family->getClosestMatch(style, ch, variant),
static_cast<int>(start), 0});
run = &result->back();
lastFamily = family.get();
} else if (family.get() == lastFamily &&
// We need to change this condition to more general logic. And
// when changing the font, it is necessary to check whether the
// existing characters also have glyphs.
!(U_GET_GC_MASK(prevCh) & U_GC_L_MASK) &&
(U_GET_GC_MASK(ch) & U_GC_L_MASK)) {
size_t start = utf16Pos;
auto current_font = family->getClosestMatch(style, ch, variant);
if (result->back().fakedFont.font != current_font.font) {
const size_t prevChLength = U16_LENGTH(prevCh);
run->end -= prevChLength;
if (run->start == run->end) {
result->pop_back();
}
start -= prevChLength;
}
result->push_back({current_font, static_cast<int>(start), 0});
run = &result->back();
lastFamily = family.get();
}
Expand Down
23 changes: 18 additions & 5 deletions third_party/txt/src/minikin/FontFamily.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,28 @@ static FontFakery computeFakery(FontStyle wanted, FontStyle actual) {
return FontFakery(isFakeBold, isFakeItalic);
}

FakedFont FontFamily::getClosestMatch(FontStyle style) const {
FakedFont FontFamily::getClosestMatch(
FontStyle style,
uint32_t codepoint /* = 0 */,
uint32_t variationSelector /* = 0 */) const {
int bestMatch = INT_MAX;
const Font* bestFont = nullptr;
int bestMatch = 0;
for (size_t i = 0; i < mFonts.size(); i++) {
const Font& font = mFonts[i];
int match = computeMatch(font.style, style);
if (i == 0 || match < bestMatch) {
bestFont = &font;
bestMatch = match;
bool result = false;
if (codepoint != 0) {
hb_font_t* hb_font = getHbFontLocked(font.typeface.get());
uint32_t unusedGlyph = 0;
result = hb_font_get_glyph(hb_font, codepoint, variationSelector,
&unusedGlyph);
hb_font_destroy(hb_font);
}
if (!codepoint || (codepoint && result)) {
if (match < bestMatch) {
bestFont = &font;
bestMatch = match;
}
}
}
if (bestFont != nullptr) {
Expand Down
4 changes: 3 additions & 1 deletion third_party/txt/src/minikin/FontFamily.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ class FontFamily {
static bool analyzeStyle(const std::shared_ptr<MinikinFont>& typeface,
int* weight,
bool* italic);
FakedFont getClosestMatch(FontStyle style) const;
FakedFont getClosestMatch(FontStyle style,
uint32_t codepoint = 0,
uint32_t variationSelector = 0) const;

uint32_t langId() const { return mLangId; }
int variant() const { return mVariant; }
Expand Down
22 changes: 22 additions & 0 deletions third_party/txt/src/txt/font_collection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,28 @@ void FontCollection::SortSkTypefaces(
int a_delta = std::abs(a_style.width() - SkFontStyle::kNormal_Width);
int b_delta = std::abs(b_style.width() - SkFontStyle::kNormal_Width);

{
// A workaround to prevent emoji fonts being selected for normal text
// when normal and emojis are mixed at same font family.

bool a_isContainEmoji = false;
bool b_isContainEmoji = false;
SkString postScriptName;
a->getPostScriptName(&postScriptName);
if (postScriptName.contains("Emoji")) {
a_isContainEmoji = true;
}
b->getPostScriptName(&postScriptName);
if (postScriptName.contains("Emoji")) {
b_isContainEmoji = true;
}
if (a_isContainEmoji && !b_isContainEmoji) {
return false;
} else if (!a_isContainEmoji && b_isContainEmoji) {
return true;
}
}

if (a_delta != b_delta) {
// If a family name query is so generic it ends up bringing in fonts
// of multiple widths (e.g. condensed, expanded), opt to be
Expand Down
6 changes: 5 additions & 1 deletion third_party/txt/src/txt/platform_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
namespace txt {

std::vector<std::string> GetDefaultFontFamilies() {
#ifdef FLUTTER_USE_FONTCONFIG
return {"TizenDefaultFont"};
#else
return {
"SamsungOneUI",
"SamsungOneUIArabic",
Expand Down Expand Up @@ -72,11 +75,12 @@ std::vector<std::string> GetDefaultFontFamilies() {
"BreezeSansFallback",
"BreezeColorEmoji",
};
#endif
}

sk_sp<SkFontMgr> GetDefaultFontManager() {
#ifdef FLUTTER_USE_FONTCONFIG
return SkFontMgr_New_FontConfig(nullptr);
return SkFontMgr::RefDefault();
#else
return SkFontMgr_New_Custom_Directory("/usr/share/fonts");
#endif
Expand Down