diff --git a/.gitignore b/.gitignore index 55c8283b..78ae3376 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ -compile +release +build +debug .pytest_cache .dirstamp a.out @@ -29,8 +31,6 @@ tags *.o *.a fuzz/*_fuzzer -Vips-8.0.gir -Vips-8.0.typelib .*.swp *.lo *.bak diff --git a/libvips/foreign/svgload.c b/libvips/foreign/svgload.c index fd6fd3a0..4b86980b 100644 --- a/libvips/foreign/svgload.c +++ b/libvips/foreign/svgload.c @@ -24,6 +24,8 @@ * - librsvg can no longer render very large images :( * 14/10/21 * - allow utf-8 headers for svg detection + * 28/4/22 + * - support rsvg_handle_get_intrinsic_size_in_pixels() */ /* @@ -317,8 +319,75 @@ vips_foreign_load_svg_get_flags( VipsForeignLoad *load ) return( VIPS_FOREIGN_SEQUENTIAL ); } +#ifdef HAVE_RSVG_HANDLE_GET_INTRINSIC_SIZE_IN_PIXELS + static int -vips_foreign_load_svg_parse( VipsForeignLoadSvg *svg, VipsImage *out ) +vips_foreign_load_svg_get_size( VipsForeignLoadSvg *svg, + int *out_width, int *out_height ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( svg ); + + double width; + double height; + double scale; + + /* If the SVG does not define a width or height we will fall back to + * this size. The SVG will be rendered to fit this viewport + * by rsvg_handle_render_document() below. + */ + width = 1928; + height = 1080; + + /* Get dimensions with the default scale. + */ + rsvg_handle_set_dpi( svg->page, 72.0 ); + rsvg_handle_get_intrinsic_size_in_pixels( svg->page, &width, &height ); + if( width <= 0 || height <= 0 ) { + vips_error( class->nickname, "%s", _( "bad dimensions" ) ); + return( -1 ); + } + + /* Calculate dimensions at required dpi/scale. + */ + scale = svg->scale * svg->dpi / 72.0; + if( scale != 1.0 ) { + double scaled_width; + double scaled_height; + + rsvg_handle_set_dpi( svg->page, svg->dpi * svg->scale ); + rsvg_handle_get_intrinsic_size_in_pixels( svg->page, + &scaled_width, &scaled_height ); + + if( scaled_width == width && + scaled_height == height ) { + /* SVG without width and height always reports the same + * dimensions regardless of dpi. Apply dpi/scale using + * cairo instead. + */ + svg->cairo_scale = scale; + width = width * scale; + height = height * scale; + } + else { + /* SVG with width and height reports correctly scaled + * dimensions. + */ + width = scaled_width; + height = scaled_height; + } + } + + *out_width = VIPS_ROUND_UINT( width ); + *out_height = VIPS_ROUND_UINT( height ); + + return ( 0 ); +} + +#else /*!HAVE_RSVG_HANDLE_GET_INTRINSIC_SIZE_IN_PIXELS*/ + +static int +vips_foreign_load_svg_get_size( VipsForeignLoadSvg *svg, + int *out_width, int *out_height ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( svg ); @@ -326,7 +395,6 @@ vips_foreign_load_svg_parse( VipsForeignLoadSvg *svg, VipsImage *out ) int width; int height; double scale; - double res; /* Calculate dimensions at default dpi/scale. */ @@ -366,6 +434,24 @@ vips_foreign_load_svg_parse( VipsForeignLoadSvg *svg, VipsImage *out ) } } + *out_width = width; + *out_height = height; + + return ( 0 ); +} + +#endif/*HAVE_RSVG_HANDLE_GET_INTRINSIC_SIZE_IN_PIXELS*/ + +static int +vips_foreign_load_svg_parse( VipsForeignLoadSvg *svg, VipsImage *out ) +{ + int width; + int height; + double res; + + if( vips_foreign_load_svg_get_size( svg, &width, &height ) ) + return( -1 ); + /* We need pixels/mm for vips. */ res = svg->dpi / 25.4; diff --git a/meson.build b/meson.build index 3718cb88..b1683e70 100644 --- a/meson.build +++ b/meson.build @@ -354,6 +354,10 @@ if librsvg_dep.found() and cairo_dep.found() if librsvg_dep.version().version_compare('>=2.46') cfg_var.set('HAVE_RSVG_HANDLE_RENDER_DOCUMENT', '1') endif + # 2.56 for rsvg_handle_get_intrinsic_size_in_pixels + if librsvg_dep.version().version_compare('>=2.52') + cfg_var.set('HAVE_RSVG_HANDLE_GET_INTRINSIC_SIZE_IN_PIXELS', '1') + endif endif openslide_dep = dependency('openslide', version: '>=3.3.0', required: get_option('openslide'))