Use FontWeight symbols when available on Mac.
Newer versions of macOS have NSFontWeightXXX symbols and iOS has
UIFontWeightXXX symbols to provide the conversion between [-1, 1]
CTFontDescriptor weights and [0, 1000] CSS weights. Currently the
values these symbols provide are hard coded (for expediency), but the
symbols should be used when available since the values may change
without notice.
Change-Id: I0875c6a96c5b14e456f91bccf7a84f0306a3d63a
Reviewed-on: https://skia-review.googlesource.com/10163
Reviewed-by: Mike Klein <mtklein@chromium.org>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index af6bbda..3364148 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -700,6 +700,8 @@
"src/ports/SkImageGeneratorCG.cpp",
]
libs += [
+ # AppKit symbols NSFontWeightXXX may be dlsym'ed.
+ "AppKit.framework",
"ApplicationServices.framework",
"OpenGL.framework",
]
@@ -718,6 +720,9 @@
"CoreText.framework",
"ImageIO.framework",
"MobileCoreServices.framework",
+
+ # UIKit symbols UIFontWeightXXX may be dlsym'ed.
+ "UIKit.framework",
]
}
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index ca236a3..176a20c 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -46,6 +46,8 @@
#include "SkTypeface_mac.h"
#include "SkUtils.h"
+#include <dlfcn.h>
+
// Experimental code to use a global lock whenever we access CG, to see if this reduces
// crashes in Chrome
#define USE_GLOBAL_MUTEX_FOR_CG_ACCESS
@@ -311,6 +313,56 @@
CGFloat operator()(CGFloat s) { return s; }
};
+/** Returns the [-1, 1] CTFontDescriptor weights for the
+ * <0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000> CSS weights.
+ *
+ * It is assumed that the values will be interpolated linearly between these points.
+ * NSFontWeightXXX were added in 10.11, appear in 10.10, but do not appear in 10.9.
+ * The actual values appear to be stable, but they may change in the future without notice.
+ */
+static CGFloat(&get_NSFontWeight_mapping())[11] {
+
+ // Declarations in <AppKit/AppKit.h> on macOS, <UIKit/UIKit.h> on iOS
+#ifdef SK_BUILD_FOR_MAC
+# define SK_KIT_FONT_WEIGHT_PREFIX "NS"
+#endif
+#ifdef SK_BUILD_FOR_IOS
+# define SK_KIT_FONT_WEIGHT_PREFIX "UI"
+#endif
+ static constexpr struct {
+ CGFloat defaultValue;
+ const char* name;
+ } nsFontWeightLoaderInfos[] = {
+ { -0.80f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightUltraLight" },
+ { -0.60f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightThin" },
+ { -0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightLight" },
+ { 0.00f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightRegular" },
+ { 0.23f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightMedium" },
+ { 0.30f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightSemibold" },
+ { 0.40f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBold" },
+ { 0.56f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightHeavy" },
+ { 0.62f, SK_KIT_FONT_WEIGHT_PREFIX "FontWeightBlack" },
+ };
+
+ static_assert(SK_ARRAY_COUNT(nsFontWeightLoaderInfos) == 9, "");
+ static CGFloat nsFontWeights[11];
+ static SkOnce once;
+ once([&] {
+ size_t i = 0;
+ nsFontWeights[i++] = -1.00;
+ for (const auto& nsFontWeightLoaderInfo : nsFontWeightLoaderInfos) {
+ void* nsFontWeightValuePtr = dlsym(RTLD_DEFAULT, nsFontWeightLoaderInfo.name);
+ if (nsFontWeightValuePtr) {
+ nsFontWeights[i++] = *(static_cast<CGFloat*>(nsFontWeightValuePtr));
+ } else {
+ nsFontWeights[i++] = nsFontWeightLoaderInfo.defaultValue;
+ }
+ }
+ nsFontWeights[i++] = 1.00;
+ });
+ return nsFontWeights;
+}
+
/** Convert the [0, 1000] CSS weight to [-1, 1] CTFontDescriptor weight (for system fonts).
*
* The -1 to 1 weights reported by CTFontDescriptors have different mappings depending on if the
@@ -322,31 +374,15 @@
// Note that Mac supports the old OS2 version A so 0 through 10 are as if multiplied by 100.
// However, on this end we can't tell, so this is ignored.
- /** This mapping for native fonts is determined by running the following in an .mm file
- * #include <AppKit/AppKit>
- * printf("{ 100, % #.2f },\n", NSFontWeightUltraLight);
- * printf("{ 200, % #.2f },\n", NSFontWeightThin);
- * printf("{ 300, % #.2f },\n", NSFontWeightLight);
- * printf("{ 400, % #.2f },\n", NSFontWeightRegular);
- * printf("{ 500, % #.2f },\n", NSFontWeightMedium);
- * printf("{ 600, % #.2f },\n", NSFontWeightSemibold);
- * printf("{ 700, % #.2f },\n", NSFontWeightBold);
- * printf("{ 800, % #.2f },\n", NSFontWeightHeavy);
- * printf("{ 900, % #.2f },\n", NSFontWeightBlack);
- */
- static constexpr Interpolator::Mapping nativeWeightMappings[] = {
- { 0, -1.00 },
- { 100, -0.80 },
- { 200, -0.60 },
- { 300, -0.40 },
- { 400, 0.00 },
- { 500, 0.23 },
- { 600, 0.30 },
- { 700, 0.40 },
- { 800, 0.56 },
- { 900, 0.62 },
- { 1000, 1.00 },
- };
+ static Interpolator::Mapping nativeWeightMappings[11];
+ static SkOnce once;
+ once([&] {
+ CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
+ for (int i = 0; i < 11; ++i) {
+ nativeWeightMappings[i].src_val = i * 100;
+ nativeWeightMappings[i].dst_val = nsFontWeights[i];
+ }
+ });
static constexpr Interpolator nativeInterpolator(
nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));
@@ -385,31 +421,15 @@
static constexpr Interpolator dataProviderInterpolator(
dataProviderWeightMappings, SK_ARRAY_COUNT(dataProviderWeightMappings));
- /** This mapping for native fonts is determined by running the following in an .mm file
- * #include <AppKit/AppKit>
- * printf("{ % #.2f, 100 },\n", NSFontWeightUltraLight);
- * printf("{ % #.2f, 200 },\n", NSFontWeightThin);
- * printf("{ % #.2f, 300 },\n", NSFontWeightLight);
- * printf("{ % #.2f, 400 },\n", NSFontWeightRegular);
- * printf("{ % #.2f, 500 },\n", NSFontWeightMedium);
- * printf("{ % #.2f, 600 },\n", NSFontWeightSemibold);
- * printf("{ % #.2f, 700 },\n", NSFontWeightBold);
- * printf("{ % #.2f, 800 },\n", NSFontWeightHeavy);
- * printf("{ % #.2f, 900 },\n", NSFontWeightBlack);
- */
- static constexpr Interpolator::Mapping nativeWeightMappings[] = {
- { -1.00, 0 },
- { -0.80, 100 },
- { -0.60, 200 },
- { -0.40, 300 },
- { 0.00, 400 },
- { 0.23, 500 },
- { 0.30, 600 },
- { 0.40, 700 },
- { 0.56, 800 },
- { 0.62, 900 },
- { 1.00, 1000 },
- };
+ static Interpolator::Mapping nativeWeightMappings[11];
+ static SkOnce once;
+ once([&] {
+ CGFloat(&nsFontWeights)[11] = get_NSFontWeight_mapping();
+ for (int i = 0; i < 11; ++i) {
+ nativeWeightMappings[i].src_val = nsFontWeights[i];
+ nativeWeightMappings[i].dst_val = i * 100;
+ }
+ });
static constexpr Interpolator nativeInterpolator(
nativeWeightMappings, SK_ARRAY_COUNT(nativeWeightMappings));