From 339b1580ea6f82d0f05e2e1efd5410b21aff7430 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Fri, 27 Mar 2026 14:34:12 +0100 Subject: [PATCH 1/4] Meson: Fix compilation with CLangCL Support for __uint128_t in CLangCL is currently broken [1]. Avoid using that type for now. As of today MSVC doesn't support 128-bit integral types; with this change we get feature-parity between MSVC and CLangCL, so this shouldn't be a problem. References: * Clang-cl generates a call to an undefined symbol __udivti3 https://github.com/llvm/llvm-project/issues/25679 --- meson.build | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 11525ea84..48fd6bb13 100644 --- a/meson.build +++ b/meson.build @@ -148,9 +148,13 @@ check_headers = [ check_types = [ ['uint64_t', {'headers': ['stdint.h']}], ['uint128_t', {'headers': ['stdint.h']}], - ['__uint128_t'] ] +# https://github.com/llvm/llvm-project/issues/25679 +if cc.get_id() != 'clang-cl' + check_types += [ ['__uint128_t'] ] +endif + check_funcs = [ 'alarm', 'ctime_r', From 8a8262e9cde0a6368d1da6be8904b26a546adad7 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Fri, 27 Mar 2026 19:18:14 +0100 Subject: [PATCH 2/4] cairo-script: Fix build on 64bit Windows with LZO enabled lzo_uint is a typedef for a machine-sized unsigned integral. We track sizes using unsigned long, which is machine-sized on most (all?) Unices, but 32bit on 64bit Windows. This means that lzo_uint and unsigned long are not really interchangeable (should have used size_t!). Fix the build by using intermediate variables. The cairo-script file format ensures that uncompressed data fits within 4GB. Fixes -Wincompatible-pointer-types errors. --- util/cairo-script/cairo-script-file.c | 7 ++- util/cairo-script/cairo-script-operators.c | 60 ++++++++++++---------- util/cairo-script/cairo-script-scanner.c | 7 ++- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/util/cairo-script/cairo-script-file.c b/util/cairo-script/cairo-script-file.c index c45cc5086..0da4bb649 100644 --- a/util/cairo-script/cairo-script-file.c +++ b/util/cairo-script/cairo-script-file.c @@ -162,7 +162,6 @@ csi_file_new_from_string (csi_t *ctx, file->base.ref = 1; if (src->deflate) { - uLongf len = src->deflate; csi_object_t tmp_obj; csi_string_t *tmp_str; csi_status_t status; @@ -179,20 +178,26 @@ csi_file_new_from_string (csi_t *ctx, break; case ZLIB: + { #if HAVE_ZLIB + uLongf len = src->deflate; if (uncompress ((Bytef *) tmp_str->string, &len, (Bytef *) src->string, src->len) != Z_OK) #endif status = _csi_error (CAIRO_STATUS_NO_MEMORY); break; + } case LZO: + { #if HAVE_LZO + lzo_uint len = src->deflate; if (lzo2a_decompress ((lzo_bytep) src->string, src->len, (lzo_bytep) tmp_str->string, &len, NULL)) #endif status = _csi_error (CAIRO_STATUS_NO_MEMORY); break; + } } if (_csi_unlikely (status)) { csi_string_free (ctx, tmp_str); diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c index a5eca6ffc..b3b03457f 100644 --- a/util/cairo-script/cairo-script-operators.c +++ b/util/cairo-script/cairo-script-operators.c @@ -1758,46 +1758,47 @@ _mmap_bytes (const struct mmap_vec *vec, int count) static void * inflate_string (csi_t *ctx, csi_string_t *src) { - uLongf len; uint8_t *bytes; - len = src->deflate; - bytes = _csi_alloc (ctx, len + 1); + bytes = _csi_alloc (ctx, src->deflate + 1); if (bytes == NULL) return NULL; switch (src->method) { - default: - case NONE: - free (bytes); - return NULL; - case ZLIB: + { #if HAVE_ZLIB - if (uncompress ((Bytef *) bytes, &len, - (Bytef *) src->string, src->len) != Z_OK) -#endif + uLongf length = src->deflate; + if (uncompress ((Bytef *) bytes, &length, + (Bytef *) src->string, src->len) == Z_OK) { - _csi_free (ctx, bytes); - return NULL; + bytes[length] = '\0'; + return bytes; } - break; - - case LZO: -#if HAVE_LZO - if (lzo2a_decompress ((Bytef *) src->string, src->len, - (Bytef *) bytes, &len, - NULL)) #endif - { - _csi_free (ctx, bytes); - return NULL; - } break; } + case LZO: + { +#if HAVE_LZO + lzo_uint length = src->deflate; + if (lzo2a_decompress ((Bytef *) src->string, src->len, + (Bytef *) bytes, &length, + NULL) == LZO_E_OK) + { + bytes[length] = '\0'; + return bytes; + } +#endif + break; + } + case NONE: + default: + break; + } - bytes[len] = '\0'; - return bytes; + _csi_free (ctx, bytes); + return NULL; } static csi_status_t @@ -2982,7 +2983,6 @@ _image_read_raw (csi_t *ctx, len == src->datum.string->deflate) { csi_string_t *s = src->datum.string; - unsigned long out = s->deflate; switch (s->method) { default: @@ -2992,21 +2992,27 @@ err_decompress: return _csi_error (CSI_STATUS_READ_ERROR); case ZLIB: + { #if HAVE_ZLIB + uLongf out = s->deflate; if (uncompress ((Bytef *) data, &out, (Bytef *) s->string, s->len) != Z_OK) #endif goto err_decompress; break; + } case LZO: + { #if HAVE_LZO + lzo_uint out = s->deflate; if (lzo2a_decompress ((Bytef *) s->string, s->len, (Bytef *) data, &out, NULL)) #endif goto err_decompress; break; + } } } else diff --git a/util/cairo-script/cairo-script-scanner.c b/util/cairo-script/cairo-script-scanner.c index 167cd7a1e..09677a1e1 100644 --- a/util/cairo-script/cairo-script-scanner.c +++ b/util/cairo-script/cairo-script-scanner.c @@ -1595,7 +1595,10 @@ _translate_string (csi_t *ctx, #if HAVE_LZO if (method == NONE && buf_len > 16) { - unsigned long mem_len = 2*string->len > LZO2A_999_MEM_COMPRESS ? 2*string->len : LZO2A_999_MEM_COMPRESS; + lzo_uint mem_len = 2 * (lzo_uint)string->len; + if (mem_len < LZO2A_999_MEM_COMPRESS) + mem_len = LZO2A_999_MEM_COMPRESS; + void *mem = malloc (mem_len); void *work = malloc(LZO2A_999_MEM_COMPRESS); @@ -1628,7 +1631,7 @@ _translate_string (csi_t *ctx, method = NONE; deflate = 0; } else { - unsigned long mem_len = 2*string->deflate; + lzo_uint mem_len = 2*string->deflate; void *mem = malloc (mem_len); void *work = malloc(LZO2A_999_MEM_COMPRESS); From 01e522b2000997c20e994adf0161504fdcc44ec8 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Mon, 27 Apr 2026 18:44:06 +0200 Subject: [PATCH 3/4] Fix build with CAIRO_NO_MUTEX The LibreOffice project builds Cairo with -DCAIRO_NO_MUTEX. IMHO that's quite risky for big projects where you don't control all the code that uses Cairo, but I assume they know what they're doing. This change should have been part of commit 87f7c60bf7, but admittetly CAIRO_NO_MUTEX builds are not actively tested. Fixes #921 --- src/cairo-image-source.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c index eaf72e2cc..b752041cf 100644 --- a/src/cairo-image-source.c +++ b/src/cairo-image-source.c @@ -62,9 +62,10 @@ #endif #if PIXMAN_HAS_ATOMIC_OPS -static pixman_image_t *__pixman_transparent_image; -static pixman_image_t *__pixman_black_image; -static pixman_image_t *__pixman_white_image; + +static cairo_atomic_intptr_t __pixman_transparent_image; /* (pixman_image_t *) */ +static cairo_atomic_intptr_t __pixman_black_image; +static cairo_atomic_intptr_t __pixman_white_image; static pixman_image_t * _pixman_transparent_image (void) @@ -73,7 +74,7 @@ _pixman_transparent_image (void) TRACE ((stderr, "%s\n", __FUNCTION__)); - image = __pixman_transparent_image; + image = (pixman_image_t *) _cairo_atomic_ptr_get (&__pixman_transparent_image); if (unlikely (image == NULL)) { pixman_color_t color; @@ -105,7 +106,7 @@ _pixman_black_image (void) TRACE ((stderr, "%s\n", __FUNCTION__)); - image = __pixman_black_image; + image = (pixman_image_t *) _cairo_atomic_ptr_get (&__pixman_black_image); if (unlikely (image == NULL)) { pixman_color_t color; @@ -137,7 +138,7 @@ _pixman_white_image (void) TRACE ((stderr, "%s\n", __FUNCTION__)); - image = __pixman_white_image; + image = (pixman_image_t *) _cairo_atomic_ptr_get (&__pixman_white_image); if (unlikely (image == NULL)) { pixman_color_t color; @@ -178,6 +179,7 @@ static struct { static int n_cached; #else /* !PIXMAN_HAS_ATOMIC_OPS */ + static pixman_image_t * _pixman_transparent_image (void) { @@ -198,6 +200,7 @@ _pixman_white_image (void) TRACE ((stderr, "%s\n", __FUNCTION__)); return _pixman_image_for_color (CAIRO_COLOR_WHITE); } + #endif /* !PIXMAN_HAS_ATOMIC_OPS */ From d97438f1be9a01bc305df2bbb415d1f3b8b507eb Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Fri, 27 Mar 2026 16:01:15 +0100 Subject: [PATCH 4/4] Drop unneeded assert We can't ensure that no error happened whatsoever. Fixes #929 --- src/cairo-colr-glyph-render.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cairo-colr-glyph-render.c b/src/cairo-colr-glyph-render.c index d28e0ba16..d3e523d25 100644 --- a/src/cairo-colr-glyph-render.c +++ b/src/cairo-colr-glyph-render.c @@ -1095,8 +1095,6 @@ draw_paint (cairo_colr_glyph_render_t *render, FT_Vector orig_delta; cairo_status_t status = CAIRO_STATUS_SUCCESS; - assert (cairo_status (cr) == CAIRO_STATUS_SUCCESS); - if (!FT_Get_Paint (render->face, *paint, &p)) return CAIRO_STATUS_NO_MEMORY;