forked from firka/flutter
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:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user