Add support for .svgz files to svgload
This commit is contained in:
parent
65105a9442
commit
14953c19e7
@ -54,6 +54,16 @@
|
|||||||
|
|
||||||
#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.
|
||||||
|
*/
|
||||||
|
#ifndef LIBRSVG_FEATURES_H
|
||||||
|
#include <librsvg/librsvg-features.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZIP)
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _VipsForeignLoadSvg {
|
typedef struct _VipsForeignLoadSvg {
|
||||||
VipsForeignLoad parent_object;
|
VipsForeignLoad parent_object;
|
||||||
@ -315,6 +325,9 @@ vips_foreign_load_svg_file_header( VipsForeignLoad *load )
|
|||||||
|
|
||||||
static const char *vips_foreign_svg_suffs[] = {
|
static const char *vips_foreign_svg_suffs[] = {
|
||||||
".svg",
|
".svg",
|
||||||
|
#if LIBRSVG_CHECK_FEATURE(SVGZ)
|
||||||
|
".svgz",
|
||||||
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -364,13 +377,66 @@ 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_ZIP)
|
||||||
|
static void *
|
||||||
|
vips_zalloc( void *opaque, unsigned items, unsigned size )
|
||||||
|
{
|
||||||
|
return( g_malloc0_n( items, size ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_zfree( void *opaque, void *ptr )
|
||||||
|
{
|
||||||
|
return( g_free( ptr ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
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 )
|
||||||
{
|
{
|
||||||
char *str = (char *) buf;
|
unsigned char *str = (unsigned char *) buf;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#if LIBRSVG_CHECK_FEATURE(SVGZ) && defined(HAVE_ZIP)
|
||||||
|
/* Check for SVGZ gzip signature and inflate.
|
||||||
|
* Minimum gzip size is 18 bytes, starting with 1F 8B.
|
||||||
|
*/
|
||||||
|
if( len >= 18 && str[0] == 0x1f && str[1] == 0x8b ) {
|
||||||
|
z_stream zs;
|
||||||
|
size_t opos = 0;
|
||||||
|
unsigned char obuf[224];
|
||||||
|
|
||||||
|
zs.zalloc = (alloc_func) vips_zalloc;
|
||||||
|
zs.zfree = (free_func) vips_zfree;
|
||||||
|
zs.opaque = Z_NULL;
|
||||||
|
zs.next_in = str;
|
||||||
|
zs.avail_in = len;
|
||||||
|
|
||||||
|
if( inflateInit2(&zs, 15 | 32) != Z_OK ) {
|
||||||
|
vips_error( "svgload",
|
||||||
|
"%s", _( "Zlib init failed" ) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
zs.avail_out = sizeof(obuf) - opos;
|
||||||
|
zs.next_out = obuf + opos;
|
||||||
|
if( inflate(&zs, Z_NO_FLUSH) < Z_OK ) {
|
||||||
|
vips_error( "svgload",
|
||||||
|
"%s", _( "Zlib inflate failed" ) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
opos = sizeof(obuf) - zs.avail_out;
|
||||||
|
} while( opos < sizeof(obuf) && zs.avail_out == 0 );
|
||||||
|
|
||||||
|
inflateEnd(&zs);
|
||||||
|
|
||||||
|
str = obuf;
|
||||||
|
len = opos;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* SVG documents are very freeform. They normally look like:
|
/* SVG documents are very freeform. They normally look like:
|
||||||
*
|
*
|
||||||
* <?xml version="1.0" encoding="UTF-8"?>
|
* <?xml version="1.0" encoding="UTF-8"?>
|
||||||
@ -390,15 +456,10 @@ 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( 0 );
|
||||||
|
|
||||||
for( i = 0; i < 200 && i < len - 5; i++ ) {
|
for( i = 0; i < 200 && i < len - 5; i++ ) {
|
||||||
char txt[5];
|
if( strncmp( (const char *) str + i, "<svg", 4 ) == 0 )
|
||||||
|
|
||||||
/* 5, since we include the \0 at the end.
|
|
||||||
*/
|
|
||||||
vips_strncpy( txt, buf + i, 5 );
|
|
||||||
if( strcasecmp( txt, "<svg" ) == 0 )
|
|
||||||
return( 1 );
|
return( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
test/images/vips-profile.svgz
Normal file
BIN
test/images/vips-profile.svgz
Normal file
Binary file not shown.
@ -50,6 +50,7 @@ class TestForeign(unittest.TestCase):
|
|||||||
self.pdf_file = "images/ISO_12233-reschart.pdf"
|
self.pdf_file = "images/ISO_12233-reschart.pdf"
|
||||||
self.cmyk_pdf_file = "images/cmyktest.pdf"
|
self.cmyk_pdf_file = "images/cmyktest.pdf"
|
||||||
self.svg_file = "images/vips-profile.svg"
|
self.svg_file = "images/vips-profile.svg"
|
||||||
|
self.svgz_file = "images/vips-profile.svgz"
|
||||||
|
|
||||||
self.colour = Vips.Image.jpegload(self.jpeg_file)
|
self.colour = Vips.Image.jpegload(self.jpeg_file)
|
||||||
self.mono = self.colour.extract_band(1)
|
self.mono = self.colour.extract_band(1)
|
||||||
@ -499,6 +500,9 @@ class TestForeign(unittest.TestCase):
|
|||||||
self.file_loader("svgload", self.svg_file, svg_valid)
|
self.file_loader("svgload", self.svg_file, svg_valid)
|
||||||
self.buffer_loader("svgload_buffer", self.svg_file, svg_valid)
|
self.buffer_loader("svgload_buffer", self.svg_file, svg_valid)
|
||||||
|
|
||||||
|
self.file_loader("svgload", self.svgz_file, svg_valid)
|
||||||
|
self.buffer_loader("svgload_buffer", self.svgz_file, svg_valid)
|
||||||
|
|
||||||
im = Vips.Image.new_from_file(self.svg_file)
|
im = Vips.Image.new_from_file(self.svg_file)
|
||||||
x = Vips.Image.new_from_file(self.svg_file, scale = 2)
|
x = Vips.Image.new_from_file(self.svg_file, scale = 2)
|
||||||
self.assertLess(abs(im.width * 2 - x.width), 2)
|
self.assertLess(abs(im.width * 2 - x.width), 2)
|
||||||
|
Loading…
Reference in New Issue
Block a user