Submitted By: Xi Ruoyao Date: 2025-01-31 Initial Package Version: 4.16.12 Upstream Status: Committed Origin: Upstream MR 8158 Description: Fix compatibility with libpng >= 1.6.45 From 58844ec795819df880ff0bf6b05a11999d0b9aff Mon Sep 17 00:00:00 2001 From: Alessandro Astone Date: Tue, 28 Jan 2025 18:05:07 +0100 Subject: [PATCH] png: handle cICP chunk via libpng API libpng 1.6.45 has gained the ability to read and write the cICP chunk. libpng will now recognize the cICP chunk as a "known" chunk and thus will not present it as a "user" chunk anymore, breaking our handling. We thus need to switch to using the API. The png data changes because libpng writes the cICP chunk at a different position than we were, so adjust the tests reference data accordingly. Fixes: #7271 --- gdk/loaders/gdkpng.c | 39 +++++++++++++++++-- testsuite/gsk/meson.build | 18 ++++++--- .../nodeparser/empty-texture-scale.ref.node | 4 +- .../gsk/nodeparser/empty-texture.ref.node | 4 +- .../gsk/nodeparser/texture-fail.ref.node | 4 +- testsuite/gsk/nodeparser/texture-names.node | 4 +- .../nodeparser/texture-scale-filters.ref.node | 16 ++++---- .../texture-scale-unknown-filter.ref.node | 4 +- 8 files changed, 66 insertions(+), 27 deletions(-) diff --git a/gdk/loaders/gdkpng.c b/gdk/loaders/gdkpng.c index 212e3de1776..b82fd05ebdb 100644 --- a/gdk/loaders/gdkpng.c +++ b/gdk/loaders/gdkpng.c @@ -130,6 +130,7 @@ png_simple_warning_callback (png_structp png, /* }}} */ /* {{{ Color profile handling */ +#if PNG_LIBPNG_VER < 10645 typedef struct { gboolean cicp_chunk_read; @@ -174,6 +175,7 @@ gdk_png_get_color_state_from_cicp (const CICPData *data, return gdk_color_state_new_for_cicp (&cicp, error); } +#endif static GdkColorState * gdk_png_get_color_state (png_struct *png, @@ -181,16 +183,35 @@ gdk_png_get_color_state (png_struct *png, GError **error) { GdkColorState *color_state; - CICPData *cicp; int intent; - cicp = png_get_user_chunk_ptr (png); +#if PNG_LIBPNG_VER >= 10645 + png_byte color_primaries; + png_byte transfer_function; + png_byte matrix_coefficients; + png_byte range; - if (cicp->cicp_chunk_read) + if (png_get_cICP (png, info, &color_primaries, &transfer_function, &matrix_coefficients, &range)) { GError *local_error = NULL; + GdkCicp cicp; + cicp.color_primaries = color_primaries; + cicp.transfer_function = transfer_function; + cicp.matrix_coefficients = matrix_coefficients; + cicp.range = range; + + color_state = gdk_color_state_new_for_cicp (&cicp, error); +#else + CICPData *cicp; + + cicp = png_get_user_chunk_ptr (png); + if (cicp->cicp_chunk_read) + { + GError *local_error = NULL; color_state = gdk_png_get_color_state_from_cicp (cicp, &local_error); +#endif + if (color_state) { g_debug ("Color state from cICP data: %s", gdk_color_state_get_name (color_state)); @@ -236,6 +257,13 @@ gdk_png_set_color_state (png_struct *png, if (cicp) { +#if PNG_LIBPNG_VER >= 10645 + png_set_cICP (png, info, + (png_byte) cicp->color_primaries, + (png_byte) cicp->transfer_function, + (png_byte) 0 /* png only supports this */, + (png_byte) cicp->range); +#else png_unknown_chunk chunk = { .name = { 'c', 'I', 'C', 'P', '\0' }, .data = chunk_data, @@ -249,6 +277,7 @@ gdk_png_set_color_state (png_struct *png, chunk_data[3] = (png_byte) cicp->range; png_set_unknown_chunks (png, info, &chunk, 1); +#endif } else { @@ -287,7 +316,9 @@ gdk_load_png (GBytes *bytes, GdkColorState *color_state; GdkTexture *texture; int bpp; +#if PNG_LIBPNG_VER < 10645 CICPData cicp = { FALSE, }; +#endif G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME; @@ -309,7 +340,9 @@ gdk_load_png (GBytes *bytes, g_error ("Out of memory"); png_set_read_fn (png, &io, png_read_func); +#if PNG_LIBPNG_VER < 10645 png_set_read_user_chunk_fn (png, &cicp, png_read_chunk_func); +#endif if (sigsetjmp (png_jmpbuf (png), 1)) { diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 6e2ee41fa75..72b6174f609 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -380,9 +380,7 @@ node_parser_tests = [ 'empty-subsurface.ref.node', 'empty-text.node', 'empty-text.ref.node', - 'empty-texture.node', 'empty-texture.ref.node', - 'empty-texture-scale.node', 'empty-texture-scale.ref.node', 'empty-transform.node', 'empty-transform.ref.node', @@ -442,14 +440,10 @@ node_parser_tests = [ 'text-font-options-error.ref.node', 'text-font-options-error.ref.errors', 'text-no-color.node', - 'texture-fail.node', 'texture-fail.ref.node', 'texture-fail.errors', - 'texture-names.node', - 'texture-scale-filters.node', 'texture-scale-filters.ref.node', 'texture-scale-unknown-filter.errors', - 'texture-scale-unknown-filter.node', 'texture-scale-unknown-filter.ref.node', 'transform-fail.node', 'transform-fail.ref.node', @@ -458,6 +452,18 @@ node_parser_tests = [ #'widgetfactory.node', ] +# libpng 1.6.45 changes the chunk order. These ref tests can only pass on libpng >=1.6.45 +if png_dep.version().version_compare('>=1.6.45') +node_parser_tests += [ + 'empty-texture-scale.node', + 'empty-texture.node', + 'texture-fail.node', + 'texture-names.node', + 'texture-scale-filters.node', + 'texture-scale-unknown-filter.node', +] +endif + foreach test : node_parser_tests if test.endswith('.node') and not test.endswith('.ref.node') test('parser ' + test, node_parser, diff --git a/testsuite/gsk/nodeparser/empty-texture-scale.ref.node b/testsuite/gsk/nodeparser/empty-texture-scale.ref.node index d91d33481dd..3bf6759a40b 100644 --- a/testsuite/gsk/nodeparser/empty-texture-scale.ref.node +++ b/testsuite/gsk/nodeparser/empty-texture-scale.ref.node @@ -1,8 +1,8 @@ texture-scale { bounds: 0 0 50 50; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ FQAAAABJRU5ErkJggg==\ "); } diff --git a/testsuite/gsk/nodeparser/empty-texture.ref.node b/testsuite/gsk/nodeparser/empty-texture.ref.node index 4a52442007d..bebc47a93b1 100644 --- a/testsuite/gsk/nodeparser/empty-texture.ref.node +++ b/testsuite/gsk/nodeparser/empty-texture.ref.node @@ -1,8 +1,8 @@ texture { bounds: 0 0 50 50; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ FQAAAABJRU5ErkJggg==\ "); } diff --git a/testsuite/gsk/nodeparser/texture-fail.ref.node b/testsuite/gsk/nodeparser/texture-fail.ref.node index 4a52442007d..bebc47a93b1 100644 --- a/testsuite/gsk/nodeparser/texture-fail.ref.node +++ b/testsuite/gsk/nodeparser/texture-fail.ref.node @@ -1,8 +1,8 @@ texture { bounds: 0 0 50 50; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ FQAAAABJRU5ErkJggg==\ "); } diff --git a/testsuite/gsk/nodeparser/texture-names.node b/testsuite/gsk/nodeparser/texture-names.node index c03aef5571c..2656455007d 100644 --- a/testsuite/gsk/nodeparser/texture-names.node +++ b/testsuite/gsk/nodeparser/texture-names.node @@ -1,8 +1,8 @@ texture { bounds: 0 0 1 1; texture: "texture1" url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAANSURBVAiZY/jPwPAfAAUAAf+rzjaJAAAAAElFTkSuQmCC\ +iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAANSURBVAiZY/jPwPAfAAUAAf+rzjaJAAAAAElFTkSuQmCC\ "); } texture { diff --git a/testsuite/gsk/nodeparser/texture-scale-filters.ref.node b/testsuite/gsk/nodeparser/texture-scale-filters.ref.node index ac17829ce7d..f9b66bf6a81 100644 --- a/testsuite/gsk/nodeparser/texture-scale-filters.ref.node +++ b/testsuite/gsk/nodeparser/texture-scale-filters.ref.node @@ -1,30 +1,30 @@ texture-scale { bounds: 0 0 50 50; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ "); } texture-scale { bounds: 0 0 50 50; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ "); } texture-scale { bounds: 0 0 50 50; filter: nearest; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ "); } texture-scale { bounds: 0 0 50 50; filter: trilinear; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAAYSURBVBiVY/zPwPCfgQjARIyiUYXUUwgAPZwCEvXDjugAAAAASUVORK5CYII=\ "); } diff --git a/testsuite/gsk/nodeparser/texture-scale-unknown-filter.ref.node b/testsuite/gsk/nodeparser/texture-scale-unknown-filter.ref.node index d91d33481dd..3bf6759a40b 100644 --- a/testsuite/gsk/nodeparser/texture-scale-unknown-filter.ref.node +++ b/testsuite/gsk/nodeparser/texture-scale-unknown-filter.ref.node @@ -1,8 +1,8 @@ texture-scale { bounds: 0 0 50 50; texture: url("data:image/png;base64,\ -iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARjSUNQAQ0A\ -AZxpOzIAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ +iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGNJQ1ABDQABnGk7MgAAAAFzUkdC\ +AK7OHOkAAAApSURBVBiVY/zPcOY/AxpgZDBhRBdjQhfABQZQIYajGRgYGLB5cCh4BgDPjgXd7dTX\ FQAAAABJRU5ErkJggg==\ "); } -- GitLab