Cache result of CTFontCopyVariationAxes.

CTFontCopyVariationAxes appears to be extremely slow due to localizing
the name of the axis. WebKit moved to using the internal SPI
CTFontCopyVariationAxesInternal to avoid this cost. Since Skia would
like to avoid using internal SPI, just cache this information per
typeface to avoid the cost of calling it as often.

Bug: https://github.com/flutter/flutter/issues/100523
Bug: https://bugs.webkit.org/show_bug.cgi?id=232690
Change-Id: I175e34e9aa526d58e6b7a4ff54cb13d1ef8a9fd9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/524760
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
This commit is contained in:
Ben Wagner 2022-03-25 15:22:00 -04:00 committed by SkCQ
parent 55ec347276
commit e85afc2b18
4 changed files with 39 additions and 17 deletions

View File

@ -563,7 +563,8 @@ protected:
return nullptr;
}
CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(ct.get(), args);
SkUniqueCFRef<CFArrayRef> axes(CTFontCopyVariationAxes(ct.get()));
CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(ct.get(), axes.get(), args);
SkUniqueCFRef<CTFontRef> ctVariant;
if (ctVariation.variation) {

View File

@ -718,8 +718,8 @@ void SkScalerContext_Mac::generateFontMetrics(SkFontMetrics* metrics) {
metrics->fFlags |= SkFontMetrics::kUnderlineThicknessIsValid_Flag;
metrics->fFlags |= SkFontMetrics::kUnderlinePositionIsValid_Flag;
SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fCTFont.get()));
if (ctAxes && CFArrayGetCount(ctAxes.get()) > 0) {
CFArrayRef ctAxes = ((SkTypeface_Mac*)this->getTypeface())->getVariationAxes();
if (ctAxes && CFArrayGetCount(ctAxes) > 0) {
// The bounds are only valid for the default variation.
metrics->fFlags |= SkFontMetrics::kBoundsInvalid_Flag;
}

View File

@ -566,8 +566,8 @@ std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics(
}
}
SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ctFont.get()));
if (ctAxes && CFArrayGetCount(ctAxes.get()) > 0) {
CFArrayRef ctAxes = this->getVariationAxes();
if (ctAxes && CFArrayGetCount(ctAxes) > 0) {
info->fFlags |= SkAdvancedTypefaceMetrics::kVariable_FontFlag;
}
@ -787,14 +787,21 @@ bool SkTypeface_Mac::onGlyphMaskNeedsCurrentColor() const {
return this->fHasColorGlyphs;
}
CFArrayRef SkTypeface_Mac::getVariationAxes() const {
fInitVariationAxes([this]{
fVariationAxes.reset(CTFontCopyVariationAxes(fFontRef.get()));
});
return fVariationAxes.get();
}
int SkTypeface_Mac::onGetVariationDesignPosition(
SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
{
SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
CFArrayRef ctAxes = this->getVariationAxes();
if (!ctAxes) {
return -1;
}
CFIndex axisCount = CFArrayGetCount(ctAxes.get());
CFIndex axisCount = CFArrayGetCount(ctAxes);
if (!coordinates || coordinateCount < axisCount) {
return axisCount;
}
@ -807,7 +814,7 @@ int SkTypeface_Mac::onGetVariationDesignPosition(
for (int i = 0; i < axisCount; ++i) {
CFDictionaryRef axisInfoDict;
if (!SkCFDynamicCast(CFArrayGetValueAtIndex(ctAxes.get(), i), &axisInfoDict, "Axis")) {
if (!SkCFDynamicCast(CFArrayGetValueAtIndex(ctAxes, i), &axisInfoDict, "Axis")) {
return -1;
}
@ -1119,15 +1126,15 @@ int SkTypeface_Mac::onCountGlyphs() const {
}
/** Creates a dictionary suitable for setting the axes on a CTFont. */
CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, const SkFontArguments& args) {
CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, CFArrayRef ctAxes,
const SkFontArguments& args) {
OpszVariation opsz;
constexpr const SkFourByteTag opszTag = SkSetFourByteTag('o','p','s','z');
SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct));
if (!ctAxes) {
return CTFontVariation();
}
CFIndex axisCount = CFArrayGetCount(ctAxes.get());
CFIndex axisCount = CFArrayGetCount(ctAxes);
// On 10.12 and later, this only returns non-default variations.
SkUniqueCFRef<CFDictionaryRef> oldCtVariation(CTFontCopyVariation(ct));
@ -1142,7 +1149,7 @@ CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, const SkFontArgum
for (int i = 0; i < axisCount; ++i) {
CFDictionaryRef axisInfoDict;
if (!SkCFDynamicCast(CFArrayGetValueAtIndex(ctAxes.get(), i), &axisInfoDict, "Axis")) {
if (!SkCFDynamicCast(CFArrayGetValueAtIndex(ctAxes, i), &axisInfoDict, "Axis")) {
return CTFontVariation();
}
@ -1224,7 +1231,9 @@ CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, const SkFontArgum
}
sk_sp<SkTypeface> SkTypeface_Mac::onMakeClone(const SkFontArguments& args) const {
CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(fFontRef.get(), args);
CTFontVariation ctVariation = SkCTVariationFromSkFontArguments(fFontRef.get(),
this->getVariationAxes(),
args);
SkUniqueCFRef<CTFontRef> ctVariant;
if (ctVariation.variation) {
@ -1273,11 +1282,11 @@ sk_sp<SkTypeface> SkTypeface_Mac::onMakeClone(const SkFontArguments& args) const
int SkTypeface_Mac::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
int parameterCount) const
{
SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
CFArrayRef ctAxes = this->getVariationAxes();
if (!ctAxes) {
return -1;
}
CFIndex axisCount = CFArrayGetCount(ctAxes.get());
CFIndex axisCount = CFArrayGetCount(ctAxes);
if (!parameters || parameterCount < axisCount) {
return axisCount;
@ -1289,7 +1298,7 @@ int SkTypeface_Mac::onGetVariationDesignParameters(SkFontParameters::Variation::
for (int i = 0; i < axisCount; ++i) {
CFDictionaryRef axisInfoDict;
if (!SkCFDynamicCast(CFArrayGetValueAtIndex(ctAxes.get(), i), &axisInfoDict, "Axis")) {
if (!SkCFDynamicCast(CFArrayGetValueAtIndex(ctAxes, i), &axisInfoDict, "Axis")) {
return -1;
}

View File

@ -55,7 +55,8 @@ struct CTFontVariation {
OpszVariation opsz;
};
CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, const SkFontArguments& args);
CTFontVariation SkCTVariationFromSkFontArguments(CTFontRef ct, CFArrayRef ctAxes,
const SkFontArguments& args);
SkUniqueCFRef<CTFontRef> SkCTFontCreateExactCopy(CTFontRef baseFont, CGFloat textSize,
OpszVariation opsz);
@ -91,6 +92,15 @@ public:
const OpszVariation fOpszVariation;
const bool fHasColorGlyphs;
/**
* CTFontCopyVariationAxes provides the localized name of all axes, making it very slow.
* This is unfortunate, its result is needed just to see if there are any axes at all.
* To avoid calling internal APIs cache the result of CTFontCopyVariationAxes.
* https://github.com/WebKit/WebKit/commit/1842365d413ed87868e7d33d4fad1691fa3a8129
* https://bugs.webkit.org/show_bug.cgi?id=232690
*/
CFArrayRef getVariationAxes() const;
protected:
int onGetUPEM() const override;
std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override;
@ -121,8 +131,10 @@ protected:
private:
mutable std::unique_ptr<SkStreamAsset> fStream;
mutable SkUniqueCFRef<CFArrayRef> fVariationAxes;
bool fIsFromStream;
mutable SkOnce fInitStream;
mutable SkOnce fInitVariationAxes;
using INHERITED = SkTypeface;
};