[Fonts] Fix outdated workaround in SkFontMgr `remove_weak` would use `is_weak`, which used an outdated workaround for not having a method to check the binding of an FcPattern. Now that there exists an `FcPatternGetWithBinding`, we can use that instead. Change-Id: I1ba74672a8f27630dce57d6396d5f675c89d3579 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1329557 Reviewed-by: Florin Malita <fmalita@google.com> Commit-Queue: Alexis Cruz-Ayala <alexisdavidc@google.com>
diff --git a/src/ports/SkFontMgr_fontconfig.cpp b/src/ports/SkFontMgr_fontconfig.cpp index 863e85c..403a551 100644 --- a/src/ports/SkFontMgr_fontconfig.cpp +++ b/src/ports/SkFontMgr_fontconfig.cpp
@@ -166,85 +166,6 @@ return matrix; } -enum SkWeakReturn { - kIsWeak_WeakReturn, - kIsStrong_WeakReturn, - kNoId_WeakReturn -}; -/** Ideally there would exist a call like - * FcResult FcPatternIsWeak(pattern, object, id, FcBool* isWeak); - * Sometime after 2.12.4 FcPatternGetWithBinding was added which can retrieve the binding. - * - * However, there is no such call and as of Fc 2.11.0 even FcPatternEquals ignores the weak bit. - * Currently, the only reliable way of finding the weak bit is by its effect on matching. - * The weak bit only affects the matching of FC_FAMILY and FC_POSTSCRIPT_NAME object values. - * A element with the weak bit is scored after FC_LANG, without the weak bit is scored before. - * Note that the weak bit is stored on the element, not on the value it holds. - */ -static SkWeakReturn is_weak(FcPattern* pattern, const char object[], int id) { - FCLocker::AssertHeld(); - - FcResult result; - - // Create a copy of the pattern with only the value 'pattern'['object'['id']] in it. - // Internally, FontConfig pattern objects are linked lists, so faster to remove from head. - SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr)); - SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly)); - FcBool hasId = true; - for (int i = 0; hasId && i < id; ++i) { - hasId = FcPatternRemove(minimal, object, 0); - } - if (!hasId) { - return kNoId_WeakReturn; - } - FcValue value; - result = FcPatternGet(minimal, object, 0, &value); - if (result != FcResultMatch) { - return kNoId_WeakReturn; - } - while (hasId) { - hasId = FcPatternRemove(minimal, object, 1); - } - - // Create a font set with two patterns. - // 1. the same 'object' as minimal and a lang object with only 'nomatchlang'. - // 2. a different 'object' from minimal and a lang object with only 'matchlang'. - SkAutoFcFontSet fontSet; - - SkAutoFcLangSet strongLangSet; - FcLangSetAdd(strongLangSet, (const FcChar8*)"nomatchlang"); - SkAutoFcPattern strong(FcPatternDuplicate(minimal)); - FcPatternAddLangSet(strong, FC_LANG, strongLangSet); - - SkAutoFcLangSet weakLangSet; - FcLangSetAdd(weakLangSet, (const FcChar8*)"matchlang"); - SkAutoFcPattern weak; - FcPatternAddString(weak, object, (const FcChar8*)"nomatchstring"); - FcPatternAddLangSet(weak, FC_LANG, weakLangSet); - - FcFontSetAdd(fontSet, strong.release()); - FcFontSetAdd(fontSet, weak.release()); - - // Add 'matchlang' to the copy of the pattern. - FcPatternAddLangSet(minimal, FC_LANG, weakLangSet); - - // Run a match against the copy of the pattern. - // If the 'id' was weak, then we should match the pattern with 'matchlang'. - // If the 'id' was strong, then we should match the pattern with 'nomatchlang'. - - // Note that this config is only used for FcFontRenderPrepare, which we don't even want. - // However, there appears to be no way to match/sort without it. - SkAutoFcConfig config; - FcFontSet* fontSets[1] = { fontSet }; - SkAutoFcPattern match(FcFontSetMatch(config, fontSets, std::size(fontSets), - minimal, &result)); - - FcLangSet* matchLangSet; - FcPatternGetLangSet(match, FC_LANG, 0, &matchLangSet); - return FcLangEqual == FcLangSetHasLang(matchLangSet, (const FcChar8*)"matchlang") - ? kIsWeak_WeakReturn : kIsStrong_WeakReturn; -} - /** Removes weak elements from either FC_FAMILY or FC_POSTSCRIPT_NAME objects in the property. * This can be quite expensive, and should not be used more than once per font lookup. * This removes all of the weak elements after the last strong element. @@ -252,22 +173,21 @@ void SkFontMgr_fontconfig_priv::remove_weak(FcPattern* pattern, const char object[]) { FCLocker::AssertHeld(); - SkAutoFcObjectSet requestedObjectOnly(FcObjectSetBuild(object, nullptr)); - SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly)); - int lastStrongId = -1; int numIds; - SkWeakReturn result; - for (int id = 0; ; ++id) { - result = is_weak(minimal, object, 0); - if (kNoId_WeakReturn == result) { + for (int id = 0;; ++id) { + FcValue value; + FcValueBinding binding; + FcResult result = FcPatternGetWithBinding( + pattern, object, id, &value, &binding); + if (result != FcResultMatch) { numIds = id; break; } - if (kIsStrong_WeakReturn == result) { + + if (binding != FcValueBindingWeak) { lastStrongId = id; } - SkAssertResult(FcPatternRemove(minimal, object, 0)); } // If they were all weak, then leave the pattern alone.