]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/draw.c
Update web pages
[imagemagick] / MagickCore / draw.c
index 4ce90d8993495ac385056f83970fb9712b64ac40..5cb4d4da5c8aadd26faca821b9aafe81a5a27147 100644 (file)
@@ -1428,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);
@@ -1699,9 +1699,6 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
   PointInfo
     point;
 
-  PixelInfo
-    start_color;
-
   PrimitiveInfo
     *primitive_info;
 
@@ -1720,13 +1717,17 @@ 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.
   */
@@ -1752,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.
   */
@@ -1783,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;
@@ -1956,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
@@ -2091,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;
@@ -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;
@@ -2349,6 +2352,8 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
                   graphic_context[n]->affine.ty;
                 (void) FormatLocaleString(key,MagickPathExtent,"%s",name);
                 (void) SetImageArtifact(image,key,token);
+                (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",
@@ -2487,13 +2492,25 @@ 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)
@@ -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)
 {
@@ -3255,6 +3304,8 @@ MagickExport MagickBooleanType DrawGradientImage(Image *image,
     (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;
@@ -3486,7 +3537,8 @@ MagickExport MagickBooleanType DrawPatternPath(Image *image,
 
   const char
     *geometry,
-    *path;
+    *path,
+    *type;
 
   DrawInfo
     *clone_info;
@@ -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,8 +3867,8 @@ static MagickBooleanType DrawPolygonPrimitive(Image *image,
     bounds;
 
   ssize_t
-    start,
-    stop,
+    start_y,
+    stop_y,
     y;
 
   /*
@@ -3871,13 +3928,13 @@ RestoreMSCWarning
       /*
         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;
@@ -3892,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)
           {
@@ -3908,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) GetFillColor(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);
@@ -3934,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();
@@ -3960,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.
@@ -3986,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);
@@ -4819,28 +4876,35 @@ MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info)
   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,"kerning");
+  option=GetImageOption(clone_info,"family");
   if (option != (const char *) NULL)
-    draw_info->kerning=StringToDouble(option,(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,"direction");
-  if (option != (const char *) NULL)
-    draw_info->direction=(DirectionType) ParseCommandOption(
-      MagickDirectionOptions,MagickFalse,option);
-  else
-    draw_info->direction=UndefinedDirection;
-  option=GetImageOption(clone_info,"fill");
+  option=GetImageOption(clone_info,"kerning");
   if (option != (const char *) NULL)
-    (void) QueryColorCompliance(option,AllCompliance,&draw_info->fill,
-      exception);
+    draw_info->kerning=StringToDouble(option,(char **) NULL);
   option=GetImageOption(clone_info,"stroke");
   if (option != (const char *) NULL)
     (void) QueryColorCompliance(option,AllCompliance,&draw_info->stroke,
@@ -4848,14 +4912,25 @@ MagickExport void GetDrawInfo(const ImageInfo *image_info,DrawInfo *draw_info)
   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,"gravity");
+  option=GetImageOption(clone_info,"weight");
   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=MagickCoreSignature;
   clone_info=DestroyImageInfo(clone_info);