Merge branch 'revise-svgload'

This commit is contained in:
John Cupitt 2019-09-12 13:11:17 +01:00
commit d8cb96581d
1 changed files with 29 additions and 37 deletions

View File

@ -17,6 +17,8 @@
* 28/6/19 * 28/6/19
* - add "unlimited" * - add "unlimited"
* - requires us to use the gio API to librsvg * - requires us to use the gio API to librsvg
* 11/9/19
* - rework as a sequential loader to reduce overcomputation
*/ */
/* /*
@ -239,15 +241,13 @@ vips_foreign_load_svg_dispose( GObject *gobject )
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_svg_get_flags_filename( const char *filename ) vips_foreign_load_svg_get_flags_filename( const char *filename )
{ {
/* We can render any part of the page on demand. return( VIPS_FOREIGN_SEQUENTIAL );
*/
return( VIPS_FOREIGN_PARTIAL );
} }
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_svg_get_flags( VipsForeignLoad *load ) vips_foreign_load_svg_get_flags( VipsForeignLoad *load )
{ {
return( VIPS_FOREIGN_PARTIAL ); return( VIPS_FOREIGN_SEQUENTIAL );
} }
static void static void
@ -328,6 +328,12 @@ vips_foreign_load_svg_generate( VipsRegion *or,
cairo_t *cr; cairo_t *cr;
int y; int y;
#ifdef DEBUG
printf( "vips_foreign_load_svg_generate:\n "
"left = %d, top = %d, width = %d, height = %d\n",
r->left, r->top, r->width, r->height );
#endif /*DEBUG*/
/* rsvg won't always paint the background. /* rsvg won't always paint the background.
*/ */
vips_region_black( or ); vips_region_black( or );
@ -371,44 +377,30 @@ vips_foreign_load_svg_load( VipsForeignLoad *load )
{ {
VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) load; VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) load;
VipsImage **t = (VipsImage **) VipsImage **t = (VipsImage **)
vips_object_local_array( (VipsObject *) load, 2 ); vips_object_local_array( (VipsObject *) load, 3 );
int tile_width;
int tile_height;
int max_tiles;
/* Read to this image, then cache to out, see below.
*/
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 ) )
return( -1 );
/* librsvg starts to fail if any axis in a single render call is over /* librsvg starts to fail if any axis in a single render call is over
* 32767. Use a tilecache so we can render very wide images, though we * RSVG_MAX_WIDTH pixels. vips_sequential() will use a tilecache where
* set it up like a linecache. * 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.
* *
* Don't thread the cache: we rely on this to keep calls to rsvg * Make tiles 2000 pixels high to limit overcomputation.
* single-threaded.
*
* Make tiles 2000 pixels high to limit overcomputation. Make sure we
* have two rows of tiles so we don't recompute requests that cross
* tile boundaries.
*/ */
tile_width = VIPS_MIN( t[0]->Xsize, RSVG_MAX_WIDTH ); t[0] = vips_image_new();
max_tiles = 2 * VIPS_ROUND_UP( t[0]->Xsize, RSVG_MAX_WIDTH ) / vips_foreign_load_svg_parse( svg, t[0] );
RSVG_MAX_WIDTH; if( vips_image_generate( t[0],
tile_height = 2000; NULL, vips_foreign_load_svg_generate, NULL, svg, NULL ) ||
if( vips_tilecache( t[0], &t[1], vips_tilecache( t[0], &t[1],
"tile_width", tile_width, "tile_width", VIPS_MIN( t[0]->Xsize, RSVG_MAX_WIDTH ),
"tile_height", tile_height, "tile_height", 2000,
"max_tiles", max_tiles, "max_tiles", 1,
"access", VIPS_ACCESS_SEQUENTIAL, NULL ) ||
NULL ) ) vips_sequential( t[1], &t[2],
return( -1 ); "tile_height", 2000,
if( vips_image_write( t[1], load->real ) ) NULL ) ||
vips_image_write( t[2], load->real ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );