Reland "Reland "Test mac system font variations.""

This reverts commit 759f2613b5718a41672e77c4d091dafd503ae53a.

Reason for revert: Fix bzl build.

Original change's description:
> Revert "Reland "Test mac system font variations.""
>
> This reverts commit ba55be671d57cb94bb300cf925714be562976dde.
>
> Reason for revert: G3 roll
>
> (08:59:24) ERROR: third_party/skia/HEAD/BUILD:926:10: Compiling third_party/skia/HEAD/tests/TypefaceMacTest.cpp failed: (Exit 1) driver_is_not_gcc failed: error executing command third_party/crosstool/v18/stable/toolchain/bin/driver_is_not_gcc '-frandom-seed=blaze-out/k8-fastbuild/bin/third_party/skia/HEAD/_objs/dm/TypefaceMacTest.pic.o' -DSK_USE_FREETYPE_EMBOLDEN ... (remaining 383 argument(s) skipped).  [forge_remote_host=ixog19]
> third_party/skia/HEAD/tests/TypefaceMacTest.cpp:31:45: error: unknown type name 'CTFontRef'
>     auto makeSystemFont = [](float size) -> CTFontRef {
>                                             ^
> third_party/skia/HEAD/tests/TypefaceMacTest.cpp:33:46: error: use of undeclared identifier 'kCTFontUIFontSystem'
>         return CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, nullptr);
>                                              ^
> 2 errors generated.
>
> Original change's description:
> > Reland "Test mac system font variations."
> >
> > This reverts commit 4c0b9b90d63a155a7137dd1ebe08f74222051fb6.
> >
> > Reason for revert: Work around broken -Wrange-loop-analysis
> >
> > Original change's description:
> > > Revert "Test mac system font variations."
> > >
> > > This reverts commit a612dc77d75fda3c9d7fb26ce3e2cd916e8c76cb.
> > >
> > > Reason for revert: Breaking iOS builds.
> > >
> > > Original change's description:
> > > > Test mac system font variations.
> > > >
> > > > On macOS system fonts are special and sometimes have different behavior
> > > > from fonts generated from data. Add a test which exercises several
> > > > expectations about changing the variation on the system ui font.
> > > >
> > > > Bug: skia:10968
> > > > Change-Id: Ia10dfbf7f4f0ff099f9bfebf95481c95c7d3715f
> > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372218
> > > > Commit-Queue: Ben Wagner <bungeman@google.com>
> > > > Reviewed-by: Herb Derby <herb@google.com>
> > >
> > > TBR=bungeman@google.com,herb@google.com,drott@google.com
> > >
> > > Change-Id: Iccc05f25d827ab85c507b5f3bde936561349e2b8
> > > No-Presubmit: true
> > > No-Tree-Checks: true
> > > No-Try: true
> > > Bug: skia:10968
> > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372678
> > > Reviewed-by: Jim Van Verth <jvanverth@google.com>
> > > Commit-Queue: Jim Van Verth <jvanverth@google.com>
> >
> > # Not skipping CQ checks because this is a reland.
> >
> > Bug: skia:10968
> > Change-Id: Ifddc6c5ada335d97f7796df7f6ea10577f6bc252
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372776
> > Commit-Queue: Ben Wagner <bungeman@google.com>
> > Reviewed-by: Ben Wagner <bungeman@google.com>
>
> # Not skipping CQ checks because original CL landed > 1 day ago.
>
> Bug: skia:10968
> Change-Id: Ia5ff4ff827e3f79ff17b4d99458ffb45b7c36c58
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/373277
> Reviewed-by: Mike Klein <mtklein@google.com>
> Commit-Queue: Mike Klein <mtklein@google.com>

Bug: skia:10968
Change-Id: Ieb79128745dc934a7469d84b27a9e9f3306704df
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/373620
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 0bff535..f62fe24 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -492,6 +492,7 @@
     "src/ports/SkTypeface_mac_ct.cpp",
     "src/ports/SkTypeface_mac_ct.h",
   ]
+  sources_for_tests = [ "tests/TypefaceMacTest.cpp" ]
 
   if (is_mac) {
     frameworks = [
@@ -1962,6 +1963,7 @@
       ":flags",
       ":fontmgr_android_tests",
       ":fontmgr_fontconfig_tests",
+      ":fontmgr_mac_ct_tests",
       ":skia",
       ":test",
       ":tool_utils",
diff --git a/modules/canvaskit/compile_gm.sh b/modules/canvaskit/compile_gm.sh
index 16a960d..5604427 100755
--- a/modules/canvaskit/compile_gm.sh
+++ b/modules/canvaskit/compile_gm.sh
@@ -196,6 +196,7 @@
 "tests/EncodeTest.cpp:"\
 "tests/FontMgrAndroidParserTest.cpp:"\
 "tests/FontMgrFontConfigTest.cpp:"\
+"tests/TypefaceMacTest.cpp:"\
 "tests/SkVMTest.cpp:"
 
 # These tests do complex things with TestContexts, which is not easily supported for the WASM
diff --git a/public.bzl b/public.bzl
index d33a9bc..09daa00 100644
--- a/public.bzl
+++ b/public.bzl
@@ -634,6 +634,7 @@
         "gm/video_decoder.cpp",
         "tests/FontMgrAndroidParserTest.cpp",  # Android-only.
         "tests/FontMgrFontConfigTest.cpp",  # FontConfig-only.
+        "tests/TypefaceMacTest.cpp",  # CoreText-only.
         "tests/SkParagraphTest.cpp",  # Skipping tests for now.
         "tests/skia_test.cpp",  # Old main.
         "tools/gpu/d3d/*",
@@ -658,12 +659,12 @@
     return skia_glob(DM_SRCS_ALL) + skia_select(
         os_conditions,
         [
-            ["tests/FontMgrFontConfigTest.cpp"],
-            ["tests/FontMgrAndroidParserTest.cpp"],
-            [],  # iOS
+            ["tests/FontMgrFontConfigTest.cpp"],  # Unix
+            ["tests/FontMgrAndroidParserTest.cpp"],  # Android
+            ["tests/TypefaceMacTest.cpp"],  # iOS
             [],  # WASM
             [],  # Fuchsia
-            [],  # macOS
+            ["tests/TypefaceMacTest.cpp"],  # macOS
         ],
     )
 
diff --git a/tests/TypefaceMacTest.cpp b/tests/TypefaceMacTest.cpp
new file mode 100644
index 0000000..ff0c953
--- /dev/null
+++ b/tests/TypefaceMacTest.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkFontMgr.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkTypeface.h"
+#include "include/ports/SkTypeface_mac.h"
+#include "src/core/SkZip.h"
+#include "tests/Test.h"
+
+#include <stdarg.h>
+#include <string>
+#include <vector>
+
+#if 0
+static void SkMaybeDebugf(const char format[], ...) {
+    va_list args;
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
+}
+#else
+static void SkMaybeDebugf(const char format[], ...) { }
+#endif
+
+DEF_TEST(TypefaceMacVariation, reporter) {
+    auto makeSystemFont = [](float size) -> CTFontRef {
+        // kCTFontUIFontSystem, kCTFontUIFontMessage
+        return CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, nullptr);
+    };
+
+    auto tagToString = [](SkFourByteTag tag) -> std::string {
+      char buffer[5];
+      buffer[0] = (tag & 0xff000000) >> 24;
+      buffer[1] = (tag & 0xff0000) >> 16;
+      buffer[2] = (tag & 0xff00) >> 8;
+      buffer[3] = tag & 0xff;
+      buffer[4] = 0;
+      return std::string(buffer);
+    };
+
+    // This typeface has the issue.
+    sk_sp<SkTypeface> typeface(SkMakeTypefaceFromCTFont(makeSystemFont(30)));
+
+    // Since MakeFromFile creates at default size 12, these two are more comparable.
+    // The first one has the issue and the second does not.
+    //typeface = SkMakeTypefaceFromCTFont(makeSystemFont(12));
+    //typeface = SkTypeface::MakeFromFile("/System/Library/Fonts/SFNS.ttf");
+
+    // Setting the initial opsz <= min, the reported wght axis is strange, but draws the same?
+    //typeface = SkMakeTypefaceFromCTFont(makeSystemFont(17));
+    //typeface = SkMakeTypefaceFromCTFont(makeSystemFont(17.01));
+
+    // Setting the initial opsz >= max, the requested variation doesn't take effect?
+    //typeface = SkMakeTypefaceFromCTFont(makeSystemFont(95.9));
+    //typeface = SkMakeTypefaceFromCTFont(makeSystemFont(96));
+
+    if (!typeface) {
+        REPORTER_ASSERT(reporter, typeface);
+        return;
+    }
+    using Coordinate = SkFontArguments::VariationPosition::Coordinate;
+    using Axis = SkFontParameters::Variation::Axis;
+
+    const int originalPositionCount = typeface->getVariationDesignPosition(nullptr, 0);
+    std::vector<Coordinate> originalPosition(originalPositionCount);
+    const int retrievedOriginalPositionCount =
+        typeface->getVariationDesignPosition(originalPosition.data(), originalPosition.size());
+    if (!(retrievedOriginalPositionCount == originalPositionCount)) {
+        REPORTER_ASSERT(reporter, retrievedOriginalPositionCount == originalPositionCount);
+        return;
+    }
+
+    constexpr SkFourByteTag kGRADTag = SkSetFourByteTag('G', 'R', 'A', 'D');
+    constexpr SkFourByteTag kWghtTag = SkSetFourByteTag('w', 'g', 'h', 't');
+    constexpr SkFourByteTag kWdthTag = SkSetFourByteTag('w', 'd', 't', 'h');
+    constexpr SkFourByteTag kOpszTag = SkSetFourByteTag('o', 'p', 's', 'z');
+
+    SkMaybeDebugf("Original: ");
+    for (auto& originalCoordinate : originalPosition) {
+        SkMaybeDebugf("(%s: %f) ", tagToString(originalCoordinate.axis).c_str(),
+                                   originalCoordinate.value);
+    }
+    SkMaybeDebugf("\n\n");
+
+    const int originalAxisCount = typeface->getVariationDesignParameters(nullptr, 0);
+    std::vector<Axis> originalAxes(originalAxisCount);
+    const int returnedOriginalAxisCount =
+        typeface->getVariationDesignParameters(originalAxes.data(), originalAxes.size());
+    if (!(returnedOriginalAxisCount == originalAxisCount)) {
+        REPORTER_ASSERT(reporter, returnedOriginalAxisCount == originalAxisCount);
+        return;
+    }
+
+    for (bool omitOpsz : {false, true}) {
+    for (SkFourByteTag axisToBump : { 0u, kOpszTag, kWdthTag, kGRADTag }) {
+    for (float testCoordinate : {100, 300, 400, 500, 700, 900}) {
+        std::vector<Coordinate> expectedPosition;
+        std::vector<Coordinate> requestPosition;
+        SkMaybeDebugf("Request : ");
+        for (auto& originalCoordinate : originalPosition) {
+            float requestValue = originalCoordinate.value;
+            if (originalCoordinate.axis == kOpszTag && omitOpsz) {
+                SkMaybeDebugf("#%s: %f# ", tagToString(originalCoordinate.axis).c_str(),
+                                           requestValue);
+            } else {
+                if (originalCoordinate.axis == axisToBump) {
+                    // CoreText floats for the variation coordinates have limited precision.
+                    // 'opsz' sems to have more precision since it is set somewhat independently.
+                    //requestValue = nextafter(requestValue, HUGE_VALF); // Does not work.
+                    requestValue += requestValue / 1024.0f; // Expect at least 10 bits.
+                }
+                if (originalCoordinate.axis == kWghtTag) {
+                    requestValue = testCoordinate;
+                }
+                SkMaybeDebugf("(%s: %f) ", tagToString(originalCoordinate.axis).c_str(),
+                                           requestValue);
+                requestPosition.push_back({originalCoordinate.axis, requestValue});
+            }
+
+            float expectedValue = requestValue;
+            for (auto& originalAxis : originalAxes) {
+                if (originalAxis.tag == originalCoordinate.axis) {
+                    expectedValue = std::min(expectedValue, originalAxis.max);
+                    expectedValue = std::max(expectedValue, originalAxis.min);
+                }
+            }
+            expectedPosition.push_back({originalCoordinate.axis, expectedValue});
+        }
+        SkMaybeDebugf("\n");
+
+        SkMaybeDebugf("Expected: ");
+        for (auto& expectedCoordinate : expectedPosition) {
+             SkMaybeDebugf("(%s: %f) ", tagToString(expectedCoordinate.axis).c_str(),
+                                        expectedCoordinate.value);
+        }
+        SkMaybeDebugf("\n");
+
+        SkFontArguments::VariationPosition variationPosition =
+            { requestPosition.data(), (int)requestPosition.size() };
+        sk_sp<SkTypeface> cloneTypeface(
+            typeface->makeClone(SkFontArguments().setVariationDesignPosition(variationPosition)));
+
+        const int cloneAxisCount = cloneTypeface->getVariationDesignPosition(nullptr, 0);
+        std::vector<Coordinate> clonePosition(cloneAxisCount);
+        const int retrievedCloneAxisCount =
+            cloneTypeface->getVariationDesignPosition(clonePosition.data(), clonePosition.size());
+        if (!(retrievedCloneAxisCount == cloneAxisCount)) {
+            REPORTER_ASSERT(reporter, retrievedCloneAxisCount == cloneAxisCount);
+            continue;
+        }
+
+        SkMaybeDebugf("Result  : ");
+        for (auto& cloneCoordinate : clonePosition) {
+             SkMaybeDebugf("(%s: %f) ", tagToString(cloneCoordinate.axis).c_str(),
+                                        cloneCoordinate.value);
+        }
+        SkMaybeDebugf("\n");
+
+        if (clonePosition.size() != expectedPosition.size()) {
+            REPORTER_ASSERT(reporter, clonePosition.size() == expectedPosition.size());
+            continue;
+        }
+
+        auto compareCoordinate = [](const Coordinate& a, const Coordinate& b) -> bool {
+            return a.axis < b.axis;
+        };
+        std::sort(clonePosition.begin(), clonePosition.end(), compareCoordinate);
+        std::sort(expectedPosition.begin(), expectedPosition.end(), compareCoordinate);
+        for (const auto&& [clone, expected] : SkMakeZip(clonePosition, expectedPosition)) {
+            REPORTER_ASSERT(reporter, clone.axis == expected.axis);
+            REPORTER_ASSERT(reporter, clone.value == expected.value);
+        }
+
+        SkMaybeDebugf("\n");
+    }
+    }
+    }
+}