Sort the Skia typefaces in a font style set into a consistent order (flutter/engine#11056)

When Minikin searches for a font based on a font style, it will score the fonts
in the family and choose the best match.  However, multiple fonts may have
equal scores (e.g. searching for a font with weight 600 when the set includes
fonts with weights 500 and 700).  In this case Minikin will select the first
font in the list with the best score.

However, the fonts in a font family's SkFontStyleSet may not always be provided
in a consistent order by the SkFontMgr.  So if the minikin::FontFamily list is
populated based on the SkFontStyleSet order, then a query for a given style might
not always return the same font.

This change sorts the typefaces in the SkFontStyleSet before converting them
into a Minikin font family.

Fixes https://github.com/flutter/flutter/issues/31212
This commit is contained in:
Jason Simmons
2019-08-16 14:09:41 -07:00
committed by GitHub
parent d3c46983fa
commit ed7e571669

View File

@@ -209,26 +209,33 @@ std::shared_ptr<minikin::FontFamily> FontCollection::CreateMinikinFontFamily(
return nullptr;
}
std::vector<minikin::Font> minikin_fonts;
// Add fonts to the Minikin font family.
std::vector<sk_sp<SkTypeface>> skia_typefaces;
for (int i = 0; i < font_style_set->count(); ++i) {
TRACE_EVENT0("flutter", "CreateMinikinFont");
// Create the skia typeface.
TRACE_EVENT0("flutter", "CreateSkiaTypeface");
sk_sp<SkTypeface> skia_typeface(
sk_sp<SkTypeface>(font_style_set->createTypeface(i)));
if (skia_typeface == nullptr) {
continue;
if (skia_typeface != nullptr) {
skia_typefaces.emplace_back(std::move(skia_typeface));
}
}
std::sort(skia_typefaces.begin(), skia_typefaces.end(),
[](const sk_sp<SkTypeface>& a, const sk_sp<SkTypeface>& b) {
SkFontStyle a_style = a->fontStyle();
SkFontStyle b_style = b->fontStyle();
return (a_style.weight() != b_style.weight())
? a_style.weight() < b_style.weight()
: a_style.slant() < b_style.slant();
});
std::vector<minikin::Font> minikin_fonts;
for (const sk_sp<SkTypeface>& skia_typeface : skia_typefaces) {
// Create the minikin font from the skia typeface.
// Divide by 100 because the weights are given as "100", "200", etc.
minikin::Font minikin_font(
minikin_fonts.emplace_back(
std::make_shared<FontSkia>(skia_typeface),
minikin::FontStyle{skia_typeface->fontStyle().weight() / 100,
skia_typeface->isItalic()});
minikin_fonts.emplace_back(std::move(minikin_font));
}
return std::make_shared<minikin::FontFamily>(std::move(minikin_fonts));