% Read/Write Scalable Vector Graphics Format %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% William Radcliffe %
% March 2000 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
#include "MagickCore/cache.h"
#include "MagickCore/constitute.h"
#include "MagickCore/composite-private.h"
+#include "MagickCore/delegate.h"
+#include "MagickCore/delegate-private.h"
#include "MagickCore/draw.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/utility.h"
#if defined(MAGICKCORE_XML_DELEGATE)
# if defined(MAGICKCORE_WINDOWS_SUPPORT)
-# if defined(__MINGW32__)
+# if defined(__MINGW32__) || defined(__MINGW64__)
# define _MSC_VER
# else
# include <win32config.h>
#if defined(MAGICKCORE_RSVG_DELEGATE)
#include "librsvg/rsvg.h"
-#if defined(MAGICKCORE_CAIRO_DELEGATE)
+#if !defined(LIBRSVG_CHECK_VERSION)
+#include "librsvg/rsvg-cairo.h"
+#include "librsvg/librsvg-features.h"
+#elif !LIBRSVG_CHECK_VERSION(2,36,2)
#include "librsvg/rsvg-cairo.h"
-#endif
#include "librsvg/librsvg-features.h"
#endif
+#endif
\f
/*
Typedef declarations.
if (svg_info->text != (char *) NULL)
svg_info->text=DestroyString(svg_info->text);
if (svg_info->scale != (double *) NULL)
- svg_info->scale=(double *) (svg_info->scale);
+ svg_info->scale=(double *) RelinquishMagickMemory(svg_info->scale);
if (svg_info->title != (char *) NULL)
svg_info->title=DestroyString(svg_info->title);
if (svg_info->comment != (char *) NULL)
assert(string != (const char *) NULL);
p=(const char *) string;
GetMagickToken(p,&p,token);
- value=InterpretLocaleValue(token,(char **) NULL);
+ value=StringToDouble(token,(char **) NULL);
if (strchr(token,'%') != (char *) NULL)
{
double
if (type > 0)
{
if (svg_info->view_box.width == 0.0)
- return(1000.0);
+ return(0.0);
return(svg_info->view_box.width*value/100.0);
}
if (type < 0)
{
if (svg_info->view_box.height == 0.0)
- return(1000.0);
+ return(0.0);
return(svg_info->view_box.height*value/100.0);
}
alpha=value-svg_info->view_box.width;
if (LocaleNCompare(token,"pc",2) == 0)
return(DefaultResolution*svg_info->scale[0]/6.0*value);
if (LocaleNCompare(token,"pt",2) == 0)
- return(svg_info->scale[0]*value);
+ return(1.25*svg_info->scale[0]*value);
if (LocaleNCompare(token,"px",2) == 0)
return(value);
return(value);
if (LocaleCompare((const char *) name,"text") == 0)
{
(void) FormatLocaleFile(svg_info->file,"push graphic-context\n");
+ svg_info->bounds.x=0.0;
+ svg_info->bounds.y=0.0;
+ svg_info->bounds.width=0.0;
+ svg_info->bounds.height=0.0;
break;
}
if (LocaleCompare((const char *) name,"tspan") == 0)
(void) FormatLocaleFile(svg_info->file,"fill-rule '%s'\n",value);
break;
}
- if (LocaleCompare(keyword,"fill-opacity") == 0)
+ if (LocaleCompare(keyword,"fill-alpha") == 0)
{
- (void) FormatLocaleFile(svg_info->file,"fill-opacity '%s'\n",
+ (void) FormatLocaleFile(svg_info->file,"fill-alpha '%s'\n",
value);
break;
}
{
p=(const char *) value;
GetMagickToken(p,&p,token);
- affine.sx=InterpretLocaleValue(value,(char **) NULL);
+ affine.sx=StringToDouble(value,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.rx=InterpretLocaleValue(token,(char **) NULL);
+ affine.rx=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.ry=InterpretLocaleValue(token,(char **) NULL);
+ affine.ry=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.sy=InterpretLocaleValue(token,(char **) NULL);
+ affine.sy=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.tx=InterpretLocaleValue(token,(char **) NULL);
+ affine.tx=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.ty=InterpretLocaleValue(token,(char **) NULL);
+ affine.ty=StringToDouble(token,(char **) NULL);
break;
}
break;
transform.rx=affine.rx*current.sx+affine.sy*current.rx;
transform.ry=affine.sx*current.ry+affine.ry*current.sy;
transform.sy=affine.rx*current.ry+affine.sy*current.sy;
- transform.tx=affine.sx*current.tx+affine.ry*current.ty+
- affine.tx;
- transform.ty=affine.rx*current.tx+affine.sy*current.ty+
- affine.ty;
+ transform.tx=affine.tx*current.sx+affine.ty*current.ry+
+ current.tx;
+ transform.ty=affine.tx*current.rx+affine.ty*current.sy+
+ current.ty;
}
(void) FormatLocaleFile(svg_info->file,
"affine %g %g %g %g %g %g\n",transform.sx,
"fill '%s'\n",color);
break;
}
- if (LocaleCompare(value,"#00000000") == 0)
+ if (LocaleCompare(value,"#000000ff") == 0)
(void) FormatLocaleFile(svg_info->file,
- "fill '#000000'\n");
+ "fill '#000000'\n");
else
(void) FormatLocaleFile(svg_info->file,"fill '%s'\n",
- value);
+ value);
break;
}
if (LocaleCompare(keyword,"fillcolor") == 0)
"fill-rule '%s'\n",value);
break;
}
- if (LocaleCompare(keyword,"fill-opacity") == 0)
+ if (LocaleCompare(keyword,"fill-alpha") == 0)
{
(void) FormatLocaleFile(svg_info->file,
- "fill-opacity '%s'\n",value);
+ "fill-alpha '%s'\n",value);
break;
}
if (LocaleCompare(keyword,"font-family") == 0)
"stroke '%s'\n",color);
break;
}
- if (LocaleCompare(value,"#00000000") == 0)
+ if (LocaleCompare(value,"#000000ff") == 0)
(void) FormatLocaleFile(svg_info->file,
- "fill '#000000'\n");
+ "fill '#000000'\n");
else
(void) FormatLocaleFile(svg_info->file,
- "stroke '%s'\n",value);
+ "stroke '%s'\n",value);
break;
}
if (LocaleCompare(keyword,"stroke-antialiasing") == 0)
{
p=(const char *) value;
GetMagickToken(p,&p,token);
- affine.sx=InterpretLocaleValue(value,(char **) NULL);
+ affine.sx=StringToDouble(value,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.rx=InterpretLocaleValue(token,(char **) NULL);
+ affine.rx=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.ry=InterpretLocaleValue(token,(char **) NULL);
+ affine.ry=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.sy=InterpretLocaleValue(token,(char **) NULL);
+ affine.sy=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.tx=InterpretLocaleValue(token,(char **) NULL);
+ affine.tx=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- affine.ty=InterpretLocaleValue(token,(char **) NULL);
+ affine.ty=StringToDouble(token,(char **) NULL);
break;
}
break;
p=(const char *) value;
GetMagickToken(p,&p,token);
- angle=InterpretLocaleValue(value,(char **) NULL);
+ angle=StringToDouble(value,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- x=InterpretLocaleValue(token,(char **) NULL);
+ x=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- y=InterpretLocaleValue(token,(char **) NULL);
+ y=StringToDouble(token,(char **) NULL);
affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
transform.rx=affine.rx*current.sx+affine.sy*current.rx;
transform.ry=affine.sx*current.ry+affine.ry*current.sy;
transform.sy=affine.rx*current.ry+affine.sy*current.sy;
- transform.tx=affine.sx*current.tx+affine.ry*current.ty+
- affine.tx;
- transform.ty=affine.rx*current.tx+affine.sy*current.ty+
- affine.ty;
+ transform.tx=affine.tx*current.sx+affine.ty*current.ry+
+ current.tx;
+ transform.ty=affine.tx*current.rx+affine.ty*current.sy+
+ current.ty;
}
(void) FormatLocaleFile(svg_info->file,
- "affine %g %g %g %g 0.0 0.0\n",transform.sx,transform.rx,
- transform.ry,transform.sy);
+ "affine %g %g %g %g %g %g\n",transform.sx,transform.rx,
+ transform.ry,transform.sy,transform.tx,transform.ty);
for (j=0; tokens[j] != (char *) NULL; j++)
tokens[j]=DestroyString(tokens[j]);
tokens=(char **) RelinquishMagickMemory(tokens);
{
p=(const char *) value;
GetMagickToken(p,&p,token);
- svg_info->view_box.x=InterpretLocaleValue(token,(char **) NULL);
+ svg_info->view_box.x=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- svg_info->view_box.y=InterpretLocaleValue(token,(char **) NULL);
+ svg_info->view_box.y=StringToDouble(token,(char **) NULL);
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- svg_info->view_box.width=InterpretLocaleValue(token,
+ svg_info->view_box.width=StringToDouble(token,
(char **) NULL);
if (svg_info->bounds.width == 0)
svg_info->bounds.width=svg_info->view_box.width;
GetMagickToken(p,&p,token);
if (*token == ',')
GetMagickToken(p,&p,token);
- svg_info->view_box.height=InterpretLocaleValue(token,
+ svg_info->view_box.height=StringToDouble(token,
(char **) NULL);
if (svg_info->bounds.height == 0)
svg_info->bounds.height=svg_info->view_box.height;
{
double
sx,
- sy;
+ sy,
+ tx,
+ ty;
if ((svg_info->view_box.width == 0.0) ||
(svg_info->view_box.height == 0.0))
(double) svg_info->width,(double) svg_info->height);
sx=(double) svg_info->width/svg_info->view_box.width;
sy=(double) svg_info->height/svg_info->view_box.height;
- (void) FormatLocaleFile(svg_info->file,"affine %g 0 0 %g 0.0 0.0\n",
- sx,sy);
+ tx=svg_info->view_box.x != 0.0 ? (double) -sx*svg_info->view_box.x :
+ 0.0;
+ ty=svg_info->view_box.y != 0.0 ? (double) -sy*svg_info->view_box.y :
+ 0.0;
+ (void) FormatLocaleFile(svg_info->file,"affine %g 0 0 %g %g %g\n",
+ sx,sy,tx,ty);
}
}
(void) LogMagickEvent(CoderEvent,GetMagickModule()," )");
static void SVGCharacters(void *context,const xmlChar *c,int length)
{
+ char
+ *text;
+
register char
*p;
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.characters(%s,%.20g)",c,(double) length);
svg_info=(SVGInfo *) context;
- if (svg_info->text != (char *) NULL)
- svg_info->text=(char *) ResizeQuantumMemory(svg_info->text,
- strlen(svg_info->text)+length+MaxTextExtent,sizeof(*svg_info->text));
- else
- {
- svg_info->text=(char *) AcquireQuantumMemory(length+MaxTextExtent,
- sizeof(*svg_info->text));
- if (svg_info->text != (char *) NULL)
- *svg_info->text='\0';
- }
- if (svg_info->text == (char *) NULL)
+ text=(char *) AcquireQuantumMemory(length+1,sizeof(*text));
+ if (text == (char *) NULL)
return;
- p=svg_info->text+strlen(svg_info->text);
+ p=text;
for (i=0; i < (ssize_t) length; i++)
*p++=c[i];
*p='\0';
+ StripString(text);
+ if (svg_info->text == (char *) NULL)
+ svg_info->text=text;
+ else
+ {
+ (void) ConcatenateString(&svg_info->text,text);
+ text=DestroyString(text);
+ }
}
static void SVGReference(void *context,const xmlChar *name)
parser->inputTab=parser_context.inputTab;
}
-#if defined(MAGICKCORE_RSVG_DELEGATE)
-static void SVGSetImageSize(int *width,int *height,gpointer context)
-{
- Image
- *image;
-
- image=(Image *) context;
- *width=(int) (*width*image->x_resolution/72.0);
- *height=(int) (*height*image->y_resolution/72.0);
-}
-#endif
-
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
+/*
+ Static declarations.
+*/
+static char
+ SVGDensityGeometry[] = "90.0x90.0";
+\f
+
static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
{
char
image=DestroyImageList(image);
return((Image *) NULL);
}
+ if ((image->resolution.x == 0.0) || (image->resolution.y == 0.0))
+ {
+ GeometryInfo
+ geometry_info;
+
+ int
+ flags;
+
+ flags=ParseGeometry(SVGDensityGeometry,&geometry_info);
+ image->resolution.x=geometry_info.rho;
+ image->resolution.y=geometry_info.sigma;
+ if ((flags & SigmaValue) == 0)
+ image->resolution.y=image->resolution.x;
+ }
if (LocaleCompare(image_info->magick,"MSVG") != 0)
{
+ const DelegateInfo
+ *delegate_info;
+
+ delegate_info=GetDelegateInfo("svg:decode",(char *) NULL,exception);
+ if (delegate_info != (const DelegateInfo *) NULL)
+ {
+ char
+ background[MaxTextExtent],
+ command[MaxTextExtent],
+ density[MaxTextExtent],
+ filename[MaxTextExtent],
+ opacity[MaxTextExtent],
+ unique[MaxTextExtent];
+
+ int
+ status;
+
+ /*
+ Our best hope for compliance to the SVG standard.
+ */
+ (void) AcquireUniqueFilename(filename);
+ (void) AcquireUniqueFilename(unique);
+ (void) FormatLocaleString(density,MaxTextExtent,"%.20g,%.20g",
+ image->resolution.x,image->resolution.y);
+ (void) FormatLocaleString(background,MaxTextExtent,
+ "rgb(%.20g%%,%.20g%%,%.20g%%)",
+ 100.0*QuantumScale*image->background_color.red,
+ 100.0*QuantumScale*image->background_color.green,
+ 100.0*QuantumScale*image->background_color.blue);
+ (void) FormatLocaleString(opacity,MaxTextExtent,"%.20g",
+ QuantumScale*image->background_color.alpha);
+ (void) FormatLocaleString(command,MaxTextExtent,
+ GetDelegateCommands(delegate_info),image->filename,filename,density,
+ background,opacity,unique);
+ status=SystemCommand(MagickFalse,image_info->verbose,command,
+ exception);
+ (void) RelinquishUniqueFileResource(unique);
+ if (status == 0)
+ {
+ ImageInfo
+ *read_info;
+
+ read_info=CloneImageInfo(image_info);
+ (void) CopyMagickString(read_info->filename,filename,
+ MaxTextExtent);
+ image=ReadImage(read_info,exception);
+ read_info=DestroyImageInfo(read_info);
+ (void) RelinquishUniqueFileResource(filename);
+ if (image != (Image *) NULL)
+ return(image);
+ }
+ (void) RelinquishUniqueFileResource(filename);
+ }
+ {
#if defined(MAGICKCORE_RSVG_DELEGATE)
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- cairo_surface_t
- *cairo_surface;
+ cairo_surface_t
+ *cairo_surface;
+
+ cairo_t
+ *cairo_image;
- cairo_t
- *cairo_info;
+ MemoryInfo
+ *pixel_info;
- register unsigned char
- *p;
+ register unsigned char
+ *p;
- RsvgDimensionData
- dimension_info;
+ RsvgDimensionData
+ dimension_info;
- unsigned char
- *pixels;
+ unsigned char
+ *pixels;
#else
- GdkPixbuf
- *pixel_info;
+ GdkPixbuf
+ *pixel_buffer;
- register const guchar
- *p;
+ register const guchar
+ *p;
#endif
- GError
- *error;
+ GError
+ *error;
- ssize_t
- y;
+ ssize_t
+ y;
- PixelInfo
- fill_color;
+ PixelInfo
+ fill_color;
- register ssize_t
- x;
+ register ssize_t
+ x;
- register Quantum
- *q;
+ register Quantum
+ *q;
- RsvgHandle
- *svg_handle;
+ RsvgHandle
+ *svg_handle;
- svg_handle=rsvg_handle_new();
- if (svg_handle == (RsvgHandle *) NULL)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- rsvg_handle_set_base_uri(svg_handle,image_info->filename);
- rsvg_handle_set_size_callback(svg_handle,SVGSetImageSize,image,NULL);
- if ((image->x_resolution != 72.0) && (image->y_resolution != 72.0))
- rsvg_handle_set_dpi_x_y(svg_handle,image->x_resolution,
- image->y_resolution);
- while ((n=ReadBlob(image,MaxTextExtent,message)) != 0)
- {
+ svg_handle=rsvg_handle_new();
+ if (svg_handle == (RsvgHandle *) NULL)
+ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ rsvg_handle_set_base_uri(svg_handle,image_info->filename);
+ if ((image->resolution.x != 90.0) && (image->resolution.y != 90.0))
+ rsvg_handle_set_dpi_x_y(svg_handle,image->resolution.x,
+ image->resolution.y);
+ while ((n=ReadBlob(image,MaxTextExtent,message)) != 0)
+ {
+ error=(GError *) NULL;
+ (void) rsvg_handle_write(svg_handle,message,n,&error);
+ if (error != (GError *) NULL)
+ g_error_free(error);
+ }
error=(GError *) NULL;
- (void) rsvg_handle_write(svg_handle,message,n,&error);
+ rsvg_handle_close(svg_handle,&error);
if (error != (GError *) NULL)
g_error_free(error);
- }
- error=(GError *) NULL;
- rsvg_handle_close(svg_handle,&error);
- if (error != (GError *) NULL)
- g_error_free(error);
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- rsvg_handle_get_dimensions(svg_handle,&dimension_info);
- image->columns=dimension_info.width;
- image->rows=dimension_info.height;
- pixels=(unsigned char *) NULL;
+ rsvg_handle_get_dimensions(svg_handle,&dimension_info);
+ image->columns=image->resolution.x*dimension_info.width/90.0;
+ image->rows=image->resolution.y*dimension_info.height/90.0;
+ pixel_info=(MemoryInfo *) NULL;
#else
- pixel_info=rsvg_handle_get_pixbuf(svg_handle);
- rsvg_handle_free(svg_handle);
- image->columns=gdk_pixbuf_get_width(pixel_info);
- image->rows=gdk_pixbuf_get_height(pixel_info);
+ pixel_buffer=rsvg_handle_get_pixbuf(svg_handle);
+ rsvg_handle_free(svg_handle);
+ image->columns=gdk_pixbuf_get_width(pixel_buffer);
+ image->rows=gdk_pixbuf_get_height(pixel_buffer);
#endif
- image->matte=MagickTrue;
- SetImageProperty(image,"svg:base-uri",
- rsvg_handle_get_base_uri(svg_handle));
- SetImageProperty(image,"svg:title",rsvg_handle_get_title(svg_handle));
- SetImageProperty(image,"svg:description",
- rsvg_handle_get_desc(svg_handle));
- if ((image->columns == 0) || (image->rows == 0))
- {
+ image->alpha_trait=BlendPixelTrait;
+ SetImageProperty(image,"svg:base-uri",
+ rsvg_handle_get_base_uri(svg_handle),exception);
+ if ((image->columns == 0) || (image->rows == 0))
+ {
#if !defined(MAGICKCORE_CAIRO_DELEGATE)
- g_object_unref(G_OBJECT(pixel_info));
+ g_object_unref(G_OBJECT(pixel_buffer));
#endif
- g_object_unref(svg_handle);
- ThrowReaderException(MissingDelegateError,
- "NoDecodeDelegateForThisImageFormat");
- }
- if (image_info->ping == MagickFalse)
- {
+ g_object_unref(svg_handle);
+ ThrowReaderException(MissingDelegateError,
+ "NoDecodeDelegateForThisImageFormat");
+ }
+ if (image_info->ping == MagickFalse)
+ {
+ size_t
+ stride;
+
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- pixels=(unsigned char *) AcquireQuantumMemory(image->columns,4*
- image->rows*sizeof(*pixels));
- if (pixels == (unsigned char *) NULL)
- {
- g_object_unref(svg_handle);
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- }
+ stride=4*image->columns;
+#if defined(MAGICKCORE_PANGOCAIRO_DELEGATE)
+ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32,
+ image->columns);
+#endif
+ pixel_info=AcquireVirtualMemory(stride,image->rows*sizeof(*pixels));
+ if (pixel_info == (MemoryInfo *) NULL)
+ {
+ g_object_unref(svg_handle);
+ ThrowReaderException(ResourceLimitError,
+ "MemoryAllocationFailed");
+ }
+ pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
#endif
- (void) SetImageBackgroundColor(image);
+ (void) SetImageBackgroundColor(image,exception);
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- cairo_surface=cairo_image_surface_create_for_data(pixels,
- CAIRO_FORMAT_ARGB32,image->columns,image->rows,4*image->columns);
- if (cairo_surface == (cairo_surface_t *) NULL)
- {
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
- g_object_unref(svg_handle);
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- }
- cairo_info=cairo_create(cairo_surface);
- cairo_set_operator(cairo_info,CAIRO_OPERATOR_CLEAR);
- cairo_paint(cairo_info);
- cairo_set_operator(cairo_info,CAIRO_OPERATOR_OVER);
- rsvg_handle_render_cairo(svg_handle,cairo_info);
- cairo_destroy(cairo_info);
- cairo_surface_destroy(cairo_surface);
- g_object_unref(svg_handle);
- p=pixels;
+ cairo_surface=cairo_image_surface_create_for_data(pixels,
+ CAIRO_FORMAT_ARGB32,image->columns,image->rows,stride);
+ if (cairo_surface == (cairo_surface_t *) NULL)
+ {
+ pixel_info=RelinquishVirtualMemory(pixel_info);
+ g_object_unref(svg_handle);
+ ThrowReaderException(ResourceLimitError,
+ "MemoryAllocationFailed");
+ }
+ cairo_image=cairo_create(cairo_surface);
+ cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cairo_image);
+ cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER);
+ cairo_scale(cairo_image,image->resolution.x/90.0,
+ image->resolution.y/90.0);
+ rsvg_handle_render_cairo(svg_handle,cairo_image);
+ cairo_destroy(cairo_image);
+ cairo_surface_destroy(cairo_surface);
+ g_object_unref(svg_handle);
+ p=pixels;
#else
- p=gdk_pixbuf_get_pixels(pixel_info);
+ p=gdk_pixbuf_get_pixels(pixel_buffer);
#endif
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
- if (q == (Quantum *) NULL)
- break;
- for (x=0; x < (ssize_t) image->columns; x++)
+ GetPixelInfo(image,&fill_color);
+ for (y=0; y < (ssize_t) image->rows; y++)
{
+ q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+ if (q == (Quantum *) NULL)
+ break;
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- fill_color.blue=ScaleCharToQuantum(*p++);
- fill_color.green=ScaleCharToQuantum(*p++);
- fill_color.red=ScaleCharToQuantum(*p++);
+ fill_color.blue=ScaleCharToQuantum(*p++);
+ fill_color.green=ScaleCharToQuantum(*p++);
+ fill_color.red=ScaleCharToQuantum(*p++);
#else
- fill_color.red=ScaleCharToQuantum(*p++);
- fill_color.green=ScaleCharToQuantum(*p++);
- fill_color.blue=ScaleCharToQuantum(*p++);
+ fill_color.red=ScaleCharToQuantum(*p++);
+ fill_color.green=ScaleCharToQuantum(*p++);
+ fill_color.blue=ScaleCharToQuantum(*p++);
#endif
- fill_color.alpha=ScaleCharToQuantum(*p++);
+ fill_color.alpha=ScaleCharToQuantum(*p++);
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- {
- double
- gamma;
-
- gamma=1.0-QuantumScale*fill_color.alpha;
- gamma=1.0/(fabs((double) gamma) <= MagickEpsilon ? 1.0 : gamma);
- fill_color.blue*=gamma;
- fill_color.green*=gamma;
- fill_color.red*=gamma;
- }
+ {
+ double
+ gamma;
+
+ gamma=QuantumScale*fill_color.alpha;
+ gamma=PerceptibleReciprocal(gamma);
+ fill_color.blue*=gamma;
+ fill_color.green*=gamma;
+ fill_color.red*=gamma;
+ }
#endif
- CompositePixelOver(image,&fill_color,fill_color.alpha,q,
- (MagickRealType) GetPixelAlpha(image,q),q);
- q+=GetPixelChannels(image);
- }
- if (SyncAuthenticPixels(image,exception) == MagickFalse)
- break;
- if (image->previous == (Image *) NULL)
- {
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
- if (status == MagickFalse)
- break;
+ CompositePixelOver(image,&fill_color,fill_color.alpha,q,(double)
+ GetPixelAlpha(image,q),q);
+ q+=GetPixelChannels(image);
}
+ if (SyncAuthenticPixels(image,exception) == MagickFalse)
+ break;
+ if (image->previous == (Image *) NULL)
+ {
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ y,image->rows);
+ if (status == MagickFalse)
+ break;
+ }
+ }
}
- }
#if defined(MAGICKCORE_CAIRO_DELEGATE)
- if (pixels != (unsigned char *) NULL)
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ if (pixel_info != (MemoryInfo *) NULL)
+ pixel_info=RelinquishVirtualMemory(pixel_info);
#else
- g_object_unref(G_OBJECT(pixel_info));
+ g_object_unref(G_OBJECT(pixel_buffer));
#endif
- (void) CloseBlob(image);
- return(GetFirstImageInList(image));
+ (void) CloseBlob(image);
+ return(GetFirstImageInList(image));
#endif
+ }
}
/*
Open draw file.
/*
Parse SVG file.
*/
+ if (image == (Image *) NULL)
+ return((Image *) NULL);
svg_info=AcquireSVGInfo();
if (svg_info == (SVGInfo *) NULL)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ {
+ (void) fclose(file);
+ ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ }
svg_info->file=file;
svg_info->exception=exception;
svg_info->image=image;
(void) CloneString(&svg_info->size,image_info->size);
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"begin SAX");
- xmlInitParser();
(void) xmlSubstituteEntitiesDefault(1);
(void) ResetMagickMemory(&sax_modules,0,sizeof(sax_modules));
sax_modules.internalSubset=SVGInternalSubset;
xmlFreeParserCtxt(svg_info->parser);
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"end SAX");
- xmlCleanupParser();
(void) fclose(file);
(void) CloseBlob(image);
image->columns=svg_info->width;
if (image != (Image *) NULL)
{
if (svg_info->title != (char *) NULL)
- (void) SetImageProperty(image,"svg:title",svg_info->title);
+ (void) SetImageProperty(image,"svg:title",svg_info->title,exception);
if (svg_info->comment != (char *) NULL)
- (void) SetImageProperty(image,"svg:comment",svg_info->comment);
+ (void) SetImageProperty(image,"svg:comment",svg_info->comment,
+ exception);
}
svg_info=DestroySVGInfo(svg_info);
(void) RelinquishUniqueFileResource(filename);
(void) CopyMagickString(version,"XML " LIBXML_DOTTED_VERSION,MaxTextExtent);
#endif
#if defined(MAGICKCORE_RSVG_DELEGATE)
- rsvg_init();
+#if !GLIB_CHECK_VERSION(2,35,0)
+ g_type_init();
+#endif
+#if defined(MAGICKCORE_XML_DELEGATE)
+ xmlInitParser();
+#endif
(void) FormatLocaleString(version,MaxTextExtent,"RSVG %d.%d.%d",
LIBRSVG_MAJOR_VERSION,LIBRSVG_MINOR_VERSION,LIBRSVG_MICRO_VERSION);
#endif
entry->blob_support=MagickFalse;
entry->seekable_stream=MagickFalse;
entry->description=ConstantString("Scalable Vector Graphics");
+ entry->mime_type=ConstantString("image/svg+xml");
if (*version != '\0')
entry->version=ConstantString(version);
entry->magick=(IsImageFormatHandler *) IsSVG;
entry->blob_support=MagickFalse;
entry->seekable_stream=MagickFalse;
entry->description=ConstantString("Compressed Scalable Vector Graphics");
+ entry->mime_type=ConstantString("image/svg+xml");
if (*version != '\0')
entry->version=ConstantString(version);
entry->magick=(IsImageFormatHandler *) IsSVG;
(void) UnregisterMagickInfo("SVGZ");
(void) UnregisterMagickInfo("SVG");
(void) UnregisterMagickInfo("MSVG");
-#if defined(MAGICKCORE_RSVG_DELEGATE)
- rsvg_term();
+#if defined(MAGICKCORE_XML_DELEGATE)
+ xmlCleanupParser();
#endif
}
\f
return(p != point ? MagickTrue : MagickFalse);
}
-static MagickBooleanType TraceSVGImage(Image *image)
+static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception)
{
ssize_t
y;
*/
fitting_options=at_fitting_opts_new();
output_options=at_output_opts_new();
- type=GetImageType(image,&image->exception);
+ type=GetImageType(image,exception);
number_planes=3;
if ((type == BilevelType) || (type == GrayscaleType))
number_planes=1;
i=0;
for (y=0; y < (ssize_t) image->rows; y++)
{
- p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
GetPixelInfo(image,&pixel);
for (y=0; y < (ssize_t) image->rows; y++)
{
- p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
- SetPixelInfo(image,p,&pixel);
- (void) QueryMagickColorname(image,&pixel,SVGCompliance,tuple,
- &image->exception);
+ GetPixelInfoPixel(image,p,&pixel);
+ (void) QueryColorname(image,&pixel,SVGCompliance,tuple,exception);
(void) FormatLocaleString(message,MaxTextExtent,
" <circle cx=\"%.20g\" cy=\"%.20g\" r=\"1\" fill=\"%s\"/>\n",
(double) x,(double) y,tuple);
}
value=GetImageArtifact(image,"MVG");
if (value == (char *) NULL)
- return(TraceSVGImage(image));
+ return(TraceSVGImage(image,exception));
/*
Write SVG header.
*/
if (LocaleCompare("affine",keyword) == 0)
{
GetMagickToken(q,&q,token);
- affine.sx=InterpretLocaleValue(token,(char **) NULL);
+ affine.sx=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.rx=InterpretLocaleValue(token,(char **) NULL);
+ affine.rx=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.ry=InterpretLocaleValue(token,(char **) NULL);
+ affine.ry=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.sy=InterpretLocaleValue(token,(char **) NULL);
+ affine.sy=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.tx=InterpretLocaleValue(token,(char **) NULL);
+ affine.tx=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.ty=InterpretLocaleValue(token,(char **) NULL);
+ affine.ty=StringToDouble(token,(char **) NULL);
break;
}
if (LocaleCompare("angle",keyword) == 0)
{
GetMagickToken(q,&q,token);
- affine.rx=InterpretLocaleValue(token,(char **) NULL);
- affine.ry=InterpretLocaleValue(token,(char **) NULL);
+ affine.rx=StringToDouble(token,(char **) NULL);
+ affine.ry=StringToDouble(token,(char **) NULL);
break;
}
if (LocaleCompare("arc",keyword) == 0)
(void) WriteBlobString(image,message);
break;
}
- if (LocaleCompare("fill-opacity",keyword) == 0)
+ if (LocaleCompare("fill-alpha",keyword) == 0)
{
GetMagickToken(q,&q,token);
(void) FormatLocaleString(message,MaxTextExtent,
- "fill-opacity:%s;",token);
+ "fill-alpha:%s;",token);
(void) WriteBlobString(image,message);
break;
}
GetMagickToken(q,&q,token);
(void) CopyMagickString(type,token,MaxTextExtent);
GetMagickToken(q,&q,token);
- svg_info.segment.x1=InterpretLocaleValue(token,(char **) NULL);
- svg_info.element.cx=InterpretLocaleValue(token,(char **) NULL);
+ svg_info.segment.x1=StringToDouble(token,(char **) NULL);
+ svg_info.element.cx=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.segment.y1=InterpretLocaleValue(token,(char **) NULL);
- svg_info.element.cy=InterpretLocaleValue(token,(char **) NULL);
+ svg_info.segment.y1=StringToDouble(token,(char **) NULL);
+ svg_info.element.cy=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.segment.x2=InterpretLocaleValue(token,(char **) NULL);
- svg_info.element.major=InterpretLocaleValue(token,
+ svg_info.segment.x2=StringToDouble(token,(char **) NULL);
+ svg_info.element.major=StringToDouble(token,
(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.segment.y2=InterpretLocaleValue(token,(char **) NULL);
- svg_info.element.minor=InterpretLocaleValue(token,
+ svg_info.segment.y2=StringToDouble(token,(char **) NULL);
+ svg_info.element.minor=StringToDouble(token,
(char **) NULL);
(void) FormatLocaleString(message,MaxTextExtent,
"<%sGradient id=\"%s\" x1=\"%g\" y1=\"%g\" x2=\"%g\" "
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.element.angle=InterpretLocaleValue(token,
+ svg_info.element.angle=StringToDouble(token,
(char **) NULL);
(void) FormatLocaleString(message,MaxTextExtent,
"<%sGradient id=\"%s\" cx=\"%g\" cy=\"%g\" r=\"%g\" "
GetMagickToken(q,&q,token);
(void) CopyMagickString(name,token,MaxTextExtent);
GetMagickToken(q,&q,token);
- svg_info.bounds.x=InterpretLocaleValue(token,(char **) NULL);
+ svg_info.bounds.x=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.bounds.y=InterpretLocaleValue(token,(char **) NULL);
+ svg_info.bounds.y=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.bounds.width=InterpretLocaleValue(token,
+ svg_info.bounds.width=StringToDouble(token,
(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- svg_info.bounds.height=InterpretLocaleValue(token,
+ svg_info.bounds.height=StringToDouble(token,
(char **) NULL);
(void) FormatLocaleString(message,MaxTextExtent,
"<pattern id=\"%s\" x=\"%g\" y=\"%g\" width=\"%g\" "
if (LocaleCompare("scale",keyword) == 0)
{
GetMagickToken(q,&q,token);
- affine.sx=InterpretLocaleValue(token,(char **) NULL);
+ affine.sx=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.sy=InterpretLocaleValue(token,(char **) NULL);
+ affine.sy=StringToDouble(token,(char **) NULL);
break;
}
if (LocaleCompare("skewX",keyword) == 0)
if (LocaleCompare("translate",keyword) == 0)
{
GetMagickToken(q,&q,token);
- affine.tx=InterpretLocaleValue(token,(char **) NULL);
+ affine.tx=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- affine.ty=InterpretLocaleValue(token,(char **) NULL);
+ affine.ty=StringToDouble(token,(char **) NULL);
break;
}
status=MagickFalse;
if (IsPoint(q) == MagickFalse)
break;
GetMagickToken(q,&q,token);
- point.x=InterpretLocaleValue(token,(char **) NULL);
+ point.x=StringToDouble(token,(char **) NULL);
GetMagickToken(q,&q,token);
if (*token == ',')
GetMagickToken(q,&q,token);
- point.y=InterpretLocaleValue(token,(char **) NULL);
+ point.y=StringToDouble(token,(char **) NULL);
GetMagickToken(q,(const char **) NULL,token);
if (*token == ',')
GetMagickToken(q,&q,token);