PointInfo
point;
- PixelInfo
- start_color;
-
PrimitiveInfo
*primitive_info;
size_t
length,
- number_points;
+ number_points,
+ number_stops;
ssize_t
j,
k,
n;
+ StopInfo
+ *stops;
+
/*
Ensure the annotation info is valid.
*/
primitive_extent=(double) strlen(primitive);
(void) SetImageArtifact(image,"MVG",primitive);
n=0;
+ number_stops=0;
+ stops=(StopInfo *) NULL;
/*
Allocate primitive info memory.
*/
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;
}
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)
}
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);
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)
{
(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;
% 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
MagickBooleanType
status;
- register ssize_t
- i;
-
/*
Set gradient start-stop end points.
*/
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;
/*
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);
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 *,
icc_color,
status;
- PixelInfo
- start_color,
- stop_color;
+ StopInfo
+ *stops;
/*
Initialize Image structure.
(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);