]> granicus.if.org Git - imagemagick/blobdiff - coders/svg.c
Added support for writing RLE compressed TGA files.
[imagemagick] / coders / svg.c
index 8a60045968f2f6e96c58f8c9c07415462b8b70ce..e94646142b429ed9e6b36062aa4fbe82416e97cf 100644 (file)
 %                  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  %
@@ -49,6 +49,8 @@
 #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"
@@ -73,7 +75,7 @@
 #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.
@@ -186,7 +191,7 @@ typedef struct _SVGInfo
   Forward declarations.
 */
 static MagickBooleanType
-  WriteSVGImage(const ImageInfo *,Image *);
+  WriteSVGImage(const ImageInfo *,Image *,ExceptionInfo *);
 \f
 /*
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -273,7 +278,7 @@ static SVGInfo *DestroySVGInfo(SVGInfo *svg_info)
   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)
@@ -297,7 +302,7 @@ static double GetUserSpaceCoordinateValue(const SVGInfo *svg_info,int type,
   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
@@ -307,13 +312,13 @@ static double GetUserSpaceCoordinateValue(const SVGInfo *svg_info,int type,
       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;
@@ -334,7 +339,7 @@ static double GetUserSpaceCoordinateValue(const SVGInfo *svg_info,int type,
   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);
@@ -1092,6 +1097,10 @@ static void SVGStartElement(void *context,const xmlChar *name,
       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)
@@ -1116,7 +1125,8 @@ static void SVGStartElement(void *context,const xmlChar *name,
               draw_info->pointsize=svg_info->pointsize;
               draw_info->text=AcquireString(svg_info->text);
               (void) ConcatenateString(&draw_info->text," ");
-              GetTypeMetrics(svg_info->image,draw_info,&metrics);
+              (void) GetTypeMetrics(svg_info->image,draw_info,
+                &metrics,svg_info->exception);
               svg_info->bounds.x+=metrics.width;
               draw_info=DestroyDrawInfo(draw_info);
               *svg_info->text='\0';
@@ -1231,9 +1241,9 @@ static void SVGStartElement(void *context,const xmlChar *name,
               (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;
             }
@@ -1301,27 +1311,27 @@ static void SVGStartElement(void *context,const xmlChar *name,
                       {
                         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;
@@ -1405,10 +1415,10 @@ static void SVGStartElement(void *context,const xmlChar *name,
                 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,
@@ -1655,12 +1665,12 @@ static void SVGStartElement(void *context,const xmlChar *name,
                           "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)
@@ -1675,10 +1685,10 @@ static void SVGStartElement(void *context,const xmlChar *name,
                           "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)
@@ -1748,12 +1758,12 @@ static void SVGStartElement(void *context,const xmlChar *name,
                           "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)
@@ -1918,27 +1928,27 @@ static void SVGStartElement(void *context,const xmlChar *name,
                       {
                         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;
@@ -1955,15 +1965,15 @@ static void SVGStartElement(void *context,const xmlChar *name,
 
                         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))));
@@ -2038,14 +2048,14 @@ static void SVGStartElement(void *context,const xmlChar *name,
                 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);
@@ -2065,22 +2075,22 @@ static void SVGStartElement(void *context,const xmlChar *name,
             {
               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;
@@ -2161,7 +2171,9 @@ static void SVGStartElement(void *context,const xmlChar *name,
         {
           double
             sx,
-            sy;
+            sy,
+            tx,
+            ty;
 
           if ((svg_info->view_box.width == 0.0) ||
               (svg_info->view_box.height == 0.0))
@@ -2172,8 +2184,12 @@ static void SVGStartElement(void *context,const xmlChar *name,
             (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(),"  )");
@@ -2431,7 +2447,8 @@ static void SVGEndElement(void *context,const xmlChar *name)
               draw_info->pointsize=svg_info->pointsize;
               draw_info->text=AcquireString(svg_info->text);
               (void) ConcatenateString(&draw_info->text," ");
-              GetTypeMetrics(svg_info->image,draw_info,&metrics);
+              (void) GetTypeMetrics(svg_info->image,draw_info,&metrics,
+                svg_info->exception);
               svg_info->bounds.x+=metrics.width;
               draw_info=DestroyDrawInfo(draw_info);
               *svg_info->text='\0';
@@ -2460,6 +2477,9 @@ static void SVGEndElement(void *context,const xmlChar *name)
 
 static void SVGCharacters(void *context,const xmlChar *c,int length)
 {
+  char
+    *text;
+
   register char
     *p;
 
@@ -2475,22 +2495,21 @@ static void SVGCharacters(void *context,const xmlChar *c,int length)
   (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)
@@ -2720,22 +2739,17 @@ static void SVGExternalSubset(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
@@ -2776,190 +2790,271 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
       image_info->filename);
   assert(exception->signature == MagickSignature);
-  image=AcquireImage(image_info);
+  image=AcquireImage(image_info,exception);
   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   if (status == MagickFalse)
     {
       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_info;
+        cairo_t
+          *cairo_image;
 
-      register unsigned char
-        *p;
+        MemoryInfo
+          *pixel_info;
 
-      RsvgDimensionData
-        dimension_info;
+        register unsigned char
+          *p;
+
+        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;
 
-      PixelPacket
-        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 == (const 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.
@@ -2979,9 +3074,14 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
   /*
     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;
@@ -2992,7 +3092,6 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
     (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;
@@ -3039,7 +3138,6 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
   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;
@@ -3077,9 +3175,10 @@ static Image *ReadSVGImage(const ImageInfo *image_info,ExceptionInfo *exception)
   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);
@@ -3123,7 +3222,12 @@ ModuleExport size_t RegisterSVGImage(void)
   (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
@@ -3135,6 +3239,7 @@ ModuleExport size_t RegisterSVGImage(void)
   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;
@@ -3148,6 +3253,7 @@ ModuleExport size_t RegisterSVGImage(void)
   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;
@@ -3191,8 +3297,8 @@ ModuleExport void UnregisterSVGImage(void)
   (void) UnregisterMagickInfo("SVGZ");
   (void) UnregisterMagickInfo("SVG");
   (void) UnregisterMagickInfo("MSVG");
-#if defined(MAGICKCORE_RSVG_DELEGATE)
-  rsvg_term();
+#if defined(MAGICKCORE_XML_DELEGATE)
+  xmlCleanupParser();
 #endif
 }
 \f
@@ -3212,7 +3318,8 @@ ModuleExport void UnregisterSVGImage(void)
 %
 %  The format of the WriteSVGImage method is:
 %
-%      MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
+%      MagickBooleanType WriteSVGImage(const ImageInfo *image_info,
+%        Image *image,ExceptionInfo *exception)
 %
 %  A description of each parameter follows.
 %
@@ -3220,6 +3327,8 @@ ModuleExport void UnregisterSVGImage(void)
 %
 %    o image:  The image.
 %
+%    o exception: return any errors or warnings in this structure.
+%
 */
 
 static void AffineToTransform(Image *image,AffineMatrix *affine)
@@ -3293,7 +3402,7 @@ static MagickBooleanType IsPoint(const char *point)
   return(p != point ? MagickTrue : MagickFalse);
 }
 
-static MagickBooleanType TraceSVGImage(Image *image)
+static MagickBooleanType TraceSVGImage(Image *image,ExceptionInfo *exception)
 {
   ssize_t
     y;
@@ -3332,7 +3441,7 @@ static MagickBooleanType TraceSVGImage(Image *image)
     */
     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;
@@ -3340,7 +3449,7 @@ static MagickBooleanType TraceSVGImage(Image *image)
     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++)
@@ -3388,14 +3497,13 @@ static MagickBooleanType TraceSVGImage(Image *image)
     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);
@@ -3409,7 +3517,8 @@ static MagickBooleanType TraceSVGImage(Image *image)
   return(MagickTrue);
 }
 
-static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
+static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image,
+  ExceptionInfo *exception)
 {
 #define BezierQuantum  200
 
@@ -3471,7 +3580,9 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
   assert(image->signature == MagickSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+  assert(exception != (ExceptionInfo *) NULL);
+  assert(exception->signature == MagickSignature);
+  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   if (status == MagickFalse)
     return(status);
   value=GetImageArtifact(image,"SVG");
@@ -3483,7 +3594,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
     }
   value=GetImageArtifact(image,"MVG");
   if (value == (char *) NULL)
-    return(TraceSVGImage(image));
+    return(TraceSVGImage(image,exception));
   /*
     Write SVG header.
   */
@@ -3551,34 +3662,34 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
         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)
@@ -3684,11 +3795,11 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
             (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;
           }
@@ -3893,24 +4004,24 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
                 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\" "
@@ -3921,7 +4032,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
                     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\" "
@@ -3949,20 +4060,20 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
                 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\" "
@@ -4007,11 +4118,11 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
         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)
@@ -4162,11 +4273,11 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
         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;
@@ -4215,11 +4326,11 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
       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);
@@ -4235,7 +4346,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
         number_points,sizeof(*primitive_info));
       if (primitive_info == (PrimitiveInfo *) NULL)
         {
-          (void) ThrowMagickException(&image->exception,GetMagickModule(),
+          (void) ThrowMagickException(exception,GetMagickModule(),
             ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
           break;
         }
@@ -4431,7 +4542,7 @@ static MagickBooleanType WriteSVGImage(const ImageInfo *image_info,Image *image)
               number_points,sizeof(*primitive_info));
             if (primitive_info == (PrimitiveInfo *) NULL)
               {
-                (void) ThrowMagickException(&image->exception,GetMagickModule(),
+                (void) ThrowMagickException(exception,GetMagickModule(),
                   ResourceLimitError,"MemoryAllocationFailed","`%s'",
                   image->filename);
                 break;