From ea8f8c6f7677893191e2a3ad4b170afb1237be42 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Fri, 16 Aug 2019 10:52:43 -0700 Subject: [PATCH] Sort the Skia typefaces in a font style set into a consistent order 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 --- third_party/txt/src/txt/font_collection.cc | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/third_party/txt/src/txt/font_collection.cc b/third_party/txt/src/txt/font_collection.cc index 1ee1f8f0908b6..25c2fc79fbba7 100644 --- a/third_party/txt/src/txt/font_collection.cc +++ b/third_party/txt/src/txt/font_collection.cc @@ -209,26 +209,33 @@ std::shared_ptr FontCollection::CreateMinikinFontFamily( return nullptr; } - std::vector minikin_fonts; - - // Add fonts to the Minikin font family. + std::vector> 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 skia_typeface( sk_sp(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& a, const sk_sp& 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_fonts; + for (const sk_sp& 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(skia_typeface), minikin::FontStyle{skia_typeface->fontStyle().weight() / 100, skia_typeface->isItalic()}); - - minikin_fonts.emplace_back(std::move(minikin_font)); } return std::make_shared(std::move(minikin_fonts));