]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/draw.c
Fixed signature of the custom stream functions.
[imagemagick] / MagickCore / draw.c
index 8cbc92b0be31be24731f21d2e66204976f88dbd1..3b308327a879d968afd52ae2c320da1b99630190 100644 (file)
 %                                 July 1998                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2017 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  %
 %  obtain a copy of the License at                                            %
 %                                                                             %
-%    http://www.imagemagick.org/script/license.php                            %
+%    https://www.imagemagick.org/script/license.php                           %
 %                                                                             %
 %  Unless required by applicable law or agreed to in writing, software        %
 %  distributed under the License is distributed on an "AS IS" BASIS,          %
@@ -50,6 +50,7 @@
 #include "MagickCore/artifact.h"
 #include "MagickCore/blob.h"
 #include "MagickCore/cache.h"
+#include "MagickCore/cache-private.h"
 #include "MagickCore/cache-view.h"
 #include "MagickCore/channel.h"
 #include "MagickCore/color.h"
 #include "MagickCore/string-private.h"
 #include "MagickCore/thread-private.h"
 #include "MagickCore/token.h"
-#include "MagickCore/transform.h"
+#include "MagickCore/transform-private.h"
 #include "MagickCore/utility.h"
 \f
 /*
   Define declarations.
 */
 #define BezierQuantum  200
+#define DrawEpsilon  (1.0e-10)
+
 \f
 /*
   Typedef declarations.
@@ -253,8 +256,10 @@ MagickExport DrawInfo *CloneDrawInfo(const ImageInfo *image_info,
   if (draw_info == (DrawInfo *) NULL)
     return(clone_info);
   exception=AcquireExceptionInfo();
-  (void) CloneString(&clone_info->primitive,draw_info->primitive);
-  (void) CloneString(&clone_info->geometry,draw_info->geometry);
+  if (clone_info->primitive != (char *) NULL)
+    (void) CloneString(&clone_info->primitive,draw_info->primitive);
+  if (draw_info->geometry != (char *) NULL)
+    (void) CloneString(&clone_info->geometry,draw_info->geometry);
   clone_info->viewbox=draw_info->viewbox;
   clone_info->affine=draw_info->affine;
   clone_info->gravity=draw_info->gravity;
@@ -276,30 +281,37 @@ MagickExport DrawInfo *CloneDrawInfo(const ImageInfo *image_info,
   clone_info->dash_offset=draw_info->dash_offset;
   clone_info->decorate=draw_info->decorate;
   clone_info->compose=draw_info->compose;
-  (void) CloneString(&clone_info->text,draw_info->text);
-  (void) CloneString(&clone_info->font,draw_info->font);
-  (void) CloneString(&clone_info->metrics,draw_info->metrics);
-  (void) CloneString(&clone_info->family,draw_info->family);
+  if (draw_info->text != (char *) NULL)
+    (void) CloneString(&clone_info->text,draw_info->text);
+  if (draw_info->font != (char *) NULL)
+    (void) CloneString(&clone_info->font,draw_info->font);
+  if (draw_info->metrics != (char *) NULL)
+    (void) CloneString(&clone_info->metrics,draw_info->metrics);
+  if (draw_info->family != (char *) NULL)
+    (void) CloneString(&clone_info->family,draw_info->family);
   clone_info->style=draw_info->style;
   clone_info->stretch=draw_info->stretch;
   clone_info->weight=draw_info->weight;
-  (void) CloneString(&clone_info->encoding,draw_info->encoding);
+  if (draw_info->encoding != (char *) NULL)
+    (void) CloneString(&clone_info->encoding,draw_info->encoding);
   clone_info->pointsize=draw_info->pointsize;
   clone_info->kerning=draw_info->kerning;
   clone_info->interline_spacing=draw_info->interline_spacing;
   clone_info->interword_spacing=draw_info->interword_spacing;
   clone_info->direction=draw_info->direction;
-  (void) CloneString(&clone_info->density,draw_info->density);
+  if (draw_info->density != (char *) NULL)
+    (void) CloneString(&clone_info->density,draw_info->density);
   clone_info->align=draw_info->align;
   clone_info->undercolor=draw_info->undercolor;
   clone_info->border_color=draw_info->border_color;
-  (void) CloneString(&clone_info->server_name,draw_info->server_name);
+  if (draw_info->server_name != (char *) NULL)
+    (void) CloneString(&clone_info->server_name,draw_info->server_name);
   if (draw_info->dash_pattern != (double *) NULL)
     {
       register ssize_t
         x;
 
-      for (x=0; draw_info->dash_pattern[x] != 0.0; x++) ;
+      for (x=0; fabs(draw_info->dash_pattern[x]) >= DrawEpsilon; x++) ;
       clone_info->dash_pattern=(double *) AcquireQuantumMemory((size_t) x+1UL,
         sizeof(*clone_info->dash_pattern));
       if (clone_info->dash_pattern == (double *) NULL)
@@ -324,11 +336,13 @@ MagickExport DrawInfo *CloneDrawInfo(const ImageInfo *image_info,
         draw_info->gradient.stops,(size_t) number_stops*
         sizeof(*clone_info->gradient.stops));
     }
-  (void) CloneString(&clone_info->clip_mask,draw_info->clip_mask);
+  if (draw_info->clip_mask != (char *) NULL)
+    (void) CloneString(&clone_info->clip_mask,draw_info->clip_mask);
   clone_info->bounds=draw_info->bounds;
   clone_info->clip_units=draw_info->clip_units;
   clone_info->render=draw_info->render;
-  clone_info->alpha=draw_info->alpha;
+  clone_info->fill_alpha=draw_info->fill_alpha;
+  clone_info->stroke_alpha=draw_info->stroke_alpha;
   clone_info->element_reference=draw_info->element_reference;
   clone_info->debug=IsEventLogging();
   exception=DestroyExceptionInfo(exception);
@@ -381,13 +395,13 @@ static int CompareEdges(const void *x,const void *y)
   */
   p=(const EdgeInfo *) x;
   q=(const EdgeInfo *) y;
-  if ((p->points[0].y-MagickEpsilon) > q->points[0].y)
+  if ((p->points[0].y-DrawEpsilon) > q->points[0].y)
     return(1);
-  if ((p->points[0].y+MagickEpsilon) < q->points[0].y)
+  if ((p->points[0].y+DrawEpsilon) < q->points[0].y)
     return(-1);
-  if ((p->points[0].x-MagickEpsilon) > q->points[0].x)
+  if ((p->points[0].x-DrawEpsilon) > q->points[0].x)
     return(1);
-  if ((p->points[0].x+MagickEpsilon) < q->points[0].x)
+  if ((p->points[0].x+DrawEpsilon) < q->points[0].x)
     return(-1);
   if (((p->points[1].x-p->points[0].x)*(q->points[1].y-q->points[0].y)-
        (p->points[1].y-p->points[0].y)*(q->points[1].x-q->points[0].x)) > 0.0)
@@ -419,10 +433,10 @@ static void LogPolygonInfo(const PolygonInfo *polygon_info)
     (void) LogMagickEvent(DrawEvent,GetMagickModule(),"      ghostline: %s",
       p->ghostline != MagickFalse ? "transparent" : "opaque");
     (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-      "      bounds: %g %g - %g %g",p->bounds.x1,p->bounds.y1,
+      "      bounds: %g,%g - %g,%g",p->bounds.x1,p->bounds.y1,
       p->bounds.x2,p->bounds.y2);
     for (j=0; j < (ssize_t) p->number_points; j++)
-      (void) LogMagickEvent(DrawEvent,GetMagickModule(),"        %g %g",
+      (void) LogMagickEvent(DrawEvent,GetMagickModule(),"        %g,%g",
         p->points[j].x,p->points[j].y);
     p++;
   }
@@ -445,8 +459,7 @@ static void ReversePoints(PointInfo *points,const size_t number_points)
   }
 }
 
-static PolygonInfo *ConvertPathToPolygon(
-  const DrawInfo *magick_unused(draw_info),const PathInfo *path_info)
+static PolygonInfo *ConvertPathToPolygon(const PathInfo *path_info)
 {
   long
     direction,
@@ -481,10 +494,12 @@ static PolygonInfo *ConvertPathToPolygon(
   if (polygon_info == (PolygonInfo *) NULL)
     return((PolygonInfo *) NULL);
   number_edges=16;
-  polygon_info->edges=(EdgeInfo *) AcquireQuantumMemory((size_t) number_edges,
+  polygon_info->edges=(EdgeInfo *) AcquireQuantumMemory(number_edges,
     sizeof(*polygon_info->edges));
   if (polygon_info->edges == (EdgeInfo *) NULL)
     return((PolygonInfo *) NULL);
+  (void) ResetMagickMemory(polygon_info->edges,0,number_edges*
+    sizeof(*polygon_info->edges));
   direction=0;
   edge=0;
   ghostline=MagickFalse;
@@ -548,7 +563,7 @@ static PolygonInfo *ConvertPathToPolygon(
       Line to.
     */
     next_direction=((path_info[i].point.y > point.y) ||
-      ((path_info[i].point.y == point.y) &&
+      ((fabs(path_info[i].point.y-point.y) < DrawEpsilon) &&
        (path_info[i].point.x > point.x))) ? 1 : -1;
     if ((points != (PointInfo *) NULL) && (direction != 0) &&
         (direction != next_direction))
@@ -685,15 +700,14 @@ static void LogPathInfo(const PathInfo *path_info)
   (void) LogMagickEvent(DrawEvent,GetMagickModule(),"    begin vector-path");
   for (p=path_info; p->code != EndCode; p++)
     (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-      "      %g %g %s",p->point.x,p->point.y,p->code == GhostlineCode ?
+      "      %g,%g %s",p->point.x,p->point.y,p->code == GhostlineCode ?
       "moveto ghostline" : p->code == OpenCode ? "moveto open" :
       p->code == MoveToCode ? "moveto" : p->code == LineToCode ? "lineto" :
       "?");
   (void) LogMagickEvent(DrawEvent,GetMagickModule(),"    end vector-path");
 }
 
-static PathInfo *ConvertPrimitiveToPath(
-  const DrawInfo *magick_unused(draw_info),const PrimitiveInfo *primitive_info)
+static PathInfo *ConvertPrimitiveToPath(const PrimitiveInfo *primitive_info)
 {
   PathInfo
     *path_info;
@@ -718,11 +732,11 @@ static PathInfo *ConvertPrimitiveToPath(
   */
   switch (primitive_info->primitive)
   {
-    case PointPrimitive:
+    case AlphaPrimitive:
     case ColorPrimitive:
-    case MattePrimitive:
-    case TextPrimitive:
     case ImagePrimitive:
+    case PointPrimitive:
+    case TextPrimitive:
       return((PathInfo *) NULL);
     default:
       break;
@@ -753,8 +767,8 @@ static PathInfo *ConvertPrimitiveToPath(
     /*
       Eliminate duplicate points.
     */
-    if ((i == 0) || (fabs(q.x-primitive_info[i].point.x) >= MagickEpsilon) ||
-        (fabs(q.y-primitive_info[i].point.y) >= MagickEpsilon))
+    if ((i == 0) || (fabs(q.x-primitive_info[i].point.x) >= DrawEpsilon) ||
+        (fabs(q.y-primitive_info[i].point.y) >= DrawEpsilon))
       {
         path_info[n].code=code;
         path_info[n].point=primitive_info[i].point;
@@ -763,8 +777,8 @@ static PathInfo *ConvertPrimitiveToPath(
       }
     if (coordinates > 0)
       continue;
-    if ((fabs(p.x-primitive_info[i].point.x) < MagickEpsilon) &&
-        (fabs(p.y-primitive_info[i].point.y) < MagickEpsilon))
+    if ((fabs(p.x-primitive_info[i].point.x) < DrawEpsilon) &&
+        (fabs(p.y-primitive_info[i].point.y) < DrawEpsilon))
       continue;
     /*
       Mark the p point as open if it does not match the q.
@@ -813,7 +827,7 @@ MagickExport DrawInfo *DestroyDrawInfo(DrawInfo *draw_info)
   if (draw_info->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(draw_info != (DrawInfo *) NULL);
-  assert(draw_info->signature == MagickSignature);
+  assert(draw_info->signature == MagickCoreSignature);
   if (draw_info->primitive != (char *) NULL)
     draw_info->primitive=DestroyString(draw_info->primitive);
   if (draw_info->text != (char *) NULL)
@@ -845,7 +859,7 @@ MagickExport DrawInfo *DestroyDrawInfo(DrawInfo *draw_info)
       draw_info->gradient.stops);
   if (draw_info->clip_mask != (char *) NULL)
     draw_info->clip_mask=DestroyString(draw_info->clip_mask);
-  draw_info->signature=(~MagickSignature);
+  draw_info->signature=(~MagickCoreSignature);
   draw_info=(DrawInfo *) RelinquishMagickMemory(draw_info);
   return(draw_info);
 }
@@ -973,7 +987,7 @@ static SegmentInfo AffineEdge(const Image *image,const AffineMatrix *affine,
   inverse_edge.x2=edge->x2;
   inverse_edge.y2=edge->y2;
   z=affine->ry*y+affine->tx;
-  if (affine->sx >= MagickEpsilon)
+  if (affine->sx >= DrawEpsilon)
     {
       intercept=(-z/affine->sx);
       x=intercept;
@@ -985,7 +999,7 @@ static SegmentInfo AffineEdge(const Image *image,const AffineMatrix *affine,
         inverse_edge.x2=x;
     }
   else
-    if (affine->sx < -MagickEpsilon)
+    if (affine->sx < -DrawEpsilon)
       {
         intercept=(-z+(double) image->columns)/affine->sx;
         x=intercept;
@@ -1006,7 +1020,7 @@ static SegmentInfo AffineEdge(const Image *image,const AffineMatrix *affine,
     Determine top and bottom edges.
   */
   z=affine->sy*y+affine->ty;
-  if (affine->rx >= MagickEpsilon)
+  if (affine->rx >= DrawEpsilon)
     {
       intercept=(-z/affine->rx);
       x=intercept;
@@ -1018,7 +1032,7 @@ static SegmentInfo AffineEdge(const Image *image,const AffineMatrix *affine,
         inverse_edge.x2=x;
     }
   else
-    if (affine->rx < -MagickEpsilon)
+    if (affine->rx < -DrawEpsilon)
       {
         intercept=(-z+(double) image->rows)/affine->rx;
         x=intercept;
@@ -1059,27 +1073,6 @@ static AffineMatrix InverseAffineMatrix(const AffineMatrix *affine)
   return(inverse_affine);
 }
 
-static inline ssize_t MagickAbsoluteValue(const ssize_t x)
-{
-  if (x < 0)
-    return(-x);
-  return(x);
-}
-
-static inline double MagickMax(const double x,const double y)
-{
-  if (x > y)
-    return(x);
-  return(y);
-}
-
-static inline double MagickMin(const double x,const double y)
-{
-  if (x < y)
-    return(x);
-  return(y);
-}
-
 MagickExport MagickBooleanType DrawAffineImage(Image *image,
   const Image *source,const AffineMatrix *affine,ExceptionInfo *exception)
 {
@@ -1099,8 +1092,7 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image,
   PointInfo
     extent[4],
     min,
-    max,
-    point;
+    max;
 
   register ssize_t
     i;
@@ -1117,11 +1109,11 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image,
     Determine bounding box.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(source != (const Image *) NULL);
-  assert(source->signature == MagickSignature);
+  assert(source->signature == MagickCoreSignature);
   assert(affine != (AffineMatrix *) NULL);
   extent[0].x=0.0;
   extent[0].y=0.0;
@@ -1133,6 +1125,9 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image,
   extent[3].y=(double) source->rows-1.0;
   for (i=0; i < 4; i++)
   {
+    PointInfo
+      point;
+
     point=extent[i];
     extent[i].x=point.x*affine->sx+point.y*affine->ry+affine->tx;
     extent[i].y=point.x*affine->rx+point.y*affine->sy+affine->ty;
@@ -1183,7 +1178,7 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image,
       x;
 
     register Quantum
-      *restrict q;
+      *magick_restrict q;
 
     SegmentInfo
       inverse_edge;
@@ -1213,7 +1208,7 @@ MagickExport MagickBooleanType DrawAffineImage(Image *image,
       GetPixelInfoPixel(image,q,&composite);
       CompositePixelInfoOver(&pixel,pixel.alpha,&composite,composite.alpha,
         &composite);
-      SetPixelInfoPixel(image,&composite,q);
+      SetPixelViaPixelInfo(image,&composite,q);
       x_offset++;
       q+=GetPixelChannels(image);
     }
@@ -1282,10 +1277,10 @@ static void DrawBoundingRectangles(Image *image,const DrawInfo *draw_info,
     coordinates;
 
   clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
-  (void) QueryColorCompliance("#0000",AllCompliance,&clone_info->fill,
+  (void) QueryColorCompliance("#000F",AllCompliance,&clone_info->fill,
     exception);
-  resolution.x=DefaultResolution;
-  resolution.y=DefaultResolution;
+  resolution.x=96.0;
+  resolution.y=96.0;
   if (clone_info->density != (char *) NULL)
     {
       GeometryInfo
@@ -1300,7 +1295,7 @@ static void DrawBoundingRectangles(Image *image,const DrawInfo *draw_info,
       if ((flags & SigmaValue) == MagickFalse)
         resolution.y=resolution.x;
     }
-  mid=(resolution.x/72.0)*ExpandAffine(&clone_info->affine)*
+  mid=(resolution.x/96.0)*ExpandAffine(&clone_info->affine)*
     clone_info->stroke_width/2.0;
   bounds.x1=0.0;
   bounds.y1=0.0;
@@ -1400,7 +1395,7 @@ MagickExport MagickBooleanType DrawClipPath(Image *image,
   const DrawInfo *draw_info,const char *name,ExceptionInfo *exception)
 {
   char
-    filename[MaxTextExtent];
+    filename[MagickPathExtent];
 
   Image
     *clip_mask;
@@ -1415,11 +1410,11 @@ MagickExport MagickBooleanType DrawClipPath(Image *image,
     status;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(draw_info != (const DrawInfo *) NULL);
-  (void) FormatLocaleString(filename,MaxTextExtent,"%s",name);
+  (void) FormatLocaleString(filename,MagickPathExtent,"%s",name);
   value=GetImageArtifact(image,filename);
   if (value == (const char *) NULL)
     return(MagickFalse);
@@ -1428,7 +1423,7 @@ MagickExport MagickBooleanType DrawClipPath(Image *image,
     return(MagickFalse);
   (void) QueryColorCompliance("#0000",AllCompliance,
     &clip_mask->background_color,exception);
-  clip_mask->background_color.alpha=(Quantum) TransparentAlpha;
+  clip_mask->background_color.alpha=(MagickRealType) TransparentAlpha;
   (void) SetImageBackgroundColor(clip_mask,exception);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(DrawEvent,GetMagickModule(),"\nbegin clip-path %s",
@@ -1439,7 +1434,7 @@ MagickExport MagickBooleanType DrawClipPath(Image *image,
     exception);
   clone_info->clip_mask=(char *) NULL;
   status=NegateImage(clip_mask,MagickFalse,exception);
-  (void) SetImageMask(image,clip_mask,exception);
+  (void) SetImageMask(image,ReadPixelMask,clip_mask,exception);
   clip_mask=DestroyImage(clip_mask);
   status&=DrawImage(image,clone_info,exception);
   clone_info=DestroyDrawInfo(clone_info);
@@ -1515,18 +1510,19 @@ static MagickBooleanType DrawDashPolygon(const DrawInfo *draw_info,
   assert(draw_info != (const DrawInfo *) NULL);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(DrawEvent,GetMagickModule(),"    begin draw-dash");
-  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
-  clone_info->miterlimit=0;
   for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++) ;
   number_vertices=(size_t) i;
   dash_polygon=(PrimitiveInfo *) AcquireQuantumMemory((size_t)
     (2UL*number_vertices+1UL),sizeof(*dash_polygon));
   if (dash_polygon == (PrimitiveInfo *) NULL)
     return(MagickFalse);
+  clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
+  clone_info->miterlimit=0;
   dash_polygon[0]=primitive_info[0];
   scale=ExpandAffine(&draw_info->affine);
   length=scale*(draw_info->dash_pattern[0]-0.5);
-  offset=draw_info->dash_offset != 0.0 ? scale*draw_info->dash_offset : 0.0;
+  offset=fabs(draw_info->dash_offset) >= DrawEpsilon ?
+    scale*draw_info->dash_offset : 0.0;
   j=1;
   for (n=0; offset > 0.0; j=0)
   {
@@ -1552,19 +1548,19 @@ static MagickBooleanType DrawDashPolygon(const DrawInfo *draw_info,
   status=MagickTrue;
   maximum_length=0.0;
   total_length=0.0;
-  for (i=1; i < (ssize_t) number_vertices; i++)
+  for (i=1; (i < (ssize_t) number_vertices) && (length >= 0.0); i++)
   {
     dx=primitive_info[i].point.x-primitive_info[i-1].point.x;
     dy=primitive_info[i].point.y-primitive_info[i-1].point.y;
     maximum_length=hypot((double) dx,dy);
-    if (length == 0.0)
+    if (fabs(length) < DrawEpsilon)
       {
         n++;
-        if (draw_info->dash_pattern[n] == 0.0)
+        if (fabs(draw_info->dash_pattern[n]) < DrawEpsilon)
           n=0;
         length=scale*(draw_info->dash_pattern[n]+(n == 0 ? -0.5 : 0.5));
       }
-    for (total_length=0.0; (total_length+length) <= maximum_length; )
+    for (total_length=0.0; (length >= 0.0) && (maximum_length >= (total_length+length)); )
     {
       total_length+=length;
       if ((n & 0x01) != 0)
@@ -1592,7 +1588,7 @@ static MagickBooleanType DrawDashPolygon(const DrawInfo *draw_info,
           status&=DrawStrokePolygon(image,clone_info,dash_polygon,exception);
         }
       n++;
-      if (draw_info->dash_pattern[n] == 0.0)
+      if (fabs(draw_info->dash_pattern[n]) < DrawEpsilon)
         n=0;
       length=scale*(draw_info->dash_pattern[n]+(n == 0 ? -0.5 : 0.5));
     }
@@ -1606,8 +1602,8 @@ static MagickBooleanType DrawDashPolygon(const DrawInfo *draw_info,
   if ((total_length <= maximum_length) && ((n & 0x01) == 0) && (j > 1))
     {
       dash_polygon[j]=primitive_info[i-1];
-      dash_polygon[j].point.x+=MagickEpsilon;
-      dash_polygon[j].point.y+=MagickEpsilon;
+      dash_polygon[j].point.x+=DrawEpsilon;
+      dash_polygon[j].point.y+=DrawEpsilon;
       dash_polygon[j].coordinates=1;
       j++;
       dash_polygon[0].coordinates=(size_t) j;
@@ -1662,7 +1658,7 @@ static inline MagickBooleanType IsPoint(const char *point)
     value;
 
   value=StringToDouble(point,&p);
-  return((value == 0.0) && (p == point) ? MagickFalse : MagickTrue);
+  return((fabs(value) < DrawEpsilon) && (p == point) ? MagickFalse : MagickTrue);
 }
 
 static inline void TracePoint(PrimitiveInfo *primitive_info,
@@ -1682,37 +1678,37 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
     current;
 
   char
-    key[2*MaxTextExtent],
-    keyword[MaxTextExtent],
-    geometry[MaxTextExtent],
-    name[MaxTextExtent],
-    pattern[MaxTextExtent],
+    keyword[MagickPathExtent],
+    geometry[MagickPathExtent],
+    *next_token,
+    pattern[MagickPathExtent],
     *primitive,
     *token;
 
   const char
     *q;
 
+  double
+    angle,
+    factor,
+    points_extent,
+    primitive_extent;
+
   DrawInfo
     **graphic_context;
 
   MagickBooleanType
     proceed;
 
+  MagickSizeType
+    number_points;
+
   MagickStatusType
     status;
 
-  double
-    angle,
-    factor,
-    primitive_extent;
-
   PointInfo
     point;
 
-  PixelInfo
-    start_color;
-
   PrimitiveInfo
     *primitive_info;
 
@@ -1730,23 +1726,23 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
     bounds;
 
   size_t
-    length,
-    number_points;
+    extent,
+    number_stops;
 
   ssize_t
     j,
     k,
     n;
 
-  /*
-    Ensure the annotation info is valid.
-  */
+  StopInfo
+    *stops;
+
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(draw_info != (DrawInfo *) NULL);
-  assert(draw_info->signature == MagickSignature);
+  assert(draw_info->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   if ((draw_info->primitive == (char *) NULL) ||
@@ -1763,11 +1759,12 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
   primitive_extent=(double) strlen(primitive);
   (void) SetImageArtifact(image,"MVG",primitive);
   n=0;
+  number_stops=0;
+  stops=(StopInfo *) NULL;
   /*
     Allocate primitive info memory.
   */
-  graphic_context=(DrawInfo **) AcquireMagickMemory(
-    sizeof(*graphic_context));
+  graphic_context=(DrawInfo **) AcquireMagickMemory(sizeof(*graphic_context));
   if (graphic_context == (DrawInfo **) NULL)
     {
       primitive=DestroyString(primitive);
@@ -1794,8 +1791,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       graphic_context[n]->viewbox.height=image->rows;
     }
   token=AcquireString(primitive);
-  (void) QueryColorCompliance("#000000",AllCompliance,&start_color,
-    exception);
+  extent=strlen(token)+MagickPathExtent;
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   status=MagickTrue;
@@ -1804,7 +1800,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
     /*
       Interpret graphic primitive.
     */
-    GetMagickToken(q,&q,keyword);
+    GetNextToken(q,&q,MagickPathExtent,keyword);
     if (*keyword == '\0')
       break;
     if (*keyword == '#')
@@ -1829,28 +1825,45 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       {
         if (LocaleCompare("affine",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            affine.sx=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
+            affine.sx=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.rx=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
+            affine.rx=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.ry=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
+            affine.ry=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.sy=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
+            affine.sy=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.tx=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
+            affine.tx=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.ty=StringToDouble(token,(char **) NULL);
+              GetNextToken(q,&q,extent,token);
+            affine.ty=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            break;
+          }
+        if (LocaleCompare("alpha",keyword) == 0)
+          {
+            primitive_type=AlphaPrimitive;
             break;
           }
         if (LocaleCompare("arc",keyword) == 0)
@@ -1871,7 +1884,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("border-color",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             (void) QueryColorCompliance(token,AllCompliance,
               &graphic_context[n]->border_color,exception);
             break;
@@ -1887,7 +1900,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             /*
               Create clip mask.
             */
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             (void) CloneString(&graphic_context[n]->clip_mask,token);
             (void) DrawClipPath(image,graphic_context[n],
               graphic_context[n]->clip_mask,exception);
@@ -1898,7 +1911,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               fill_rule;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             fill_rule=ParseCommandOption(MagickFillRuleOptions,MagickFalse,
               token);
             if (fill_rule == -1)
@@ -1912,7 +1925,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               clip_units;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             clip_units=ParseCommandOption(MagickClipPathOptions,MagickFalse,
               token);
             if (clip_units == -1)
@@ -1953,7 +1966,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               decorate;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             decorate=ParseCommandOption(MagickDecorateOptions,MagickFalse,
               token);
             if (decorate == -1)
@@ -1962,12 +1975,18 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               graphic_context[n]->decorate=(DecorationType) decorate;
             break;
           }
+        if (LocaleCompare("density",keyword) == 0)
+          {
+            GetNextToken(q,&q,extent,token);
+            (void) CloneString(&graphic_context[n]->density,token);
+            break;
+          }
         if (LocaleCompare("direction",keyword) == 0)
           {
             ssize_t
               direction;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             direction=ParseCommandOption(MagickDirectionOptions,MagickFalse,
               token);
             if (direction == -1)
@@ -1989,7 +2008,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("encoding",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             (void) CloneString(&graphic_context[n]->encoding,token);
             break;
           }
@@ -2001,8 +2020,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       {
         if (LocaleCompare("fill",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            (void) FormatLocaleString(pattern,MaxTextExtent,"%s",token);
+            GetNextToken(q,&q,extent,token);
+            (void) FormatLocaleString(pattern,MagickPathExtent,"%s",token);
             if (GetImageArtifact(image,pattern) != (const char *) NULL)
               (void) DrawPatternPath(image,draw_info,token,
                 &graphic_context[n]->fill_pattern,exception);
@@ -2010,6 +2029,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               {
                 status&=QueryColorCompliance(token,AllCompliance,
                   &graphic_context[n]->fill,exception);
+                if (graphic_context[n]->fill_alpha != OpaqueAlpha)
+                  graphic_context[n]->fill.alpha=graphic_context[n]->fill_alpha;
                 if (status == MagickFalse)
                   {
                     ImageInfo
@@ -2017,7 +2038,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
 
                     pattern_info=AcquireImageInfo();
                     (void) CopyMagickString(pattern_info->filename,token,
-                      MaxTextExtent);
+                      MagickPathExtent);
                     graphic_context[n]->fill_pattern=ReadImage(pattern_info,
                       exception);
                     CatchException(exception);
@@ -2026,12 +2047,15 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               }
             break;
           }
-        if (LocaleCompare("fill-alpha",keyword) == 0)
+        if (LocaleCompare("fill-opacity",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             factor=strchr(token,'%') != (char *) NULL ? 0.01 : 1.0;
-            graphic_context[n]->fill.alpha=(double) QuantumRange*
-              factor*StringToDouble(token,(char **) NULL);
+            graphic_context[n]->fill.alpha=(MagickRealType) (QuantumRange-
+              ClampToQuantum((MagickRealType) QuantumRange*(1.0-factor*
+              StringToDouble(token,&next_token))));
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("fill-rule",keyword) == 0)
@@ -2039,7 +2063,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               fill_rule;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             fill_rule=ParseCommandOption(MagickFillRuleOptions,MagickFalse,
               token);
             if (fill_rule == -1)
@@ -2050,23 +2074,25 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("font",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             (void) CloneString(&graphic_context[n]->font,token);
             if (LocaleCompare("none",token) == 0)
-              graphic_context[n]->font=(char *)
-                RelinquishMagickMemory(graphic_context[n]->font);
+              graphic_context[n]->font=(char *) RelinquishMagickMemory(
+                graphic_context[n]->font);
             break;
           }
         if (LocaleCompare("font-family",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             (void) CloneString(&graphic_context[n]->family,token);
             break;
           }
         if (LocaleCompare("font-size",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            graphic_context[n]->pointsize=StringToDouble(token,(char **) NULL);
+            GetNextToken(q,&q,extent,token);
+            graphic_context[n]->pointsize=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("font-stretch",keyword) == 0)
@@ -2074,7 +2100,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               stretch;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             stretch=ParseCommandOption(MagickStretchOptions,MagickFalse,token);
             if (stretch == -1)
               status=MagickFalse;
@@ -2087,7 +2113,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               style;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             style=ParseCommandOption(MagickStyleOptions,MagickFalse,token);
             if (style == -1)
               status=MagickFalse;
@@ -2097,20 +2123,14 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("font-weight",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            graphic_context[n]->weight=StringToUnsignedLong(token);
-            if (LocaleCompare(token,"all") == 0)
-              graphic_context[n]->weight=0;
-            if (LocaleCompare(token,"bold") == 0)
-              graphic_context[n]->weight=700;
-            if (LocaleCompare(token,"bolder") == 0)
-              if (graphic_context[n]->weight <= 800)
-                graphic_context[n]->weight+=100;
-            if (LocaleCompare(token,"lighter") == 0)
-              if (graphic_context[n]->weight >= 100)
-                graphic_context[n]->weight-=100;
-            if (LocaleCompare(token,"normal") == 0)
-              graphic_context[n]->weight=400;
+            ssize_t
+              weight;
+
+            GetNextToken(q,&q,extent,token);
+            weight=ParseCommandOption(MagickWeightOptions,MagickFalse,token);
+            if (weight == -1)
+              weight=(ssize_t) StringToUnsignedLong(token);
+            graphic_context[n]->weight=(size_t) weight;
             break;
           }
         status=MagickFalse;
@@ -2121,7 +2141,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       {
         if (LocaleCompare("gradient-units",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             break;
           }
         if (LocaleCompare("gravity",keyword) == 0)
@@ -2129,7 +2149,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               gravity;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             gravity=ParseCommandOption(MagickGravityOptions,MagickFalse,token);
             if (gravity == -1)
               status=MagickFalse;
@@ -2149,7 +2169,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               compose;
 
             primitive_type=ImagePrimitive;
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             compose=ParseCommandOption(MagickComposeOptions,MagickFalse,token);
             if (compose == -1)
               status=MagickFalse;
@@ -2159,16 +2179,20 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("interline-spacing",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             graphic_context[n]->interline_spacing=StringToDouble(token,
-              (char **) NULL);
+              &next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("interword-spacing",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             graphic_context[n]->interword_spacing=StringToDouble(token,
-              (char **) NULL);
+              &next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         status=MagickFalse;
@@ -2179,8 +2203,10 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       {
         if (LocaleCompare("kerning",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            graphic_context[n]->kerning=StringToDouble(token,(char **) NULL);
+            GetNextToken(q,&q,extent,token);
+            graphic_context[n]->kerning=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         status=MagickFalse;
@@ -2195,32 +2221,29 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           status=MagickFalse;
         break;
       }
-      case 'm':
-      case 'M':
-      {
-        if (LocaleCompare("matte",keyword) == 0)
-          primitive_type=MattePrimitive;
-        else
-          status=MagickFalse;
-        break;
-      }
       case 'o':
       case 'O':
       {
         if (LocaleCompare("offset",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             break;
           }
         if (LocaleCompare("opacity",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             factor=strchr(token,'%') != (char *) NULL ? 0.01 : 1.0;
-            graphic_context[n]->alpha=ClampToQuantum(QuantumRange*(1.0-((1.0-
-              QuantumScale*graphic_context[n]->alpha)*factor*
-              StringToDouble(token,(char **) NULL))));
-            graphic_context[n]->fill.alpha=(double) graphic_context[n]->alpha;
-            graphic_context[n]->stroke.alpha=(double) graphic_context[n]->alpha;
+            graphic_context[n]->alpha=(Quantum) (QuantumRange*(1.0-
+              (QuantumScale*graphic_context[n]->alpha*(1.0-factor*
+              StringToDouble(token,&next_token)))));
+            graphic_context[n]->fill_alpha=QuantumRange*(1.0-(QuantumScale*
+              graphic_context[n]->fill_alpha*(1.0-factor*StringToDouble(token,
+              &next_token))));
+            graphic_context[n]->stroke_alpha=QuantumRange*(1.0-(QuantumScale*
+              graphic_context[n]->stroke_alpha*(1.0-factor*StringToDouble(token,
+              &next_token))));
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         status=MagickFalse;
@@ -2251,7 +2274,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("pop",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             if (LocaleCompare("clip-path",token) == 0)
               break;
             if (LocaleCompare("defs",token) == 0)
@@ -2264,13 +2287,15 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                   {
                     (void) ThrowMagickException(exception,GetMagickModule(),
                       DrawError,"UnbalancedGraphicContextPushPop","`%s'",token);
+                    status=MagickFalse;
                     n=0;
                     break;
                   }
                 if (graphic_context[n]->clip_mask != (char *) NULL)
                   if (LocaleCompare(graphic_context[n]->clip_mask,
                       graphic_context[n-1]->clip_mask) != 0)
-                    (void) SetImageMask(image,(Image *) NULL,exception);
+                    (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
+                      exception);
                 graphic_context[n]=DestroyDrawInfo(graphic_context[n]);
                 n--;
                 break;
@@ -2282,69 +2307,77 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("push",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             if (LocaleCompare("clip-path",token) == 0)
               {
                 char
-                  name[MaxTextExtent];
+                  name[MagickPathExtent];
 
-                GetMagickToken(q,&q,token);
-                (void) FormatLocaleString(name,MaxTextExtent,"%s",token);
+                GetNextToken(q,&q,extent,token);
+                (void) FormatLocaleString(name,MagickPathExtent,"%s",token);
                 for (p=q; *q != '\0'; )
                 {
-                  GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
                   if (LocaleCompare(token,"pop") != 0)
                     continue;
-                  GetMagickToken(q,(const char **) NULL,token);
+                  GetNextToken(q,(const char **) NULL,extent,token);
                   if (LocaleCompare(token,"clip-path") != 0)
                     continue;
                   break;
                 }
                 (void) CopyMagickString(token,p,(size_t) (q-p-4+1));
                 (void) SetImageArtifact(image,name,token);
-                GetMagickToken(q,&q,token);
+                GetNextToken(q,&q,extent,token);
                 break;
               }
             if (LocaleCompare("gradient",token) == 0)
               {
                 char
-                  key[2*MaxTextExtent],
-                  name[MaxTextExtent],
-                  type[MaxTextExtent];
+                  key[2*MagickPathExtent],
+                  name[MagickPathExtent],
+                  type[MagickPathExtent];
 
                 SegmentInfo
                   segment;
 
-                GetMagickToken(q,&q,token);
-                (void) CopyMagickString(name,token,MaxTextExtent);
-                GetMagickToken(q,&q,token);
-                (void) CopyMagickString(type,token,MaxTextExtent);
-                GetMagickToken(q,&q,token);
-                segment.x1=StringToDouble(token,(char **) NULL);
-                GetMagickToken(q,&q,token);
+                GetNextToken(q,&q,extent,token);
+                (void) CopyMagickString(name,token,MagickPathExtent);
+                GetNextToken(q,&q,extent,token);
+                (void) CopyMagickString(type,token,MagickPathExtent);
+                GetNextToken(q,&q,extent,token);
+                segment.x1=StringToDouble(token,&next_token);
+                if (token == next_token)
+                  status=MagickFalse;
+                GetNextToken(q,&q,extent,token);
                 if (*token == ',')
-                  GetMagickToken(q,&q,token);
-                segment.y1=StringToDouble(token,(char **) NULL);
-                GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
+                segment.y1=StringToDouble(token,&next_token);
+                if (token == next_token)
+                  status=MagickFalse;
+                GetNextToken(q,&q,extent,token);
                 if (*token == ',')
-                  GetMagickToken(q,&q,token);
-                segment.x2=StringToDouble(token,(char **) NULL);
-                GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
+                segment.x2=StringToDouble(token,&next_token);
+                if (token == next_token)
+                  status=MagickFalse;
+                GetNextToken(q,&q,extent,token);
                 if (*token == ',')
-                  GetMagickToken(q,&q,token);
-                segment.y2=StringToDouble(token,(char **) NULL);
+                  GetNextToken(q,&q,extent,token);
+                segment.y2=StringToDouble(token,&next_token);
+                if (token == next_token)
+                  status=MagickFalse;
                 if (LocaleCompare(type,"radial") == 0)
                   {
-                    GetMagickToken(q,&q,token);
+                    GetNextToken(q,&q,extent,token);
                     if (*token == ',')
-                      GetMagickToken(q,&q,token);
+                      GetNextToken(q,&q,extent,token);
                   }
                 for (p=q; *q != '\0'; )
                 {
-                  GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
                   if (LocaleCompare(token,"pop") != 0)
                     continue;
-                  GetMagickToken(q,(const char **) NULL,token);
+                  GetNextToken(q,(const char **) NULL,extent,token);
                   if (LocaleCompare(token,"gradient") != 0)
                     continue;
                   break;
@@ -2362,62 +2395,79 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                 bounds.y2=graphic_context[n]->affine.rx*segment.x2+
                   graphic_context[n]->affine.sy*segment.y2+
                   graphic_context[n]->affine.ty;
-                (void) FormatLocaleString(key,MaxTextExtent,"%s",name);
+                (void) FormatLocaleString(key,MagickPathExtent,"%s",name);
                 (void) SetImageArtifact(image,key,token);
-                (void) FormatLocaleString(key,MaxTextExtent,"%s-geometry",name);
-                (void) FormatLocaleString(geometry,MaxTextExtent,
+                (void) FormatLocaleString(key,MagickPathExtent,"%s-type",name);
+                (void) SetImageArtifact(image,key,type);
+                (void) FormatLocaleString(key,MagickPathExtent,"%s-geometry",
+                  name);
+                (void) FormatLocaleString(geometry,MagickPathExtent,
                   "%gx%g%+.15g%+.15g",
                   MagickMax(fabs(bounds.x2-bounds.x1+1.0),1.0),
                   MagickMax(fabs(bounds.y2-bounds.y1+1.0),1.0),
                   bounds.x1,bounds.y1);
                 (void) SetImageArtifact(image,key,geometry);
-                GetMagickToken(q,&q,token);
+                GetNextToken(q,&q,extent,token);
                 break;
               }
             if (LocaleCompare("pattern",token) == 0)
               {
+                char
+                  key[2*MagickPathExtent],
+                  name[MagickPathExtent];
+
                 RectangleInfo
-                  bounds;
-
-                GetMagickToken(q,&q,token);
-                (void) CopyMagickString(name,token,MaxTextExtent);
-                GetMagickToken(q,&q,token);
-                bounds.x=(ssize_t) ceil(StringToDouble(token,(char **) NULL)-
-                  0.5);
-                GetMagickToken(q,&q,token);
+                  pattern_bounds;
+
+                GetNextToken(q,&q,extent,token);
+                (void) CopyMagickString(name,token,MagickPathExtent);
+                GetNextToken(q,&q,extent,token);
+                pattern_bounds.x=(ssize_t) ceil(StringToDouble(token,
+                  &next_token)-0.5);
+                if (token == next_token)
+                  status=MagickFalse;
+                GetNextToken(q,&q,extent,token);
                 if (*token == ',')
-                  GetMagickToken(q,&q,token);
-                bounds.y=(ssize_t) ceil(StringToDouble(token,(char **) NULL)-
-                  0.5);
-                GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
+                pattern_bounds.y=(ssize_t) ceil(StringToDouble(token,
+                  &next_token)-0.5);
+                if (token == next_token)
+                  status=MagickFalse;
+                GetNextToken(q,&q,extent,token);
                 if (*token == ',')
-                  GetMagickToken(q,&q,token);
-                bounds.width=(size_t) floor(StringToDouble(token,
-                  (char **) NULL)+0.5);
-                GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
+                pattern_bounds.width=(size_t) floor(StringToDouble(token,
+                  &next_token)+0.5);
+                if (token == next_token)
+                  status=MagickFalse;
+                GetNextToken(q,&q,extent,token);
                 if (*token == ',')
-                  GetMagickToken(q,&q,token);
-                bounds.height=(size_t) floor(StringToDouble(token,
-                  (char **) NULL)+0.5);
+                  GetNextToken(q,&q,extent,token);
+                pattern_bounds.height=(size_t) floor(StringToDouble(token,
+                  &next_token)+0.5);
+                if (token == next_token)
+                  status=MagickFalse;
                 for (p=q; *q != '\0'; )
                 {
-                  GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
                   if (LocaleCompare(token,"pop") != 0)
                     continue;
-                  GetMagickToken(q,(const char **) NULL,token);
+                  GetNextToken(q,(const char **) NULL,extent,token);
                   if (LocaleCompare(token,"pattern") != 0)
                     continue;
                   break;
                 }
                 (void) CopyMagickString(token,p,(size_t) (q-p-4+1));
-                (void) FormatLocaleString(key,MaxTextExtent,"%s",name);
+                (void) FormatLocaleString(key,MagickPathExtent,"%s",name);
                 (void) SetImageArtifact(image,key,token);
-                (void) FormatLocaleString(key,MaxTextExtent,"%s-geometry",name);
-                (void) FormatLocaleString(geometry,MaxTextExtent,
-                  "%.20gx%.20g%+.20g%+.20g",(double) bounds.width,(double)
-                  bounds.height,(double) bounds.x,(double) bounds.y);
+                (void) FormatLocaleString(key,MagickPathExtent,"%s-geometry",
+                  name);
+                (void) FormatLocaleString(geometry,MagickPathExtent,
+                  "%.20gx%.20g%+.20g%+.20g",(double)pattern_bounds.width,
+                  (double)pattern_bounds.height,(double)pattern_bounds.x,
+                  (double)pattern_bounds.y);
                 (void) SetImageArtifact(image,key,geometry);
-                GetMagickToken(q,&q,token);
+                GetNextToken(q,&q,extent,token);
                 break;
               }
             if (LocaleCompare("graphic-context",token) == 0)
@@ -2454,8 +2504,10 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("rotate",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            angle=StringToDouble(token,(char **) NULL);
+            GetNextToken(q,&q,extent,token);
+            angle=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             affine.sx=cos(DegreesToRadians(fmod((double) angle,360.0)));
             affine.rx=sin(DegreesToRadians(fmod((double) angle,360.0)));
             affine.ry=(-sin(DegreesToRadians(fmod((double) angle,360.0))));
@@ -2475,25 +2527,33 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       {
         if (LocaleCompare("scale",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            affine.sx=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
+            affine.sx=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.sy=StringToDouble(token,(char **) NULL);
+              GetNextToken(q,&q,extent,token);
+            affine.sy=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("skewX",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            angle=StringToDouble(token,(char **) NULL);
+            GetNextToken(q,&q,extent,token);
+            angle=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             affine.ry=sin(DegreesToRadians(angle));
             break;
           }
         if (LocaleCompare("skewY",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            angle=StringToDouble(token,(char **) NULL);
+            GetNextToken(q,&q,extent,token);
+            angle=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             affine.rx=(-tan(DegreesToRadians(angle)/2.0));
             break;
           }
@@ -2502,19 +2562,33 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             PixelInfo
               stop_color;
 
-            GetMagickToken(q,&q,token);
+            number_stops++;
+            if (number_stops == 1)
+              stops=(StopInfo *) AcquireQuantumMemory(2,sizeof(*stops));
+            else if (number_stops > 2)
+              stops=(StopInfo *) ResizeQuantumMemory(stops,number_stops,
+                sizeof(*stops));
+            if (stops == (StopInfo *) NULL)
+              {
+                (void) ThrowMagickException(exception,GetMagickModule(),
+                  ResourceLimitError,"MemoryAllocationFailed","`%s'",
+                  image->filename);
+                break;
+              }
+            GetNextToken(q,&q,extent,token);
             (void) QueryColorCompliance(token,AllCompliance,&stop_color,
               exception);
-            (void) GradientImage(image,LinearGradient,ReflectSpread,
-              &start_color,&stop_color,exception);
-            start_color=stop_color;
-            GetMagickToken(q,&q,token);
+            stops[number_stops-1].color=stop_color;
+            GetNextToken(q,&q,extent,token);
+            stops[number_stops-1].offset=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("stroke",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            (void) FormatLocaleString(pattern,MaxTextExtent,"%s",token);
+            GetNextToken(q,&q,extent,token);
+            (void) FormatLocaleString(pattern,MagickPathExtent,"%s",token);
             if (GetImageArtifact(image,pattern) != (const char *) NULL)
               (void) DrawPatternPath(image,draw_info,token,
                 &graphic_context[n]->stroke_pattern,exception);
@@ -2522,6 +2596,9 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               {
                 status&=QueryColorCompliance(token,AllCompliance,
                   &graphic_context[n]->stroke,exception);
+                if (graphic_context[n]->stroke_alpha != OpaqueAlpha)
+                  graphic_context[n]->stroke.alpha=
+                    graphic_context[n]->stroke_alpha;
                 if (status == MagickFalse)
                   {
                     ImageInfo
@@ -2529,7 +2606,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
 
                     pattern_info=AcquireImageInfo();
                     (void) CopyMagickString(pattern_info->filename,token,
-                      MaxTextExtent);
+                      MagickPathExtent);
                     graphic_context[n]->stroke_pattern=ReadImage(pattern_info,
                       exception);
                     CatchException(exception);
@@ -2540,7 +2617,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("stroke-antialias",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             graphic_context[n]->stroke_antialias=
               StringToLong(token) != 0 ? MagickTrue : MagickFalse;
             break;
@@ -2553,17 +2630,17 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             if (IsPoint(q) != MagickFalse)
               {
                 const char
-                  *p;
+                  *r;
 
-                p=q;
-                GetMagickToken(p,&p,token);
+                r=q;
+                GetNextToken(r,&r,extent,token);
                 if (*token == ',')
-                  GetMagickToken(p,&p,token);
+                  GetNextToken(r,&r,extent,token);
                 for (x=0; IsPoint(token) != MagickFalse; x++)
                 {
-                  GetMagickToken(p,&p,token);
+                  GetNextToken(r,&r,extent,token);
                   if (*token == ',')
-                    GetMagickToken(p,&p,token);
+                    GetNextToken(r,&r,extent,token);
                 }
                 graphic_context[n]->dash_pattern=(double *)
                   AcquireQuantumMemory((size_t) (2UL*x+1UL),
@@ -2573,15 +2650,20 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                     (void) ThrowMagickException(exception,GetMagickModule(),
                       ResourceLimitError,"MemoryAllocationFailed","`%s'",
                       image->filename);
+                    status=MagickFalse;
                     break;
                   }
                 for (j=0; j < x; j++)
                 {
-                  GetMagickToken(q,&q,token);
+                  GetNextToken(q,&q,extent,token);
                   if (*token == ',')
-                    GetMagickToken(q,&q,token);
+                    GetNextToken(q,&q,extent,token);
                   graphic_context[n]->dash_pattern[j]=StringToDouble(token,
-                    (char **) NULL);
+                    &next_token);
+                  if (token == next_token)
+                    status=MagickFalse;
+                  if (graphic_context[n]->dash_pattern[j] < 0.0)
+                    status=MagickFalse;
                 }
                 if ((x & 0x01) != 0)
                   for ( ; j < (2*x); j++)
@@ -2590,14 +2672,16 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                 graphic_context[n]->dash_pattern[j]=0.0;
                 break;
               }
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             break;
           }
         if (LocaleCompare("stroke-dashoffset",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             graphic_context[n]->dash_offset=StringToDouble(token,
-              (char **) NULL);
+              &next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("stroke-linecap",keyword) == 0)
@@ -2605,7 +2689,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               linecap;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             linecap=ParseCommandOption(MagickLineCapOptions,MagickFalse,token);
             if (linecap == -1)
               status=MagickFalse;
@@ -2618,7 +2702,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               linejoin;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             linejoin=ParseCommandOption(MagickLineJoinOptions,MagickFalse,
               token);
             if (linejoin == -1)
@@ -2629,23 +2713,27 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("stroke-miterlimit",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             graphic_context[n]->miterlimit=StringToUnsignedLong(token);
             break;
           }
         if (LocaleCompare("stroke-opacity",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             factor=strchr(token,'%') != (char *) NULL ? 0.01 : 1.0;
-            graphic_context[n]->stroke.alpha=(double) QuantumRange*
-              factor*StringToDouble(token,(char **) NULL);
+            graphic_context[n]->stroke.alpha=(MagickRealType) (QuantumRange-
+              ClampToQuantum((MagickRealType) QuantumRange*(1.0-factor*
+              StringToDouble(token,&next_token))));
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         if (LocaleCompare("stroke-width",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            graphic_context[n]->stroke_width=StringToDouble(token,
-              (char **) NULL);
+            GetNextToken(q,&q,extent,token);
+            graphic_context[n]->stroke_width=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         status=MagickFalse;
@@ -2664,7 +2752,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               align;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             align=ParseCommandOption(MagickAlignOptions,MagickFalse,token);
             if (align == -1)
               status=MagickFalse;
@@ -2677,7 +2765,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             ssize_t
               align;
 
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             align=ParseCommandOption(MagickAlignOptions,MagickFalse,token);
             if (align == -1)
               status=MagickFalse;
@@ -2687,26 +2775,30 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("text-antialias",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            graphic_context[n]->text_antialias=
-              StringToLong(token) != 0 ? MagickTrue : MagickFalse;
+            GetNextToken(q,&q,extent,token);
+            graphic_context[n]->text_antialias=StringToLong(token) != 0 ?
+              MagickTrue : MagickFalse;
             break;
           }
         if (LocaleCompare("text-undercolor",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             (void) QueryColorCompliance(token,AllCompliance,
               &graphic_context[n]->undercolor,exception);
             break;
           }
         if (LocaleCompare("translate",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
-            affine.tx=StringToDouble(token,(char **) NULL);
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
+            affine.tx=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
-            affine.ty=StringToDouble(token,(char **) NULL);
+              GetNextToken(q,&q,extent,token);
+            affine.ty=StringToDouble(token,&next_token);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         status=MagickFalse;
@@ -2717,24 +2809,32 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       {
         if (LocaleCompare("viewbox",keyword) == 0)
           {
-            GetMagickToken(q,&q,token);
+            GetNextToken(q,&q,extent,token);
             graphic_context[n]->viewbox.x=(ssize_t) ceil(StringToDouble(token,
-              (char **) NULL)-0.5);
-            GetMagickToken(q,&q,token);
+              &next_token)-0.5);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
             graphic_context[n]->viewbox.y=(ssize_t) ceil(StringToDouble(token,
-              (char **) NULL)-0.5);
-            GetMagickToken(q,&q,token);
+              &next_token)-0.5);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
             graphic_context[n]->viewbox.width=(size_t) floor(StringToDouble(
-              token,(char **) NULL)+0.5);
-            GetMagickToken(q,&q,token);
+              token,&next_token)+0.5);
+            if (token == next_token)
+              status=MagickFalse;
+            GetNextToken(q,&q,extent,token);
             if (*token == ',')
-              GetMagickToken(q,&q,token);
+              GetNextToken(q,&q,extent,token);
             graphic_context[n]->viewbox.height=(size_t) floor(StringToDouble(
-              token,(char **) NULL)+0.5);
+              token,&next_token)+0.5);
+            if (token == next_token)
+              status=MagickFalse;
             break;
           }
         status=MagickFalse;
@@ -2748,8 +2848,10 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
     }
     if (status == MagickFalse)
       break;
-    if ((affine.sx != 1.0) || (affine.rx != 0.0) || (affine.ry != 0.0) ||
-        (affine.sy != 1.0) || (affine.tx != 0.0) || (affine.ty != 0.0))
+    if ((fabs(affine.sx-1.0) >= DrawEpsilon) ||
+        (fabs(affine.rx) >= DrawEpsilon) || (fabs(affine.ry) >= DrawEpsilon) ||
+        (fabs(affine.sy-1.0) >= DrawEpsilon) ||
+        (fabs(affine.tx) >= DrawEpsilon) || (fabs(affine.ty) >= DrawEpsilon))
       {
         graphic_context[n]->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
         graphic_context[n]->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
@@ -2762,9 +2864,25 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       }
     if (primitive_type == UndefinedPrimitive)
       {
+        if (*q == '\0')
+          {
+            if (number_stops > 1)
+              {
+                GradientType
+                  type;
+
+              type=LinearGradient;
+              if (draw_info->gradient.type == RadialGradient)
+                type=RadialGradient;
+              (void) GradientImage(image,type,PadSpread,stops,number_stops,
+                exception);
+             }
+           if (number_stops > 0)
+             stops=(StopInfo *) RelinquishMagickMemory(stops);
+          }
         if (image->debug != MagickFalse)
-          (void) LogMagickEvent(DrawEvent,GetMagickModule(),"  %.*s",
-            (int) (q-p),p);
+          (void) LogMagickEvent(DrawEvent,GetMagickModule(),"  %.*s",(int)
+            (q-p),p);
         continue;
       }
     /*
@@ -2781,15 +2899,19 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       */
       if (IsPoint(q) == MagickFalse)
         break;
-      GetMagickToken(q,&q,token);
-      point.x=StringToDouble(token,(char **) NULL);
-      GetMagickToken(q,&q,token);
+      GetNextToken(q,&q,extent,token);
+      point.x=StringToDouble(token,&next_token);
+      if (token == next_token)
+        status=MagickFalse;
+      GetNextToken(q,&q,extent,token);
       if (*token == ',')
-        GetMagickToken(q,&q,token);
-      point.y=StringToDouble(token,(char **) NULL);
-      GetMagickToken(q,(const char **) NULL,token);
+        GetNextToken(q,&q,extent,token);
+      point.y=StringToDouble(token,&next_token);
+      if (token == next_token)
+        status=MagickFalse;
+      GetNextToken(q,(const char **) NULL,extent,token);
       if (*token == ',')
-        GetMagickToken(q,&q,token);
+        GetNextToken(q,&q,extent,token);
       primitive_info[i].primitive=primitive_type;
       primitive_info[i].point=point;
       primitive_info[i].coordinates=0;
@@ -2800,12 +2922,10 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       number_points<<=1;
       primitive_info=(PrimitiveInfo *) ResizeQuantumMemory(primitive_info,
         (size_t) number_points,sizeof(*primitive_info));
-      if (primitive_info == (PrimitiveInfo *) NULL)
-        {
-          (void) ThrowMagickException(exception,GetMagickModule(),
-            ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
-          break;
-        }
+      if ((primitive_info == (PrimitiveInfo *) NULL) ||
+          (number_points != (MagickSizeType) ((size_t) number_points)))
+        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+          image->filename);
     }
     primitive_info[j].primitive=primitive_type;
     primitive_info[j].coordinates=(size_t) x;
@@ -2833,12 +2953,12 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
     /*
       Speculate how many points our primitive might consume.
     */
-    length=primitive_info[j].coordinates;
+    points_extent=(double) primitive_info[j].coordinates;
     switch (primitive_type)
     {
       case RectanglePrimitive:
       {
-        length*=5;
+        points_extent*=5;
         break;
       }
       case RoundRectanglePrimitive:
@@ -2851,8 +2971,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
         alpha=bounds.x2-bounds.x1;
         beta=bounds.y2-bounds.y1;
         radius=hypot((double) alpha,(double) beta);
-        length*=5;
-        length+=2*((size_t) ceil((double) MagickPI*radius))+6*BezierQuantum+360;
+        points_extent*=5;
+        points_extent+=2*ceil((double) MagickPI*radius)+6*BezierQuantum+360;
         break;
       }
       case BezierPrimitive:
@@ -2860,7 +2980,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
         if (primitive_info[j].coordinates > 107)
           (void) ThrowMagickException(exception,GetMagickModule(),DrawError,
             "TooManyBezierCoordinates","`%s'",token);
-        length=BezierQuantum*primitive_info[j].coordinates;
+        points_extent=(double) (BezierQuantum*primitive_info[j].coordinates);
         break;
       }
       case PathPrimitive:
@@ -2869,8 +2989,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           *s,
           *t;
 
-        GetMagickToken(q,&q,token);
-        length=1;
+        GetNextToken(q,&q,extent,token);
+        points_extent=1;
         t=token;
         for (s=token; *s != '\0'; s=t)
         {
@@ -2884,9 +3004,9 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               t++;
               continue;
             }
-          length++;
+          points_extent++;
         }
-        length=length*BezierQuantum/2;
+        points_extent=points_extent*BezierQuantum;
         break;
       }
       case CirclePrimitive:
@@ -2901,21 +3021,28 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
         alpha=bounds.x2-bounds.x1;
         beta=bounds.y2-bounds.y1;
         radius=hypot((double) alpha,(double) beta);
-        length=2*((size_t) ceil((double) MagickPI*radius))+6*BezierQuantum+360;
+        points_extent=2*ceil((double) MagickPI*radius)+6*BezierQuantum+360;
         break;
       }
       default:
         break;
     }
-    if ((size_t) (i+length) >= number_points)
+    if (((double) ((size_t) points_extent)) < points_extent)
+      {
+        (void) ThrowMagickException(exception,GetMagickModule(),
+          ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
+        break;
+      }
+    if (((MagickSizeType) (i+points_extent)) >= number_points)
       {
         /*
           Resize based on speculative points required by primitive.
         */
-        number_points+=length+1;
+        number_points+=points_extent+1;
         primitive_info=(PrimitiveInfo *) ResizeQuantumMemory(primitive_info,
           (size_t) number_points,sizeof(*primitive_info));
-        if (primitive_info == (PrimitiveInfo *) NULL)
+        if ((primitive_info == (PrimitiveInfo *) NULL) ||
+            (number_points != (MagickSizeType) ((size_t) number_points)))
           {
             (void) ThrowMagickException(exception,GetMagickModule(),
               ResourceLimitError,"MemoryAllocationFailed","`%s'",
@@ -3035,8 +3162,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
         i=(ssize_t) (j+TracePath(primitive_info+j,token));
         break;
       }
+      case AlphaPrimitive:
       case ColorPrimitive:
-      case MattePrimitive:
       {
         ssize_t
           method;
@@ -3046,7 +3173,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             status=MagickFalse;
             break;
           }
-        GetMagickToken(q,&q,token);
+        GetNextToken(q,&q,extent,token);
         method=ParseCommandOption(MagickMethodOptions,MagickFalse,token);
         if (method == -1)
           status=MagickFalse;
@@ -3062,7 +3189,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             break;
           }
         if (*token != ',')
-          GetMagickToken(q,&q,token);
+          GetNextToken(q,&q,extent,token);
         primitive_info[j].text=AcquireString(token);
         break;
       }
@@ -3073,7 +3200,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             status=MagickFalse;
             break;
           }
-        GetMagickToken(q,&q,token);
+        GetNextToken(q,&q,extent,token);
         primitive_info[j].text=AcquireString(token);
         break;
       }
@@ -3212,25 +3339,42 @@ static inline double GetStopColorOffset(const GradientInfo *gradient,
     }
     case RadialGradient:
     {
-      double
-        length,
-        offset;
-
       PointInfo
         v;
 
-      v.x=(double) x-gradient->center.x;
-      v.y=(double) y-gradient->center.y;
-      length=sqrt(v.x*v.x+v.y*v.y);
       if (gradient->spread == RepeatSpread)
-        return(length);
-      offset=length/gradient->radius;
-      return(offset);
+        {
+          v.x=(double) x-gradient->center.x;
+          v.y=(double) y-gradient->center.y;
+          return(sqrt(v.x*v.x+v.y*v.y));
+        }
+      v.x=(double) (((x-gradient->center.x)*cos(DegreesToRadians(
+        gradient->angle)))+((y-gradient->center.y)*sin(DegreesToRadians(
+        gradient->angle))))/gradient->radii.x;
+      v.y=(double) (((x-gradient->center.x)*sin(DegreesToRadians(
+        gradient->angle)))-((y-gradient->center.y)*cos(DegreesToRadians(
+        gradient->angle))))/gradient->radii.y;
+      return(sqrt(v.x*v.x+v.y*v.y));
     }
   }
   return(0.0);
 }
 
+static int StopInfoCompare(const void *x,const void *y)
+{
+  StopInfo
+    *stop_1,
+    *stop_2;
+
+  stop_1=(StopInfo *) x;
+  stop_2=(StopInfo *) y;
+  if (stop_1->offset > stop_2->offset)
+    return(1);
+  if (fabs(stop_1->offset-stop_2->offset) <= DrawEpsilon)
+    return(0);
+  return(-1);
+}
+
 MagickExport MagickBooleanType DrawGradientImage(Image *image,
   const DrawInfo *draw_info,ExceptionInfo *exception)
 {
@@ -3265,11 +3409,13 @@ MagickExport MagickBooleanType DrawGradientImage(Image *image,
     Draw linear or radial gradient on image.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(draw_info != (const DrawInfo *) NULL);
   gradient=(&draw_info->gradient);
+  qsort(gradient->stops,gradient->number_stops,sizeof(StopInfo),
+    StopInfoCompare);
   gradient_vector=(&gradient->gradient_vector);
   point.x=gradient_vector->x2-gradient_vector->x1;
   point.y=gradient_vector->y2-gradient_vector->y1;
@@ -3293,7 +3439,7 @@ MagickExport MagickBooleanType DrawGradientImage(Image *image,
       offset;
 
     register Quantum
-      *restrict q;
+      *magick_restrict q;
 
     register ssize_t
       i,
@@ -3451,7 +3597,7 @@ MagickExport MagickBooleanType DrawGradientImage(Image *image,
       }
       CompositePixelInfoOver(&composite,composite.alpha,&pixel,pixel.alpha,
         &pixel);
-      SetPixelInfoPixel(image,&pixel,q);
+      SetPixelViaPixelInfo(image,&pixel,q);
       q+=GetPixelChannels(image);
     }
     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
@@ -3497,11 +3643,12 @@ MagickExport MagickBooleanType DrawPatternPath(Image *image,
   ExceptionInfo *exception)
 {
   char
-    property[MaxTextExtent];
+    property[MagickPathExtent];
 
   const char
     *geometry,
-    *path;
+    *path,
+    *type;
 
   DrawInfo
     *clone_info;
@@ -3513,16 +3660,16 @@ MagickExport MagickBooleanType DrawPatternPath(Image *image,
     status;
 
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(draw_info != (const DrawInfo *) NULL);
   assert(name != (const char *) NULL);
-  (void) FormatLocaleString(property,MaxTextExtent,"%s",name);
+  (void) FormatLocaleString(property,MagickPathExtent,"%s",name);
   path=GetImageArtifact(image,property);
   if (path == (const char *) NULL)
     return(MagickFalse);
-  (void) FormatLocaleString(property,MaxTextExtent,"%s-geometry",name);
+  (void) FormatLocaleString(property,MagickPathExtent,"%s-geometry",name);
   geometry=GetImageArtifact(image,property);
   if (geometry == (const char *) NULL)
     return(MagickFalse);
@@ -3541,6 +3688,11 @@ MagickExport MagickBooleanType DrawPatternPath(Image *image,
   clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
   clone_info->fill_pattern=NewImageList();
   clone_info->stroke_pattern=NewImageList();
+  (void) FormatLocaleString(property,MagickPathExtent,"%s-type",name);
+  type=GetImageArtifact(image,property);
+  if (type != (const char *) NULL)
+    clone_info->gradient.type=(GradientType) ParseCommandOption(
+      MagickGradientOptions,MagickFalse,type);
   (void) CloneString(&clone_info->primitive,path);
   status=DrawImage(*pattern,clone_info,exception);
   clone_info=DestroyDrawInfo(clone_info);
@@ -3593,11 +3745,11 @@ static PolygonInfo **DestroyPolygonThreadSet(PolygonInfo **polygon_info)
   return(polygon_info);
 }
 
-static PolygonInfo **AcquirePolygonThreadSet(const DrawInfo *draw_info,
+static PolygonInfo **AcquirePolygonThreadSet(
   const PrimitiveInfo *primitive_info)
 {
   PathInfo
-    *restrict path_info;
+    *magick_restrict path_info;
 
   PolygonInfo
     **polygon_info;
@@ -3614,12 +3766,12 @@ static PolygonInfo **AcquirePolygonThreadSet(const DrawInfo *draw_info,
   if (polygon_info == (PolygonInfo **) NULL)
     return((PolygonInfo **) NULL);
   (void) ResetMagickMemory(polygon_info,0,number_threads*sizeof(*polygon_info));
-  path_info=ConvertPrimitiveToPath(draw_info,primitive_info);
+  path_info=ConvertPrimitiveToPath(primitive_info);
   if (path_info == (PathInfo *) NULL)
     return(DestroyPolygonThreadSet(polygon_info));
   for (i=0; i < (ssize_t) number_threads; i++)
   {
-    polygon_info[i]=ConvertPathToPolygon(draw_info,path_info);
+    polygon_info[i]=ConvertPathToPolygon(path_info);
     if (polygon_info[i] == (PolygonInfo *) NULL)
       return(DestroyPolygonThreadSet(polygon_info));
   }
@@ -3728,7 +3880,7 @@ static double GetFillAlpha(PolygonInfo *polygon_info,const double mid,
               else
                 {
                   beta=1.0;
-                  if (distance != 1.0)
+                  if (fabs(distance-1.0) >= DrawEpsilon)
                     beta=sqrt((double) distance);
                   alpha=beta-mid-0.5;
                   if (*stroke_alpha < ((alpha-0.25)*(alpha-0.25)))
@@ -3745,10 +3897,10 @@ static double GetFillAlpha(PolygonInfo *polygon_info,const double mid,
         }
       if (distance > 1.0)
         continue;
-      if (beta == 0.0)
+      if (fabs(beta) < DrawEpsilon)
         {
           beta=1.0;
-          if (distance != 1.0)
+          if (fabs(distance-1.0) >= DrawEpsilon)
             beta=sqrt(distance);
         }
       alpha=beta-1.0;
@@ -3813,7 +3965,7 @@ static MagickBooleanType DrawPolygonPrimitive(Image *image,
     mid;
 
   PolygonInfo
-    **restrict polygon_info;
+    **magick_restrict polygon_info;
 
   register EdgeInfo
     *p;
@@ -3825,23 +3977,23 @@ static MagickBooleanType DrawPolygonPrimitive(Image *image,
     bounds;
 
   ssize_t
-    start,
-    stop,
+    start_y,
+    stop_y,
     y;
 
   /*
     Compute bounding box.
   */
   assert(image != (Image *) NULL);
-  assert(image->signature == MagickSignature);
+  assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   assert(draw_info != (DrawInfo *) NULL);
-  assert(draw_info->signature == MagickSignature);
+  assert(draw_info->signature == MagickCoreSignature);
   assert(primitive_info != (PrimitiveInfo *) NULL);
   if (primitive_info->coordinates == 0)
     return(MagickTrue);
-  polygon_info=AcquirePolygonThreadSet(draw_info,primitive_info);
+  polygon_info=AcquirePolygonThreadSet(primitive_info);
   if (polygon_info == (PolygonInfo **) NULL)
     return(MagickFalse);
 DisableMSCWarning(4127)
@@ -3880,18 +4032,19 @@ RestoreMSCWarning
     image->rows ? (double) image->rows-1 : bounds.y2;
   status=MagickTrue;
   image_view=AcquireAuthenticCacheView(image,exception);
-  if (primitive_info->coordinates == 1)
+  if ((primitive_info->coordinates == 1) ||
+      (polygon_info[0]->number_edges == 0))
     {
       /*
         Draw point.
       */
-      start=(ssize_t) ceil(bounds.y1-0.5);
-      stop=(ssize_t) floor(bounds.y2+0.5);
+      start_y=(ssize_t) ceil(bounds.y1-0.5);
+      stop_y=(ssize_t) floor(bounds.y2+0.5);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
       #pragma omp parallel for schedule(static,4) shared(status) \
         magick_threads(image,image,1,1)
 #endif
-      for (y=start; y <= stop; y++)
+      for (y=start_y; y <= stop_y; y++)
       {
         MagickBooleanType
           sync;
@@ -3903,18 +4056,18 @@ RestoreMSCWarning
           x;
 
         register Quantum
-          *restrict q;
+          *magick_restrict q;
 
         ssize_t
-          start,
-          stop;
+          start_x,
+          stop_x;
 
         if (status == MagickFalse)
           continue;
-        start=(ssize_t) ceil(bounds.x1-0.5);
-        stop=(ssize_t) floor(bounds.x2+0.5);
-        x=start;
-        q=GetCacheViewAuthenticPixels(image_view,x,y,(size_t) (stop-x+1),1,
+        start_x=(ssize_t) ceil(bounds.x1-0.5);
+        stop_x=(ssize_t) floor(bounds.x2+0.5);
+        x=start_x;
+        q=GetCacheViewAuthenticPixels(image_view,x,y,(size_t) (stop_x-x+1),1,
           exception);
         if (q == (Quantum *) NULL)
           {
@@ -3922,13 +4075,13 @@ RestoreMSCWarning
             continue;
           }
         GetPixelInfo(image,&pixel);
-        for ( ; x <= stop; x++)
+        for ( ; x <= stop_x; x++)
         {
           if ((x == (ssize_t) ceil(primitive_info->point.x-0.5)) &&
               (y == (ssize_t) ceil(primitive_info->point.y-0.5)))
             {
-              (void) GetStrokeColor(draw_info,x,y,&pixel,exception);
-              SetPixelInfoPixel(image,&pixel,q);
+              GetFillColor(draw_info,x-start_x,y-start_y,&pixel,exception);
+              SetPixelViaPixelInfo(image,&pixel,q);
             }
           q+=GetPixelChannels(image);
         }
@@ -3946,15 +4099,15 @@ RestoreMSCWarning
   /*
     Draw polygon or line.
   */
-  if (image->alpha_trait != BlendPixelTrait)
+  if (image->alpha_trait == UndefinedPixelTrait)
     (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
-  start=(ssize_t) ceil(bounds.y1-0.5);
-  stop=(ssize_t) floor(bounds.y2+0.5);
+  start_y=(ssize_t) ceil(bounds.y1-0.5);
+  stop_y=(ssize_t) floor(bounds.y2+0.5);
 #if defined(MAGICKCORE_OPENMP_SUPPORT)
   #pragma omp parallel for schedule(static,4) shared(status) \
     magick_threads(image,image,1,1)
 #endif
-  for (y=start; y <= stop; y++)
+  for (y=start_y; y <= stop_y; y++)
   {
     const int
       id = GetOpenMPThreadId();
@@ -3968,27 +4121,26 @@ RestoreMSCWarning
       stroke_color;
 
     register Quantum
-      *restrict q;
+      *magick_restrict q;
 
     register ssize_t
       x;
 
     ssize_t
-      start,
-      stop;
+      start_x,
+      stop_x;
 
     if (status == MagickFalse)
       continue;
-    start=(ssize_t) ceil(bounds.x1-0.5);
-    stop=(ssize_t) floor(bounds.x2+0.5);
-    q=GetCacheViewAuthenticPixels(image_view,start,y,(size_t) (stop-start+1),1,
-      exception);
+    start_x=(ssize_t) ceil(bounds.x1-0.5);
+    stop_x=(ssize_t) floor(bounds.x2+0.5);
+    q=GetCacheViewAuthenticPixels(image_view,start_x,y,(size_t) (stop_x-start_x+      1),1,exception);
     if (q == (Quantum *) NULL)
       {
         status=MagickFalse;
         continue;
       }
-    for (x=start; x <= stop; x++)
+    for (x=start_x; x <= stop_x; x++)
     {
       /*
         Fill and/or stroke.
@@ -4000,11 +4152,11 @@ RestoreMSCWarning
           fill_alpha=fill_alpha > 0.25 ? 1.0 : 0.0;
           stroke_alpha=stroke_alpha > 0.25 ? 1.0 : 0.0;
         }
-      (void) GetFillColor(draw_info,x,y,&fill_color,exception);
+      GetFillColor(draw_info,x-start_x,y-start_y,&fill_color,exception);
       fill_alpha=fill_alpha*fill_color.alpha;
       CompositePixelOver(image,&fill_color,fill_alpha,q,(double)
         GetPixelAlpha(image,q),q);
-      (void) GetStrokeColor(draw_info,x,y,&stroke_color,exception);
+      GetStrokeColor(draw_info,x-start_x,y-start_y,&stroke_color,exception);
       stroke_alpha=stroke_alpha*stroke_color.alpha;
       CompositePixelOver(image,&stroke_color,stroke_alpha,q,(double)
         GetPixelAlpha(image,q),q);
@@ -4080,10 +4232,10 @@ static void LogPrimitiveInfo(const PrimitiveInfo *primitive_info)
   y=(ssize_t) ceil(primitive_info->point.y-0.5);
   switch (primitive_info->primitive)
   {
-    case PointPrimitive:
+    case AlphaPrimitive:
     {
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-        "PointPrimitive %.20g,%.20g %s",(double) x,(double) y,
+        "AlphaPrimitive %.20g,%.20g %s",(double) x,(double) y,
         methods[primitive_info->method]);
       return;
     }
@@ -4094,23 +4246,23 @@ static void LogPrimitiveInfo(const PrimitiveInfo *primitive_info)
         methods[primitive_info->method]);
       return;
     }
-    case MattePrimitive:
+    case ImagePrimitive:
     {
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-        "MattePrimitive %.20g,%.20g %s",(double) x,(double) y,
-        methods[primitive_info->method]);
+        "ImagePrimitive %.20g,%.20g",(double) x,(double) y);
       return;
     }
-    case TextPrimitive:
+    case PointPrimitive:
     {
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-        "TextPrimitive %.20g,%.20g",(double) x,(double) y);
+        "PointPrimitive %.20g,%.20g %s",(double) x,(double) y,
+        methods[primitive_info->method]);
       return;
     }
-    case ImagePrimitive:
+    case TextPrimitive:
     {
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-        "ImagePrimitive %.20g,%.20g",(double) x,(double) y);
+        "TextPrimitive %.20g,%.20g",(double) x,(double) y);
       return;
     }
     default:
@@ -4131,8 +4283,8 @@ static void LogPrimitiveInfo(const PrimitiveInfo *primitive_info)
         p=point;
       }
     point=primitive_info[i].point;
-    if ((fabs(q.x-point.x) >= MagickEpsilon) ||
-        (fabs(q.y-point.y) >= MagickEpsilon))
+    if ((fabs(q.x-point.x) >= DrawEpsilon) ||
+        (fabs(q.y-point.y) >= DrawEpsilon))
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
         "      %.20g: %.18g,%.18g",(double) coordinates,point.x,point.y);
     else
@@ -4142,8 +4294,8 @@ static void LogPrimitiveInfo(const PrimitiveInfo *primitive_info)
     coordinates--;
     if (coordinates > 0)
       continue;
-    if ((fabs(p.x-point.x) >= MagickEpsilon) ||
-        (fabs(p.y-point.y) >= MagickEpsilon))
+    if ((fabs(p.x-point.x) >= DrawEpsilon) ||
+        (fabs(p.y-point.y) >= DrawEpsilon))
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),"    end last (%.20g)",
         (double) coordinates);
     else
@@ -4174,7 +4326,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
         "  begin draw-primitive");
       (void) LogMagickEvent(DrawEvent,GetMagickModule(),
-        "    affine: %g %g %g %g %g %g",draw_info->affine.sx,
+        "    affine: %g,%g,%g,%g,%g,%g",draw_info->affine.sx,
         draw_info->affine.rx,draw_info->affine.ry,draw_info->affine.sy,
         draw_info->affine.tx,draw_info->affine.ty);
     }
@@ -4188,29 +4340,10 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
   image_view=AcquireAuthenticCacheView(image,exception);
   switch (primitive_info->primitive)
   {
-    case PointPrimitive:
-    {
-      PixelInfo
-        fill_color;
-
-      register Quantum
-        *q;
-
-      if ((y < 0) || (y >= (ssize_t) image->rows))
-        break;
-      if ((x < 0) || (x >= (ssize_t) image->columns))
-        break;
-      q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
-      if (q == (Quantum *) NULL)
-        break;
-      (void) GetFillColor(draw_info,x,y,&fill_color,exception);
-      CompositePixelOver(image,&fill_color,(double) fill_color.alpha,q,
-        (double) GetPixelAlpha(image,q),q);
-      (void) SyncCacheViewAuthenticPixels(image_view,exception);
-      break;
-    }
-    case ColorPrimitive:
+    case AlphaPrimitive:
     {
+      if (image->alpha_trait == UndefinedPixelTrait)
+        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
       switch (primitive_info->method)
       {
         case PointMethod:
@@ -4225,9 +4358,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
           if (q == (Quantum *) NULL)
             break;
-          GetPixelInfo(image,&pixel);
-          (void) GetFillColor(draw_info,x,y,&pixel,exception);
-          SetPixelInfoPixel(image,&pixel,q);
+          GetFillColor(draw_info,x,y,&pixel,exception);
+          SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
           (void) SyncCacheViewAuthenticPixels(image_view,exception);
           break;
         }
@@ -4242,10 +4374,11 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
 
           (void) GetOneCacheViewVirtualPixelInfo(image_view,x,y,&target,
             exception);
+          GetPixelInfo(image,&pixel);
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             register Quantum
-              *restrict q;
+              *magick_restrict q;
 
             q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
               exception);
@@ -4259,8 +4392,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
                   q+=GetPixelChannels(image);
                   continue;
                 }
-              (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelInfoPixel(image,&pixel,q);
+              GetFillColor(draw_info,x,y,&pixel,exception);
+              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4272,6 +4405,9 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         case FloodfillMethod:
         case FillToBorderMethod:
         {
+          ChannelType
+            channel_mask;
+
           PixelInfo
             target;
 
@@ -4283,9 +4419,11 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
               target.green=(double) draw_info->border_color.green;
               target.blue=(double) draw_info->border_color.blue;
             }
+          channel_mask=SetImageChannelMask(image,AlphaChannel);
           status&=FloodfillPaintImage(image,draw_info,&target,x,y,
             primitive_info->method == FloodfillMethod ? MagickFalse :
             MagickTrue,exception);
+          (void) SetImageChannelMask(image,channel_mask);
           break;
         }
         case ResetMethod:
@@ -4296,14 +4434,10 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           PixelInfo
             pixel;
 
-          GetPixelInfo(image,&pixel);
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             register Quantum
-              *restrict q;
-
-            register ssize_t
-              x;
+              *magick_restrict q;
 
             q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
               exception);
@@ -4311,8 +4445,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
               break;
             for (x=0; x < (ssize_t) image->columns; x++)
             {
-              (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelInfoPixel(image,&pixel,q);
+              GetFillColor(draw_info,x,y,&pixel,exception);
+              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4324,10 +4458,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       }
       break;
     }
-    case MattePrimitive:
+    case ColorPrimitive:
     {
-      if (image->alpha_trait != BlendPixelTrait)
-        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
       switch (primitive_info->method)
       {
         case PointMethod:
@@ -4342,8 +4474,9 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
           if (q == (Quantum *) NULL)
             break;
-          (void) GetFillColor(draw_info,x,y,&pixel,exception);
-          SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
+          GetPixelInfo(image,&pixel);
+          GetFillColor(draw_info,x,y,&pixel,exception);
+          SetPixelViaPixelInfo(image,&pixel,q);
           (void) SyncCacheViewAuthenticPixels(image_view,exception);
           break;
         }
@@ -4358,14 +4491,10 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
 
           (void) GetOneCacheViewVirtualPixelInfo(image_view,x,y,&target,
             exception);
-          GetPixelInfo(image,&pixel);
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             register Quantum
-              *restrict q;
-
-            register ssize_t
-              x;
+              *magick_restrict q;
 
             q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
               exception);
@@ -4379,8 +4508,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
                   q+=GetPixelChannels(image);
                   continue;
                 }
-              (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
+              GetFillColor(draw_info,x,y,&pixel,exception);
+              SetPixelViaPixelInfo(image,&pixel,q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4392,9 +4521,6 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         case FloodfillMethod:
         case FillToBorderMethod:
         {
-          ChannelType
-            channel_mask;
-
           PixelInfo
             target;
 
@@ -4406,11 +4532,9 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
               target.green=(double) draw_info->border_color.green;
               target.blue=(double) draw_info->border_color.blue;
             }
-          channel_mask=SetImageChannelMask(image,AlphaChannel);
           status&=FloodfillPaintImage(image,draw_info,&target,x,y,
             primitive_info->method == FloodfillMethod ? MagickFalse :
             MagickTrue,exception);
-          (void) SetImageChannelMask(image,channel_mask);
           break;
         }
         case ResetMethod:
@@ -4421,13 +4545,11 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           PixelInfo
             pixel;
 
+          GetPixelInfo(image,&pixel);
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             register Quantum
-              *restrict q;
-
-            register ssize_t
-              x;
+              *magick_restrict q;
 
             q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
               exception);
@@ -4435,8 +4557,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
               break;
             for (x=0; x < (ssize_t) image->columns; x++)
             {
-              (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
+              GetFillColor(draw_info,x,y,&pixel,exception);
+              SetPixelViaPixelInfo(image,&pixel,q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4448,32 +4570,13 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       }
       break;
     }
-    case TextPrimitive:
-    {
-      char
-        geometry[MaxTextExtent];
-
-      DrawInfo
-        *clone_info;
-
-      if (primitive_info->text == (char *) NULL)
-        break;
-      clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
-      (void) CloneString(&clone_info->text,primitive_info->text);
-      (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
-        primitive_info->point.x,primitive_info->point.y);
-      (void) CloneString(&clone_info->geometry,geometry);
-      status&=AnnotateImage(image,clone_info,exception);
-      clone_info=DestroyDrawInfo(clone_info);
-      break;
-    }
     case ImagePrimitive:
     {
       AffineMatrix
         affine;
 
       char
-        composite_geometry[MaxTextExtent];
+        composite_geometry[MagickPathExtent];
 
       Image
         *composite_image;
@@ -4497,7 +4600,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       else
         {
           (void) CopyMagickString(clone_info->filename,primitive_info->text,
-            MaxTextExtent);
+            MagickPathExtent);
           composite_image=ReadImage(clone_info,exception);
         }
       clone_info=DestroyImageInfo(clone_info);
@@ -4510,19 +4613,16 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       if (((x1 != 0L) && (x1 != (ssize_t) composite_image->columns)) ||
           ((y1 != 0L) && (y1 != (ssize_t) composite_image->rows)))
         {
-          char
-            geometry[MaxTextExtent];
-
           /*
             Resize image.
           */
-          (void) FormatLocaleString(geometry,MaxTextExtent,"%gx%g!",
-            primitive_info[1].point.x,primitive_info[1].point.y);
+          (void) FormatLocaleString(composite_geometry,MagickPathExtent,
+            "%gx%g!",primitive_info[1].point.x,primitive_info[1].point.y);
           composite_image->filter=image->filter;
-          (void) TransformImage(&composite_image,(char *) NULL,geometry,
-            exception);
+          (void) TransformImage(&composite_image,(char *) NULL,
+            composite_geometry,exception);
         }
-      if (composite_image->alpha_trait != BlendPixelTrait)
+      if (composite_image->alpha_trait == UndefinedPixelTrait)
         (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,
           exception);
       if (draw_info->alpha != OpaqueAlpha)
@@ -4531,7 +4631,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       image->gravity=draw_info->gravity;
       geometry.x=x;
       geometry.y=y;
-      (void) FormatLocaleString(composite_geometry,MaxTextExtent,
+      (void) FormatLocaleString(composite_geometry,MagickPathExtent,
         "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,(double)
         composite_image->rows,(double) geometry.x,(double) geometry.y);
       (void) ParseGravityGeometry(image,composite_geometry,&geometry,exception);
@@ -4547,6 +4647,46 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       composite_image=DestroyImage(composite_image);
       break;
     }
+    case PointPrimitive:
+    {
+      PixelInfo
+        fill_color;
+
+      register Quantum
+        *q;
+
+      if ((y < 0) || (y >= (ssize_t) image->rows))
+        break;
+      if ((x < 0) || (x >= (ssize_t) image->columns))
+        break;
+      q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
+      if (q == (Quantum *) NULL)
+        break;
+      GetFillColor(draw_info,x,y,&fill_color,exception);
+      CompositePixelOver(image,&fill_color,(double) fill_color.alpha,q,
+        (double) GetPixelAlpha(image,q),q);
+      (void) SyncCacheViewAuthenticPixels(image_view,exception);
+      break;
+    }
+    case TextPrimitive:
+    {
+      char
+        geometry[MagickPathExtent];
+
+      DrawInfo
+        *clone_info;
+
+      if (primitive_info->text == (char *) NULL)
+        break;
+      clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
+      (void) CloneString(&clone_info->text,primitive_info->text);
+      (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
+        primitive_info->point.x,primitive_info->point.y);
+      (void) CloneString(&clone_info->geometry,geometry);
+      status&=AnnotateImage(image,clone_info,exception);
+      clone_info=DestroyDrawInfo(clone_info);
+      break;
+    }
     default:
     {
       double
@@ -4560,8 +4700,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         LogPrimitiveInfo(primitive_info);
       scale=ExpandAffine(&draw_info->affine);
       if ((draw_info->dash_pattern != (double *) NULL) &&
-          (draw_info->dash_pattern[0] != 0.0) &&
-          ((scale*draw_info->stroke_width) >= MagickEpsilon) &&
+          (fabs(draw_info->dash_pattern[0]) >= DrawEpsilon) &&
+          (fabs(scale*draw_info->stroke_width) >= DrawEpsilon) &&
           (draw_info->stroke.alpha != (Quantum) TransparentAlpha))
         {
           /*
@@ -4569,7 +4709,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           */
           clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
           clone_info->stroke_width=0.0;
-          clone_info->stroke.alpha=(Quantum) TransparentAlpha;
+          clone_info->stroke.alpha=(MagickRealType) TransparentAlpha;
           status&=DrawPolygonPrimitive(image,clone_info,primitive_info,
             exception);
           clone_info=DestroyDrawInfo(clone_info);
@@ -4578,7 +4718,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         }
       mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0;
       if ((mid > 1.0) &&
-          (draw_info->stroke.alpha != (Quantum) TransparentAlpha))
+          ((draw_info->stroke.alpha != (Quantum) TransparentAlpha) ||
+           (draw_info->stroke_pattern != (Image *) NULL)))
         {
           MagickBooleanType
             closed_path;
@@ -4588,8 +4729,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           */
           for (i=0; primitive_info[i].primitive != UndefinedPrimitive; i++) ;
           closed_path=
-            (primitive_info[i-1].point.x == primitive_info[0].point.x) &&
-            (primitive_info[i-1].point.y == primitive_info[0].point.y) ?
+            (fabs(primitive_info[i-1].point.x-primitive_info[0].point.x) < DrawEpsilon) &&
+            (fabs(primitive_info[i-1].point.y-primitive_info[0].point.y) < DrawEpsilon) ?
             MagickTrue : MagickFalse;
           i=(ssize_t) primitive_info[0].coordinates;
           if ((((draw_info->linecap == RoundCap) ||
@@ -4603,7 +4744,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
             }
           clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
           clone_info->stroke_width=0.0;
-          clone_info->stroke.alpha=(Quantum) TransparentAlpha;
+          clone_info->stroke.alpha=(MagickRealType) TransparentAlpha;
           status&=DrawPolygonPrimitive(image,clone_info,primitive_info,
             exception);
           clone_info=DestroyDrawInfo(clone_info);
@@ -4662,10 +4803,10 @@ static void DrawRoundLinecap(Image *image,const DrawInfo *draw_info,
   for (i=0; i < 4; i++)
     linecap[i]=(*primitive_info);
   linecap[0].coordinates=4;
-  linecap[1].point.x+=(double) (10.0*MagickEpsilon);
-  linecap[2].point.x+=(double) (10.0*MagickEpsilon);
-  linecap[2].point.y+=(double) (10.0*MagickEpsilon);
-  linecap[3].point.y+=(double) (10.0*MagickEpsilon);
+  linecap[1].point.x+=2.0*DrawEpsilon;
+  linecap[2].point.x+=2.0*DrawEpsilon;
+  linecap[2].point.y+=2.0*DrawEpsilon;
+  linecap[3].point.y+=2.0*DrawEpsilon;
   linecap[4].primitive=UndefinedPrimitive;
   (void) DrawPolygonPrimitive(image,draw_info,linecap,exception);
 }
@@ -4703,7 +4844,7 @@ static MagickBooleanType DrawStrokePolygon(Image *image,
   if (clone_info->stroke_pattern != (Image *) NULL)
     clone_info->fill_pattern=CloneImage(clone_info->stroke_pattern,0,0,
       MagickTrue,exception);
-  clone_info->stroke.alpha=(Quantum) TransparentAlpha;
+  clone_info->stroke.alpha=(MagickRealType) TransparentAlpha;
   clone_info->stroke_width=0.0;
   clone_info->fill_rule=NonZeroRule;
   status=MagickTrue;
@@ -4715,8 +4856,8 @@ static MagickBooleanType DrawStrokePolygon(Image *image,
       break;
     stroke_polygon=(PrimitiveInfo *) RelinquishMagickMemory(stroke_polygon);
     q=p+p->coordinates-1;
-    closed_path=(q->point.x == p->point.x) && (q->point.y == p->point.y) ?
-      MagickTrue : MagickFalse;
+    closed_path=(fabs(q->point.x-p->point.x) < DrawEpsilon) &&
+      (fabs(q->point.y-p->point.y) < DrawEpsilon) ? MagickTrue : MagickFalse;
     if ((draw_info->linecap == RoundCap) && (closed_path == MagickFalse))
       {
         DrawRoundLinecap(image,draw_info,p,exception);
@@ -4788,18 +4929,25 @@ MagickExport void GetAffineMatrix(AffineMatrix *affine_matrix)
 */
 MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info)
 {
+  char
+    *next_token;
+
   const char
     *option;
 
   ExceptionInfo
     *exception;
 
+  ImageInfo
+    *clone_info;
+
   /*
     Initialize draw attributes.
   */
   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
   assert(draw_info != (DrawInfo *) NULL);
   (void) ResetMagickMemory(draw_info,0,sizeof(*draw_info));
+  clone_info=CloneImageInfo(image_info);
   GetAffineMatrix(&draw_info->affine);
   exception=AcquireExceptionInfo();
   (void) QueryColorCompliance("#000F",AllCompliance,&draw_info->fill,
@@ -4807,70 +4955,88 @@ MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info)
   (void) QueryColorCompliance("#0000",AllCompliance,&draw_info->stroke,
     exception);
   draw_info->stroke_width=1.0;
-  draw_info->alpha=OpaqueAlpha;
   draw_info->fill_rule=EvenOddRule;
+  draw_info->alpha=OpaqueAlpha;
+  draw_info->fill_alpha=OpaqueAlpha;
+  draw_info->stroke_alpha=OpaqueAlpha;
   draw_info->linecap=ButtCap;
   draw_info->linejoin=MiterJoin;
   draw_info->miterlimit=10;
   draw_info->decorate=NoDecoration;
   draw_info->pointsize=12.0;
-  draw_info->undercolor.alpha=(Quantum) TransparentAlpha;
+  draw_info->undercolor.alpha=(MagickRealType) TransparentAlpha;
   draw_info->compose=OverCompositeOp;
   draw_info->render=MagickTrue;
   draw_info->debug=IsEventLogging();
-  if (image_info != (ImageInfo *) NULL)
+  draw_info->stroke_antialias=clone_info->antialias;
+  if (clone_info->font != (char *) NULL)
+    draw_info->font=AcquireString(clone_info->font);
+  if (clone_info->density != (char *) NULL)
+    draw_info->density=AcquireString(clone_info->density);
+  draw_info->text_antialias=clone_info->antialias;
+  if (fabs(clone_info->pointsize) >= DrawEpsilon)
+    draw_info->pointsize=clone_info->pointsize;
+  draw_info->border_color=clone_info->border_color;
+  if (clone_info->server_name != (char *) NULL)
+    draw_info->server_name=AcquireString(clone_info->server_name);
+  option=GetImageOption(clone_info,"direction");
+  if (option != (const char *) NULL)
+    draw_info->direction=(DirectionType) ParseCommandOption(
+      MagickDirectionOptions,MagickFalse,option);
+  else
+    draw_info->direction=UndefinedDirection;
+  option=GetImageOption(clone_info,"encoding");
+  if (option != (const char *) NULL)
+    (void) CloneString(&draw_info->encoding,option);
+  option=GetImageOption(clone_info,"family");
+  if (option != (const char *) NULL)
+    (void) CloneString(&draw_info->family,option);
+  option=GetImageOption(clone_info,"fill");
+  if (option != (const char *) NULL)
+    (void) QueryColorCompliance(option,AllCompliance,&draw_info->fill,
+      exception);
+  option=GetImageOption(clone_info,"gravity");
+  if (option != (const char *) NULL)
+    draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
+      MagickFalse,option);
+  option=GetImageOption(clone_info,"interline-spacing");
+  if (option != (const char *) NULL)
+    draw_info->interline_spacing=StringToDouble(option,&next_token);
+  option=GetImageOption(clone_info,"interword-spacing");
+  if (option != (const char *) NULL)
+    draw_info->interword_spacing=StringToDouble(option,&next_token);
+  option=GetImageOption(clone_info,"kerning");
+  if (option != (const char *) NULL)
+    draw_info->kerning=StringToDouble(option,&next_token);
+  option=GetImageOption(clone_info,"stroke");
+  if (option != (const char *) NULL)
+    (void) QueryColorCompliance(option,AllCompliance,&draw_info->stroke,
+      exception);
+  option=GetImageOption(clone_info,"strokewidth");
+  if (option != (const char *) NULL)
+    draw_info->stroke_width=StringToDouble(option,&next_token);
+  option=GetImageOption(clone_info,"style");
+  if (option != (const char *) NULL)
+    draw_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
+      MagickFalse,option);
+  option=GetImageOption(clone_info,"undercolor");
+  if (option != (const char *) NULL)
+    (void) QueryColorCompliance(option,AllCompliance,&draw_info->undercolor,
+      exception);
+  option=GetImageOption(clone_info,"weight");
+  if (option != (const char *) NULL)
     {
-      draw_info->stroke_antialias=image_info->antialias;
-      if (image_info->font != (char *) NULL)
-        draw_info->font=AcquireString(image_info->font);
-      if (image_info->density != (char *) NULL)
-        draw_info->density=AcquireString(image_info->density);
-      draw_info->text_antialias=image_info->antialias;
-      if (image_info->pointsize != 0.0)
-        draw_info->pointsize=image_info->pointsize;
-      draw_info->border_color=image_info->border_color;
-      if (image_info->server_name != (char *) NULL)
-        draw_info->server_name=AcquireString(image_info->server_name);
-      option=GetImageOption(image_info,"encoding");
-      if (option != (const char *) NULL)
-        (void) CloneString(&draw_info->encoding,option);
-      option=GetImageOption(image_info,"kerning");
-      if (option != (const char *) NULL)
-        draw_info->kerning=StringToDouble(option,(char **) NULL);
-      option=GetImageOption(image_info,"interline-spacing");
-      if (option != (const char *) NULL)
-        draw_info->interline_spacing=StringToDouble(option,(char **) NULL);
-      option=GetImageOption(image_info,"interword-spacing");
-      if (option != (const char *) NULL)
-        draw_info->interword_spacing=StringToDouble(option,(char **) NULL);
-      option=GetImageOption(image_info,"direction");
-      if (option != (const char *) NULL)
-        draw_info->direction=(DirectionType) ParseCommandOption(
-          MagickDirectionOptions,MagickFalse,option);
-      else
-        draw_info->direction=UndefinedDirection;
-      option=GetImageOption(image_info,"fill");
-      if (option != (const char *) NULL)
-        (void) QueryColorCompliance(option,AllCompliance,&draw_info->fill,
-          exception);
-      option=GetImageOption(image_info,"stroke");
-      if (option != (const char *) NULL)
-        (void) QueryColorCompliance(option,AllCompliance,&draw_info->stroke,
-          exception);
-      option=GetImageOption(image_info,"strokewidth");
-      if (option != (const char *) NULL)
-        draw_info->stroke_width=StringToDouble(option,(char **) NULL);
-      option=GetImageOption(image_info,"undercolor");
-      if (option != (const char *) NULL)
-        (void) QueryColorCompliance(option,AllCompliance,&draw_info->undercolor,
-          exception);
-      option=GetImageOption(image_info,"gravity");
-      if (option != (const char *) NULL)
-        draw_info->gravity=(GravityType) ParseCommandOption(
-          MagickGravityOptions,MagickFalse,option);
+      ssize_t
+        weight;
+
+      weight=ParseCommandOption(MagickWeightOptions,MagickFalse,option);
+      if (weight == -1)
+        weight=(ssize_t) StringToUnsignedLong(option);
+      draw_info->weight=(size_t) weight;
     }
   exception=DestroyExceptionInfo(exception);
-  draw_info->signature=MagickSignature;
+  draw_info->signature=MagickCoreSignature;
+  clone_info=DestroyImageInfo(clone_info);
 }
 \f
 /*
@@ -4974,14 +5140,15 @@ static void TraceArcPath(PrimitiveInfo *primitive_info,const PointInfo start,
   size_t
     arc_segments;
 
-  if ((start.x == end.x) && (start.y == end.y))
+  if ((fabs(start.x-end.x) < DrawEpsilon) &&
+      (fabs(start.y-end.y) < DrawEpsilon))
     {
       TracePoint(primitive_info,end);
       return;
     }
   radii.x=fabs(arc.x);
   radii.y=fabs(arc.y);
-  if ((radii.x == 0.0) || (radii.y == 0.0))
+  if ((fabs(radii.x) < DrawEpsilon) || (fabs(radii.y) < DrawEpsilon))
     {
       TraceLine(primitive_info,start,end);
       return;
@@ -4992,7 +5159,7 @@ static void TraceArcPath(PrimitiveInfo *primitive_info,const PointInfo start,
   center.y=(double) (cosine*(end.y-start.y)/2-sine*(end.x-start.x)/2);
   delta=(center.x*center.x)/(radii.x*radii.x)+(center.y*center.y)/
     (radii.y*radii.y);
-  if (delta < MagickEpsilon)
+  if (delta < DrawEpsilon)
     {
       TraceLine(primitive_info,start,end);
       return;
@@ -5022,12 +5189,11 @@ static void TraceArcPath(PrimitiveInfo *primitive_info,const PointInfo start,
   alpha=atan2(points[0].y-center.y,points[0].x-center.x);
   theta=atan2(points[1].y-center.y,points[1].x-center.x)-alpha;
   if ((theta < 0.0) && (sweep != MagickFalse))
-    theta+=(double) (2.0*MagickPI);
+    theta+=2.0*MagickPI;
   else
     if ((theta > 0.0) && (sweep == MagickFalse))
-      theta-=(double) (2.0*MagickPI);
-  arc_segments=(size_t) ceil(fabs((double) (theta/(0.5*MagickPI+
-    MagickEpsilon))));
+      theta-=2.0*MagickPI;
+  arc_segments=(size_t) ceil(fabs((double) (theta/(0.5*MagickPI+DrawEpsilon))));
   p=primitive_info;
   for (i=0; i < (ssize_t) arc_segments; i++)
   {
@@ -5123,8 +5289,7 @@ static void TraceBezier(PrimitiveInfo *primitive_info,
     number_coordinates,sizeof(*coefficients));
   points=(PointInfo *) AcquireQuantumMemory((size_t) control_points,
     sizeof(*points));
-  if ((coefficients == (double *) NULL) ||
-      (points == (PointInfo *) NULL))
+  if ((coefficients == (double *) NULL) || (points == (PointInfo *) NULL))
     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   /*
     Compute bezier points.
@@ -5213,20 +5378,20 @@ static void TraceEllipse(PrimitiveInfo *primitive_info,const PointInfo start,
   /*
     Ellipses are just short segmented polys.
   */
-  if ((stop.x == 0.0) && (stop.y == 0.0))
+  if ((fabs(stop.x) < DrawEpsilon) && (fabs(stop.y) < DrawEpsilon))
     {
       TracePoint(primitive_info,start);
       return;
     }
   delta=2.0/MagickMax(stop.x,stop.y);
-  step=(double) (MagickPI/8.0);
-  if ((delta >= 0.0) && (delta < (double) (MagickPI/8.0)))
-    step=(double) (MagickPI/(4*(MagickPI/delta/2+0.5)));
+  step=MagickPI/8.0;
+  if ((delta >= 0.0) && (delta < (MagickPI/8.0)))
+    step=MagickPI/(4*(MagickPI/delta/2+0.5));
   angle.x=DegreesToRadians(degrees.x);
   y=degrees.y;
   while (y < degrees.x)
     y+=360.0;
-  angle.y=(double) DegreesToRadians(y);
+  angle.y=DegreesToRadians(y);
   for (p=primitive_info; angle.x < angle.y; angle.x+=step)
   {
     point.x=cos(fmod(angle.x,DegreesToRadians(360.0)))*stop.x+start.x;
@@ -5250,8 +5415,8 @@ static void TraceLine(PrimitiveInfo *primitive_info,const PointInfo start,
   const PointInfo end)
 {
   TracePoint(primitive_info,start);
-  if ((fabs(start.x-end.x) < MagickEpsilon) &&
-      (fabs(start.y-end.y) < MagickEpsilon))
+  if ((fabs(start.x-end.x) < DrawEpsilon) &&
+      (fabs(start.y-end.y) < DrawEpsilon))
     {
       primitive_info->primitive=PointPrimitive;
       primitive_info->coordinates=1;
@@ -5265,24 +5430,25 @@ static void TraceLine(PrimitiveInfo *primitive_info,const PointInfo start,
 static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
 {
   char
-    token[MaxTextExtent];
+    *next_token,
+    token[MagickPathExtent];
 
   const char
     *p;
 
-  int
-    attribute,
-    last_attribute;
-
   double
     x,
     y;
 
+  int
+    attribute,
+    last_attribute;
+
   PointInfo
-    end,
-    points[4],
-    point,
-    start;
+    end = {0.0, 0.0},
+    points[4] = { {0.0,0.0}, {0.0,0.0}, {0.0,0.0}, {0.0,0.0} },
+    point = {0.0, 0.0},
+    start = {0.0, 0.0};
 
   PrimitiveType
     primitive_type;
@@ -5298,15 +5464,8 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
     z_count;
 
   attribute=0;
-  end.x=0.0;
-  end.y=0.0;
-  point.x=0.0;
-  point.y=0.0;
-  start.x=0.0;
-  start.y=0.0;
   number_coordinates=0;
   z_count=0;
-  (void) ResetMagickMemory(points,0,sizeof(*points));
   primitive_type=primitive_info->primitive;
   q=primitive_info;
   for (p=path; *p != '\0'; )
@@ -5322,13 +5481,13 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
       case 'a':
       case 'A':
       {
+        double
+          angle;
+
         MagickBooleanType
           large_arc,
           sweep;
 
-        double
-          angle;
-
         PointInfo
           arc;
 
@@ -5337,34 +5496,34 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
         */
         do
         {
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          arc.x=StringToDouble(token,(char **) NULL);
-          GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          arc.x=StringToDouble(token,&next_token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          arc.y=StringToDouble(token,(char **) NULL);
-          GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          arc.y=StringToDouble(token,&next_token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          angle=StringToDouble(token,(char **) NULL);
-          GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          angle=StringToDouble(token,&next_token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
           large_arc=StringToLong(token) != 0 ? MagickTrue : MagickFalse;
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
           sweep=StringToLong(token) != 0 ? MagickTrue : MagickFalse;
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          x=StringToDouble(token,(char **) NULL);
-          GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          x=StringToDouble(token,&next_token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          y=StringToDouble(token,(char **) NULL);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          y=StringToDouble(token,&next_token);
           end.x=(double) (attribute == (int) 'A' ? x : point.x+x);
           end.y=(double) (attribute == (int) 'A' ? y : point.y+y);
           TraceArcPath(q,point,end,arc,angle,large_arc,sweep);
@@ -5388,14 +5547,14 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
           points[0]=point;
           for (i=1; i < 4; i++)
           {
-            GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            x=StringToDouble(token,(char **) NULL);
-            GetMagickToken(p,&p,token);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            x=StringToDouble(token,&next_token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            y=StringToDouble(token,(char **) NULL);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            y=StringToDouble(token,&next_token);
             end.x=(double) (attribute == (int) 'C' ? x : point.x+x);
             end.y=(double) (attribute == (int) 'C' ? y : point.y+y);
             points[i]=end;
@@ -5413,10 +5572,10 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
       {
         do
         {
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          x=StringToDouble(token,(char **) NULL);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          x=StringToDouble(token,&next_token);
           point.x=(double) (attribute == (int) 'H' ? x: point.x+x);
           TracePoint(q,point);
           q+=q->coordinates;
@@ -5428,14 +5587,14 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
       {
         do
         {
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          x=StringToDouble(token,(char **) NULL);
-          GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          x=StringToDouble(token,&next_token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          y=StringToDouble(token,(char **) NULL);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          y=StringToDouble(token,&next_token);
           point.x=(double) (attribute == (int) 'L' ? x : point.x+x);
           point.y=(double) (attribute == (int) 'L' ? y : point.y+y);
           TracePoint(q,point);
@@ -5455,14 +5614,14 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
         i=0;
         do
         {
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          x=StringToDouble(token,(char **) NULL);
-          GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          x=StringToDouble(token,&next_token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          y=StringToDouble(token,(char **) NULL);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          y=StringToDouble(token,&next_token);
           point.x=(double) (attribute == (int) 'M' ? x : point.x+x);
           point.y=(double) (attribute == (int) 'M' ? y : point.y+y);
           if (i == 0)
@@ -5489,14 +5648,14 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
           points[0]=point;
           for (i=1; i < 3; i++)
           {
-            GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            x=StringToDouble(token,(char **) NULL);
-            GetMagickToken(p,&p,token);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            x=StringToDouble(token,&next_token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            y=StringToDouble(token,(char **) NULL);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            y=StringToDouble(token,&next_token);
             if (*p == ',')
               p++;
             end.x=(double) (attribute == (int) 'Q' ? x : point.x+x);
@@ -5524,14 +5683,14 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
           points[1].y=2.0*points[3].y-points[2].y;
           for (i=2; i < 4; i++)
           {
-            GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            x=StringToDouble(token,(char **) NULL);
-            GetMagickToken(p,&p,token);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            x=StringToDouble(token,&next_token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            y=StringToDouble(token,(char **) NULL);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            y=StringToDouble(token,&next_token);
             if (*p == ',')
               p++;
             end.x=(double) (attribute == (int) 'S' ? x : point.x+x);
@@ -5540,8 +5699,8 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
           }
           if (strchr("CcSs",last_attribute) == (char *) NULL)
             {
-              points[0]=points[2];
-              points[1]=points[3];
+              points[0]=point;
+              points[1]=point;
             }
           for (i=0; i < 4; i++)
             (q+i)->point=points[i];
@@ -5564,22 +5723,22 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
           points[1].y=2.0*points[2].y-points[1].y;
           for (i=2; i < 3; i++)
           {
-            GetMagickToken(p,&p,token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            x=StringToDouble(token,(char **) NULL);
-            GetMagickToken(p,&p,token);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            x=StringToDouble(token,&next_token);
+            GetNextToken(p,&p,MagickPathExtent,token);
             if (*token == ',')
-              GetMagickToken(p,&p,token);
-            y=StringToDouble(token,(char **) NULL);
+              GetNextToken(p,&p,MagickPathExtent,token);
+            y=StringToDouble(token,&next_token);
             end.x=(double) (attribute == (int) 'T' ? x : point.x+x);
             end.y=(double) (attribute == (int) 'T' ? y : point.y+y);
             points[i]=end;
           }
           if (strchr("QqTt",last_attribute) == (char *) NULL)
             {
-              points[0]=points[2];
-              points[1]=points[3];
+              points[0]=point;
+              points[1]=point;
             }
           for (i=0; i < 3; i++)
             (q+i)->point=points[i];
@@ -5594,10 +5753,10 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
       {
         do
         {
-          GetMagickToken(p,&p,token);
+          GetNextToken(p,&p,MagickPathExtent,token);
           if (*token == ',')
-            GetMagickToken(p,&p,token);
-          y=StringToDouble(token,(char **) NULL);
+            GetNextToken(p,&p,MagickPathExtent,token);
+          y=StringToDouble(token,&next_token);
           point.y=(double) (attribute == (int) 'V' ? y : point.y+y);
           TracePoint(q,point);
           q+=q->coordinates;
@@ -5750,8 +5909,8 @@ static void TraceSquareLinecap(PrimitiveInfo *primitive_info,
   {
     dx=primitive_info[0].point.x-primitive_info[i].point.x;
     dy=primitive_info[0].point.y-primitive_info[i].point.y;
-    if ((fabs((double) dx) >= MagickEpsilon) ||
-        (fabs((double) dy) >= MagickEpsilon))
+    if ((fabs((double) dx) >= DrawEpsilon) ||
+        (fabs((double) dy) >= DrawEpsilon))
       break;
   }
   if (i == (ssize_t) number_vertices)
@@ -5765,8 +5924,8 @@ static void TraceSquareLinecap(PrimitiveInfo *primitive_info,
   {
     dx=primitive_info[number_vertices-1].point.x-primitive_info[j].point.x;
     dy=primitive_info[number_vertices-1].point.y-primitive_info[j].point.y;
-    if ((fabs((double) dx) >= MagickEpsilon) ||
-        (fabs((double) dy) >= MagickEpsilon))
+    if ((fabs((double) dx) >= DrawEpsilon) ||
+        (fabs((double) dy) >= DrawEpsilon))
       break;
   }
   distance=hypot((double) dx,(double) dy);
@@ -5776,16 +5935,6 @@ static void TraceSquareLinecap(PrimitiveInfo *primitive_info,
     dy*(distance+offset)/distance);
 }
 
-static inline double DrawEpsilonReciprocal(const double x)
-{
-#define DrawEpsilon  ((double) 1.0e-10)
-
-  double sign = x < (double) 0.0 ? (double) -1.0 :
-    (double) 1.0;
-  return((sign*x) >= DrawEpsilon ? (double) 1.0/x : sign*(
-    (double) 1.0/DrawEpsilon));
-}
-
 static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
   const PrimitiveInfo *primitive_info)
 {
@@ -5796,6 +5945,12 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
       q;
   } LineSegment;
 
+  double
+    delta_theta,
+    dot_product,
+    mid,
+    miterlimit;
+
   LineSegment
     dx,
     dy,
@@ -5806,12 +5961,6 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
   MagickBooleanType
     closed_path;
 
-  double
-    delta_theta,
-    dot_product,
-    mid,
-    miterlimit;
-
   PointInfo
     box_p[5],
     box_q[5],
@@ -5855,11 +6004,11 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
   (void) CopyMagickMemory(polygon_primitive,primitive_info,(size_t)
     number_vertices*sizeof(*polygon_primitive));
   closed_path=
-    (primitive_info[number_vertices-1].point.x == primitive_info[0].point.x) &&
-    (primitive_info[number_vertices-1].point.y == primitive_info[0].point.y) ?
+    (fabs(primitive_info[number_vertices-1].point.x-primitive_info[0].point.x) < DrawEpsilon) &&
+    (fabs(primitive_info[number_vertices-1].point.y-primitive_info[0].point.y) < DrawEpsilon) ?
     MagickTrue : MagickFalse;
-  if ((draw_info->linejoin == RoundJoin) ||
-      ((draw_info->linejoin == MiterJoin) && (closed_path != MagickFalse)))
+  if (((draw_info->linejoin == RoundJoin) ||
+       (draw_info->linejoin == MiterJoin)) && (closed_path != MagickFalse))
     {
       polygon_primitive[number_vertices]=primitive_info[1];
       number_vertices++;
@@ -5874,16 +6023,35 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
   {
     dx.p=polygon_primitive[n].point.x-polygon_primitive[0].point.x;
     dy.p=polygon_primitive[n].point.y-polygon_primitive[0].point.y;
-    if ((fabs(dx.p) >= MagickEpsilon) || (fabs(dy.p) >= MagickEpsilon))
+    if ((fabs(dx.p) >= DrawEpsilon) || (fabs(dy.p) >= DrawEpsilon))
       break;
   }
   if (n == (ssize_t) number_vertices)
     n=(ssize_t) number_vertices-1L;
-  slope.p=DrawEpsilonReciprocal(dx.p)*dy.p;
-  inverse_slope.p=(-1.0*DrawEpsilonReciprocal(slope.p));
+  slope.p=0.0;
+  inverse_slope.p=0.0;
+  if (fabs(dx.p) < DrawEpsilon)
+    {
+      if (dx.p >= 0.0)
+        slope.p=dy.p < 0.0 ? -1.0/DrawEpsilon : 1.0/DrawEpsilon;
+      else
+        slope.p=dy.p < 0.0 ? 1.0/DrawEpsilon : -1.0/DrawEpsilon;
+    }
+  else
+    if (fabs(dy.p) < DrawEpsilon)
+      {
+        if (dy.p >= 0.0)
+          inverse_slope.p=dx.p < 0.0 ? -1.0/DrawEpsilon : 1.0/DrawEpsilon;
+        else
+          inverse_slope.p=dx.p < 0.0 ? 1.0/DrawEpsilon : -1.0/DrawEpsilon;
+      }
+    else
+      {
+        slope.p=dy.p/dx.p;
+        inverse_slope.p=(-1.0/slope.p);
+      }
   mid=ExpandAffine(&draw_info->affine)*draw_info->stroke_width/2.0;
-  miterlimit=(double) (draw_info->miterlimit*draw_info->miterlimit*
-    mid*mid);
+  miterlimit=(double) (draw_info->miterlimit*draw_info->miterlimit*mid*mid);
   if ((draw_info->linecap == SquareCap) && (closed_path == MagickFalse))
     TraceSquareLinecap(polygon_primitive,number_vertices,mid);
   offset.x=sqrt((double) (mid*mid/(inverse_slope.p*inverse_slope.p+1.0)));
@@ -5927,8 +6095,28 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
     dot_product=dx.q*dx.q+dy.q*dy.q;
     if (dot_product < 0.25)
       continue;
-    slope.q=DrawEpsilonReciprocal(dx.q)*dy.q;
-    inverse_slope.q=(-1.0*DrawEpsilonReciprocal(slope.q));
+    slope.q=0.0;
+    inverse_slope.q=0.0;
+    if (fabs(dx.q) < DrawEpsilon)
+      {
+        if (dx.q >= 0.0)
+          slope.q=dy.q < 0.0 ? -1.0/DrawEpsilon : 1.0/DrawEpsilon;
+        else
+          slope.q=dy.q < 0.0 ? 1.0/DrawEpsilon : -1.0/DrawEpsilon;
+      }
+    else
+      if (fabs(dy.q) < DrawEpsilon)
+        {
+          if (dy.q >= 0.0)
+            inverse_slope.q=dx.q < 0.0 ? -1.0/DrawEpsilon : 1.0/DrawEpsilon;
+          else
+            inverse_slope.q=dx.q < 0.0 ? 1.0/DrawEpsilon : -1.0/DrawEpsilon;
+        }
+      else
+        {
+          slope.q=dy.q/dx.q;
+          inverse_slope.q=(-1.0/slope.q);
+        }
     offset.x=sqrt((double) (mid*mid/(inverse_slope.q*inverse_slope.q+1.0)));
     offset.y=(double) (offset.x*inverse_slope.q);
     dot_product=dy.q*offset.x-dx.q*offset.y;
@@ -5954,7 +6142,7 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
         box_q[3].x=polygon_primitive[i].point.x-offset.x;
         box_q[3].y=polygon_primitive[i].point.y-offset.y;
       }
-    if (fabs((double) (slope.p-slope.q)) < MagickEpsilon)
+    if (fabs((double) (slope.p-slope.q)) < DrawEpsilon)
       {
         box_p[4]=box_p[1];
         box_q[4]=box_q[1];
@@ -5970,17 +6158,29 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
       }
     if (q >= (ssize_t) (max_strokes-6*BezierQuantum-360))
       {
-         max_strokes+=6*BezierQuantum+360;
-         path_p=(PointInfo *) ResizeQuantumMemory(path_p,(size_t) max_strokes,
-           sizeof(*path_p));
-         path_q=(PointInfo *) ResizeQuantumMemory(path_q,(size_t) max_strokes,
-           sizeof(*path_q));
-         if ((path_p == (PointInfo *) NULL) || (path_q == (PointInfo *) NULL))
-           {
-             polygon_primitive=(PrimitiveInfo *)
-               RelinquishMagickMemory(polygon_primitive);
-             return((PrimitiveInfo *) NULL);
-           }
+        if (~max_strokes < (6*BezierQuantum+360))
+          {
+            path_p=(PointInfo *) RelinquishMagickMemory(path_p);
+            path_q=(PointInfo *) RelinquishMagickMemory(path_q);
+          }
+        else
+          {
+            max_strokes+=6*BezierQuantum+360;
+            path_p=(PointInfo *) ResizeQuantumMemory(path_p,max_strokes,
+              sizeof(*path_p));
+            path_q=(PointInfo *) ResizeQuantumMemory(path_q,max_strokes,
+              sizeof(*path_q));
+          }
+        if ((path_p == (PointInfo *) NULL) || (path_q == (PointInfo *) NULL))
+          {
+            if (path_p != (PointInfo *) NULL)
+              path_p=(PointInfo *) RelinquishMagickMemory(path_p);
+            if (path_q != (PointInfo *) NULL)
+              path_q=(PointInfo *) RelinquishMagickMemory(path_q);
+            polygon_primitive=(PrimitiveInfo *)
+              RelinquishMagickMemory(polygon_primitive);
+            return((PrimitiveInfo *) NULL);
+          }
       }
     dot_product=dx.q*dy.p-dx.p*dy.q;
     if (dot_product <= 0.0)
@@ -6034,7 +6234,7 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
           theta.p=atan2(box_q[1].y-center.y,box_q[1].x-center.x);
           theta.q=atan2(box_q[2].y-center.y,box_q[2].x-center.x);
           if (theta.q < theta.p)
-            theta.q+=(double) (2.0*MagickPI);
+            theta.q+=2.0*MagickPI;
           arc_segments=(size_t) ceil((double) ((theta.q-theta.p)/
             (2.0*sqrt((double) (1.0/mid)))));
           path_q[q].x=box_q[1].x;
@@ -6106,7 +6306,7 @@ static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,
           theta.p=atan2(box_p[1].y-center.y,box_p[1].x-center.x);
           theta.q=atan2(box_p[2].y-center.y,box_p[2].x-center.x);
           if (theta.p < theta.q)
-            theta.p+=(double) (2.0*MagickPI);
+            theta.p+=2.0*MagickPI;
           arc_segments=(size_t) ceil((double) ((theta.p-theta.q)/
             (2.0*sqrt((double) (1.0/mid)))));
           path_p[p++]=box_p[1];