From 4dfe063ec44b8ececffa06fad671f59903e15935 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 22 Apr 2026 13:00:22 -0700 Subject: [PATCH 05/29] Add API for setting subpixel antialiasing --- src/cairo-compositor-private.h | 3 ++- src/cairo-compositor.c | 3 ++- src/cairo-no-compositor.c | 3 ++- src/cairo-quartz-surface.c | 12 ++++++++- src/cairo-surface-private.h | 1 + src/cairo-surface.c | 49 ++++++++++++++++++++++++++++++++++ src/cairo-xcb-private.h | 3 ++- src/cairo-xcb-surface-render.c | 3 ++- src/cairo-xcb-surface.c | 3 ++- src/cairo.h | 20 ++++++++++++++ 10 files changed, 93 insertions(+), 7 deletions(-) diff --git a/src/cairo-compositor-private.h b/src/cairo-compositor-private.h index 019972333..cce1c09f7 100644 --- a/src/cairo-compositor-private.h +++ b/src/cairo-compositor-private.h @@ -85,7 +85,8 @@ struct cairo_compositor { cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t overlap); + cairo_bool_t overlap, + cairo_bool_t permit_subpixel_antialiasing); }; struct cairo_mask_compositor { diff --git a/src/cairo-compositor.c b/src/cairo-compositor.c index 2f49f7f20..606043cdf 100644 --- a/src/cairo-compositor.c +++ b/src/cairo-compositor.c @@ -290,7 +290,8 @@ _cairo_compositor_glyphs (const cairo_compositor_t *compositor, compositor = compositor->delegate; status = compositor->glyphs (compositor, &extents, - scaled_font, glyphs, num_glyphs, overlap); + scaled_font, glyphs, num_glyphs, overlap, + surface->permit_subpixel_antialiasing); compositor = compositor->delegate; } while (status == CAIRO_INT_STATUS_UNSUPPORTED); diff --git a/src/cairo-no-compositor.c b/src/cairo-no-compositor.c index 1602a12f6..e86e3021c 100644 --- a/src/cairo-no-compositor.c +++ b/src/cairo-no-compositor.c @@ -91,7 +91,8 @@ _cairo_no_compositor_glyphs (const cairo_compositor_t *compositor, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t overlap) + cairo_bool_t overlap, + cairo_bool_t permit_subpixel_antialiasing) { ASSERT_NOT_REACHED; return CAIRO_INT_STATUS_NOTHING_TO_DO; diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 0a5c72f0d..f3d2cd54e 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -1871,7 +1871,8 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t overlap) + cairo_bool_t overlap, + cairo_bool_t permit_subpixel_antialiasing) { CGAffineTransform textTransform, invTextTransform; CGGlyph glyphs_static[CAIRO_STACK_ARRAY_LENGTH (CGPoint)]; @@ -1885,6 +1886,7 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, CTFontRef ctFont = NULL; cairo_bool_t didForceFontSmoothing = FALSE; + cairo_antialias_t effective_antialiasing; if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_QUARTZ) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1904,6 +1906,14 @@ _cairo_quartz_cg_glyphs (const cairo_compositor_t *compositor, ctFont = _cairo_quartz_scaled_font_get_ct_font (scaled_font); _cairo_quartz_set_antialiasing (state.cgMaskContext, scaled_font->options.antialias); + effective_antialiasing = scaled_font->options.antialias; + if (effective_antialiasing == CAIRO_ANTIALIAS_SUBPIXEL && + !permit_subpixel_antialiasing) { + effective_antialiasing = CAIRO_ANTIALIAS_GRAY; + } + + _cairo_quartz_set_antialiasing (state.cgMaskContext, effective_antialiasing); + if (num_glyphs > ARRAY_LENGTH (glyphs_static)) { cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof (CGGlyph) + sizeof (CGPoint)); if (unlikely (cg_glyphs == NULL)) { diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h index 35b559f9c..71112afa5 100644 --- a/src/cairo-surface-private.h +++ b/src/cairo-surface-private.h @@ -71,6 +71,7 @@ struct _cairo_surface { unsigned has_font_options : 1; unsigned owns_device : 1; unsigned is_vector : 1; + unsigned permit_subpixel_antialiasing : 1; cairo_user_data_array_t user_data; cairo_user_data_array_t mime_data; diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 86c1837b9..0192f9e1a 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -114,6 +114,7 @@ const cairo_surface_t name = { \ FALSE, /* has_font_options */ \ FALSE, /* owns_device */ \ FALSE, /* is_vector */ \ + FALSE, /* permit_subpixel_antialiasing */ \ { 0, 0, 0, NULL, }, /* user_data */ \ { 0, 0, 0, NULL, }, /* mime_data */ \ { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \ @@ -427,6 +428,7 @@ _cairo_surface_init (cairo_surface_t *surface, surface->serial = 0; surface->damage = NULL; surface->owns_device = (device != NULL); + surface->permit_subpixel_antialiasing = TRUE; _cairo_user_data_array_init (&surface->user_data); _cairo_user_data_array_init (&surface->mime_data); @@ -462,6 +464,8 @@ _cairo_surface_copy_similar_properties (cairo_surface_t *surface, _cairo_font_options_fini (&options); } + surface->permit_subpixel_antialiasing = other->permit_subpixel_antialiasing; + cairo_surface_set_fallback_resolution (surface, other->x_fallback_resolution, other->y_fallback_resolution); @@ -1627,6 +1631,51 @@ cairo_surface_get_font_options (cairo_surface_t *surface, _cairo_font_options_init_copy (options, &surface->font_options); } +/** + * cairo_surface_set_subpixel_antialiasing: + * @surface: a #cairo_surface_t + * + * Sets whether the surface permits subpixel antialiasing. By default, + * surfaces permit subpixel antialiasing. + * + * Enabling subpixel antialiasing for CONTENT_COLOR_ALPHA surfaces generally + * requires that the pixels in the areas under a subpixel antialiasing + * operation already be opaque. + **/ +void +cairo_surface_set_subpixel_antialiasing (cairo_surface_t *surface, + cairo_subpixel_antialiasing_t enabled) +{ + if (surface->status) + return; + + if (surface->finished) { + _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); + return; + } + + surface->permit_subpixel_antialiasing = + enabled == CAIRO_SUBPIXEL_ANTIALIASING_ENABLED; +} + +/** + * cairo_surface_get_subpixel_antialiasing: + * @surface: a #cairo_surface_t + * + * Gets whether the surface supports subpixel antialiasing. By default, + * CAIRO_CONTENT_COLOR surfaces support subpixel antialiasing but other + * surfaces do not. + **/ +cairo_subpixel_antialiasing_t +cairo_surface_get_subpixel_antialiasing (cairo_surface_t *surface) +{ + if (surface->status) + return CAIRO_SUBPIXEL_ANTIALIASING_DISABLED; + + return surface->permit_subpixel_antialiasing ? + CAIRO_SUBPIXEL_ANTIALIASING_ENABLED : CAIRO_SUBPIXEL_ANTIALIASING_DISABLED; +} + cairo_status_t _cairo_surface_flush (cairo_surface_t *surface, unsigned flags) { diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h index 95805f8a9..89b2e7846 100644 --- a/src/cairo-xcb-private.h +++ b/src/cairo-xcb-private.h @@ -443,7 +443,8 @@ _cairo_xcb_render_compositor_glyphs (const cairo_compositor_t *compositor, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t overlap); + cairo_bool_t overlap, + cairo_bool_t permit_subpixel_antialiasing); cairo_private void _cairo_xcb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font); diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index 2777c3cda..e25a3d334 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -4814,7 +4814,8 @@ _cairo_xcb_render_compositor_glyphs (const cairo_compositor_t *compositor, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t overlap) + cairo_bool_t overlap, + cairo_bool_t permit_subpixel_antialiasing) { cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface; cairo_operator_t op = composite->op; diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index 302d3fbe0..f63c64e42 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -906,7 +906,8 @@ _cairo_xcb_fallback_compositor_glyphs (const cairo_compositor_t *compositor, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, - cairo_bool_t overlap) + cairo_bool_t overlap, + cairo_bool_t permit_subpixel_antialiasing) { cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface; cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents); diff --git a/src/cairo.h b/src/cairo.h index 326a23485..5758e3427 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -2737,6 +2737,26 @@ cairo_surface_show_page (cairo_surface_t *surface); cairo_public cairo_bool_t cairo_surface_has_show_text_glyphs (cairo_surface_t *surface); +/** + * _cairo_subpixel_antialiasing_t: + * @CAIRO_SUBPIXEL_ANTIALIASING_ENABLED: subpixel antialiasing is enabled + * for this surface. + * @CAIRO_SUBPIXEL_ANTIALIASING_DISABLED: subpixel antialiasing is disabled + * for this surface. + */ +typedef enum _cairo_subpixel_antialiasing_t { + CAIRO_SUBPIXEL_ANTIALIASING_ENABLED, + CAIRO_SUBPIXEL_ANTIALIASING_DISABLED +} cairo_subpixel_antialiasing_t; + +cairo_public void +cairo_surface_set_subpixel_antialiasing (cairo_surface_t *surface, + cairo_subpixel_antialiasing_t enabled); + +cairo_public cairo_subpixel_antialiasing_t +cairo_surface_get_subpixel_antialiasing (cairo_surface_t *surface); + + /* Image-surface functions */ cairo_public cairo_surface_t * -- 2.53.0