Bug 1844464 - patch 1 - Optimize gfxFontShaper::MergeFontFeatures by using a sorted array rather than nsTHashMap to accumulate the features. r=gfx-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D184101
This commit is contained in:
Jonathan Kew 2023-07-25 13:15:37 +00:00
parent 020b36d696
commit e2b1b7a6d7
5 changed files with 46 additions and 30 deletions

View file

@ -93,7 +93,7 @@ bool gfxCoreTextShaper::ShapeText(DrawTarget* aDrawTarget,
// among them.
const gfxFontStyle* style = mFont->GetStyle();
gfxFontEntry* entry = mFont->GetFontEntry();
auto handleFeatureTag = [](const uint32_t& aTag, uint32_t& aValue,
auto handleFeatureTag = [](uint32_t aTag, uint32_t aValue,
void* aUserArg) -> void {
if (aTag == HB_TAG('s', 'm', 'c', 'p') && aValue) {
*static_cast<bool*>(aUserArg) = true;

View file

@ -38,6 +38,7 @@
#include "nsUnicodeProperties.h"
#include "nsStyleConsts.h"
#include "mozilla/AppUnits.h"
#include "mozilla/HashTable.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Preferences.h"
@ -550,7 +551,7 @@ static void LookupAlternateValues(const gfxFontFeatureValueSet& aFeatureLookup,
void gfxFontShaper::MergeFontFeatures(
const gfxFontStyle* aStyle, const nsTArray<gfxFontFeature>& aFontFeatures,
bool aDisableLigatures, const nsACString& aFamilyName, bool aAddSmallCaps,
void (*aHandleFeature)(const uint32_t&, uint32_t&, void*),
void (*aHandleFeature)(uint32_t, uint32_t, void*),
void* aHandleFeatureData) {
const nsTArray<gfxFontFeature>& styleRuleFeatures = aStyle->featureSettings;
@ -563,11 +564,29 @@ void gfxFontShaper::MergeFontFeatures(
return;
}
nsTHashMap<nsUint32HashKey, uint32_t> mergedFeatures;
AutoTArray<gfxFontFeature, 32> mergedFeatures;
struct FeatureTagCmp {
bool Equals(const gfxFontFeature& a, const gfxFontFeature& b) const {
return a.mTag == b.mTag;
}
bool LessThan(const gfxFontFeature& a, const gfxFontFeature& b) const {
return a.mTag < b.mTag;
}
} cmp;
auto addOrReplace = [&](const gfxFontFeature& aFeature) {
auto index = mergedFeatures.BinaryIndexOf(aFeature, cmp);
if (index == nsTArray<gfxFontFeature>::NoIndex) {
mergedFeatures.InsertElementSorted(aFeature, cmp);
} else {
mergedFeatures[index].mValue = aFeature.mValue;
}
};
// add feature values from font
for (const gfxFontFeature& feature : aFontFeatures) {
mergedFeatures.InsertOrUpdate(feature.mTag, feature.mValue);
addOrReplace(feature);
}
// font-variant-caps - handled here due to the need for fallback handling
@ -578,33 +597,33 @@ void gfxFontShaper::MergeFontFeatures(
break;
case NS_FONT_VARIANT_CAPS_ALLSMALL:
mergedFeatures.InsertOrUpdate(HB_TAG('c', '2', 's', 'c'), 1);
addOrReplace(gfxFontFeature{HB_TAG('c', '2', 's', 'c'), 1});
// fall through to the small-caps case
[[fallthrough]];
case NS_FONT_VARIANT_CAPS_SMALLCAPS:
mergedFeatures.InsertOrUpdate(HB_TAG('s', 'm', 'c', 'p'), 1);
addOrReplace(gfxFontFeature{HB_TAG('s', 'm', 'c', 'p'), 1});
break;
case NS_FONT_VARIANT_CAPS_ALLPETITE:
mergedFeatures.InsertOrUpdate(aAddSmallCaps ? HB_TAG('c', '2', 's', 'c')
: HB_TAG('c', '2', 'p', 'c'),
1);
addOrReplace(gfxFontFeature{aAddSmallCaps ? HB_TAG('c', '2', 's', 'c')
: HB_TAG('c', '2', 'p', 'c'),
1});
// fall through to the petite-caps case
[[fallthrough]];
case NS_FONT_VARIANT_CAPS_PETITECAPS:
mergedFeatures.InsertOrUpdate(aAddSmallCaps ? HB_TAG('s', 'm', 'c', 'p')
: HB_TAG('p', 'c', 'a', 'p'),
1);
addOrReplace(gfxFontFeature{aAddSmallCaps ? HB_TAG('s', 'm', 'c', 'p')
: HB_TAG('p', 'c', 'a', 'p'),
1});
break;
case NS_FONT_VARIANT_CAPS_TITLING:
mergedFeatures.InsertOrUpdate(HB_TAG('t', 'i', 't', 'l'), 1);
addOrReplace(gfxFontFeature{HB_TAG('t', 'i', 't', 'l'), 1});
break;
case NS_FONT_VARIANT_CAPS_UNICASE:
mergedFeatures.InsertOrUpdate(HB_TAG('u', 'n', 'i', 'c'), 1);
addOrReplace(gfxFontFeature{HB_TAG('u', 'n', 'i', 'c'), 1});
break;
default:
@ -617,10 +636,10 @@ void gfxFontShaper::MergeFontFeatures(
case NS_FONT_VARIANT_POSITION_NORMAL:
break;
case NS_FONT_VARIANT_POSITION_SUPER:
mergedFeatures.InsertOrUpdate(HB_TAG('s', 'u', 'p', 's'), 1);
addOrReplace(gfxFontFeature{HB_TAG('s', 'u', 'p', 's'), 1});
break;
case NS_FONT_VARIANT_POSITION_SUB:
mergedFeatures.InsertOrUpdate(HB_TAG('s', 'u', 'b', 's'), 1);
addOrReplace(gfxFontFeature{HB_TAG('s', 'u', 'b', 's'), 1});
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected variantSubSuper");
@ -638,15 +657,15 @@ void gfxFontShaper::MergeFontFeatures(
}
for (const gfxFontFeature& feature : featureList) {
mergedFeatures.InsertOrUpdate(feature.mTag, feature.mValue);
addOrReplace(gfxFontFeature{feature.mTag, feature.mValue});
}
}
auto disableOptionalLigatures = [&]() -> void {
mergedFeatures.InsertOrUpdate(HB_TAG('l', 'i', 'g', 'a'), 0);
mergedFeatures.InsertOrUpdate(HB_TAG('c', 'l', 'i', 'g'), 0);
mergedFeatures.InsertOrUpdate(HB_TAG('d', 'l', 'i', 'g'), 0);
mergedFeatures.InsertOrUpdate(HB_TAG('h', 'l', 'i', 'g'), 0);
addOrReplace(gfxFontFeature{HB_TAG('l', 'i', 'g', 'a'), 0});
addOrReplace(gfxFontFeature{HB_TAG('c', 'l', 'i', 'g'), 0});
addOrReplace(gfxFontFeature{HB_TAG('d', 'l', 'i', 'g'), 0});
addOrReplace(gfxFontFeature{HB_TAG('h', 'l', 'i', 'g'), 0});
};
// Add features that are already resolved to tags & values in the style.
@ -664,7 +683,7 @@ void gfxFontShaper::MergeFontFeatures(
// features specified directly as tags will come last and therefore
// take precedence over everything else.
if (feature.mTag) {
mergedFeatures.InsertOrUpdate(feature.mTag, feature.mValue);
addOrReplace(gfxFontFeature{feature.mTag, feature.mValue});
} else if (aDisableLigatures) {
// Handle ligature-disabling setting at the boundary between high-
// and low-level features.
@ -673,10 +692,8 @@ void gfxFontShaper::MergeFontFeatures(
}
}
if (mergedFeatures.Count() != 0) {
for (auto iter = mergedFeatures.Iter(); !iter.Done(); iter.Next()) {
aHandleFeature(iter.Key(), iter.Data(), aHandleFeatureData);
}
for (const auto& f : mergedFeatures) {
aHandleFeature(f.mTag, f.mValue, aHandleFeatureData);
}
}

View file

@ -683,7 +683,7 @@ class gfxFontShaper {
static void MergeFontFeatures(
const gfxFontStyle* aStyle, const nsTArray<gfxFontFeature>& aFontFeatures,
bool aDisableLigatures, const nsACString& aFamilyName, bool aAddSmallCaps,
void (*aHandleFeature)(const uint32_t&, uint32_t&, void*),
void (*aHandleFeature)(uint32_t, uint32_t, void*),
void* aHandleFeatureData);
protected:

View file

@ -98,7 +98,7 @@ struct GrFontFeatures {
rlbox_sandbox_gr* mSandbox;
};
static void AddFeature(const uint32_t& aTag, uint32_t& aValue, void* aUserArg) {
static void AddFeature(uint32_t aTag, uint32_t aValue, void* aUserArg) {
GrFontFeatures* f = static_cast<GrFontFeatures*>(aUserArg);
tainted_gr<const gr_feature_ref*> fref =

View file

@ -1058,8 +1058,7 @@ static hb_bool_t HBUnicodeDecompose(hb_unicode_funcs_t* ufuncs,
return false;
}
static void AddOpenTypeFeature(const uint32_t& aTag, uint32_t& aValue,
void* aUserArg) {
static void AddOpenTypeFeature(uint32_t aTag, uint32_t aValue, void* aUserArg) {
nsTArray<hb_feature_t>* features =
static_cast<nsTArray<hb_feature_t>*>(aUserArg);