]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/draw.c
Update web pages
[imagemagick] / MagickCore / draw.c
index ecbe42da6c247b5e9081a3bcdf3d1a11a2815802..5cb4d4da5c8aadd26faca821b9aafe81a5a27147 100644 (file)
@@ -18,7 +18,7 @@
 %                                 July 1998                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2015 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  %
@@ -253,8 +253,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,24 +278,31 @@ 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
@@ -324,7 +333,8 @@ 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;
@@ -718,11 +728,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;
@@ -813,7 +823,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 +855,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);
 }
@@ -1059,27 +1069,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)
 {
@@ -1117,11 +1106,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;
@@ -1213,7 +1202,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);
     }
@@ -1400,7 +1389,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 +1404,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);
@@ -1439,7 +1428,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);
@@ -1682,11 +1671,11 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
     current;
 
   char
-    key[2*MaxTextExtent],
-    keyword[MaxTextExtent],
-    geometry[MaxTextExtent],
-    name[MaxTextExtent],
-    pattern[MaxTextExtent],
+    key[2*MagickPathExtent],
+    keyword[MagickPathExtent],
+    geometry[MagickPathExtent],
+    name[MagickPathExtent],
+    pattern[MagickPathExtent],
     *primitive,
     *token;
 
@@ -1710,9 +1699,6 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
   PointInfo
     point;
 
-  PixelInfo
-    start_color;
-
   PrimitiveInfo
     *primitive_info;
 
@@ -1731,22 +1717,26 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
 
   size_t
     length,
-    number_points;
+    number_points,
+    number_stops;
 
   ssize_t
     j,
     k,
     n;
 
+  StopInfo
+    *stops;
+
   /*
     Ensure the annotation info is valid.
   */
   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,6 +1753,8 @@ 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.
   */
@@ -1794,8 +1786,6 @@ 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);
   if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
     return(MagickFalse);
   status=MagickTrue;
@@ -1853,6 +1843,11 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             affine.ty=StringToDouble(token,(char **) NULL);
             break;
           }
+        if (LocaleCompare("alpha",keyword) == 0)
+          {
+            primitive_type=AlphaPrimitive;
+            break;
+          }
         if (LocaleCompare("arc",keyword) == 0)
           {
             primitive_type=ArcPrimitive;
@@ -1962,6 +1957,12 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
               graphic_context[n]->decorate=(DecorationType) decorate;
             break;
           }
+        if (LocaleCompare("density",keyword) == 0)
+          {
+            GetMagickToken(q,&q,token);
+            (void) CloneString(&graphic_context[n]->density,token);
+            break;
+          }
         if (LocaleCompare("direction",keyword) == 0)
           {
             ssize_t
@@ -2002,7 +2003,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
         if (LocaleCompare("fill",keyword) == 0)
           {
             GetMagickToken(q,&q,token);
-            (void) FormatLocaleString(pattern,MaxTextExtent,"%s",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);
@@ -2017,7 +2018,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,7 +2027,7 @@ 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);
             factor=strchr(token,'%') != (char *) NULL ? 0.01 : 1.0;
@@ -2097,20 +2098,15 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("font-weight",keyword) == 0)
           {
+            ssize_t
+              weight;
+
             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;
+            weight=ParseCommandOption(MagickWeightOptions,MagickFalse,
+              token);
+            if (weight == -1)
+              weight=StringToUnsignedLong(token);
+            graphic_context[n]->weight=(size_t) weight;
             break;
           }
         status=MagickFalse;
@@ -2195,15 +2191,6 @@ 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':
       {
@@ -2270,7 +2257,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                 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;
@@ -2286,10 +2274,10 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             if (LocaleCompare("clip-path",token) == 0)
               {
                 char
-                  name[MaxTextExtent];
+                  name[MagickPathExtent];
 
                 GetMagickToken(q,&q,token);
-                (void) FormatLocaleString(name,MaxTextExtent,"%s",token);
+                (void) FormatLocaleString(name,MagickPathExtent,"%s",token);
                 for (p=q; *q != '\0'; )
                 {
                   GetMagickToken(q,&q,token);
@@ -2308,17 +2296,17 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             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);
+                (void) CopyMagickString(name,token,MagickPathExtent);
                 GetMagickToken(q,&q,token);
-                (void) CopyMagickString(type,token,MaxTextExtent);
+                (void) CopyMagickString(type,token,MagickPathExtent);
                 GetMagickToken(q,&q,token);
                 segment.x1=StringToDouble(token,(char **) NULL);
                 GetMagickToken(q,&q,token);
@@ -2362,10 +2350,12 @@ 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),
@@ -2380,7 +2370,7 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                   bounds;
 
                 GetMagickToken(q,&q,token);
-                (void) CopyMagickString(name,token,MaxTextExtent);
+                (void) CopyMagickString(name,token,MagickPathExtent);
                 GetMagickToken(q,&q,token);
                 bounds.x=(ssize_t) ceil(StringToDouble(token,(char **) NULL)-
                   0.5);
@@ -2410,10 +2400,10 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                   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,
+                (void) FormatLocaleString(key,MagickPathExtent,"%s-geometry",name);
+                (void) FormatLocaleString(geometry,MagickPathExtent,
                   "%.20gx%.20g%+.20g%+.20g",(double) bounds.width,(double)
                   bounds.height,(double) bounds.x,(double) bounds.y);
                 (void) SetImageArtifact(image,key,geometry);
@@ -2502,19 +2492,31 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
             PixelInfo
               stop_color;
 
+            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;
+              }
             GetMagickToken(q,&q,token);
             (void) QueryColorCompliance(token,AllCompliance,&stop_color,
               exception);
-            (void) GradientImage(image,LinearGradient,ReflectSpread,
-              &start_color,&stop_color,exception);
-            start_color=stop_color;
+            stops[number_stops-1].color=stop_color;
             GetMagickToken(q,&q,token);
+            stops[number_stops-1].offset=StringToDouble(token,(char **) NULL);
             break;
           }
         if (LocaleCompare("stroke",keyword) == 0)
           {
             GetMagickToken(q,&q,token);
-            (void) FormatLocaleString(pattern,MaxTextExtent,"%s",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);
@@ -2529,7 +2531,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);
@@ -2762,6 +2764,22 @@ 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);
@@ -2843,7 +2861,16 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
       }
       case RoundRectanglePrimitive:
       {
-        length*=16*BezierQuantum+5;
+        double
+          alpha,
+          beta,
+          radius;
+
+        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;
         break;
       }
       case BezierPrimitive:
@@ -3026,8 +3053,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;
@@ -3222,6 +3249,22 @@ static inline double GetStopColorOffset(const GradientInfo *gradient,
   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) <= MagickEpsilon)
+    return(0);
+  return(-1);
+}
+
 MagickExport MagickBooleanType DrawGradientImage(Image *image,
   const DrawInfo *draw_info,ExceptionInfo *exception)
 {
@@ -3256,11 +3299,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;
@@ -3442,7 +3487,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)
@@ -3488,11 +3533,12 @@ MagickExport MagickBooleanType DrawPatternPath(Image *image,
   ExceptionInfo *exception)
 {
   char
-    property[MaxTextExtent];
+    property[MagickPathExtent];
 
   const char
     *geometry,
-    *path;
+    *path,
+    *type;
 
   DrawInfo
     *clone_info;
@@ -3504,16 +3550,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);
@@ -3532,6 +3578,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);
@@ -3816,19 +3867,19 @@ 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);
@@ -3871,18 +3922,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;
@@ -3897,15 +3949,15 @@ RestoreMSCWarning
           *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)
           {
@@ -3913,13 +3965,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);
+              (void) GetFillColor(draw_info,x-start_x,y-start_y,&pixel,exception);
+              SetPixelViaPixelInfo(image,&pixel,q);
             }
           q+=GetPixelChannels(image);
         }
@@ -3939,13 +3991,13 @@ RestoreMSCWarning
   */
   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();
@@ -3965,21 +4017,21 @@ RestoreMSCWarning
       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,
+    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.
@@ -3991,11 +4043,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);
+      (void) 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);
+      (void) 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);
@@ -4071,10 +4123,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;
     }
@@ -4085,23 +4137,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:
@@ -4179,29 +4231,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:
@@ -4216,9 +4249,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);
+          SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
           (void) SyncCacheViewAuthenticPixels(image_view,exception);
           break;
         }
@@ -4233,11 +4265,15 @@ 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;
+
             q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
               exception);
             if (q == (Quantum *) NULL)
@@ -4251,7 +4287,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
                   continue;
                 }
               (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelInfoPixel(image,&pixel,q);
+              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4263,6 +4299,9 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         case FloodfillMethod:
         case FillToBorderMethod:
         {
+          ChannelType
+            channel_mask;
+
           PixelInfo
             target;
 
@@ -4274,9 +4313,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:
@@ -4287,7 +4328,6 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           PixelInfo
             pixel;
 
-          GetPixelInfo(image,&pixel);
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             register Quantum
@@ -4303,7 +4343,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
             for (x=0; x < (ssize_t) image->columns; x++)
             {
               (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelInfoPixel(image,&pixel,q);
+              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4315,10 +4355,8 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
       }
       break;
     }
-    case MattePrimitive:
+    case ColorPrimitive:
     {
-      if (image->alpha_trait == UndefinedPixelTrait)
-        (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
       switch (primitive_info->method)
       {
         case PointMethod:
@@ -4333,8 +4371,9 @@ 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);
-          SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
+          SetPixelViaPixelInfo(image,&pixel,q);
           (void) SyncCacheViewAuthenticPixels(image_view,exception);
           break;
         }
@@ -4349,15 +4388,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;
 
-            register ssize_t
-              x;
-
             q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
               exception);
             if (q == (Quantum *) NULL)
@@ -4371,7 +4406,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
                   continue;
                 }
               (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
+              SetPixelViaPixelInfo(image,&pixel,q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4383,9 +4418,6 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         case FloodfillMethod:
         case FillToBorderMethod:
         {
-          ChannelType
-            channel_mask;
-
           PixelInfo
             target;
 
@@ -4397,11 +4429,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:
@@ -4412,6 +4442,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           PixelInfo
             pixel;
 
+          GetPixelInfo(image,&pixel);
           for (y=0; y < (ssize_t) image->rows; y++)
           {
             register Quantum
@@ -4427,7 +4458,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
             for (x=0; x < (ssize_t) image->columns; x++)
             {
               (void) GetFillColor(draw_info,x,y,&pixel,exception);
-              SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
+              SetPixelViaPixelInfo(image,&pixel,q);
               q+=GetPixelChannels(image);
             }
             sync=SyncCacheViewAuthenticPixels(image_view,exception);
@@ -4439,32 +4470,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;
@@ -4488,7 +4500,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);
@@ -4502,12 +4514,12 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
           ((y1 != 0L) && (y1 != (ssize_t) composite_image->rows)))
         {
           char
-            geometry[MaxTextExtent];
+            geometry[MagickPathExtent];
 
           /*
             Resize image.
           */
-          (void) FormatLocaleString(geometry,MaxTextExtent,"%gx%g!",
+          (void) FormatLocaleString(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,
@@ -4522,7 +4534,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);
@@ -4538,6 +4550,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;
+      (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 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
@@ -4785,12 +4837,16 @@ MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info)
   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,
@@ -4809,59 +4865,75 @@ MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info)
   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 (clone_info->pointsize != 0.0)
+    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,(char **) NULL);
+  option=GetImageOption(clone_info,"interword-spacing");
+  if (option != (const char *) NULL)
+    draw_info->interword_spacing=StringToDouble(option,(char **) NULL);
+  option=GetImageOption(clone_info,"kerning");
+  if (option != (const char *) NULL)
+    draw_info->kerning=StringToDouble(option,(char **) NULL);
+  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,(char **) NULL);
+  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=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
 /*
@@ -5256,7 +5328,7 @@ static void TraceLine(PrimitiveInfo *primitive_info,const PointInfo start,
 static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
 {
   char
-    token[MaxTextExtent];
+    token[MagickPathExtent];
 
   const char
     *p;
@@ -5270,10 +5342,10 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
     y;
 
   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;
@@ -5289,15 +5361,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'; )
@@ -5531,8 +5596,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];
@@ -5569,8 +5634,8 @@ static size_t TracePath(PrimitiveInfo *primitive_info,const char *path)
           }
           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];
@@ -5769,12 +5834,10 @@ static void TraceSquareLinecap(PrimitiveInfo *primitive_info,
 
 static inline double DrawEpsilonReciprocal(const double x)
 {
-#define DrawEpsilon  ((double) 1.0e-10)
+#define DrawEpsilon  (1.0e-6)
 
-  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));
+  double sign = x < 0.0 ? -1.0 : 1.0;
+  return((sign*x) >= DrawEpsilon ? 1.0/x : sign*(1.0/DrawEpsilon));
 }
 
 static PrimitiveInfo *TraceStrokePolygon(const DrawInfo *draw_info,