Merge branch 'revise-svgload'
This commit is contained in:
commit
d8cb96581d
|
@ -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 );
|
||||||
|
|
Loading…
Reference in New Issue