From 3537bb1c6649392218b8fb9d781a789f57873c05 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 23 Jan 2025 08:49:36 +0900 Subject: [PATCH] Allow building Quartz font backend for iPhoneOS The main differences between the macOS and iPhoneOS SDKs as far as cairo is concerned are: - no Carbon on iPhoneOS. - no ApplicationServices framework on iPhoneOS, which is only really used for the ATSUI backend. - no CGDisplayCopyColorSpace in CoreGraphics on iPhoneOS. Uses of the ApplicationServices framework outside the ATSUI backend were a proxy for other framework it includes automatically. We thus switch to using those other frameworks explicitly instead. Theoretically speaking, the ApplicationServices framework is expected to be linked for the FMGetATSFontRefFromFont symbol to be found at runtime, but that was already not happening because of the default use of -Wl,-dead_strip_dylibs. The presence of CGDisplayCopyColorSpace is controlled in meson.build. The use of Carbon/Carbon.h looks vestigal and is removed. Loosely based on https://gitlab.freedesktop.org/cairo/cairo/-/issues/293 --- meson.build | 11 +++++++++-- src/cairo-quartz-font.c | 7 +++++++ src/cairo-quartz-image-surface.c | 4 ++++ src/cairo-quartz-image.h | 2 -- src/cairo-quartz-surface.c | 3 +++ src/cairo-quartz.h | 7 +++++++ 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/meson.build b/meson.build index 162b2927c..ce90f1ef9 100644 --- a/meson.build +++ b/meson.build @@ -450,7 +450,7 @@ if feature_conf.get('CAIRO_HAS_XCB_SURFACE', 0) == 1 endif if host_machine.system() == 'darwin' and not get_option('quartz').disabled() - quartz_deps = dependency('appleframeworks', modules : ['CoreFoundation', 'ApplicationServices'], required: get_option('quartz')) + quartz_deps = dependency('appleframeworks', modules : ['CoreFoundation', 'CoreGraphics', 'CoreText', 'ImageIO'], required: get_option('quartz')) if quartz_deps.found() deps += [quartz_deps] @@ -470,7 +470,7 @@ if host_machine.system() == 'darwin' and not get_option('quartz').disabled() 'deps': quartz_deps, }] compiler = meson.get_compiler('c') - if compiler.has_function('CTFontDrawGlyphs', prefix: '#include ', + if compiler.has_function('CTFontDrawGlyphs', prefix: '#include ', dependencies: quartz_deps) built_features += [ { @@ -480,6 +480,13 @@ if host_machine.system() == 'darwin' and not get_option('quartz').disabled() }] feature_conf.set('CAIRO_HAS_QUARTZ_FONT', 1) endif + if compiler.has_function('CGDisplayCopyColorSpace', prefix: '#include ', + dependencies: quartz_deps) + feature_conf.set('CAIRO_HAS_QUARTZ_CGDISPLAYCOPYCOLORSPACE', 1) + endif + if compiler.has_header('ApplicationServices/ApplicationServices.h') + feature_conf.set('CAIRO_HAS_QUARTZ_APPLICATION_SERVICES', 1) + endif endif endif diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c index b1a6fd7f5..8cdebadbf 100644 --- a/src/cairo-quartz-font.c +++ b/src/cairo-quartz-font.c @@ -65,7 +65,9 @@ /* These are private functions */ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL; +#endif static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE; /* Cairo's transformations assume a unit-scaled font. */ @@ -92,7 +94,9 @@ quartz_font_ensure_symbols(void) CGContextGetAllowsFontSmoothingPtr = dlsym (RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing"); +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES FMGetATSFontRefFromFontPtr = dlsym(RTLD_DEFAULT, "FMGetATSFontRefFromFont"); +#endif _cairo_quartz_font_symbol_lookup_done = TRUE; } @@ -803,6 +807,8 @@ _cairo_quartz_scaled_font_get_ct_font (cairo_scaled_font_t *abstract_font) } } + +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES /* * compat with old ATSUI backend */ @@ -849,3 +855,4 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id) { return cairo_quartz_font_face_create_for_atsu_font_id (font_id); } +#endif diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c index 4f9bc2118..5037aae23 100644 --- a/src/cairo-quartz-image-surface.c +++ b/src/cairo-quartz-image-surface.c @@ -307,7 +307,11 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface) colorspace = _cairo_quartz_create_color_space (context); } else { +#if CAIRO_HAS_QUARTZ_CGDISPLAYCOPYCOLORSPACE colorspace = CGDisplayCopyColorSpace (CGMainDisplayID ()); +#else + colorspace = CGColorSpaceCreateDeviceRGB (); +#endif } bitinfo |= format == CAIRO_FORMAT_ARGB32 ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; diff --git a/src/cairo-quartz-image.h b/src/cairo-quartz-image.h index 0dd5abb4f..9e8409c11 100644 --- a/src/cairo-quartz-image.h +++ b/src/cairo-quartz-image.h @@ -40,8 +40,6 @@ #if CAIRO_HAS_QUARTZ_IMAGE_SURFACE -#include - CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 0a5c72f0d..90fbc6cea 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -200,8 +200,11 @@ _cairo_quartz_create_color_space (CGContextRef context) if (color_space) return color_space; } + +#if CAIRO_HAS_QUARTZ_CGDISPLAYCOPYCOLORSPACE if (!color_space) color_space = CGDisplayCopyColorSpace (CGMainDisplayID ()); +#endif if (!color_space) color_space = CGColorSpaceCreateDeviceRGB (); diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h index 9e11e876f..fc2b081f6 100644 --- a/src/cairo-quartz.h +++ b/src/cairo-quartz.h @@ -40,7 +40,12 @@ #if CAIRO_HAS_QUARTZ_SURFACE +#include +#include +#include +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES #include +#endif CAIRO_BEGIN_DECLS @@ -66,8 +71,10 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface); cairo_public cairo_font_face_t * cairo_quartz_font_face_create_for_cgfont (CGFontRef font); +#if CAIRO_HAS_QUARTZ_APPLICATION_SERVICES cairo_public cairo_font_face_t * cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id); +#endif #endif /* CAIRO_HAS_QUARTZ_FONT */