small cleanups to svgz support

This commit is contained in:
John Cupitt 2016-08-01 14:28:35 +01:00
parent fe615af233
commit b0e3035590
4 changed files with 62 additions and 36 deletions

View File

@ -31,6 +31,7 @@
- added vips_perlin(), generate Perlin noise - added vips_perlin(), generate Perlin noise
- gif loader can write 1, 2, 3, or 4 bands depending on file contents - gif loader can write 1, 2, 3, or 4 bands depending on file contents
- support --strip for pngsave - support --strip for pngsave
- add svgz support [Felix Bünemann]
30/7/16 started 8.3.3 30/7/16 started 8.3.3
- fix performance regression in 8.3.2, thanks Lovell - fix performance regression in 8.3.2, thanks Lovell

2
TODO
View File

@ -1,3 +1,5 @@
- can we hjave .svg.gz as a suffix? should be possible
- try: - try:
$ vips avg broken.jpg[fail] $ vips avg broken.jpg[fail]

View File

@ -1061,6 +1061,7 @@ PDF import with poppler-glib: $with_poppler
(requires poppler-glib 0.16.0 or later) (requires poppler-glib 0.16.0 or later)
SVG import with librsvg-2.0: $with_rsvg SVG import with librsvg-2.0: $with_rsvg
(requires librsvg-2.0 2.34.0 or later) (requires librsvg-2.0 2.34.0 or later)
zlib: $with_zlib
file import with cfitsio: $with_cfitsio file import with cfitsio: $with_cfitsio
file import/export with libwebp: $with_libwebp file import/export with libwebp: $with_libwebp
(requires libwebp-0.1.3 or later) (requires libwebp-0.1.3 or later)

View File

@ -2,6 +2,8 @@
* *
* 7/2/16 * 7/2/16
* - from svgload.c * - from svgload.c
* 1/8/16 felixbuenemann
* - add svgz support
*/ */
/* /*
@ -54,14 +56,21 @@
#include <cairo.h> #include <cairo.h>
#include <librsvg/rsvg.h> #include <librsvg/rsvg.h>
/* Old librsvg versions don't include librsvg-features.h by default,
* while newer versions deprecate direct inclusion. /* Old librsvg versions don't include librsvg-features.h by default.
* Newer versions deprecate direct inclusion.
*/ */
#ifndef LIBRSVG_FEATURES_H #ifndef LIBRSVG_FEATURES_H
#include <librsvg/librsvg-features.h> #include <librsvg/librsvg-features.h>
#endif #endif
/* A handy #define for we-will-handle-svgz.
*/
#if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZLIB) #if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZLIB)
#define HANDLE_SVGZ
#endif
#ifdef HANDLE_SVGZ
#include <zlib.h> #include <zlib.h>
#endif #endif
@ -325,6 +334,8 @@ vips_foreign_load_svg_file_header( VipsForeignLoad *load )
static const char *vips_foreign_svg_suffs[] = { static const char *vips_foreign_svg_suffs[] = {
".svg", ".svg",
/* librsvg supports svgz directly, no need to check for zlib here.
*/
#if LIBRSVG_CHECK_FEATURE(SVGZ) #if LIBRSVG_CHECK_FEATURE(SVGZ)
".svgz", ".svgz",
#endif #endif
@ -377,65 +388,77 @@ typedef VipsForeignLoadSvgClass VipsForeignLoadSvgBufferClass;
G_DEFINE_TYPE( VipsForeignLoadSvgBuffer, vips_foreign_load_svg_buffer, G_DEFINE_TYPE( VipsForeignLoadSvgBuffer, vips_foreign_load_svg_buffer,
vips_foreign_load_svg_get_type() ); vips_foreign_load_svg_get_type() );
#if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZLIB) #ifdef HANDLE_SVGZ
static void * static void *
vips_zalloc( void *opaque, unsigned items, unsigned size ) vips_foreign_load_svg_zalloc( void *opaque, unsigned items, unsigned size )
{ {
return( g_malloc0_n( items, size ) ); return( g_malloc0_n( items, size ) );
} }
static void static void
vips_zfree( void *opaque, void *ptr ) vips_foreign_load_svg_zfree( void *opaque, void *ptr )
{ {
return( g_free( ptr ) ); return( g_free( ptr ) );
} }
#endif #endif /*HANDLE_SVGZ*/
static gboolean static gboolean
vips_foreign_load_svg_is_a_buffer( const void *buf, size_t len ) vips_foreign_load_svg_is_a_buffer( const void *buf, size_t len )
{ {
unsigned char *str = (unsigned char *) buf; char *str;
#ifdef HANDLE_SVGZ
/* If the buffer looks like a zip, deflate to here and then search
* that for <svg.
*/
char obuf[224];
#endif /*HANDLE_SVGZ*/
int i; int i;
#if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZLIB) /* Start with str pointing at the argument buffer, swap to it pointing
* into obuf if we see zip data.
*/
str = (char *) buf;
#ifdef HANDLE_SVGZ
/* Check for SVGZ gzip signature and inflate. /* Check for SVGZ gzip signature and inflate.
*
* Minimum gzip size is 18 bytes, starting with 1F 8B. * Minimum gzip size is 18 bytes, starting with 1F 8B.
*/ */
if( len >= 18 && str[0] == 0x1f && str[1] == 0x8b ) { if( len >= 18 &&
str[0] == '\037' &&
str[1] == '\213' ) {
z_stream zs; z_stream zs;
size_t opos = 0; size_t opos;
unsigned char obuf[224];
zs.zalloc = (alloc_func) vips_zalloc; zs.zalloc = (alloc_func) vips_foreign_load_svg_zalloc;
zs.zfree = (free_func) vips_zfree; zs.zfree = (free_func) vips_foreign_load_svg_zfree;
zs.opaque = Z_NULL; zs.opaque = Z_NULL;
zs.next_in = str; zs.next_in = (unsigned char *) str;
zs.avail_in = len; zs.avail_in = len;
if( inflateInit2(&zs, 15 | 32) != Z_OK ) { /* There isn't really an error return from is_a_buffer()
vips_error( "svgload", */
"%s", _( "Zlib init failed" ) ); if( inflateInit2( &zs, 15 | 32 ) != Z_OK )
return( -1 ); return( FALSE );
}
opos = 0;
do { do {
zs.avail_out = sizeof(obuf) - opos; zs.avail_out = sizeof( obuf ) - opos;
zs.next_out = obuf + opos; zs.next_out = (unsigned char *) obuf + opos;
if( inflate(&zs, Z_NO_FLUSH) < Z_OK ) { if( inflate( &zs, Z_NO_FLUSH ) < Z_OK )
vips_error( "svgload", return( FALSE );
"%s", _( "Zlib inflate failed" ) ); opos = sizeof( obuf ) - zs.avail_out;
return( -1 ); } while( opos < sizeof( obuf ) &&
} zs.avail_in > 0 );
opos = sizeof(obuf) - zs.avail_out;
} while( opos < sizeof(obuf) && zs.avail_out == 0 );
inflateEnd(&zs); inflateEnd( &zs );
str = obuf; str = obuf;
len = opos; len = opos;
} }
#endif #endif /*HANDLE_SVGZ*/
/* SVG documents are very freeform. They normally look like: /* SVG documents are very freeform. They normally look like:
* *
@ -456,14 +479,13 @@ vips_foreign_load_svg_is_a_buffer( const void *buf, size_t len )
return( 0 ); return( 0 );
for( i = 0; i < 24; i++ ) for( i = 0; i < 24; i++ )
if( !isascii( str[i] ) ) if( !isascii( str[i] ) )
return( 0 ); return( FALSE );
for( i = 0; i < 200 && i < len - 5; i++ ) { for( i = 0; i < 200 && i < len - 5; i++ )
if( strncmp( (const char *) str + i, "<svg", 4 ) == 0 ) if( strncasecmp( str + i, "<svg", 4 ) == 0 )
return( 1 ); return( TRUE );
}
return( 0 ); return( FALSE );
} }
static int static int