Scale SVG without width/height attrs using cairo

This commit is contained in:
Lovell Fuller 2017-09-03 20:11:16 +01:00
parent 5a37d3e809
commit 980095a8cc

View File

@ -89,6 +89,10 @@ typedef struct _VipsForeignLoadSvg {
*/ */
double scale; double scale;
/* Scale using cairo when SVG has no width and height attributes.
*/
double cairo_scale;
RsvgHandle *page; RsvgHandle *page;
} VipsForeignLoadSvg; } VipsForeignLoadSvg;
@ -128,17 +132,46 @@ vips_foreign_load_svg_parse( VipsForeignLoadSvg *svg,
VipsImage *out ) VipsImage *out )
{ {
RsvgDimensionData dimensions; RsvgDimensionData dimensions;
int width;
int height;
double scale;
double res; double res;
rsvg_handle_set_dpi( svg->page, svg->dpi * svg->scale ); /* Calculate dimensions at default dpi/scale.
*/
rsvg_handle_set_dpi( svg->page, 72.0 );
rsvg_handle_get_dimensions( svg->page, &dimensions ); 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. /* We need pixels/mm for vips.
*/ */
res = svg->dpi / 25.4; res = svg->dpi / 25.4;
vips_image_init_fields( out, vips_image_init_fields( out,
dimensions.width, dimensions.height, width, height,
4, VIPS_FORMAT_UCHAR, 4, VIPS_FORMAT_UCHAR,
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, res, res ); VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, res, res );
@ -182,7 +215,9 @@ vips_foreign_load_svg_generate( VipsRegion *or,
cr = cairo_create( surface ); cr = cairo_create( surface );
cairo_surface_destroy( 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 /* rsvg is single-threaded, but we don't need to lock since we're
* running inside a non-threaded tilecache. * running inside a non-threaded tilecache.
@ -285,6 +320,7 @@ vips_foreign_load_svg_init( VipsForeignLoadSvg *svg )
{ {
svg->dpi = 72.0; svg->dpi = 72.0;
svg->scale = 1.0; svg->scale = 1.0;
svg->cairo_scale = 1.0;
} }
typedef struct _VipsForeignLoadSvgFile { typedef struct _VipsForeignLoadSvgFile {