diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2023-08-06 04:57:20 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2023-08-21 04:11:57 +0300 |
commit | 5c15c883a4783641f7e71a6a1f440209965eb64f (patch) | |
tree | 22506f26940deb3916b9a320e7d4485f2f58ecc1 | |
parent | 847af2a1ce67cc2ac0db1252f41ee99ff724b05b (diff) | |
download | libass-5c15c883a4783641f7e71a6a1f440209965eb64f.tar.bz2 libass-5c15c883a4783641f7e71a6a1f440209965eb64f.tar.xz |
Support Core Text on Mac OS X 10.5
Based on the logic in HarfBuzz's hb-coretext. See:
1. https://github.com/harfbuzz/harfbuzz/pull/952
2. https://github.com/harfbuzz/harfbuzz/pull/1180
Core Text was introduced in 10.5, so this is as far back as we can go.
Tested on ppc32 10.5.8 in:
https://github.com/libass/libass/issues/595#issuecomment-1324548120
Manrope Regular failed to be selected by full name,
but other fonts (including other faces of Manrope) worked fine,
so this should be good enough to avoid requiring Fontconfig.
I have tested that the code in the 10.5-compatible branch still works
on 10.13.6 (the newest macOS instance I have access to), but the API
involved is officially "deprecated" and produces deprecation warnings
during compilation unless the build's deployment target is set to a
version below 10.8. In addition, it's not unimaginable that it might
work worse in some specific situations now or in the future: for example,
it uses FSRef, which, according to the docs, is "designed to work
with 32-bit inode numbers", which "may result in performance issues"
on newer systems. As far as I'm aware, Apple doesn't tend to remove
APIs/ABIs completely except when combined with architecture changes,
but it seems the overall safest course of action is:
* to prefer the newer API if it is available at runtime,
* and to avoid referencing the older API at all
if it's known at compile-time to be unnecessary.
To nearly maximize build-environment compatibility,
use Availability.h and CHECK_AVAILABLE:
* Recent versions of Apple's compiler support __builtin_available for
OS version detection, and so does modern non-Apple Clang. This is what
Apple recommends nowadays. However, none of Apple's official compilers
on macOS up to 10.10 have had this builtin, and no third-party
compilers besides Clang have ever had it. Non-Clang compilers may
have issues with Apple's more recent SDK headers anyway, but they're
perfectly viable with older SDK releases and all the more likely
to be used when the build is being performed on an older machine,
e. g. when targeting that same machine, which is precisely where
the 10.5-compatible code is most likely to be relevant.
On 10.5 or nearby versions, the build is most likely to use one of
Apple's old compilers or a custom-built modern upstream GCC.
Apple's older method of checking for availability at runtime
is to check whether the symbol's address is NULL, which works
in all of Apple's compilers and in upstream Clang and GCC.
We implement this in our CHECK_AVAILABLE macro.
* There are multiple ways to determine whether the newer symbol
is declared at all. To keep it simple, avoid a configure check
and stick to a simple macro check.
In older versions of Apple's SDK, Core Text headers have reacted to
"Mac OS X version max allowed" control-knob macros and marked newer
APIs "unavailable" (making any use of them a compilation error) even
if they were known to that SDK. However, the exact macros differ
between SDK versions, and this mechanism (unlike the "version min
required") has apparently never been exposed in compiler/IDE knobs
and possibly not publicized at all. Newer SDKs also no longer mark
symbols unavailable in any case.
So do the simplest thing and just check for the existence
of a macro that was introduced in the same SDK version.
* In 10.5-10.6 SDKs, Core Text used AvailabilityMacros.h and its
MAC_OS_X_VERSION_MIN_REQUIRED; in later versions, it switched to
Availability.h and its __MAC_OS_X_VERSION_MIN_REQUIRED with two
leading underscores. Both headers are available since 10.5, and
Availability.h is more flexible as it has version iOS macros in
addition to macOS, which we may need for other APIs in the future,
so just use Availability.h.
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | libass/ass_coretext.c | 24 |
2 files changed, 25 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac index 012478a..c616f3a 100644 --- a/configure.ac +++ b/configure.ac @@ -146,7 +146,7 @@ AS_IF([test "x$enable_coretext" != xno], [ AC_COMPILE_IFELSE([ AC_LANG_PROGRAM( dnl# First test for legacy include [[#include <ApplicationServices/ApplicationServices.h>]], - [[CTFontDescriptorCopyAttribute(NULL, kCTFontURLAttribute);]] + [[CTFontDescriptorCopyAttribute(NULL, kCTFontNameAttribute);]] ) ], [ pkg_libs="$pkg_libs -framework ApplicationServices -framework CoreFoundation" @@ -158,7 +158,7 @@ AS_IF([test "x$enable_coretext" != xno], [ AC_COMPILE_IFELSE([ AC_LANG_PROGRAM( dnl# Otherwise check newer include style [[#include <CoreText/CoreText.h>]], - [[CTFontDescriptorCopyAttribute(NULL, kCTFontURLAttribute);]] + [[CTFontDescriptorCopyAttribute(NULL, kCTFontNameAttribute);]] ) ], [ pkg_libs="$pkg_libs -framework CoreText -framework CoreFoundation" diff --git a/libass/ass_coretext.c b/libass/ass_coretext.c index 7009264..ba40cca 100644 --- a/libass/ass_coretext.c +++ b/libass/ass_coretext.c @@ -19,6 +19,7 @@ #include "config.h" #include "ass_compat.h" +#include <Availability.h> #include <CoreFoundation/CoreFoundation.h> #include <TargetConditionals.h> #if TARGET_OS_IPHONE @@ -88,7 +89,28 @@ static bool check_glyph(void *priv, uint32_t code) static char *get_font_file(CTFontDescriptorRef fontd) { - CFURLRef url = CTFontDescriptorCopyAttribute(fontd, kCTFontURLAttribute); + CFURLRef url = NULL; + if (false) {} +#ifdef __MAC_10_6 + // Declared in SDKs since 10.6, including iOS SDKs + else if (CHECK_AVAILABLE(kCTFontURLAttribute, macOS 10.6, *)) { + url = CTFontDescriptorCopyAttribute(fontd, kCTFontURLAttribute); + } +#endif +#if !TARGET_OS_IPHONE && (!defined(__MAC_10_6) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6) + // ATS is declared deprecated in newer macOS SDKs + // and not declared at all in iOS SDKs + else { + CTFontRef font = CTFontCreateWithFontDescriptor(fontd, 0, NULL); + if (!font) + return NULL; + ATSFontRef ats_font = CTFontGetPlatformFont(font, NULL); + FSRef fs_ref; + if (ATSFontGetFileReference(ats_font, &fs_ref) == noErr) + url = CFURLCreateFromFSRef(NULL, &fs_ref); + CFRelease(font); + } +#endif if (!url) return NULL; CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); |