Add more variation support on Mac.

With the recent transition to creating fonts from data as CTFonts and
dropping variation support from macOS 10.11 and earlier, it is now
possible to reliably make variation clones and get the axis information.

Change-Id: Ia9a0922ac94a29e1508d2e74d4ce973751044866
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/259421
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/resources/fonts/Distortable.ttf b/resources/fonts/Distortable.ttf
index 95f30c3..c604d3a 100644
--- a/resources/fonts/Distortable.ttf
+++ b/resources/fonts/Distortable.ttf
Binary files differ
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 7650b04..3089251 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -741,13 +741,8 @@
     int onCountGlyphs() const override;
     void getPostScriptGlyphNames(SkString*) const override {}
     int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
-                                       int parameterCount) const override
-    {
-        return -1;
-    }
-    sk_sp<SkTypeface> onMakeClone(const SkFontArguments&) const override {
-        return nullptr;
-    }
+                                       int parameterCount) const override;
+    sk_sp<SkTypeface> onMakeClone(const SkFontArguments&) const override;
 
     void* onGetCTFontRef() const override { return (void*)fFontRef.get(); }
 
@@ -2486,6 +2481,219 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
+namespace {
+
+struct CTFontVariation {
+    SkUniqueCFRef<CFDictionaryRef> dict;
+    OpszVariation opsz;
+};
+
+/** Creates a dictionary suitable for setting the axes on a CTFont. */
+static CTFontVariation ctvariation_from_skfontarguments(CTFontRef ct,
+                                                        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());
+
+    const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
+
+    SkUniqueCFRef<CFMutableDictionaryRef> dict(
+            CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
+                                      &kCFTypeDictionaryKeyCallBacks,
+                                      &kCFTypeDictionaryValueCallBacks));
+
+    for (int i = 0; i < axisCount; ++i) {
+        CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+        if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+            return CTFontVariation();
+        }
+        CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+        CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
+        if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+            return CTFontVariation();
+        }
+        CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+        int64_t tagLong;
+        if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+            return CTFontVariation();
+        }
+
+        // The variation axes can be set to any value, but cg will effectively pin them.
+        // Pin them here to normalize.
+        CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+        CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
+        CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
+        if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
+            !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
+            !def || CFGetTypeID(def) != CFNumberGetTypeID())
+        {
+            return CTFontVariation();
+        }
+        CFNumberRef minNumber = static_cast<CFNumberRef>(min);
+        CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
+        CFNumberRef defNumber = static_cast<CFNumberRef>(def);
+        double minDouble;
+        double maxDouble;
+        double defDouble;
+        if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
+            !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
+            !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
+        {
+            return CTFontVariation();
+        }
+
+        double value = defDouble;
+        // The position may be over specified. If there are multiple values for a given axis,
+        // use the last one since that's what css-fonts-4 requires.
+        for (int j = position.coordinateCount; j --> 0;) {
+            if (position.coordinates[j].axis == tagLong) {
+                value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
+                               minDouble, maxDouble);
+                if (tagLong == opszTag) {
+                    opsz.isSet = true;
+                }
+                break;
+            }
+        }
+        if (tagLong == opszTag) {
+            opsz.value = value;
+        }
+        SkUniqueCFRef<CFNumberRef> valueNumber(
+            CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
+        CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
+    }
+    return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
+}
+
+/** Creates a dictionary suitable for setting the axes on a CTFont. */
+static CTFontVariation ctvariation_from_skfontdata(CTFontRef ct, SkFontData* fontData) {
+    // In macOS 10.15 CTFontCreate* overrides any 'opsz' variation with the 'size'.
+    // Track the 'opsz' and return it, since it is an out of band axis.
+    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());
+    if (0 == axisCount || axisCount != fontData->getAxisCount()) {
+        return CTFontVariation();
+    }
+
+    SkUniqueCFRef<CFMutableDictionaryRef> dict(
+            CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
+                                      &kCFTypeDictionaryKeyCallBacks,
+                                      &kCFTypeDictionaryValueCallBacks));
+
+    for (int i = 0; i < fontData->getAxisCount(); ++i) {
+        CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+        if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+            return CTFontVariation();
+        }
+        CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+        CFTypeRef tag = CFDictionaryGetValue(axisInfoDict,
+                                             kCTFontVariationAxisIdentifierKey);
+        if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+            return CTFontVariation();
+        }
+        CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+        int64_t tagLong;
+        if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+            return CTFontVariation();
+        }
+
+        // The variation axes can be set to any value, but cg will effectively pin them.
+        // Pin them here to normalize.
+        CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+        CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
+        if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
+            !max || CFGetTypeID(max) != CFNumberGetTypeID())
+        {
+            return CTFontVariation();
+        }
+        CFNumberRef minNumber = static_cast<CFNumberRef>(min);
+        CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
+        double minDouble;
+        double maxDouble;
+        if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
+            !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
+        {
+            return CTFontVariation();
+        }
+        double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
+
+        if (tagLong == opszTag) {
+            opsz.isSet = true;
+            opsz.value = value;
+        }
+
+        SkUniqueCFRef<CFNumberRef> valueNumber(
+                CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
+        CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
+    }
+    return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
+}
+
+static sk_sp<SkData> skdata_from_skstreamasset(std::unique_ptr<SkStreamAsset> stream) {
+    size_t size = stream->getLength();
+    if (const void* base = stream->getMemoryBase()) {
+        return SkData::MakeWithProc(base, size,
+                                    [](const void*, void* ctx) -> void {
+                                        delete (SkStreamAsset*)ctx;
+                                    }, stream.release());
+    }
+    return SkData::MakeFromStream(stream.get(), size);
+}
+
+static SkUniqueCFRef<CFDataRef> cfdata_from_skdata(sk_sp<SkData> data) {
+    void const * const addr = data->data();
+    size_t const size = data->size();
+
+    CFAllocatorContext ctx = {
+        0, // CFIndex version
+        data.release(), // void* info
+        nullptr, // const void *(*retain)(const void *info);
+        nullptr, // void (*release)(const void *info);
+        nullptr, // CFStringRef (*copyDescription)(const void *info);
+        nullptr, // void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
+        nullptr, // void*(*reallocate)(void* ptr,CFIndex newsize,CFOptionFlags hint,void* info);
+        [](void*,void* info) -> void { // void (*deallocate)(void *ptr, void *info);
+            SkASSERT(info);
+            ((SkData*)info)->unref();
+        },
+        nullptr, // CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
+    };
+    SkUniqueCFRef<CFAllocatorRef> alloc(CFAllocatorCreate(kCFAllocatorDefault, &ctx));
+    return SkUniqueCFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(
+            kCFAllocatorDefault, (const UInt8 *)addr, size, alloc.get()));
+}
+
+static SkUniqueCFRef<CTFontRef> ctfont_from_skdata(sk_sp<SkData> data, int ttcIndex) {
+    // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
+    if (ttcIndex != 0) {
+        return nullptr;
+    }
+
+    SkUniqueCFRef<CFDataRef> cfData(cfdata_from_skdata(std::move(data)));
+
+    SkUniqueCFRef<CTFontDescriptorRef> desc(
+            CTFontManagerCreateFontDescriptorFromData(cfData.get()));
+    if (!desc) {
+        return nullptr;
+    }
+    return SkUniqueCFRef<CTFontRef>(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
+}
+
 static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) {
     SkUniqueCFRef<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name));
     if (!ref) {
@@ -2574,6 +2782,109 @@
     }
 };
 
+} // namespace
+
+sk_sp<SkTypeface> SkTypeface_Mac::onMakeClone(const SkFontArguments& args) const {
+    CTFontVariation ctVariation = ctvariation_from_skfontarguments(fFontRef.get(), args);
+
+    SkUniqueCFRef<CTFontRef> ctVariant;
+    if (ctVariation.dict) {
+        SkUniqueCFRef<CFMutableDictionaryRef> attributes(
+                CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks));
+        CFDictionaryAddValue(attributes.get(),
+                             kCTFontVariationAttribute, ctVariation.dict.get());
+        SkUniqueCFRef<CTFontDescriptorRef> varDesc(
+                CTFontDescriptorCreateWithAttributes(attributes.get()));
+        ctVariant.reset(CTFontCreateCopyWithAttributes(fFontRef.get(), 0, nullptr, varDesc.get()));
+    } else {
+        ctVariant.reset((CTFontRef)CFRetain(fFontRef.get()));
+    }
+    if (!ctVariant) {
+        return nullptr;
+    }
+
+    return create_from_CTFontRef(std::move(ctVariant), nullptr, ctVariation.opsz,
+                                 fStream ? fStream->duplicate() : nullptr);
+}
+
+int SkTypeface_Mac::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
+                                                   int parameterCount) const
+{
+    SkUniqueCFRef<CFArrayRef> ctAxes(CTFontCopyVariationAxes(fFontRef.get()));
+    if (!ctAxes) {
+        return -1;
+    }
+    CFIndex axisCount = CFArrayGetCount(ctAxes.get());
+
+    if (!parameters || parameterCount < axisCount) {
+        return axisCount;
+    }
+
+    // Added in 10.13
+    CFStringRef* kCTFontVariationAxisHiddenKeyPtr =
+            static_cast<CFStringRef*>(dlsym(RTLD_DEFAULT, "kCTFontVariationAxisHiddenKey"));
+
+    for (int i = 0; i < axisCount; ++i) {
+        CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
+        if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
+            return -1;
+        }
+        CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
+
+        CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
+        if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
+            return -1;
+        }
+        CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
+        int64_t tagLong;
+        if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
+            return -1;
+        }
+
+        CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
+        CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
+        CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
+        if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
+            !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
+            !def || CFGetTypeID(def) != CFNumberGetTypeID())
+        {
+            return -1;
+        }
+        CFNumberRef minNumber = static_cast<CFNumberRef>(min);
+        CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
+        CFNumberRef defNumber = static_cast<CFNumberRef>(def);
+        double minDouble;
+        double maxDouble;
+        double defDouble;
+        if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
+            !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
+            !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
+        {
+            return -1;
+        }
+
+        SkFontParameters::Variation::Axis& skAxis = parameters[i];
+        skAxis.tag = tagLong;
+        skAxis.min = minDouble;
+        skAxis.max = maxDouble;
+        skAxis.def = defDouble;
+        skAxis.setHidden(false);
+        if (kCTFontVariationAxisHiddenKeyPtr) {
+            CFTypeRef hidden = CFDictionaryGetValue(axisInfoDict,*kCTFontVariationAxisHiddenKeyPtr);
+            if (hidden) {
+                if (CFGetTypeID(hidden) != CFBooleanGetTypeID()) {
+                    return -1;
+                }
+                CFBooleanRef hiddenBoolean = static_cast<CFBooleanRef>(hidden);
+                skAxis.setHidden(CFBooleanGetValue(hiddenBoolean));
+            }
+        }
+    }
+    return axisCount;
+}
+
 class SkFontMgr_Mac : public SkFontMgr {
     SkUniqueCFRef<CFArrayRef> fNames;
     int fCount;
@@ -2707,145 +3018,6 @@
         return create_from_CTFontRef(std::move(ct), nullptr, OpszVariation(), std::move(stream));
     }
 
-    struct CTFontVariation {
-        SkUniqueCFRef<CFDictionaryRef> dict;
-        OpszVariation opsz;
-    };
-
-    /** Creates a dictionary suitable for setting the axes on a CTFont. */
-    static CTFontVariation ctvariation_from_skfontarguments(CTFontRef ct,
-                                                            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());
-
-        const SkFontArguments::VariationPosition position = args.getVariationDesignPosition();
-
-        SkUniqueCFRef<CFMutableDictionaryRef> dict(
-                CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
-                                          &kCFTypeDictionaryKeyCallBacks,
-                                          &kCFTypeDictionaryValueCallBacks));
-
-        for (int i = 0; i < axisCount; ++i) {
-            CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
-            if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
-                return CTFontVariation();
-            }
-            CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
-            CFTypeRef tag = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisIdentifierKey);
-            if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
-                return CTFontVariation();
-            }
-            CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
-            int64_t tagLong;
-            if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
-                return CTFontVariation();
-            }
-
-            // The variation axes can be set to any value, but cg will effectively pin them.
-            // Pin them here to normalize.
-            CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
-            CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
-            CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisDefaultValueKey);
-            if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
-                !max || CFGetTypeID(max) != CFNumberGetTypeID() ||
-                !def || CFGetTypeID(def) != CFNumberGetTypeID())
-            {
-                return CTFontVariation();
-            }
-            CFNumberRef minNumber = static_cast<CFNumberRef>(min);
-            CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
-            CFNumberRef defNumber = static_cast<CFNumberRef>(def);
-            double minDouble;
-            double maxDouble;
-            double defDouble;
-            if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
-                !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) ||
-                !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble))
-            {
-                return CTFontVariation();
-            }
-
-            double value = defDouble;
-            // The position may be over specified. If there are multiple values for a given axis,
-            // use the last one since that's what css-fonts-4 requires.
-            for (int j = position.coordinateCount; j --> 0;) {
-                if (position.coordinates[j].axis == tagLong) {
-                    value = SkTPin(SkScalarToDouble(position.coordinates[j].value),
-                                   minDouble, maxDouble);
-                    if (tagLong == opszTag) {
-                        opsz.isSet = true;
-                    }
-                    break;
-                }
-            }
-            if (tagLong == opszTag) {
-                opsz.value = value;
-            }
-            SkUniqueCFRef<CFNumberRef> valueNumber(
-                CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
-            CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
-        }
-        return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
-    }
-
-    static sk_sp<SkData> skdata_from_skstreamasset(std::unique_ptr<SkStreamAsset> stream) {
-        size_t size = stream->getLength();
-        if (const void* base = stream->getMemoryBase()) {
-            return SkData::MakeWithProc(base, size,
-                                        [](const void*, void* ctx) -> void {
-                                            delete (SkStreamAsset*)ctx;
-                                        }, stream.release());
-        }
-        return SkData::MakeFromStream(stream.get(), size);
-    }
-
-    static SkUniqueCFRef<CFDataRef> cfdata_from_skdata(sk_sp<SkData> data) {
-        void const * const addr = data->data();
-        size_t const size = data->size();
-
-        CFAllocatorContext ctx = {
-            0, // CFIndex version
-            data.release(), // void* info
-            nullptr, // const void *(*retain)(const void *info);
-            nullptr, // void (*release)(const void *info);
-            nullptr, // CFStringRef (*copyDescription)(const void *info);
-            nullptr, // void * (*allocate)(CFIndex size, CFOptionFlags hint, void *info);
-            nullptr, // void*(*reallocate)(void* ptr,CFIndex newsize,CFOptionFlags hint,void* info);
-            [](void*,void* info) -> void { // void (*deallocate)(void *ptr, void *info);
-                SkASSERT(info);
-                ((SkData*)info)->unref();
-            },
-            nullptr, // CFIndex (*preferredSize)(CFIndex size, CFOptionFlags hint, void *info);
-        };
-        SkUniqueCFRef<CFAllocatorRef> alloc(CFAllocatorCreate(kCFAllocatorDefault, &ctx));
-        return SkUniqueCFRef<CFDataRef>(CFDataCreateWithBytesNoCopy(
-                kCFAllocatorDefault, (const UInt8 *)addr, size, alloc.get()));
-    }
-
-    static SkUniqueCFRef<CTFontRef> ctfont_from_skdata(sk_sp<SkData> data, int ttcIndex) {
-        // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
-        if (ttcIndex != 0) {
-            return nullptr;
-        }
-
-        SkUniqueCFRef<CFDataRef> cfData(cfdata_from_skdata(std::move(data)));
-
-        SkUniqueCFRef<CTFontDescriptorRef> desc(
-                CTFontManagerCreateFontDescriptorFromData(cfData.get()));
-        if (!desc) {
-            return nullptr;
-        }
-        return SkUniqueCFRef<CTFontRef>(CTFontCreateWithFontDescriptor(desc.get(), 0, nullptr));
-    }
-
     sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset> stream,
                                            const SkFontArguments& args) const override
     {
@@ -2888,77 +3060,6 @@
                                      std::move(stream));
     }
 
-    /** Creates a dictionary suitable for setting the axes on a CTFont. */
-    static CTFontVariation ctvariation_from_skfontdata(CTFontRef ct, SkFontData* fontData) {
-        // In macOS 10.15 CTFontCreate* overrides any 'opsz' variation with the 'size'.
-        // Track the 'opsz' and return it, since it is an out of band axis.
-        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());
-        if (0 == axisCount || axisCount != fontData->getAxisCount()) {
-            return CTFontVariation();
-        }
-
-        SkUniqueCFRef<CFMutableDictionaryRef> dict(
-                CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount,
-                                          &kCFTypeDictionaryKeyCallBacks,
-                                          &kCFTypeDictionaryValueCallBacks));
-
-        for (int i = 0; i < fontData->getAxisCount(); ++i) {
-            CFTypeRef axisInfo = CFArrayGetValueAtIndex(ctAxes.get(), i);
-            if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) {
-                return CTFontVariation();
-            }
-            CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo);
-
-            CFTypeRef tag = CFDictionaryGetValue(axisInfoDict,
-                                                 kCTFontVariationAxisIdentifierKey);
-            if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) {
-                return CTFontVariation();
-            }
-            CFNumberRef tagNumber = static_cast<CFNumberRef>(tag);
-            int64_t tagLong;
-            if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) {
-                return CTFontVariation();
-            }
-
-            // The variation axes can be set to any value, but cg will effectively pin them.
-            // Pin them here to normalize.
-            CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMinimumValueKey);
-            CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCTFontVariationAxisMaximumValueKey);
-            if (!min || CFGetTypeID(min) != CFNumberGetTypeID() ||
-                !max || CFGetTypeID(max) != CFNumberGetTypeID())
-            {
-                return CTFontVariation();
-            }
-            CFNumberRef minNumber = static_cast<CFNumberRef>(min);
-            CFNumberRef maxNumber = static_cast<CFNumberRef>(max);
-            double minDouble;
-            double maxDouble;
-            if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) ||
-                !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble))
-            {
-                return CTFontVariation();
-            }
-            double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble);
-
-            if (tagLong == opszTag) {
-                opsz.isSet = true;
-                opsz.value = value;
-            }
-
-            SkUniqueCFRef<CFNumberRef> valueNumber(
-                    CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value));
-            CFDictionaryAddValue(dict.get(), tagNumber, valueNumber.get());
-        }
-        return { SkUniqueCFRef<CFDictionaryRef>(std::move(dict)), opsz };
-    }
     sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData> fontData) const override {
         // TODO: Use CTFontManagerCreateFontDescriptorsFromData when available.
         if (fontData->getIndex() != 0) {
diff --git a/tests/TypefaceTest.cpp b/tests/TypefaceTest.cpp
index a389c8f..b21284a6 100644
--- a/tests/TypefaceTest.cpp
+++ b/tests/TypefaceTest.cpp
@@ -160,18 +160,20 @@
     sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(distortable), params);
 
     if (!typeface) {
-        // Not all SkFontMgr can makeFromStream().
-        return;
+        return;  // Not all SkFontMgr can makeFromStream().
     }
 
     int count = typeface->getVariationDesignPosition(nullptr, 0);
     if (count == -1) {
-        return;
+        return;  // The number of axes is unknown.
     }
     REPORTER_ASSERT(reporter, count == numberOfAxesInDistortable);
 
     SkFontArguments::VariationPosition::Coordinate positionRead[numberOfAxesInDistortable];
     count = typeface->getVariationDesignPosition(positionRead, SK_ARRAY_COUNT(positionRead));
+    if (count == -1) {
+        return;  // The position cannot be determined.
+    }
     REPORTER_ASSERT(reporter, count == SK_ARRAY_COUNT(positionRead));
 
     REPORTER_ASSERT(reporter, positionRead[0].axis == position[1].axis);
@@ -179,7 +181,8 @@
     // Convert to fixed for "almost equal".
     SkFixed fixedRead = SkScalarToFixed(positionRead[0].value);
     SkFixed fixedOriginal = SkScalarToFixed(position[1].value);
-    REPORTER_ASSERT(reporter, SkTAbs(fixedRead - fixedOriginal) < 2);
+    REPORTER_ASSERT(reporter, SkTAbs(fixedRead - fixedOriginal) < 2 || // variation set correctly
+                              SkTAbs(fixedRead - SK_Fixed1    ) < 2);  // variation remained default
 }
 
 DEF_TEST(TypefaceVariationIndex, reporter) {
@@ -241,7 +244,7 @@
     constexpr SkScalar minAxisInDistortable = 0.5;
     constexpr SkScalar defAxisInDistortable = 1;
     constexpr SkScalar maxAxisInDistortable = 2;
-    constexpr bool axisIsHiddenInDistortable = false;
+    constexpr bool axisIsHiddenInDistortable = true;
 
     sk_sp<SkFontMgr> fm = SkFontMgr::RefDefault();
 
@@ -249,8 +252,7 @@
     sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(distortable), params);
 
     if (!typeface) {
-        // Not all SkFontMgr can makeFromStream().
-        return;
+        return;  // Not all SkFontMgr can makeFromStream().
     }
 
     SkFontParameters::Variation::Axis parameter[numberOfAxesInDistortable];
@@ -264,8 +266,10 @@
     REPORTER_ASSERT(reporter, parameter[0].def == defAxisInDistortable);
     REPORTER_ASSERT(reporter, parameter[0].max == maxAxisInDistortable);
     REPORTER_ASSERT(reporter, parameter[0].tag == SkSetFourByteTag('w','g','h','t'));
-    REPORTER_ASSERT(reporter, parameter[0].isHidden() == axisIsHiddenInDistortable);
-
+    // This seems silly, but allows MSAN to ensure that isHidden is initialized.
+    // With GDI or before macOS 10.12, Win10, or FreeType 2.8.1 the API for hidden is missing.
+    REPORTER_ASSERT(reporter, parameter[0].isHidden() == axisIsHiddenInDistortable ||
+                              parameter[0].isHidden() == false);
 }
 
 static bool count_proc(SkTypeface* face, void* ctx) {