From 16a6c08af70cf3613f438c68a20638239fcfb07c Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 11 Jun 2021 10:35:17 +0100 Subject: [PATCH 1/2] update svgload to work with latest librsvg rsvg_handle_render_cairo() is deprecated --- configure.ac | 8 ++++++ libvips/foreign/svgload.c | 56 +++++++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index aa53f7ba..2a3bd207 100644 --- a/configure.ac +++ b/configure.ac @@ -1009,6 +1009,14 @@ if test x"$with_rsvg" != x"no"; then AC_DEFINE(HAVE_RSVG,1,[define if you have librsvg-2.0 >= 2.40.3 and cairo >= 1.2 installed.]) with_rsvg=yes PACKAGES_USED="$PACKAGES_USED librsvg-2.0 cairo" + + # 2.46 for rsvg_handle_render_document + PKG_CHECK_MODULES(RSVG_HANDLE_RENDER_DOCUMENT, librsvg-2.0 >= 2.46, + [AC_DEFINE(HAVE_RSVG_HANDLE_RENDER_DOCUMENT,1,[define if your librsvg has rsvg_handle_render_document().]) + ], + [: + ] + ) ], [ AC_MSG_WARN([librsvg-2.0 >= 2.40.3 or cairo >= 1.2 not found; disabling SVG load via rsvg]) with_rsvg=no diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index 8b9106f9..74b58c5b 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -19,6 +19,9 @@ * - requires us to use the gio API to librsvg * 11/9/19 * - rework as a sequential loader to reduce overcomputation + * 11/6/21 + * - switch to rsvg_handle_render_document() + * - librsvg can no longer render very large images :( */ /* @@ -76,10 +79,6 @@ */ #define SVG_HEADER_SIZE (1000) -/* The maximum pixel width librsvg is able to render. - */ -#define RSVG_MAX_WIDTH (32767) - /* A handy #define for we-will-handle-svgz. */ #if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZLIB) @@ -316,9 +315,9 @@ static int vips_foreign_load_svg_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { - VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) a; - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( svg ); - VipsRect *r = &or->valid; + const VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) a; + const VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( svg ); + const VipsRect *r = &or->valid; cairo_surface_t *surface; cairo_t *cr; @@ -342,22 +341,46 @@ vips_foreign_load_svg_generate( VipsRegion *or, cr = cairo_create( surface ); cairo_surface_destroy( surface ); + /* rsvg is single-threaded, but we don't need to lock since we're + * running inside a non-threaded tilecache. + */ +#ifdef HAVE_RSVG_HANDLE_RENDER_DOCUMENT +{ + RsvgRectangle viewport; + GError *error = NULL; + + cairo_translate( cr, -r->left, -r->top ); + viewport.x = 0; + viewport.y = 0; + viewport.width = or->im->Xsize; + viewport.height = or->im->Ysize; + + if( !rsvg_handle_render_document( svg->page, cr, &viewport, &error ) ) { + cairo_destroy( cr ); + vips_operation_invalidate( VIPS_OPERATION( svg ) ); + vips_error( class->nickname, + "%s", _( "SVG rendering failed" ) ); + vips_g_error( &error ); + return( -1 ); + } + + cairo_destroy( cr ); +} +#else /*!HAVE_RSVG_HANDLE_RENDER_DOCUMENT*/ cairo_scale( cr, svg->cairo_scale, svg->cairo_scale ); cairo_translate( cr, -r->left / svg->cairo_scale, -r->top / svg->cairo_scale ); - /* rsvg is single-threaded, but we don't need to lock since we're - * running inside a non-threaded tilecache. - */ if( !rsvg_handle_render_cairo( svg->page, cr ) ) { cairo_destroy( cr ); vips_operation_invalidate( VIPS_OPERATION( svg ) ); - vips_error( class->nickname, + vips_error( class->nickname, "%s", _( "SVG rendering failed" ) ); return( -1 ); } cairo_destroy( cr ); +#endif /*HAVE_RSVG_HANDLE_RENDER_DOCUMENT*/ /* Cairo makes pre-multipled BRGA -- we must byteswap and unpremultiply. */ @@ -376,21 +399,14 @@ vips_foreign_load_svg_load( VipsForeignLoad *load ) VipsImage **t = (VipsImage **) vips_object_local_array( (VipsObject *) load, 3 ); - /* librsvg starts to fail if any axis in a single render call is over - * RSVG_MAX_WIDTH pixels. vips_sequential() will use a tilecache where - * each tile is a strip the width of the image and (in this case) - * 2000 pixels high. To be able to render images wider than - * RSVG_MAX_WIDTH pixels, we need to chop these strips up. - * We use a small tilecache between the seq and our gen to do this. - * - * Make tiles 2000 pixels high to limit overcomputation. + /* Make tiles 2000 pixels high to limit overcomputation. */ t[0] = vips_image_new(); vips_foreign_load_svg_parse( svg, t[0] ); if( vips_image_generate( t[0], NULL, vips_foreign_load_svg_generate, NULL, svg, NULL ) || vips_tilecache( t[0], &t[1], - "tile_width", VIPS_MIN( t[0]->Xsize, RSVG_MAX_WIDTH ), + "tile_width", t[0]->Xsize, "tile_height", 2000, "max_tiles", 1, NULL ) || From 914c7cf18590d1d8ac931360456363693037538b Mon Sep 17 00:00:00 2001 From: Adil Benameur Date: Mon, 19 Jul 2021 01:22:46 +0200 Subject: [PATCH 2/2] added the jxl save functions to foreign.h --- libvips/include/vips/foreign.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 8b45bd31..bdc70df6 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -699,6 +699,12 @@ int vips_jxlload_buffer( void *buf, size_t len, VipsImage **out, ... ) __attribute__((sentinel)); int vips_jxlload( const char *filename, VipsImage **out, ... ) __attribute__((sentinel)); +int vips_jxlsave( VipsImage *in, const char *filename, ... ) + __attribute__((sentinel)); +int vips_jxlsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) + __attribute__((sentinel)); +int vips_jxlsave_target( VipsImage *in, VipsTarget *target, ... ) + __attribute__((sentinel)); /** * VipsForeignDzLayout: