summaryrefslogtreecommitdiffstats
path: root/external/cairo
diff options
context:
space:
mode:
Diffstat (limited to 'external/cairo')
-rw-r--r--external/cairo/ExternalPackage_cairo.mk18
-rw-r--r--external/cairo/ExternalPackage_pixman.mk18
-rw-r--r--external/cairo/ExternalProject_cairo.mk84
-rw-r--r--external/cairo/ExternalProject_pixman.mk36
-rw-r--r--external/cairo/Makefile7
-rw-r--r--external/cairo/Module_cairo.mk21
-rw-r--r--external/cairo/README6
-rw-r--r--external/cairo/UnpackedTarball_cairo.mk46
-rw-r--r--external/cairo/UnpackedTarball_pixman.mk19
-rw-r--r--external/cairo/cairo/0025-libtool-pass-use-ld.patch16
-rw-r--r--external/cairo/cairo/cairo-1.10.2.ios.patch27
-rw-r--r--external/cairo/cairo/cairo-1.10.2.no-atsui.patch22
-rw-r--r--external/cairo/cairo/cairo-libtool-rpath.patch.112
-rw-r--r--external/cairo/cairo/cairo.GL_RGBA.patch49
-rw-r--r--external/cairo/cairo/cairo.RGB24_888.patch105
-rw-r--r--external/cairo/cairo/cairo.buildfix.patch122
-rw-r--r--external/cairo/cairo/cairo.ofz46165.patch.116
-rw-r--r--external/cairo/cairo/cairo.oldfreetype.patch42
-rwxr-xr-xexternal/cairo/cairo/dummy_pkg_config3
-rw-r--r--external/cairo/cairo/san.patch.0103
-rw-r--r--external/cairo/pixman/pixman-0.24.4.patch91
-rw-r--r--external/cairo/pixman/pixman-ubsan.patch76
22 files changed, 939 insertions, 0 deletions
diff --git a/external/cairo/ExternalPackage_cairo.mk b/external/cairo/ExternalPackage_cairo.mk
new file mode 100644
index 000000000..116db8a34
--- /dev/null
+++ b/external/cairo/ExternalPackage_cairo.mk
@@ -0,0 +1,18 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_ExternalPackage_ExternalPackage,cairo,cairo))
+
+$(eval $(call gb_ExternalPackage_use_external_project,cairo,cairo))
+
+ifneq ($(DISABLE_DYNLOADING),TRUE)
+$(eval $(call gb_ExternalPackage_add_file,cairo,$(LIBO_LIB_FOLDER)/libcairo.so.2,src/.libs/libcairo.so.2.1170$(CAIRO_VERSION_MICRO).0))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/ExternalPackage_pixman.mk b/external/cairo/ExternalPackage_pixman.mk
new file mode 100644
index 000000000..85ff062f2
--- /dev/null
+++ b/external/cairo/ExternalPackage_pixman.mk
@@ -0,0 +1,18 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_ExternalPackage_ExternalPackage,pixman,pixman))
+
+$(eval $(call gb_ExternalPackage_use_external_project,pixman,pixman))
+
+ifneq ($(DISABLE_DYNLOADING),TRUE)
+$(eval $(call gb_ExternalPackage_add_file,pixman,$(LIBO_LIB_FOLDER)/libpixman-1.so.0,pixman/.libs/libpixman-1.so.0.42.2))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/ExternalProject_cairo.mk b/external/cairo/ExternalProject_cairo.mk
new file mode 100644
index 000000000..53a51b5e4
--- /dev/null
+++ b/external/cairo/ExternalProject_cairo.mk
@@ -0,0 +1,84 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_ExternalProject_ExternalProject,cairo))
+
+$(eval $(call gb_ExternalProject_use_external_project,cairo,pixman))
+
+$(eval $(call gb_ExternalProject_use_externals,cairo,\
+ fontconfig \
+ freetype \
+ libpng \
+ zlib \
+))
+
+$(eval $(call gb_ExternalProject_register_targets,cairo,\
+ build \
+))
+
+# Including -rtlib=compiler-rt in pixman_LIBS is a BAD HACK: At least when compiling with Clang
+# -fsanitize=undefined on Linux x86-64, the generated code references __muloti4, which is an
+# extension provided by libclang_rt.builtins-x86_64.a runtime, but not by GCC's libgcc_s.so.1 (which
+# ultimately boils down to a bug in LLVM, I would say). I am not sure whether it should in general
+# work to mix uses of the (default on Linux, at least) GCC libgcc_s and LLVM's libclang_rt.builtins
+# runtime libraries in one process, but for this specific case of libcairo.so it appears to work
+# well: For one, the only symbol referenced by libcairo.so from the runtime library is __muloti4;
+# for another, at least in my LLVM build, lib/clang/12.0.0/lib/linux/libclang_rt.builtins-x86_64.a
+# is only provided as a static archive; so libcairo.so will only contain a "harmless" copy of
+# __muloti4 and not have a DT_NEEDED of any libclang_rt.builtins dynamic library that it would pull
+# in at runtime.
+# But passing -rtlib=compiler-rt into cairo's configure via the more obvious LDFLAGS would fail at
+# least when building with -fsanitize=address and -fsanitize=undefined, as then the executable
+# compiled by configure when "checking whether the C compiler works" would reference
+# _Unwind_Backtrace etc. that are provided by GCC's libgcc_s.so.1 but not by LLVM's
+# libclang_rt.builtins-x86_64.a (and whatever the reason for that inconsistency). So
+# -rtlib=compiler-rt must be passed just into the linking of libcairo.so, but not generally into
+# cairo's configure. And pixman_LIBS happens to offer that. (The -Wc is necessary so that libtool
+# does not throw away the -rtlib=compiler-rt which it does not understand.)
+
+$(call gb_ExternalProject_get_state_target,cairo,build) :
+ $(call gb_Trace_StartRange,cairo,EXTERNAL)
+ $(call gb_ExternalProject_run,build,\
+ $(gb_RUN_CONFIGURE) ./configure \
+ $(if $(debug),STRIP=" ") \
+ $(if $(filter ANDROID iOS,$(OS)),CFLAGS="$(if $(debug),-g) $(ZLIB_CFLAGS) $(gb_VISIBILITY_FLAGS)") \
+ $(if $(filter EMSCRIPTEN,$(OS)),CFLAGS=" $(ZLIB_CFLAGS) -Wno-enum-conversion $(gb_EMSCRIPTEN_CPPFLAGS)" --enable-pthread=yes PTHREAD_LIBS="") \
+ $(if $(filter-out EMSCRIPTEN ANDROID iOS,$(OS)), \
+ CFLAGS="$(CFLAGS) $(call gb_ExternalProject_get_build_flags,cairo) $(ZLIB_CFLAGS)" \
+ LDFLAGS="$(call gb_ExternalProject_get_link_flags,cairo)" \
+ ) \
+ $(if $(filter ANDROID iOS,$(OS)),PKG_CONFIG=./dummy_pkg_config) \
+ LIBS="$(ZLIB_LIBS)" \
+ $(if $(filter -fsanitize=%,$(LDFLAGS)),LDFLAGS="$(LDFLAGS) -fuse-ld=bfd") \
+ pixman_CFLAGS="-I$(call gb_UnpackedTarball_get_dir,pixman)/pixman -pthread" \
+ pixman_LIBS="-L$(call gb_UnpackedTarball_get_dir,pixman)/pixman/.libs -lpixman-1 \
+ $(if $(filter LINUX,$(OS)),-Wl$(COMMA)-z$(COMMA)origin \
+ -Wl$(COMMA)-rpath$(COMMA)\\\$$\$$ORIGIN) \
+ $(if $(filter -fsanitize=%,$(CC)), \
+ $(if $(filter LINUX-X86_64-TRUE,$(OS)-$(CPUNAME)-$(COM_IS_CLANG)), \
+ -Wc$(COMMA)-rtlib=compiler-rt))" \
+ png_REQUIRES="trick_configure_into_using_png_CFLAGS_and_LIBS" \
+ png_CFLAGS="$(LIBPNG_CFLAGS)" png_LIBS="$(LIBPNG_LIBS)" \
+ $(if $(SYSTEM_FREETYPE),,FREETYPE_CFLAGS="-I$(call gb_UnpackedTarball_get_dir,freetype)/include") \
+ $(if $(SYSTEM_FONTCONFIG),,FONTCONFIG_CFLAGS="-I$(call gb_UnpackedTarball_get_dir,fontconfig)") \
+ $(if $(verbose),--disable-silent-rules,--enable-silent-rules) \
+ $(if $(filter TRUE,$(DISABLE_DYNLOADING)),--disable-shared,--disable-static) \
+ $(if $(filter EMSCRIPTEN ANDROID iOS,$(OS)),--disable-xlib --disable-xcb,$(if $(filter TRUE,$(DISABLE_GUI)),--disable-xlib --disable-xcb,--enable-xlib --enable-xcb)) \
+ $(if $(filter iOS,$(OS)),--enable-quartz --enable-quartz-font) \
+ --disable-valgrind \
+ $(if $(filter iOS,$(OS)),--disable-ft,--enable-ft --enable-fc) \
+ --disable-svg --enable-gtk-doc=no --enable-test-surfaces=no \
+ $(gb_CONFIGURE_PLATFORMS) \
+ $(if $(CROSS_COMPILING),$(if $(filter INTEL ARM,$(CPUNAME)),ac_cv_c_bigendian=no ax_cv_c_float_words_bigendian=no)) \
+ $(if $(filter MACOSX,$(OS)),--prefix=/@.__________________________________________________OOO) \
+ && cd src && $(MAKE) \
+ )
+ $(call gb_Trace_EndRange,cairo,EXTERNAL)
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/ExternalProject_pixman.mk b/external/cairo/ExternalProject_pixman.mk
new file mode 100644
index 000000000..9293b9234
--- /dev/null
+++ b/external/cairo/ExternalProject_pixman.mk
@@ -0,0 +1,36 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_ExternalProject_ExternalProject,pixman))
+
+$(eval $(call gb_ExternalProject_register_targets,pixman,\
+ build \
+))
+
+# ANDROID:
+# The pixman-cpu.c code wants to read /proc/<pid>/auxv, but
+# the Android headers don't define Elf32_auxv_t.
+#
+# Maybe we should instead just patch the arm_has_* booleans in
+# pixman-cpu.c to be hardcoded as TRUE and patch out the run-time
+# check?
+$(call gb_ExternalProject_get_state_target,pixman,build) :
+ $(call gb_Trace_StartRange,pixman,EXTERNAL)
+ $(call gb_ExternalProject_run,build,\
+ $(gb_RUN_CONFIGURE) ./configure \
+ $(if $(filter TRUE,$(DISABLE_DYNLOADING)),--disable-shared,--disable-static) \
+ $(if $(filter ANDROID,$(OS)),--disable-arm-simd --disable-arm-neon --disable-arm-a64-neon --disable-arm-iwmmxt) \
+ $(gb_CONFIGURE_PLATFORMS) \
+ $(if $(CROSS_COMPILING),$(if $(filter INTEL ARM,$(CPUNAME)),ac_cv_c_bigendian=no)) \
+ $(if $(filter EMSCRIPTEN,$(OS)),CFLAGS="-pthread") \
+ && $(MAKE) \
+ )
+ $(call gb_Trace_EndRange,pixman,EXTERNAL)
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/Makefile b/external/cairo/Makefile
new file mode 100644
index 000000000..e4968cf85
--- /dev/null
+++ b/external/cairo/Makefile
@@ -0,0 +1,7 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/Module_cairo.mk b/external/cairo/Module_cairo.mk
new file mode 100644
index 000000000..6d8a29add
--- /dev/null
+++ b/external/cairo/Module_cairo.mk
@@ -0,0 +1,21 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Module_Module,cairo))
+
+$(eval $(call gb_Module_add_targets,cairo,\
+ ExternalPackage_cairo \
+ ExternalPackage_pixman \
+ ExternalProject_cairo \
+ ExternalProject_pixman \
+ UnpackedTarball_cairo \
+ UnpackedTarball_pixman \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/README b/external/cairo/README
new file mode 100644
index 000000000..3d955dcd0
--- /dev/null
+++ b/external/cairo/README
@@ -0,0 +1,6 @@
+The graphics library, used for anti-aliasing. From [http://cairographics.org/].
+
+This code is used by default only on Linux, though it is also
+available on Mac. There is a cairo-canvas implementation that is the
+main customer, and it is enabled via 'use hardware acceleration' in
+the general options.
diff --git a/external/cairo/UnpackedTarball_cairo.mk b/external/cairo/UnpackedTarball_cairo.mk
new file mode 100644
index 000000000..e746a4899
--- /dev/null
+++ b/external/cairo/UnpackedTarball_cairo.mk
@@ -0,0 +1,46 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UnpackedTarball_UnpackedTarball,cairo))
+
+$(eval $(call gb_UnpackedTarball_set_tarball,cairo,$(CAIRO_TARBALL),,cairo))
+
+# cairo >= 1.17.6 was probably created in Fedora where
+# https://salsa.debian.org/mckinstry/libtool/-/commit/26c23f951d049241128e5e04a7bbc263e5b145f1
+# isn't applied, so add that in to avoid: /usr/bin/ld: unrecognized option '--gdb-index'
+
+$(eval $(call gb_UnpackedTarball_add_patches,cairo,\
+ external/cairo/cairo/cairo.buildfix.patch \
+ external/cairo/cairo/cairo.RGB24_888.patch \
+ external/cairo/cairo/cairo-libtool-rpath.patch.1 \
+ external/cairo/cairo/cairo.oldfreetype.patch \
+ external/cairo/cairo/san.patch.0 \
+ external/cairo/cairo/cairo.ofz46165.patch.1 \
+ external/cairo/cairo/0025-libtool-pass-use-ld.patch \
+))
+
+ifeq ($(OS),iOS)
+$(eval $(call gb_UnpackedTarball_add_patches,cairo,\
+ external/cairo/cairo/cairo-1.10.2.no-atsui.patch \
+ external/cairo/cairo/cairo-1.10.2.ios.patch \
+))
+endif
+
+# To be applied only when ENABLE_ANDROID_LOK is not defined
+ifeq ($(OS)$(ENABLE_ANDROID_LOK),ANDROID)
+$(eval $(call gb_UnpackedTarball_add_patches,cairo,\
+ external/cairo/cairo/cairo.GL_RGBA.patch \
+))
+endif
+
+ifneq (,$(filter ANDROID iOS,$(OS)))
+$(eval $(call gb_UnpackedTarball_add_file,cairo,.,external/cairo/cairo/dummy_pkg_config))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/UnpackedTarball_pixman.mk b/external/cairo/UnpackedTarball_pixman.mk
new file mode 100644
index 000000000..3f1f75616
--- /dev/null
+++ b/external/cairo/UnpackedTarball_pixman.mk
@@ -0,0 +1,19 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UnpackedTarball_UnpackedTarball,pixman))
+
+$(eval $(call gb_UnpackedTarball_set_tarball,pixman,$(PIXMAN_TARBALL),,cairo))
+
+$(eval $(call gb_UnpackedTarball_add_patches,pixman,\
+ external/cairo/pixman/pixman-0.24.4.patch \
+ external/cairo/pixman/pixman-ubsan.patch \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/cairo/cairo/0025-libtool-pass-use-ld.patch b/external/cairo/cairo/0025-libtool-pass-use-ld.patch
new file mode 100644
index 000000000..c5558ff73
--- /dev/null
+++ b/external/cairo/cairo/0025-libtool-pass-use-ld.patch
@@ -0,0 +1,16 @@
+--- a/cairo/build/ltmain.sh 2022-05-04 16:12:17.409012360 +0100
++++ b/cairo/build/ltmain.sh 2022-05-04 16:12:42.510870063 +0100
+@@ -7273,11 +7273,12 @@
+ # --sysroot=* for sysroot support
+ # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+ # -specs=* GCC specs files
++ # -fuse-ld=* Linker select flags for GCC
+ # -stdlib=* select c++ std lib with clang
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
+- -specs=*)
++ -specs=*|-fuse-ld=*)
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ func_append compile_command " $arg"
diff --git a/external/cairo/cairo/cairo-1.10.2.ios.patch b/external/cairo/cairo/cairo-1.10.2.ios.patch
new file mode 100644
index 000000000..c61faf333
--- /dev/null
+++ b/external/cairo/cairo/cairo-1.10.2.ios.patch
@@ -0,0 +1,27 @@
+--- misc/cairo-1.10.2/configure 2011-12-16 10:02:39.626077757 +0100
++++ misc/build/cairo-1.10.2/configure 2011-12-16 10:02:23.518237109 +0100
+@@ -22766,11 +22766,13 @@
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "ApplicationServices/ApplicationServices.h" "ac_cv_header_ApplicationServices_ApplicationServices_h" "$ac_includes_default"
++if false; then
+ if test "x$ac_cv_header_ApplicationServices_ApplicationServices_h" = x""yes; then :
+
+ else
+ use_quartz="no (requires ApplicationServices framework)"
+ fi
++fi
+
+
+ if test "x$use_quartz" != "xyes" ; then
+--- misc/cairo-1.10.2/src/cairo-quartz.h 2011-12-16 10:02:39.639079241 +0100
++++ misc/build/cairo-1.10.2/src/cairo-quartz.h 2011-12-16 10:01:18.404789245 +0100
+@@ -40,7 +40,7 @@
+
+ #if CAIRO_HAS_QUARTZ_SURFACE
+
+-#include <ApplicationServices/ApplicationServices.h>
++#include <CoreGraphics/CoreGraphics.h>
+
+ CAIRO_BEGIN_DECLS
+
diff --git a/external/cairo/cairo/cairo-1.10.2.no-atsui.patch b/external/cairo/cairo/cairo-1.10.2.no-atsui.patch
new file mode 100644
index 000000000..51b98afa5
--- /dev/null
+++ b/external/cairo/cairo/cairo-1.10.2.no-atsui.patch
@@ -0,0 +1,22 @@
+--- misc/cairo-1.10.2/src/cairo-quartz-font.c 2010-12-25 15:21:34.000000000 +0100
++++ misc/build/cairo-1.10.2/src/cairo-quartz-font.c 2011-12-16 09:54:18.672445207 +0100
+@@ -777,7 +777,7 @@
+ return ffont->cgFont;
+ }
+
+-#ifndef __LP64__
++#if 0
+ /*
+ * compat with old ATSUI backend
+ */
+--- misc/cairo-1.10.2/src/cairo-quartz.h 2010-06-18 13:47:13.000000000 +0200
++++ misc/build/cairo-1.10.2/src/cairo-quartz.h 2011-12-16 09:52:53.081501547 +0100
+@@ -66,7 +66,7 @@
+ cairo_public cairo_font_face_t *
+ cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
+
+-#ifndef __LP64__
++#if 0
+ cairo_public cairo_font_face_t *
+ cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id);
+ #endif
diff --git a/external/cairo/cairo/cairo-libtool-rpath.patch.1 b/external/cairo/cairo/cairo-libtool-rpath.patch.1
new file mode 100644
index 000000000..18a3507a9
--- /dev/null
+++ b/external/cairo/cairo/cairo-libtool-rpath.patch.1
@@ -0,0 +1,12 @@
+Prevent libtool from adding annoying stuff to RPATH
+
+--- cairo/configure.orig 2018-10-19 22:20:08.000000000 +0200
++++ cairo/configure 2019-09-04 17:53:00.927539686 +0200
+@@ -10432,6 +10432,7 @@
+ else
+ ld_shlibs=no
+ fi
++hardcode_libdir_flag_spec=
+ ;;
+
+ netbsd*)
diff --git a/external/cairo/cairo/cairo.GL_RGBA.patch b/external/cairo/cairo/cairo.GL_RGBA.patch
new file mode 100644
index 000000000..b1a05feb4
--- /dev/null
+++ b/external/cairo/cairo/cairo.GL_RGBA.patch
@@ -0,0 +1,49 @@
+--- misc/cairo-1.10.2/src/cairo-image-surface.c
++++ misc/cairo-1.10.2/src/cairo-image-surface.c
+@@ -97,11 +97,11 @@
+ return CAIRO_FORMAT_RGBA128F;
+ case PIXMAN_rgb_float:
+ return CAIRO_FORMAT_RGB96F;
+- case PIXMAN_a8r8g8b8:
++ case PIXMAN_a8b8g8r8: //tweaked
+ return CAIRO_FORMAT_ARGB32;
+ case PIXMAN_x2r10g10b10:
+ return CAIRO_FORMAT_RGB30;
+- case PIXMAN_x8r8g8b8:
++ case PIXMAN_x8b8g8r8: //tweaked
+ return CAIRO_FORMAT_RGB24;
+ case PIXMAN_a8:
+ return CAIRO_FORMAT_A8;
+@@ -117,7 +117,7 @@
+ #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2)
+ case PIXMAN_a8r8g8b8_sRGB:
+ #endif
+- case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8:
++ case PIXMAN_a8r8g8b8: case PIXMAN_x8r8g8b8: //tweaked
+ case PIXMAN_b8g8r8: case PIXMAN_b5g6r5:
+ case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
+ case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
+@@ -320,7 +320,7 @@
+ ret = PIXMAN_a8;
+ break;
+ case CAIRO_FORMAT_RGB24:
+- ret = PIXMAN_x8r8g8b8;
++ ret = PIXMAN_x8b8g8r8; //tweaked
+ break;
+ case CAIRO_FORMAT_RGB30:
+ ret = PIXMAN_x2r10g10b10;
+@@ -335,12 +335,12 @@
+ ret = PIXMAN_rgba_float;
+ break;
+ case CAIRO_FORMAT_RGB24_888:
+- ret = PIXMAN_r8g8b8;
++ ret = PIXMAN_b8g8r8; // tweaked
+ break;
+ case CAIRO_FORMAT_ARGB32:
+ case CAIRO_FORMAT_INVALID:
+ default:
+- ret = PIXMAN_a8r8g8b8;
++ ret = PIXMAN_a8b8g8r8; //tweaked
+ break;
+ }
+ return ret;
diff --git a/external/cairo/cairo/cairo.RGB24_888.patch b/external/cairo/cairo/cairo.RGB24_888.patch
new file mode 100644
index 000000000..6b2befabc
--- /dev/null
+++ b/external/cairo/cairo/cairo.RGB24_888.patch
@@ -0,0 +1,105 @@
+diff -ru cairo-1.17.4.orig/src/cairo.h cairo-1.17.4/src/cairo.h
+--- misc/cairo-1.17.4.orig/src/cairo.h 2021-08-29 19:43:26.976435721 +0100
++++ misc/build/cairo-1.17.4/src/cairo.h 2021-08-29 19:47:41.373919330 +0100
+@@ -407,6 +407,8 @@
+ * @CAIRO_FORMAT_RGB30: like RGB24 but with 10bpc. (Since 1.12)
+ * @CAIRO_FORMAT_RGB96F: 3 floats, R, G, B. (Since 1.17.2)
+ * @CAIRO_FORMAT_RGBA128F: 4 floats, R, G, B, A. (Since 1.17.2)
++ * @CAIRO_FORMAT_RGB24_888: each pixel is a 24-bit quantity,
++ * with Red, Green, Blue taking 8-bits each, in that order. (Since 1.1x)
+ *
+ * #cairo_format_t is used to identify the memory format of
+ * image data.
+@@ -424,9 +426,16 @@
+ CAIRO_FORMAT_RGB16_565 = 4,
+ CAIRO_FORMAT_RGB30 = 5,
+ CAIRO_FORMAT_RGB96F = 6,
+- CAIRO_FORMAT_RGBA128F = 7
++ CAIRO_FORMAT_RGBA128F = 7,
++ CAIRO_FORMAT_RGB24_888 = 8
+ } cairo_format_t;
+
++/**
++ * Need this until CAIRO_FORMAT_RGB24_888 is in some official release.
++ * Otherwise we can't reliably check if this is available or we should
++ * convert from 24-bit RGB to 32-bit RGB before passing to Cairo.
++ **/
++#define HAVE_CAIRO_FORMAT_RGB24_888
+
+ /**
+ * cairo_write_func_t:
+diff -ru cairo-1.17.4.orig/src/cairo-image-source.c cairo-1.17.4/src/cairo-image-source.c
+--- misc/cairo-1.17.4.orig/src/cairo-image-source.c 2021-08-29 19:43:26.979435585 +0100
++++ misc/build/cairo-1.17.4/src/cairo-image-source.c 2021-08-29 19:43:47.501506559 +0100
+@@ -509,6 +509,20 @@
+ color.blue = expand_channel(pixel & 0x3fff, 10);
+ return pixman_image_create_solid_fill (&color);
+
++ case CAIRO_FORMAT_RGB24_888:
++ pixel = *(uint32_t *) (image->data + y * image->stride + 3 * x);
++ pixel &= 0x00ffffff; /* ignore next pixel bits */
++ if (pixel == 0)
++ return _pixman_black_image ();
++ if (pixel == 0x00ffffff)
++ return _pixman_white_image ();
++
++ color.alpha = 0xffff;
++ color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
++ color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
++ color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
++ return pixman_image_create_solid_fill (&color);
++
+ case CAIRO_FORMAT_ARGB32:
+ case CAIRO_FORMAT_RGB24:
+ pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
+diff -ru cairo-1.17.4.orig/src/cairo-image-surface.c cairo-1.17.4/src/cairo-image-surface.c
+--- misc/cairo-1.17.4.orig/src/cairo-image-surface.c 2021-08-29 19:43:26.982435449 +0100
++++ misc/build/cairo-1.17.4/src/cairo-image-surface.c 2021-08-29 19:43:47.501506559 +0100
+@@ -109,13 +109,15 @@
+ return CAIRO_FORMAT_A1;
+ case PIXMAN_r5g6b5:
+ return CAIRO_FORMAT_RGB16_565;
++ case PIXMAN_r8g8b8:
++ return CAIRO_FORMAT_RGB24_888;
+ #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
+ case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8:
+ #endif
+ #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2)
+ case PIXMAN_a8r8g8b8_sRGB:
+ #endif
+- case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
++ case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8:
+ case PIXMAN_b8g8r8: case PIXMAN_b5g6r5:
+ case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
+ case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
+@@ -332,6 +334,9 @@
+ case CAIRO_FORMAT_RGBA128F:
+ ret = PIXMAN_rgba_float;
+ break;
++ case CAIRO_FORMAT_RGB24_888:
++ ret = PIXMAN_r8g8b8;
++ break;
+ case CAIRO_FORMAT_ARGB32:
+ case CAIRO_FORMAT_INVALID:
+ default:
+@@ -736,6 +741,8 @@
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB24:
+ return 32;
++ case CAIRO_FORMAT_RGB24_888:
++ return 24;
+ case CAIRO_FORMAT_RGB16_565:
+ return 16;
+ case CAIRO_FORMAT_A8:
+diff -ru cairo-1.17.4.orig/src/cairoint.h cairo-1.17.4/src/cairoint.h
+--- misc/cairo-1.17.4.orig/src/cairoint.h 2021-08-29 19:43:26.973435857 +0100
++++ misc/build/cairo-1.17.4/src/cairoint.h 2021-08-29 19:48:08.396696027 +0100
+@@ -1539,7 +1539,7 @@
+ * in cairo-xlib-surface.c--again see -Wswitch-enum).
+ */
+ #define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \
+- (format) <= CAIRO_FORMAT_RGBA128F)
++ (format) <= CAIRO_FORMAT_RGB24_888)
+
+ /* pixman-required stride alignment in bytes. */
+ #define CAIRO_STRIDE_ALIGNMENT (sizeof (uint32_t))
diff --git a/external/cairo/cairo/cairo.buildfix.patch b/external/cairo/cairo/cairo.buildfix.patch
new file mode 100644
index 000000000..5b64dfb59
--- /dev/null
+++ b/external/cairo/cairo/cairo.buildfix.patch
@@ -0,0 +1,122 @@
+diff -ru cairo-1.17.4.orig/build/Makefile.win32.features cairo-1.17.4/build/Makefile.win32.features
+--- misc/cairo-1.17.4.orig/build/Makefile.win32.features 2021-08-29 19:43:27.093430425 +0100
++++ misc/build/cairo-1.17.4/build/Makefile.win32.features 2021-08-29 19:43:47.496506785 +0100
+@@ -30,7 +30,7 @@
+ CAIRO_HAS_FC_FONT=0
+ CAIRO_HAS_PS_SURFACE=1
+ CAIRO_HAS_PDF_SURFACE=1
+-CAIRO_HAS_SVG_SURFACE=1
++CAIRO_HAS_SVG_SURFACE=0
+ CAIRO_HAS_TEST_SURFACES=0
+ CAIRO_HAS_TEE_SURFACE=0
+ CAIRO_HAS_XML_SURFACE=0
+diff -ru cairo-1.17.4.orig/configure cairo-1.17.4/configure
+--- misc/cairo-1.17.4.orig/configure 2021-08-29 19:43:26.966436173 +0100
++++ misc/build/cairo-1.17.4/configure 2021-08-29 19:43:47.500506604 +0100
+@@ -17149,61 +17149,12 @@
+ rm -f confcache
+
+
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5
+-$as_echo_n "checking for compress in -lz... " >&6; }
+-if ${ac_cv_lib_z_compress+:} false; then :
+- $as_echo_n "(cached) " >&6
+-else
+- ac_check_lib_save_LIBS=$LIBS
+-LIBS="-lz $LIBS"
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-
+-/* Override any GCC internal prototype to avoid an error.
+- Use char because int might match the return type of a GCC
+- builtin and then its argument prototype would still apply. */
+-#ifdef __cplusplus
+-extern "C"
+-#endif
+-char compress ();
+-int
+-main ()
+-{
+-return compress ();
+- ;
+- return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_link "$LINENO"; then :
+- ac_cv_lib_z_compress=yes
+-else
+- ac_cv_lib_z_compress=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext \
+- conftest$ac_exeext conftest.$ac_ext
+-LIBS=$ac_check_lib_save_LIBS
+-fi
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5
+-$as_echo "$ac_cv_lib_z_compress" >&6; }
+-if test "x$ac_cv_lib_z_compress" = xyes; then :
+- ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+-if test "x$ac_cv_header_zlib_h" = xyes; then :
+
+ have_libz=yes
+
+ $as_echo "#define HAVE_ZLIB 1" >>confdefs.h
+
+
+-else
+- have_libz="no (requires zlib http://www.gzip.org/zlib/)"
+-fi
+-
+-
+-else
+- have_libz="no (requires zlib http://www.gzip.org/zlib/)"
+-fi
+-
+-
+ save_LIBS="$LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzo2a_decompress in -llzo2" >&5
+ $as_echo_n "checking for lzo2a_decompress in -llzo2... " >&6; }
+@@ -24319,7 +24270,7 @@
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_VERSION - OK" >&5
+ $as_echo "$FREETYPE_VERSION - OK" >&6; }
+ ft_NONPKGCONFIG_CFLAGS=`$FREETYPE_CONFIG --cflags`
+- ft_NONPKGCONFIG_LIBS=`$FREETYPE_CONFIG --libs`
++ ft_NONPKGCONFIG_LIBS=`$FREETYPE_CONFIG --libs | $SED -e 's/-lz//g'`
+ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_VERSION - Too old" >&5
+ $as_echo "$FREETYPE_VERSION - Too old" >&6; }
+ use_ft="no ($FREETYPE_VERSION found; version $FREETYPE_MIN_VERSION from release $FREETYPE_MIN_RELEASE required)"
+@@ -24329,7 +24280,7 @@
+ fi
+
+ ft_CFLAGS="$FREETYPE_CFLAGS"
+- ft_LIBS="$FREETYPE_LIBS"
++ ft_LIBS=`echo "$FREETYPE_LIBS" | $SED -e 's/-lz//g'`
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cairo's FreeType font backend feature could be enabled" >&5
+@@ -24962,7 +24913,7 @@
+
+ # The ps backend requires zlib.
+ use_ps=$have_libz
+- ps_NONPKGCONFIG_LIBS=-lz
++ ps_NONPKGCONFIG_LIBS=$ZLIB3RDLIB
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cairo's PostScript surface backend feature could be enabled" >&5
+@@ -25355,7 +25306,7 @@
+
+ # The pdf backend requires zlib.
+ use_pdf=$have_libz
+- pdf_NONPKGCONFIG_LIBS=-lz
++ pdf_NONPKGCONFIG_LIBS=$ZLIB3RDLIB
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cairo's PDF surface backend feature could be enabled" >&5
+@@ -27218,7 +27169,7 @@
+ use_xml="no (requires --enable-png)"
+ else
+ use_xml=$have_libz
+- xml_NONPKGCONFIG_LIBS=-lz
++ xml_NONPKGCONFIG_LIBS=$ZLIB3RDLIB
+ fi
+
+
diff --git a/external/cairo/cairo/cairo.ofz46165.patch.1 b/external/cairo/cairo/cairo.ofz46165.patch.1
new file mode 100644
index 000000000..948313c2a
--- /dev/null
+++ b/external/cairo/cairo/cairo.ofz46165.patch.1
@@ -0,0 +1,16 @@
+--- a/src/cairo-pen.c 2022-03-30 09:48:14.702456922 +0100
++++ b/src/cairo-pen.c 2022-03-30 09:50:40.011793460 +0100
+@@ -289,7 +289,12 @@
+ } else if (tolerance >= major_axis) {
+ num_vertices = 4;
+ } else {
+- num_vertices = ceil (2*M_PI / acos (1 - tolerance / major_axis));
++ double divisor = acos (1 - tolerance / major_axis);
++
++ if (divisor == 0.0)
++ return 4;
++
++ num_vertices = ceil (2*M_PI / divisor);
+
+ /* number of vertices must be even */
+ if (num_vertices % 2)
diff --git a/external/cairo/cairo/cairo.oldfreetype.patch b/external/cairo/cairo/cairo.oldfreetype.patch
new file mode 100644
index 000000000..a25c8bbdd
--- /dev/null
+++ b/external/cairo/cairo/cairo.oldfreetype.patch
@@ -0,0 +1,42 @@
+--- a/cairo/src/cairo-ft-font.c 2020-09-23 15:27:09.114619562 +0200
++++ b/cairo/src/cairo-ft-font.c 2020-09-23 15:27:22.602808705 +0200
+@@ -2838,7 +2838,7 @@
+ goto cleanup;
+ }
+
+-#if FREETYPE_MAJOR > 2 || ( FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 8)
++#if 0
+ /* If FT_Get_Var_Blend_Coordinates() is available, we can check if the
+ * current design coordinates are the default coordinates. In this case
+ * the current outlines match the font tables.
+--- a/cairo/src/cairo-ft-font.c 2020-09-24 10:35:25.391941702 +0200
++++ b/cairo/src/cairo-ft-font.c 2020-09-24 10:35:39.900126419 +0200
+@@ -451,7 +451,7 @@
+ unscaled->have_color = FT_HAS_COLOR (face) != 0;
+ unscaled->have_color_set = TRUE;
+
+-#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES
++#if 0
+ {
+ FT_MM_Var *ft_mm_var;
+ if (0 == FT_Get_MM_Var (face, &ft_mm_var))
+@@ -2377,7 +2377,7 @@
+ }
+
+ current_coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
+-#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES
++#if 0
+ ret = FT_Get_Var_Design_Coordinates (face, ft_mm_var->num_axis, current_coords);
+ if (ret == 0) {
+ for (i = 0; i < ft_mm_var->num_axis; i++) {
+--- a/cairo/test/font-variations.c 2020-09-24 10:36:01.592402635 +0200
++++ b/cairo/test/font-variations.c 2020-09-24 10:36:08.728493510 +0200
+@@ -117,7 +117,7 @@
+ return CAIRO_TEST_FAILURE;
+ }
+
+-#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES
++#if 0
+ ret = FT_Get_Var_Design_Coordinates (ft_face, 20, coords);
+ if (ret != 0) {
+ cairo_test_log (ctx, "Failed to get coords");
diff --git a/external/cairo/cairo/dummy_pkg_config b/external/cairo/cairo/dummy_pkg_config
new file mode 100755
index 000000000..829303ea5
--- /dev/null
+++ b/external/cairo/cairo/dummy_pkg_config
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+
diff --git a/external/cairo/cairo/san.patch.0 b/external/cairo/cairo/san.patch.0
new file mode 100644
index 000000000..272fef628
--- /dev/null
+++ b/external/cairo/cairo/san.patch.0
@@ -0,0 +1,103 @@
+--- src/cairo-fixed-private.h
++++ src/cairo-fixed-private.h
+@@ -61,7 +61,7 @@
+ static inline cairo_fixed_t
+ _cairo_fixed_from_int (int i)
+ {
+- return i << CAIRO_FIXED_FRAC_BITS;
++ return (unsigned)i << CAIRO_FIXED_FRAC_BITS;
+ }
+
+ /* This is the "magic number" approach to converting a double into fixed
+@@ -249,7 +249,7 @@
+ } else if ((f >> CAIRO_FIXED_FRAC_BITS) > INT16_MAX) {
+ x = INT32_MAX;
+ } else {
+- x = f << (16 - CAIRO_FIXED_FRAC_BITS);
++ x = (uint32_t)f << (16 - CAIRO_FIXED_FRAC_BITS);
+ }
+
+ return x;
+--- src/cairo-gstate.c
++++ src/cairo-gstate.c
+@@ -2297,7 +2297,7 @@
+ if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+ j++;
+ }
+- memcpy (transformed_clusters, clusters,
++ if (num_clusters != 0) memcpy (transformed_clusters, clusters,
+ num_clusters * sizeof (cairo_text_cluster_t));
+ } else {
+ const cairo_glyph_t *cur_glyph;
+@@ -2352,7 +2352,7 @@
+ if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
+ j++;
+ }
+- memcpy (transformed_clusters, clusters,
++ if (num_clusters != 0) memcpy (transformed_clusters, clusters,
+ num_clusters * sizeof (cairo_text_cluster_t));
+ } else {
+ const cairo_glyph_t *cur_glyph;
+--- src/cairo-image-source.c
++++ src/cairo-image-source.c
+@@ -509,7 +509,7 @@
+ return pixman_image_create_solid_fill (&color);
+
+ case CAIRO_FORMAT_RGB24_888:
+- pixel = *(uint32_t *) (image->data + y * image->stride + 3 * x);
++ pixel = (uint32_t)(image->data + y * image->stride + 3 * x)[0] | ((uint32_t)(image->data + y * image->stride + 3 * x)[1] << 8) | ((uint32_t)(image->data + y * image->stride + 3 * x)[2] << 16);
+ pixel &= 0x00ffffff; /* ignore next pixel bits */
+ if (pixel == 0)
+ return _pixman_black_image ();
+--- src/cairo-surface.c
++++ src/cairo-surface.c
+@@ -2849,7 +2849,7 @@
+
+ if (_cairo_scaled_font_has_color_glyphs (scaled_font)) {
+ utf8_copy = malloc (sizeof (char) * utf8_len);
+- memcpy (utf8_copy, utf8, sizeof (char) * utf8_len);
++ if (utf8_len != 0) memcpy (utf8_copy, utf8, sizeof (char) * utf8_len);
+ utf8 = utf8_copy;
+
+ status = composite_color_glyphs (surface, op,
+--- src/cairo-tor-scan-converter.c
++++ src/cairo-tor-scan-converter.c
+@@ -253,7 +253,7 @@
+ #elif GRID_XY == 15
+ # define GRID_AREA_TO_ALPHA(c) (((c) << 4) + (c))
+ #elif GRID_XY == 2*256*15
+-# define GRID_AREA_TO_ALPHA(c) (((c) + ((c)<<4) + 256) >> 9)
++# define GRID_AREA_TO_ALPHA(c) (((c) + ((uint32_t)(c)<<4) + 256) >> 9)
+ #else
+ # define GRID_AREA_TO_ALPHA(c) (((c)*255 + GRID_XY/2) / GRID_XY)
+ #endif
+--- src/cairo-xlib-render-compositor.c
++++ src/cairo-xlib-render-compositor.c
+@@ -1849,8 +1849,8 @@
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+- dx = -dst_x << 16;
+- dy = -dst_y << 16;
++ dx = (unsigned)-dst_x << 16;
++ dy = (unsigned)-dst_y << 16;
+ for (i = 0; i < traps->num_traps; i++) {
+ cairo_trapezoid_t *t = &traps->traps[i];
+
+--- src/cairo-xlib-surface-shm.c
++++ src/cairo-xlib-surface-shm.c
+@@ -1152,9 +1152,11 @@
+ cairo_surface_t *surface;
+
+ surface = NULL;
+- if (has_shm (other))
+- surface = &_cairo_xlib_shm_surface_create (other, format, width, height,
+- FALSE, has_shm_pixmaps (other))->image.base;
++ if (has_shm (other)) {
++ cairo_xlib_shm_surface_t * shm_surface = _cairo_xlib_shm_surface_create (other, format, width, height,
++ FALSE, has_shm_pixmaps (other));
++ if (shm_surface) surface = &shm_surface->image.base;
++ }
+
+ return surface;
+ }
diff --git a/external/cairo/pixman/pixman-0.24.4.patch b/external/cairo/pixman/pixman-0.24.4.patch
new file mode 100644
index 000000000..a5d32f88f
--- /dev/null
+++ b/external/cairo/pixman/pixman-0.24.4.patch
@@ -0,0 +1,91 @@
+--- misc/pixman-0.24.4/Makefile.in 2011-11-06 22:11:25.000000000 +0100
++++ misc/build/pixman-0.24.4/Makefile.in 2011-12-16 09:06:45.317211035 +0100
+@@ -385,7 +385,7 @@
+ top_build_prefix = @top_build_prefix@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+-SUBDIRS = pixman demos test
++SUBDIRS = pixman
+ pkgconfigdir = $(libdir)/pkgconfig
+ pkgconfig_DATA = pixman-1.pc
+ GPGKEY = 3892336E
+--- misc/pixman-0.24.4/pixman/pixman-utils.c
++++ misc/build/pixman-0.24.4/pixman/pixman-utils.c
+@@ -27,6 +27,7 @@
+ #endif
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <limits.h>
+
+ #include "pixman-private.h"
+
+--- misc/pixman-0.24.4/pixman/pixman-glyph.c 2015-06-30 05:48:31.000000000 -0400
++++ misc/build/pixman-0.24.4/pixman/pixman-glyph.c 2017-11-25 13:26:33.075558418 -0500
+@@ -38,6 +38,7 @@
+
+ /* XXX: These numbers are arbitrary---we've never done any measurements.
+ */
++#define N_PIXELS_HIGH_WATER (4 * 1024 * 1024)
+ #define N_GLYPHS_HIGH_WATER (16384)
+ #define N_GLYPHS_LOW_WATER (8192)
+ #define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER)
+@@ -58,6 +59,7 @@
+ int n_glyphs;
+ int n_tombstones;
+ int freeze_count;
++ long n_pixels;
+ pixman_list_t mru;
+ glyph_t * glyphs[HASH_SIZE];
+ };
+@@ -133,6 +135,7 @@
+ if (*loc == TOMBSTONE)
+ cache->n_tombstones--;
+ cache->n_glyphs++;
++ cache->n_pixels += glyph->image->bits.width * glyph->image->bits.height;
+
+ *loc = glyph;
+ }
+@@ -150,6 +153,7 @@
+ cache->glyphs[idx & HASH_MASK] = TOMBSTONE;
+ cache->n_tombstones++;
+ cache->n_glyphs--;
++ cache->n_pixels -= glyph->image->bits.width * glyph->image->bits.height;
+
+ /* Eliminate tombstones if possible */
+ if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL)
+@@ -180,6 +184,7 @@
+
+ cache->n_glyphs = 0;
+ cache->n_tombstones = 0;
++ cache->n_pixels = 0;
+ }
+
+ PIXMAN_EXPORT pixman_glyph_cache_t *
+@@ -194,6 +199,7 @@
+ cache->n_glyphs = 0;
+ cache->n_tombstones = 0;
+ cache->freeze_count = 0;
++ cache->n_pixels = 0;
+
+ pixman_list_init (&cache->mru);
+
+@@ -220,9 +226,9 @@
+ pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache)
+ {
+ if (--cache->freeze_count == 0 &&
+- cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER)
++ (cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER || cache->n_pixels > N_PIXELS_HIGH_WATER))
+ {
+- if (cache->n_tombstones > N_GLYPHS_HIGH_WATER)
++ if (cache->n_tombstones > N_GLYPHS_LOW_WATER)
+ {
+ /* More than half the entries are
+ * tombstones. Just dump the whole table.
+@@ -230,7 +236,7 @@
+ clear_table (cache);
+ }
+
+- while (cache->n_glyphs > N_GLYPHS_LOW_WATER)
++ while (cache->n_glyphs > N_GLYPHS_LOW_WATER || cache->n_pixels > N_PIXELS_HIGH_WATER)
+ {
+ glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail);
diff --git a/external/cairo/pixman/pixman-ubsan.patch b/external/cairo/pixman/pixman-ubsan.patch
new file mode 100644
index 000000000..64e5778ee
--- /dev/null
+++ b/external/cairo/pixman/pixman-ubsan.patch
@@ -0,0 +1,76 @@
+diff -ru pixman-0.42.2.orig/pixman/pixman-bits-image.c pixman-0.42.2/pixman/pixman-bits-image.c
+--- misc/pixman-0.42.2.orig/pixman/pixman-bits-image.c 2022-11-03 02:25:48.000000000 +0900
++++ misc/build/pixman-0.42.2/pixman/pixman-bits-image.c 2022-11-28 21:35:25.896969126 +0900
+@@ -351,8 +351,8 @@
+ * positioned relative to a particular phase (and not relative to whatever
+ * exact fraction we happen to get here).
+ */
+- x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
+- y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
++ x = ((uint32_t)(x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
++ y = ((uint32_t)(y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
+
+ px = (x & 0xffff) >> x_phase_shift;
+ py = (y & 0xffff) >> y_phase_shift;
+diff -ru pixman-0.42.2.orig/pixman/pixman-combine32.c pixman-0.42.2/pixman/pixman-combine32.c
+--- misc/pixman-0.42.2.orig/pixman/pixman-combine32.c 2022-02-02 05:51:25.000000000 +0900
++++ misc/build/pixman-0.42.2/pixman/pixman-combine32.c 2022-11-28 21:38:48.226968594 +0900
+@@ -589,7 +589,7 @@
+ rg = DIV_ONE_UN8 (rg); \
+ rb = DIV_ONE_UN8 (rb); \
+ \
+- *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb; \
++ *(dest + i) = (uint32_t)ra << 24 | rr << 16 | rg << 8 | rb; \
+ } \
+ } \
+ \
+diff -ru pixman-0.42.2.orig/pixman/pixman-fast-path.c pixman-0.42.2/pixman/pixman-fast-path.c
+--- misc/pixman-0.42.2.orig/pixman/pixman-fast-path.c 2022-10-18 02:47:42.000000000 +0900
++++ misc/build/pixman-0.42.2/pixman/pixman-fast-path.c 2022-11-28 21:53:12.596963317 +0900
+@@ -2758,8 +2758,8 @@
+ * positioned relative to a particular phase (and not relative to whatever
+ * exact fraction we happen to get here).
+ */
+- x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
+- y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
++ x = ((uint32_t)(vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
++ y = ((uint32_t)(vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
+
+ px = (x & 0xffff) >> x_phase_shift;
+ py = (y & 0xffff) >> y_phase_shift;
+@@ -2837,9 +2837,9 @@
+ sbtot = CLIP (sbtot, 0, 0xff);
+
+ #ifdef WORDS_BIGENDIAN
+- buffer[k] = (satot << 0) | (srtot << 8) | (sgtot << 16) | (sbtot << 24);
++ buffer[k] = (satot << 0) | (srtot << 8) | (sgtot << 16) | ((uint32_t)sbtot << 24);
+ #else
+- buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
++ buffer[k] = ((uint32_t)satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0);
+ #endif
+
+ next:
+diff -ru pixman-0.42.2.orig/pixman/pixman-sse2.c pixman-0.42.2/pixman/pixman-sse2.c
+--- misc/pixman-0.42.2/pixman/pixman-sse2.c 2022-02-02 05:51:25.000000000 +0900
++++ misc/build/pixman-0.42.2/pixman/pixman-sse2.c 2022-11-28 22:11:19.276969466 +0900
+@@ -3345,7 +3345,7 @@
+
+ b = filler & 0xff;
+ w = (b << 8) | b;
+- filler = (w << 16) | w;
++ filler = ((uint32_t)w << 16) | w;
+ }
+ else if (bpp == 16)
+ {
+diff -ru pixman-0.42.2.orig/pixman/pixman-utils.c pixman-0.42.2/pixman/pixman-utils.c
+--- misc/pixman-0.42.2.orig/pixman/pixman-utils.c 2022-02-02 05:51:25.000000000 +0900
++++ misc/build/pixman-0.42.2/pixman/pixman-utils.c 2022-11-28 21:55:44.196964912 +0900
+@@ -213,7 +213,7 @@
+ g = float_to_unorm (src[i].g, 8);
+ b = float_to_unorm (src[i].b, 8);
+
+- dst[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
++ dst[i] = ((uint32_t)a << 24) | (r << 16) | (g << 8) | (b << 0);
+ }
+ }
+