]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/draw.c
Update web pages
[imagemagick] / MagickCore / draw.c
index 1dc87b05882e0d94ac4fab6f01d2c38d49e7c796..5cb4d4da5c8aadd26faca821b9aafe81a5a27147 100644 (file)
@@ -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;
@@ -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);
 }
@@ -1096,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;
@@ -1379,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;
@@ -1394,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);
@@ -1418,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);
@@ -1661,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;
 
@@ -1689,9 +1699,6 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
   PointInfo
     point;
 
-  PixelInfo
-    start_color;
-
   PrimitiveInfo
     *primitive_info;
 
@@ -1710,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) ||
@@ -1742,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.
   */
@@ -1773,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;
@@ -1946,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
@@ -1986,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);
@@ -2001,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);
@@ -2010,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;
@@ -2081,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;
@@ -2179,16 +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=AlphaPrimitive;
-            break;
-          }
-        break;
-      }
       case 'o':
       case 'O':
       {
@@ -2255,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;
@@ -2271,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);
@@ -2293,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);
@@ -2347,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),
@@ -2365,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);
@@ -2395,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);
@@ -2487,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);
@@ -2514,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);
@@ -2747,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);
@@ -3216,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)
 {
@@ -3250,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;
@@ -3482,11 +3533,12 @@ MagickExport MagickBooleanType DrawPatternPath(Image *image,
   ExceptionInfo *exception)
 {
   char
-    property[MaxTextExtent];
+    property[MagickPathExtent];
 
   const char
     *geometry,
-    *path;
+    *path,
+    *type;
 
   DrawInfo
     *clone_info;
@@ -3498,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);
@@ -3526,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);
@@ -3810,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);
@@ -3865,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;
@@ -3891,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)
           {
@@ -3907,12 +3965,12 @@ 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);
+              (void) GetFillColor(draw_info,x-start_x,y-start_y,&pixel,exception);
               SetPixelViaPixelInfo(image,&pixel,q);
             }
           q+=GetPixelChannels(image);
@@ -3933,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();
@@ -3959,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.
@@ -3985,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);
@@ -4418,7 +4476,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         affine;
 
       char
-        composite_geometry[MaxTextExtent];
+        composite_geometry[MagickPathExtent];
 
       Image
         *composite_image;
@@ -4442,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);
@@ -4456,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,
@@ -4476,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);
@@ -4516,7 +4574,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
     case TextPrimitive:
     {
       char
-        geometry[MaxTextExtent];
+        geometry[MagickPathExtent];
 
       DrawInfo
         *clone_info;
@@ -4525,7 +4583,7 @@ MagickExport MagickBooleanType DrawPrimitive(Image *image,
         break;
       clone_info=CloneDrawInfo((ImageInfo *) NULL,draw_info);
       (void) CloneString(&clone_info->text,primitive_info->text);
-      (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
+      (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);
@@ -4779,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,
@@ -4803,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
 /*
@@ -5250,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;
@@ -5264,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;
@@ -5283,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'; )
@@ -5763,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,