summaryrefslogtreecommitdiff
path: root/libs/minikin/FontCollection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/minikin/FontCollection.cpp')
-rw-r--r--libs/minikin/FontCollection.cpp85
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,