Merge pull request #724 from lovell/svg-scale

Correct scaling of SVG input without width and height attributes
This commit is contained in:
John Cupitt 2017-09-17 05:12:44 +01:00 committed by GitHub
commit 99053d41cb
1 changed files with 40 additions and 4 deletions

View File

@ -91,6 +91,10 @@ typedef struct _VipsForeignLoadSvg {
*/
double scale;
/* Scale using cairo when SVG has no width and height attributes.
*/
double cairo_scale;
RsvgHandle *page;
} VipsForeignLoadSvg;
@ -130,17 +134,46 @@ vips_foreign_load_svg_parse( VipsForeignLoadSvg *svg,
VipsImage *out )
{
RsvgDimensionData dimensions;
int width;
int height;
double scale;
double res;
rsvg_handle_set_dpi( svg->page, svg->dpi * svg->scale );
rsvg_handle_get_dimensions( svg->page, &dimensions );
/* Calculate dimensions at default dpi/scale.
*/
rsvg_handle_set_dpi( svg->page, 72.0 );
rsvg_handle_get_dimensions( svg->page, &dimensions );
width = dimensions.width;
height = dimensions.height;
/* Calculate dimensions at required dpi/scale.
*/
scale = svg->scale * svg->dpi / 72.0;
if( scale != 1.0 ) {
rsvg_handle_set_dpi( svg->page, svg->dpi * svg->scale );
rsvg_handle_get_dimensions( svg->page, &dimensions );
if( width == dimensions.width && height == dimensions.height ) {
/* SVG without width and height always reports 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 = dimensions.width;
height = dimensions.height;
}
}
/* We need pixels/mm for vips.
*/
res = svg->dpi / 25.4;
vips_image_init_fields( out,
dimensions.width, dimensions.height,
width, height,
4, VIPS_FORMAT_UCHAR,
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, res, res );
@ -184,7 +217,9 @@ vips_foreign_load_svg_generate( VipsRegion *or,
cr = cairo_create( surface );
cairo_surface_destroy( surface );
cairo_translate( cr, -r->left, -r->top );
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.
@ -295,6 +330,7 @@ vips_foreign_load_svg_init( VipsForeignLoadSvg *svg )
{
svg->dpi = 72.0;
svg->scale = 1.0;
svg->cairo_scale = 1.0;
}
typedef struct _VipsForeignLoadSvgFile {