diff options
Diffstat (limited to 'libs/minikin/FontCollection.cpp')
-rw-r--r-- | libs/minikin/FontCollection.cpp | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/libs/minikin/FontCollection.cpp b/libs/minikin/FontCollection.cpp index 0c1a173..84e5dd9 100644 --- a/libs/minikin/FontCollection.cpp +++ b/libs/minikin/FontCollection.cpp @@ -30,6 +30,8 @@ #include "minikin/Characters.h" #include "minikin/Emoji.h" #include "minikin/FontFileParser.h" +#include "minikin/MinikinExtent.h" +#include "minikin/MinikinPaint.h" using std::vector; @@ -606,6 +608,89 @@ FontCollection::FamilyMatchResult FontCollection::FamilyMatchResult::intersect( return b.build(); } +void FontCollection::filterFamilyByLocale( + const LocaleList& localeList, + const std::function<void(const FontFamily& family)>& callback) const { + for (uint8_t i = 0; i < mFamilyCount; ++i) { + const auto& family = getFamilyAt(i); + + uint32_t fontLocaleId = family->localeListId(); + if (fontLocaleId == LocaleListCache::kInvalidListId) { + continue; + } + const LocaleList& fontLocaleList = LocaleListCache::getById(fontLocaleId); + if (!localeList.atLeastOneScriptMatch(fontLocaleList)) { + continue; + } + + callback(*family.get()); + } +} + +MinikinExtent FontCollection::getReferenceExtentForLocale(const MinikinPaint& paint) const { + uint32_t localeId = paint.localeListId; + MinikinExtent result(0, 0); + for (uint8_t i = 0; i < mFamilyCount; ++i) { + const auto& family = getFamilyAt(i); + if (!family->isCustomFallback()) { + break; + } + + // Use this family + MinikinExtent extent(0, 0); + FakedFont font = getFamilyAt(i)->getClosestMatch(paint.fontStyle); + font.typeface()->GetFontExtent(&extent, paint, font.fakery); + result.extendBy(extent); + } + + if (localeId == LocaleListCache::kInvalidListId) { + return result; + } + + // If default is requested, use compact one. + const FamilyVariant requestVariant = paint.familyVariant == FamilyVariant::DEFAULT + ? FamilyVariant::COMPACT + : paint.familyVariant; + const LocaleList& requestedLocaleList = LocaleListCache::getById(localeId); + + bool familyFound = false; + filterFamilyByLocale(requestedLocaleList, [&](const FontFamily& family) { + const FamilyVariant familyVariant = family.variant() == FamilyVariant::DEFAULT + ? FamilyVariant::COMPACT + : family.variant(); + + if (familyVariant != requestVariant) { + return; + } + + MinikinExtent extent(0, 0); + FakedFont font = family.getClosestMatch(paint.fontStyle); + font.typeface()->GetFontExtent(&extent, paint, font.fakery); + result.extendBy(extent); + + familyFound = true; + }); + + // If nothing matches, try non-variant match cases since it is used for fallback. + filterFamilyByLocale(requestedLocaleList, [&](const FontFamily& family) { + // Use this family + MinikinExtent extent(0, 0); + FakedFont font = family.getClosestMatch(paint.fontStyle); + font.typeface()->GetFontExtent(&extent, paint, font.fakery); + result.extendBy(extent); + + familyFound = true; + }); + + // If nothing matches, use default font. + if (!familyFound) { + FakedFont font = getFamilyAt(0)->getClosestMatch(paint.fontStyle); + font.typeface()->GetFontExtent(&result, paint, font.fakery); + } + + return result; +} + std::vector<FontCollection::Run> FontCollection::itemize(U16StringPiece text, FontStyle, uint32_t localeListId, FamilyVariant familyVariant, |