]> granicus.if.org Git - imagemagick/commitdiff
Added support for more than 2 stop colors.
authordirk <dirk@git.imagemagick.org>
Sun, 12 Jul 2015 17:56:39 +0000 (17:56 +0000)
committerdirk <dirk@git.imagemagick.org>
Sun, 12 Jul 2015 17:56:39 +0000 (17:56 +0000)
MagickCore/draw.c
MagickCore/paint.c
MagickCore/paint.h
coders/gradient.c

index c66056146d5b82a29405f1d00172730134d9fc38..453fb3e45d897c1995cb712f1e0c29f52fe54d60 100644 (file)
@@ -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;
@@ -2492,22 +2493,28 @@ MagickExport MagickBooleanType DrawImage(Image *image,const DrawInfo *draw_info,
           }
         if (LocaleCompare("stop-color",keyword) == 0)
           {
-            GradientType
-              type;
-
             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);
-            type=LinearGradient;
-            if (draw_info->gradient.type == RadialGradient)
-              type=RadialGradient;
-            (void) GradientImage(image,type,PadSpread,&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)
@@ -2761,6 +2768,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);
@@ -3230,6 +3253,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)
 {
@@ -3269,6 +3308,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;
index 74bdb3660a8cb084bd059ebd8c49bf3f9018167a..a8a7514bf1cd58b14d7aacc3fbf700b4ae36a632 100644 (file)
@@ -405,9 +405,10 @@ MagickExport MagickBooleanType FloodfillPaintImage(Image *image,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-MagickExport MagickBooleanType GradientImage(Image *image,
-  const GradientType type,const SpreadMethod method,
-  const PixelInfo *start_color,const PixelInfo *stop_color,
+
+MagickExport MagickBooleanType GradientImage(Image *image,\r
+  const GradientType type,const SpreadMethod method,\r
+  const StopInfo *stops,const size_t number_stops,
   ExceptionInfo *exception)
 {
   DrawInfo
@@ -419,9 +420,6 @@ MagickExport MagickBooleanType GradientImage(Image *image,
   MagickBooleanType
     status;
 
-  register ssize_t
-    i;
-
   /*
     Set gradient start-stop end points.
   */
@@ -429,8 +427,8 @@ MagickExport MagickBooleanType GradientImage(Image *image,
   assert(image->signature == MagickCoreSignature);
   if (image->debug != MagickFalse)
     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
-  assert(start_color != (const PixelInfo *) NULL);
-  assert(stop_color != (const PixelInfo *) NULL);
+  assert(stops != (const StopInfo *) NULL);
+  assert(number_stops > 0);
   draw_info=AcquireDrawInfo();
   gradient=(&draw_info->gradient);
   gradient->type=type;
@@ -447,24 +445,17 @@ MagickExport MagickBooleanType GradientImage(Image *image,
   /*
     Define the gradient to fill between the stops.
   */
-  gradient->number_stops=2;
+  gradient->number_stops=number_stops;
   gradient->stops=(StopInfo *) AcquireQuantumMemory(gradient->number_stops,
     sizeof(*gradient->stops));
   if (gradient->stops == (StopInfo *) NULL)
     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
       image->filename);
-  (void) ResetMagickMemory(gradient->stops,0,gradient->number_stops*
-    sizeof(*gradient->stops));
-  for (i=0; i < (ssize_t) gradient->number_stops; i++)
-    GetPixelInfo(image,&gradient->stops[i].color);
-  gradient->stops[0].color=(*start_color);
-  gradient->stops[0].offset=0.0;
-  gradient->stops[1].color=(*stop_color);
-  gradient->stops[1].offset=1.0;
+  (void) CopyMagickMemory(gradient->stops,stops,(size_t) number_stops*
+    sizeof(*stops));
   /*
     Draw a gradient on the image.
   */
-  (void) SetImageColorspace(image,start_color->colorspace,exception);
   status=DrawGradientImage(image,draw_info,exception);
   draw_info=DestroyDrawInfo(draw_info);
   return(status);
index ea61e9756d016e769d990d57e5fbaefac9b78d98..b61a3dc241dc535f59c1be26dbeb0fc59789f9cd 100644 (file)
@@ -31,8 +31,8 @@ extern MagickExport Image
 extern MagickExport MagickBooleanType
   FloodfillPaintImage(Image *,const DrawInfo *,const PixelInfo *,const ssize_t,
     const ssize_t,const MagickBooleanType,ExceptionInfo *),
-  GradientImage(Image *,const GradientType,const SpreadMethod,const PixelInfo *,
-    const PixelInfo *,ExceptionInfo *),
+  GradientImage(Image *,const GradientType,const SpreadMethod,const StopInfo *,
+    const size_t,ExceptionInfo *),
   OpaquePaintImage(Image *,const PixelInfo *,const PixelInfo *,
     const MagickBooleanType,ExceptionInfo *),
   TransparentPaintImage(Image *,const PixelInfo *,
index 77415d08dbd31deaa801478fd5d404bcffbd0765..eca241f17e0dcfea95dc825be7606b12fee74b30 100644 (file)
@@ -108,9 +108,8 @@ static Image *ReadGRADIENTImage(const ImageInfo *image_info,
     icc_color,
     status;
 
-  PixelInfo
-    start_color,
-    stop_color;
+  StopInfo
+    *stops;
 
   /*
     Initialize Image structure.
@@ -141,32 +140,39 @@ static Image *ReadGRADIENTImage(const ImageInfo *image_info,
       (void) sscanf(image_info->filename,"%*[^-]-%[^-]",colorname+4);
       icc_color=MagickTrue;
     }
-  status=QueryColorCompliance(colorname,AllCompliance,&start_color,exception);
+  stops=(StopInfo *) AcquireQuantumMemory(2,sizeof(*stops));
+  if (stops == (StopInfo *) NULL)
+    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+  stops[0].offset=0.0;
+  stops[1].offset=1.0;
+  status=QueryColorCompliance(colorname,AllCompliance,&stops[0].color,exception);
   if (status == MagickFalse)
     {
+      stops=(StopInfo *) RelinquishMagickMemory(stops);
       image=DestroyImage(image);
       return((Image *) NULL);
     }
-  (void) SetImageColorspace(image,start_color.colorspace,exception);
+  (void) SetImageColorspace(image,stops[0].color.colorspace,exception);
   (void) CopyMagickString(colorname,"white",MagickPathExtent);
-  if (GetPixelInfoIntensity(image,&start_color) > (QuantumRange/2.0))
+  if (GetPixelInfoIntensity(image,&stops[0].color) > (QuantumRange/2.0))
     (void) CopyMagickString(colorname,"black",MagickPathExtent);
   if (icc_color == MagickFalse)
     (void) sscanf(image_info->filename,"%*[^-]-%[^-]",colorname);
   else
     (void) sscanf(image_info->filename,"%*[^-]-%*[^-]-%[^-]",colorname);
-  status=QueryColorCompliance(colorname,AllCompliance,&stop_color,exception);
+  status=QueryColorCompliance(colorname,AllCompliance,&stops[1].color,exception);
   if (status == MagickFalse)
     {
+      stops=(StopInfo *) RelinquishMagickMemory(stops);
       image=DestroyImage(image);
       return((Image *) NULL);
     }
-  image->alpha_trait=start_color.alpha_trait;
-  if (stop_color.alpha_trait != UndefinedPixelTrait)
-    image->alpha_trait=stop_color.alpha_trait;
+  image->alpha_trait=stops[0].color.alpha_trait;
+  if (stops[1].color.alpha_trait != UndefinedPixelTrait)
+    image->alpha_trait=stops[1].color.alpha_trait;
   status=GradientImage(image,LocaleCompare(image_info->magick,"GRADIENT") == 0 ?
-    LinearGradient : RadialGradient,PadSpread,&start_color,&stop_color,
-    exception);
+    LinearGradient : RadialGradient,PadSpread,stops,2,exception);
+  stops=(StopInfo *) RelinquishMagickMemory(stops);
   if (status == MagickFalse)
     {
       image=DestroyImageList(image);