blob: 28ab8f313b80d330a6d4dc6ebd0050ece950ba70 [file] [log] [blame]
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M M SSSSS L %
% MM MM SS L %
% M M M SSS L %
% M M SS L %
% M M SSSSS LLLLL %
% %
% %
% Execute Magick Scripting Language Scripts. %
% %
% Software Design %
% Cristy %
% Leonard Rosenthol %
% William Radcliffe %
% December 2001 %
% %
% %
% Copyright 1999-2019 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 %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/annotate.h"
#include "MagickCore/artifact.h"
#include "MagickCore/attribute.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
#include "MagickCore/cache-view.h"
#include "MagickCore/channel.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/colormap.h"
#include "MagickCore/composite.h"
#include "MagickCore/constitute.h"
#include "MagickCore/decorate.h"
#include "MagickCore/display.h"
#include "MagickCore/distort.h"
#include "MagickCore/draw.h"
#include "MagickCore/effect.h"
#include "MagickCore/enhance.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/fx.h"
#include "MagickCore/geometry.h"
#include "MagickCore/image.h"
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/log.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/module.h"
#include "MagickCore/option.h"
#include "MagickCore/paint.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/profile.h"
#include "MagickCore/property.h"
#include "MagickCore/quantize.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/registry.h"
#include "MagickCore/resize.h"
#include "MagickCore/resource_.h"
#include "MagickCore/segment.h"
#include "MagickCore/shear.h"
#include "MagickCore/signature.h"
#include "MagickCore/statistic.h"
#include "MagickCore/static.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/transform.h"
#include "MagickCore/threshold.h"
#include "MagickCore/utility.h"
#if defined(MAGICKCORE_XML_DELEGATE)
# if defined(MAGICKCORE_WINDOWS_SUPPORT)
# if !defined(__MINGW32__)
# include <win32config.h>
# endif
# endif
# include <libxml/xmlmemory.h>
# include <libxml/parserInternals.h>
# include <libxml/xmlerror.h>
#endif
/*
Define Declatations.
*/
#define ThrowMSLException(severity,tag,reason) \
(void) ThrowMagickException(msl_info->exception,GetMagickModule(),severity, \
tag,"`%s'",reason);
/*
Typedef declaractions.
*/
typedef struct _MSLGroupInfo
{
size_t
numImages; /* how many images are in this group */
} MSLGroupInfo;
typedef struct _MSLInfo
{
ExceptionInfo
*exception;
ssize_t
n,
number_groups;
ImageInfo
**image_info;
DrawInfo
**draw_info;
Image
**attributes,
**image;
char
*content;
MSLGroupInfo
*group_info;
#if defined(MAGICKCORE_XML_DELEGATE)
xmlParserCtxtPtr
parser;
xmlDocPtr
document;
#endif
} MSLInfo;
/*
Forward declarations.
*/
#if defined(MAGICKCORE_XML_DELEGATE)
static MagickBooleanType
WriteMSLImage(const ImageInfo *,Image *,ExceptionInfo *);
static MagickBooleanType
SetMSLAttributes(MSLInfo *,const char *,const char *);
#endif
#if defined(MAGICKCORE_XML_DELEGATE)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e a d M S L I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadMSLImage() reads a Magick Scripting Language file and returns it.
% It allocates the memory necessary for the new Image structure and returns a
% pointer to the new image.
%
% The format of the ReadMSLImage method is:
%
% Image *ReadMSLImage(const ImageInfo *image_info,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o exception: return any errors or warnings in this structure.
%
*/
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
static inline Image *GetImageCache(const ImageInfo *image_info,const char *path,
ExceptionInfo *exception)
{
char
key[MagickPathExtent];
ExceptionInfo
*sans_exception;
Image
*image;
ImageInfo
*read_info;
(void) FormatLocaleString(key,MagickPathExtent,"cache:%s",path);
sans_exception=AcquireExceptionInfo();
image=(Image *) GetImageRegistry(ImageRegistryType,key,sans_exception);
sans_exception=DestroyExceptionInfo(sans_exception);
if (image != (Image *) NULL)
return(image);
read_info=CloneImageInfo(image_info);
(void) CopyMagickString(read_info->filename,path,MagickPathExtent);
image=ReadImage(read_info,exception);
read_info=DestroyImageInfo(read_info);
if (image != (Image *) NULL)
(void) SetImageRegistry(ImageRegistryType,key,image,exception);
return(image);
}
static int IsPathDirectory(const char *path)
{
MagickBooleanType
status;
struct stat
attributes;
if ((path == (const char *) NULL) || (*path == '\0'))
return(MagickFalse);
status=GetPathAttributes(path,&attributes);
if (status == MagickFalse)
return(-1);
if (S_ISDIR(attributes.st_mode) == 0)
return(0);
return(1);
}
static int MSLIsStandalone(void *context)
{
MSLInfo
*msl_info;
/*
Is this document tagged standalone?
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.MSLIsStandalone()");
msl_info=(MSLInfo *) context;
return(msl_info->document->standalone == 1);
}
static int MSLHasInternalSubset(void *context)
{
MSLInfo
*msl_info;
/*
Does this document has an internal subset?
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.MSLHasInternalSubset()");
msl_info=(MSLInfo *) context;
return(msl_info->document->intSubset != NULL);
}
static int MSLHasExternalSubset(void *context)
{
MSLInfo
*msl_info;
/*
Does this document has an external subset?
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.MSLHasExternalSubset()");
msl_info=(MSLInfo *) context;
return(msl_info->document->extSubset != NULL);
}
static void MSLInternalSubset(void *context,const xmlChar *name,
const xmlChar *external_id,const xmlChar *system_id)
{
MSLInfo
*msl_info;
/*
Does this document has an internal subset?
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.internalSubset(%s %s %s)",name,
(external_id != (const xmlChar *) NULL ? (const char *) external_id : " "),
(system_id != (const xmlChar *) NULL ? (const char *) system_id : " "));
msl_info=(MSLInfo *) context;
(void) xmlCreateIntSubset(msl_info->document,name,external_id,system_id);
}
static xmlParserInputPtr MSLResolveEntity(void *context,
const xmlChar *public_id,const xmlChar *system_id)
{
MSLInfo
*msl_info;
xmlParserInputPtr
stream;
/*
Special entity resolver, better left to the parser, it has more
context than the application layer. The default behaviour is to
not resolve the entities, in that case the ENTITY_REF nodes are
built in the structure (and the parameter values).
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.resolveEntity(%s, %s)",
(public_id != (const xmlChar *) NULL ? (const char *) public_id : "none"),
(system_id != (const xmlChar *) NULL ? (const char *) system_id : "none"));
msl_info=(MSLInfo *) context;
stream=xmlLoadExternalEntity((const char *) system_id,(const char *)
public_id,msl_info->parser);
return(stream);
}
static xmlEntityPtr MSLGetEntity(void *context,const xmlChar *name)
{
MSLInfo
*msl_info;
/*
Get an entity by name.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.MSLGetEntity(%s)",(const char *) name);
msl_info=(MSLInfo *) context;
return(xmlGetDocEntity(msl_info->document,name));
}
static xmlEntityPtr MSLGetParameterEntity(void *context,const xmlChar *name)
{
MSLInfo
*msl_info;
/*
Get a parameter entity by name.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.getParameterEntity(%s)",(const char *) name);
msl_info=(MSLInfo *) context;
return(xmlGetParameterEntity(msl_info->document,name));
}
static void MSLEntityDeclaration(void *context,const xmlChar *name,int type,
const xmlChar *public_id,const xmlChar *system_id,xmlChar *content)
{
MSLInfo
*msl_info;
/*
An entity definition has been parsed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.entityDecl(%s, %d, %s, %s, %s)",name,type,
public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
system_id != (const xmlChar *) NULL ? (const char *) system_id : "none",
content);
msl_info=(MSLInfo *) context;
if (msl_info->parser->inSubset == 1)
(void) xmlAddDocEntity(msl_info->document,name,type,public_id,system_id,
content);
else
if (msl_info->parser->inSubset == 2)
(void) xmlAddDtdEntity(msl_info->document,name,type,public_id,system_id,
content);
}
static void MSLAttributeDeclaration(void *context,const xmlChar *element,
const xmlChar *name,int type,int value,const xmlChar *default_value,
xmlEnumerationPtr tree)
{
MSLInfo
*msl_info;
xmlChar
*fullname,
*prefix;
xmlParserCtxtPtr
parser;
/*
An attribute definition has been parsed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.attributeDecl(%s, %s, %d, %d, %s, ...)\n",element,name,type,value,
default_value);
msl_info=(MSLInfo *) context;
fullname=(xmlChar *) NULL;
prefix=(xmlChar *) NULL;
parser=msl_info->parser;
fullname=(xmlChar *) xmlSplitQName(parser,name,&prefix);
if (parser->inSubset == 1)
(void) xmlAddAttributeDecl(&parser->vctxt,msl_info->document->intSubset,
element,fullname,prefix,(xmlAttributeType) type,
(xmlAttributeDefault) value,default_value,tree);
else
if (parser->inSubset == 2)
(void) xmlAddAttributeDecl(&parser->vctxt,msl_info->document->extSubset,
element,fullname,prefix,(xmlAttributeType) type,
(xmlAttributeDefault) value,default_value,tree);
if (prefix != (xmlChar *) NULL)
xmlFree(prefix);
if (fullname != (xmlChar *) NULL)
xmlFree(fullname);
}
static void MSLElementDeclaration(void *context,const xmlChar *name,int type,
xmlElementContentPtr content)
{
MSLInfo
*msl_info;
xmlParserCtxtPtr
parser;
/*
An element definition has been parsed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.elementDecl(%s, %d, ...)",name,type);
msl_info=(MSLInfo *) context;
parser=msl_info->parser;
if (parser->inSubset == 1)
(void) xmlAddElementDecl(&parser->vctxt,msl_info->document->intSubset,
name,(xmlElementTypeVal) type,content);
else
if (parser->inSubset == 2)
(void) xmlAddElementDecl(&parser->vctxt,msl_info->document->extSubset,
name,(xmlElementTypeVal) type,content);
}
static void MSLNotationDeclaration(void *context,const xmlChar *name,
const xmlChar *public_id,const xmlChar *system_id)
{
MSLInfo
*msl_info;
xmlParserCtxtPtr
parser;
/*
What to do when a notation declaration has been parsed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.notationDecl(%s, %s, %s)",name,
public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
system_id != (const xmlChar *) NULL ? (const char *) system_id : "none");
msl_info=(MSLInfo *) context;
parser=msl_info->parser;
if (parser->inSubset == 1)
(void) xmlAddNotationDecl(&parser->vctxt,msl_info->document->intSubset,
name,public_id,system_id);
else
if (parser->inSubset == 2)
(void) xmlAddNotationDecl(&parser->vctxt,msl_info->document->intSubset,
name,public_id,system_id);
}
static void MSLUnparsedEntityDeclaration(void *context,const xmlChar *name,
const xmlChar *public_id,const xmlChar *system_id,const xmlChar *notation)
{
MSLInfo
*msl_info;
/*
What to do when an unparsed entity declaration is parsed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.unparsedEntityDecl(%s, %s, %s, %s)",name,
public_id != (const xmlChar *) NULL ? (const char *) public_id : "none",
system_id != (const xmlChar *) NULL ? (const char *) system_id : "none",
notation);
msl_info=(MSLInfo *) context;
(void) xmlAddDocEntity(msl_info->document,name,
XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,public_id,system_id,notation);
}
static void MSLSetDocumentLocator(void *context,xmlSAXLocatorPtr location)
{
MSLInfo
*msl_info;
/*
Receive the document locator at startup, actually xmlDefaultSAXLocator.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.setDocumentLocator()\n");
(void) location;
msl_info=(MSLInfo *) context;
(void) msl_info;
}
static void MSLStartDocument(void *context)
{
MSLInfo
*msl_info;
xmlParserCtxtPtr
parser;
/*
Called when the document start being processed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.startDocument()");
msl_info=(MSLInfo *) context;
parser=msl_info->parser;
msl_info->document=xmlNewDoc(parser->version);
if (msl_info->document == (xmlDocPtr) NULL)
return;
if (parser->encoding == NULL)
msl_info->document->encoding=NULL;
else
msl_info->document->encoding=xmlStrdup(parser->encoding);
msl_info->document->standalone=parser->standalone;
}
static void MSLEndDocument(void *context)
{
MSLInfo
*msl_info;
/*
Called when the document end has been detected.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule()," SAX.endDocument()");
msl_info=(MSLInfo *) context;
if (msl_info->content != (char *) NULL)
msl_info->content=DestroyString(msl_info->content);
}
static void MSLPushImage(MSLInfo *msl_info,Image *image)
{
ssize_t
n;
if (image != (Image *) NULL)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(msl_info != (MSLInfo *) NULL);
msl_info->n++;
n=msl_info->n;
msl_info->image_info=(ImageInfo **) ResizeQuantumMemory(msl_info->image_info,
(n+1),sizeof(*msl_info->image_info));
msl_info->draw_info=(DrawInfo **) ResizeQuantumMemory(msl_info->draw_info,
(n+1),sizeof(*msl_info->draw_info));
msl_info->attributes=(Image **) ResizeQuantumMemory(msl_info->attributes,
(n+1),sizeof(*msl_info->attributes));
msl_info->image=(Image **) ResizeQuantumMemory(msl_info->image,(n+1),
sizeof(*msl_info->image));
if ((msl_info->image_info == (ImageInfo **) NULL) ||
(msl_info->draw_info == (DrawInfo **) NULL) ||
(msl_info->attributes == (Image **) NULL) ||
(msl_info->image == (Image **) NULL))
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed")
msl_info->image_info[n]=CloneImageInfo(msl_info->image_info[n-1]);
msl_info->draw_info[n]=CloneDrawInfo(msl_info->image_info[n-1],
msl_info->draw_info[n-1]);
if (image == (Image *) NULL)
msl_info->attributes[n]=AcquireImage(msl_info->image_info[n],
msl_info->exception);
else
msl_info->attributes[n]=CloneImage(image,0,0,MagickTrue,
msl_info->exception);
msl_info->image[n]=(Image *) image;
if ((msl_info->image_info[n] == (ImageInfo *) NULL) ||
(msl_info->attributes[n] == (Image *) NULL))
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed")
if (msl_info->number_groups != 0)
msl_info->group_info[msl_info->number_groups-1].numImages++;
}
static void MSLPopImage(MSLInfo *msl_info)
{
if (msl_info->number_groups != 0)
return;
if (msl_info->image[msl_info->n] != (Image *) NULL)
msl_info->image[msl_info->n]=DestroyImage(msl_info->image[msl_info->n]);
msl_info->attributes[msl_info->n]=DestroyImage(
msl_info->attributes[msl_info->n]);
msl_info->draw_info[msl_info->n]=DestroyDrawInfo(
msl_info->draw_info[msl_info->n]);
msl_info->image_info[msl_info->n]=DestroyImageInfo(
msl_info->image_info[msl_info->n]);
msl_info->n--;
}
static void MSLStartElement(void *context,const xmlChar *tag,
const xmlChar **attributes)
{
AffineMatrix
affine,
current;
ChannelType
channel;
ChannelType
channel_mask;
char
*attribute,
key[MagickPathExtent],
*value;
const char
*keyword;
double
angle;
DrawInfo
*draw_info;
ExceptionInfo
*exception;
GeometryInfo
geometry_info;
Image
*image;
int
flags;
ssize_t
option,
j,
n,
x,
y;
MSLInfo
*msl_info;
RectangleInfo
geometry;
register ssize_t
i;
size_t
height,
width;
/*
Called when an opening tag has been processed.
*/
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SAX.startElement(%s",tag);
exception=AcquireExceptionInfo();
msl_info=(MSLInfo *) context;
n=msl_info->n;
keyword=(const char *) NULL;
value=(char *) NULL;
SetGeometryInfo(&geometry_info);
(void) memset(&geometry,0,sizeof(geometry));
channel=DefaultChannels;
switch (*tag)
{
case 'A':
case 'a':
{
if (LocaleCompare((const char *) tag,"add-noise") == 0)
{
Image
*noise_image;
NoiseType
noise;
/*
Add noise image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
noise=UniformNoise;
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'C':
case 'c':
{
if (LocaleCompare(keyword,"channel") == 0)
{
option=ParseChannelOption(value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedChannelType",
value);
channel=(ChannelType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'N':
case 'n':
{
if (LocaleCompare(keyword,"noise") == 0)
{
option=ParseCommandOption(MagickNoiseOptions,MagickFalse,
value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedNoiseType",
value);
noise=(NoiseType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
channel_mask=SetImageChannelMask(msl_info->image[n],channel);
noise_image=AddNoiseImage(msl_info->image[n],noise,1.0,
msl_info->exception);
(void) SetPixelChannelMask(msl_info->image[n],channel_mask);
if (noise_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=noise_image;
break;
}
if (LocaleCompare((const char *) tag,"annotate") == 0)
{
char
text[MagickPathExtent];
/*
Annotate image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
draw_info=CloneDrawInfo(msl_info->image_info[n],
msl_info->draw_info[n]);
angle=0.0;
current=draw_info->affine;
GetAffineMatrix(&affine);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'A':
case 'a':
{
if (LocaleCompare(keyword,"affine") == 0)
{
char
*p;
p=value;
draw_info->affine.sx=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.rx=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.ry=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.sy=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.tx=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.ty=StringToDouble(p,&p);
break;
}
if (LocaleCompare(keyword,"align") == 0)
{
option=ParseCommandOption(MagickAlignOptions,MagickFalse,
value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedAlignType",
value);
draw_info->align=(AlignType) option;
break;
}
if (LocaleCompare(keyword,"antialias") == 0)
{
option=ParseCommandOption(MagickBooleanOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedBooleanType",
value);
draw_info->stroke_antialias=(MagickBooleanType) option;
draw_info->text_antialias=(MagickBooleanType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'D':
case 'd':
{
if (LocaleCompare(keyword,"density") == 0)
{
CloneString(&draw_info->density,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'E':
case 'e':
{
if (LocaleCompare(keyword,"encoding") == 0)
{
CloneString(&draw_info->encoding,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'F':
case 'f':
{
if (LocaleCompare(keyword, "fill") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&draw_info->fill,exception);
break;
}
if (LocaleCompare(keyword,"family") == 0)
{
CloneString(&draw_info->family,value);
break;
}
if (LocaleCompare(keyword,"font") == 0)
{
CloneString(&draw_info->font,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParseGravityGeometry(msl_info->image[n],value,
&geometry,exception);
break;
}
if (LocaleCompare(keyword,"gravity") == 0)
{
option=ParseCommandOption(MagickGravityOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedGravityType",
value);
draw_info->gravity=(GravityType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'P':
case 'p':
{
if (LocaleCompare(keyword,"pointsize") == 0)
{
draw_info->pointsize=StringToDouble(value,(char **) NULL);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'R':
case 'r':
{
if (LocaleCompare(keyword,"rotate") == 0)
{
angle=StringToDouble(value,(char **) NULL);
affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'S':
case 's':
{
if (LocaleCompare(keyword,"scale") == 0)
{
flags=ParseGeometry(value,&geometry_info);
if ((flags & SigmaValue) == 0)
geometry_info.sigma=1.0;
affine.sx=geometry_info.rho;
affine.sy=geometry_info.sigma;
break;
}
if (LocaleCompare(keyword,"skewX") == 0)
{
angle=StringToDouble(value,(char **) NULL);
affine.ry=tan(DegreesToRadians(fmod((double) angle,
360.0)));
break;
}
if (LocaleCompare(keyword,"skewY") == 0)
{
angle=StringToDouble(value,(char **) NULL);
affine.rx=tan(DegreesToRadians(fmod((double) angle,
360.0)));
break;
}
if (LocaleCompare(keyword,"stretch") == 0)
{
option=ParseCommandOption(MagickStretchOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedStretchType",
value);
draw_info->stretch=(StretchType) option;
break;
}
if (LocaleCompare(keyword, "stroke") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&draw_info->stroke,exception);
break;
}
if (LocaleCompare(keyword,"strokewidth") == 0)
{
draw_info->stroke_width=StringToLong(value);
break;
}
if (LocaleCompare(keyword,"style") == 0)
{
option=ParseCommandOption(MagickStyleOptions,MagickFalse,
value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedStyleType",
value);
draw_info->style=(StyleType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'T':
case 't':
{
if (LocaleCompare(keyword,"text") == 0)
{
CloneString(&draw_info->text,value);
break;
}
if (LocaleCompare(keyword,"translate") == 0)
{
flags=ParseGeometry(value,&geometry_info);
if ((flags & SigmaValue) == 0)
geometry_info.sigma=1.0;
affine.tx=geometry_info.rho;
affine.ty=geometry_info.sigma;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'U':
case 'u':
{
if (LocaleCompare(keyword, "undercolor") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&draw_info->undercolor,exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'W':
case 'w':
{
if (LocaleCompare(keyword,"weight") == 0)
{
draw_info->weight=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'X':
case 'x':
{
if (LocaleCompare(keyword,"x") == 0)
{
geometry.x=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'Y':
case 'y':
{
if (LocaleCompare(keyword,"y") == 0)
{
geometry.y=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
(void) FormatLocaleString(text,MagickPathExtent,
"%.20gx%.20g%+.20g%+.20g",(double) geometry.width,(double)
geometry.height,(double) geometry.x,(double) geometry.y);
CloneString(&draw_info->geometry,text);
draw_info->affine.sx=affine.sx*current.sx+affine.ry*current.rx;
draw_info->affine.rx=affine.rx*current.sx+affine.sy*current.rx;
draw_info->affine.ry=affine.sx*current.ry+affine.ry*current.sy;
draw_info->affine.sy=affine.rx*current.ry+affine.sy*current.sy;
draw_info->affine.tx=affine.sx*current.tx+affine.ry*current.ty+
affine.tx;
draw_info->affine.ty=affine.rx*current.tx+affine.sy*current.ty+
affine.ty;
(void) AnnotateImage(msl_info->image[n],draw_info,
msl_info->exception);
draw_info=DestroyDrawInfo(draw_info);
break;
}
if (LocaleCompare((const char *) tag,"append") == 0)
{
Image
*append_image;
MagickBooleanType
stack;
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
stack=MagickFalse;
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'S':
case 's':
{
if (LocaleCompare(keyword,"stack") == 0)
{
option=ParseCommandOption(MagickBooleanOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedBooleanType",
value);
stack=(MagickBooleanType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
append_image=AppendImages(msl_info->image[n],stack,
msl_info->exception);
if (append_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=append_image;
break;
}
ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
break;
}
case 'B':
case 'b':
{
if (LocaleCompare((const char *) tag,"blur") == 0)
{
Image
*blur_image;
/*
Blur image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'C':
case 'c':
{
if (LocaleCompare(keyword,"channel") == 0)
{
option=ParseChannelOption(value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedChannelType",
value);
channel=(ChannelType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParseGeometry(value,&geometry_info);
if ((flags & SigmaValue) == 0)
geometry_info.sigma=1.0;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'R':
case 'r':
{
if (LocaleCompare(keyword,"radius") == 0)
{
geometry_info.rho=StringToDouble(value,(char **) NULL);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'S':
case 's':
{
if (LocaleCompare(keyword,"sigma") == 0)
{
geometry_info.sigma=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
channel_mask=SetImageChannelMask(msl_info->image[n],channel);
blur_image=BlurImage(msl_info->image[n],geometry_info.rho,
geometry_info.sigma,msl_info->exception);
(void) SetPixelChannelMask(msl_info->image[n],channel_mask);
if (blur_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=blur_image;
break;
}
if (LocaleCompare((const char *) tag,"border") == 0)
{
Image
*border_image;
/*
Border image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
SetGeometry(msl_info->image[n],&geometry);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'C':
case 'c':
{
if (LocaleCompare(keyword,"compose") == 0)
{
option=ParseCommandOption(MagickComposeOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedComposeType",
value);
msl_info->image[n]->compose=(CompositeOperator) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'F':
case 'f':
{
if (LocaleCompare(keyword, "fill") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&msl_info->image[n]->border_color,exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParsePageGeometry(msl_info->image[n],value,
&geometry,exception);
if ((flags & HeightValue) == 0)
geometry.height=geometry.width;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'H':
case 'h':
{
if (LocaleCompare(keyword,"height") == 0)
{
geometry.height=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'W':
case 'w':
{
if (LocaleCompare(keyword,"width") == 0)
{
geometry.width=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
border_image=BorderImage(msl_info->image[n],&geometry,
msl_info->image[n]->compose,msl_info->exception);
if (border_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=border_image;
break;
}
ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
}
case 'C':
case 'c':
{
if (LocaleCompare((const char *) tag,"colorize") == 0)
{
char
blend[MagickPathExtent];
Image
*colorize_image;
PixelInfo
target;
/*
Add noise image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
GetPixelInfo(msl_info->image[n],&target);
(void) CopyMagickString(blend,"100",MagickPathExtent);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'B':
case 'b':
{
if (LocaleCompare(keyword,"blend") == 0)
{
(void) CopyMagickString(blend,value,MagickPathExtent);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'F':
case 'f':
{
if (LocaleCompare(keyword,"fill") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&target,msl_info->exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
colorize_image=ColorizeImage(msl_info->image[n],blend,&target,
msl_info->exception);
if (colorize_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=colorize_image;
break;
}
if (LocaleCompare((const char *) tag, "charcoal") == 0)
{
double
radius = 0.0,
sigma = 1.0;
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
/*
NOTE: charcoal can have no attributes, since we use all the defaults!
*/
if (attributes != (const xmlChar **) NULL)
{
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'R':
case 'r':
{
if (LocaleCompare(keyword,"radius") == 0)
{
radius=StringToDouble(value,(char **) NULL);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
break;
}
case 'S':
case 's':
{
if (LocaleCompare(keyword,"sigma") == 0)
{
sigma = StringToLong( value );
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
break;
}
}
}
}
/*
charcoal image.
*/
{
Image
*newImage;
newImage=CharcoalImage(msl_info->image[n],radius,sigma,
msl_info->exception);
if (newImage == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=newImage;
break;
}
}
if (LocaleCompare((const char *) tag,"chop") == 0)
{
Image
*chop_image;
/*
Chop image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
SetGeometry(msl_info->image[n],&geometry);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParsePageGeometry(msl_info->image[n],value,
&geometry,exception);
if ((flags & HeightValue) == 0)
geometry.height=geometry.width;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'H':
case 'h':
{
if (LocaleCompare(keyword,"height") == 0)
{
geometry.height=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'W':
case 'w':
{
if (LocaleCompare(keyword,"width") == 0)
{
geometry.width=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'X':
case 'x':
{
if (LocaleCompare(keyword,"x") == 0)
{
geometry.x=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'Y':
case 'y':
{
if (LocaleCompare(keyword,"y") == 0)
{
geometry.y=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
chop_image=ChopImage(msl_info->image[n],&geometry,
msl_info->exception);
if (chop_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=chop_image;
break;
}
if (LocaleCompare((const char *) tag,"color-floodfill") == 0)
{
PaintMethod
paint_method;
PixelInfo
target;
/*
Color floodfill image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
draw_info=CloneDrawInfo(msl_info->image_info[n],
msl_info->draw_info[n]);
SetGeometry(msl_info->image[n],&geometry);
paint_method=FloodfillMethod;
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'B':
case 'b':
{
if (LocaleCompare(keyword,"bordercolor") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&target,exception);
paint_method=FillToBorderMethod;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'F':
case 'f':
{
if (LocaleCompare(keyword,"fill") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&draw_info->fill,exception);
break;
}
if (LocaleCompare(keyword,"fuzz") == 0)
{
msl_info->image[n]->fuzz=StringToDouble(value,
(char **) NULL);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParsePageGeometry(msl_info->image[n],value,
&geometry,exception);
if ((flags & HeightValue) == 0)
geometry.height=geometry.width;
(void) GetOneVirtualPixelInfo(msl_info->image[n],
TileVirtualPixelMethod,geometry.x,geometry.y,&target,
exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'X':
case 'x':
{
if (LocaleCompare(keyword,"x") == 0)
{
geometry.x=StringToLong(value);
(void) GetOneVirtualPixelInfo(msl_info->image[n],
TileVirtualPixelMethod,geometry.x,geometry.y,&target,
exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'Y':
case 'y':
{
if (LocaleCompare(keyword,"y") == 0)
{
geometry.y=StringToLong(value);
(void) GetOneVirtualPixelInfo(msl_info->image[n],
TileVirtualPixelMethod,geometry.x,geometry.y,&target,
exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
(void) FloodfillPaintImage(msl_info->image[n],draw_info,&target,
geometry.x,geometry.y,paint_method == FloodfillMethod ?
MagickFalse : MagickTrue,msl_info->exception);
draw_info=DestroyDrawInfo(draw_info);
break;
}
if (LocaleCompare((const char *) tag,"comment") == 0)
break;
if (LocaleCompare((const char *) tag,"composite") == 0)
{
char
composite_geometry[MagickPathExtent];
CompositeOperator
compose;
Image
*composite_image,
*rotate_image;
/*
Composite image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
composite_image=NewImageList();
compose=OverCompositeOp;
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'C':
case 'c':
{
if (LocaleCompare(keyword,"compose") == 0)
{
option=ParseCommandOption(MagickComposeOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedComposeType",
value);
compose=(CompositeOperator) option;
break;
}
break;
}
case 'I':
case 'i':
{
if (LocaleCompare(keyword,"image") == 0)
for (j=0; j < msl_info->n; j++)
{
const char
*attribute;
attribute=GetImageProperty(msl_info->attributes[j],"id",
exception);
if ((attribute != (const char *) NULL) &&
(LocaleCompare(attribute,value) == 0))
{
composite_image=CloneImage(msl_info->image[j],0,0,
MagickFalse,exception);
break;
}
}
break;
}
default:
break;
}
}
if (composite_image == (Image *) NULL)
break;
rotate_image=NewImageList();
SetGeometry(msl_info->image[n],&geometry);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'B':
case 'b':
{
if (LocaleCompare(keyword,"blend") == 0)
{
(void) SetImageArtifact(composite_image,
"compose:args",value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'C':
case 'c':
{
if (LocaleCompare(keyword,"channel") == 0)
{
option=ParseChannelOption(value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedChannelType",
value);
channel=(ChannelType) option;
break;
}
if (LocaleCompare(keyword, "color") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&composite_image->background_color,exception);
break;
}
if (LocaleCompare(keyword,"compose") == 0)
break;
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParsePageGeometry(msl_info->image[n],value,
&geometry,exception);
if ((flags & HeightValue) == 0)
geometry.height=geometry.width;
break;
}
if (LocaleCompare(keyword,"gravity") == 0)
{
option=ParseCommandOption(MagickGravityOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedGravityType",
value);
msl_info->image[n]->gravity=(GravityType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'I':
case 'i':
{
if (LocaleCompare(keyword,"image") == 0)
break;
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'M':
case 'm':
{
if (LocaleCompare(keyword,"mask") == 0)
for (j=0; j < msl_info->n; j++)
{
const char
*attribute;
attribute=GetImageProperty(msl_info->attributes[j],"id",
exception);
if ((attribute != (const char *) NULL) &&
(LocaleCompare(value,value) == 0))
{
SetImageType(composite_image,TrueColorAlphaType,
exception);
(void) CompositeImage(composite_image,
msl_info->image[j],CopyAlphaCompositeOp,MagickTrue,
0,0,exception);
break;
}
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'O':
case 'o':
{
if (LocaleCompare(keyword,"opacity") == 0)
{
ssize_t
opacity,
y;
register ssize_t
x;
register Quantum
*q;
CacheView
*composite_view;
opacity=StringToLong(value);
if (compose != DissolveCompositeOp)
{
(void) SetImageAlpha(composite_image,(Quantum)
opacity,exception);
break;
}
(void) SetImageArtifact(msl_info->image[n],
"compose:args",value);
if (composite_image->alpha_trait == UndefinedPixelTrait)
(void) SetImageAlpha(composite_image,OpaqueAlpha,
exception);
composite_view=AcquireAuthenticCacheView(composite_image,exception);
for (y=0; y < (ssize_t) composite_image->rows ; y++)
{
q=GetCacheViewAuthenticPixels(composite_view,0,y,
(ssize_t) composite_image->columns,1,exception);
for (x=0; x < (ssize_t) composite_image->columns; x++)
{
if (GetPixelAlpha(composite_image,q) == OpaqueAlpha)
SetPixelAlpha(composite_image,
ClampToQuantum(opacity),q);
q+=GetPixelChannels(composite_image);
}
if (SyncCacheViewAuthenticPixels(composite_view,exception) == MagickFalse)
break;
}
composite_view=DestroyCacheView(composite_view);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'R':
case 'r':
{
if (LocaleCompare(keyword,"rotate") == 0)
{
rotate_image=RotateImage(composite_image,
StringToDouble(value,(char **) NULL),exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'T':
case 't':
{
if (LocaleCompare(keyword,"tile") == 0)
{
MagickBooleanType
tile;
option=ParseCommandOption(MagickBooleanOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedBooleanType",
value);
tile=(MagickBooleanType) option;
(void) tile;
if (rotate_image != (Image *) NULL)
(void) SetImageArtifact(rotate_image,
"compose:outside-overlay","false");
else
(void) SetImageArtifact(composite_image,
"compose:outside-overlay","false");
image=msl_info->image[n];
height=composite_image->rows;
width=composite_image->columns;
for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) height)
for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) width)
{
if (rotate_image != (Image *) NULL)
(void) CompositeImage(image,rotate_image,compose,
MagickTrue,x,y,exception);
else
(void) CompositeImage(image,composite_image,
compose,MagickTrue,x,y,exception);
}
if (rotate_image != (Image *) NULL)
rotate_image=DestroyImage(rotate_image);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'X':
case 'x':
{
if (LocaleCompare(keyword,"x") == 0)
{
geometry.x=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'Y':
case 'y':
{
if (LocaleCompare(keyword,"y") == 0)
{
geometry.y=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
image=msl_info->image[n];
(void) FormatLocaleString(composite_geometry,MagickPathExtent,
"%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
(double) composite_image->rows,(double) geometry.x,(double)
geometry.y);
flags=ParseGravityGeometry(image,composite_geometry,&geometry,
exception);
channel_mask=SetImageChannelMask(image,channel);
if (rotate_image == (Image *) NULL)
CompositeImage(image,composite_image,compose,MagickTrue,geometry.x,
geometry.y,exception);
else
{
/*
Rotate image.
*/
geometry.x-=(ssize_t) (rotate_image->columns-
composite_image->columns)/2;
geometry.y-=(ssize_t) (rotate_image->rows-
composite_image->rows)/2;
CompositeImage(image,rotate_image,compose,MagickTrue,geometry.x,
geometry.y,exception);
rotate_image=DestroyImage(rotate_image);
}
(void) SetImageChannelMask(image,channel_mask);
composite_image=DestroyImage(composite_image);
break;
}
if (LocaleCompare((const char *) tag,"contrast") == 0)
{
MagickBooleanType
sharpen;
/*
Contrast image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
sharpen=MagickFalse;
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'S':
case 's':
{
if (LocaleCompare(keyword,"sharpen") == 0)
{
option=ParseCommandOption(MagickBooleanOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedBooleanType",
value);
sharpen=(MagickBooleanType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
(void) ContrastImage(msl_info->image[n],sharpen,
msl_info->exception);
break;
}
if (LocaleCompare((const char *) tag,"crop") == 0)
{
Image
*crop_image;
/*
Crop image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
SetGeometry(msl_info->image[n],&geometry);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParseGravityGeometry(msl_info->image[n],value,
&geometry,exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'H':
case 'h':
{
if (LocaleCompare(keyword,"height") == 0)
{
geometry.height=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'W':
case 'w':
{
if (LocaleCompare(keyword,"width") == 0)
{
geometry.width=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'X':
case 'x':
{
if (LocaleCompare(keyword,"x") == 0)
{
geometry.x=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'Y':
case 'y':
{
if (LocaleCompare(keyword,"y") == 0)
{
geometry.y=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
crop_image=CropImage(msl_info->image[n],&geometry,
msl_info->exception);
if (crop_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=crop_image;
break;
}
if (LocaleCompare((const char *) tag,"cycle-colormap") == 0)
{
ssize_t
display;
/*
Cycle-colormap image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
display=0;
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'D':
case 'd':
{
if (LocaleCompare(keyword,"display") == 0)
{
display=StringToLong(value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
(void) CycleColormapImage(msl_info->image[n],display,exception);
break;
}
ThrowMSLException(OptionError,"UnrecognizedElement",(const char *) tag);
}
case 'D':
case 'd':
{
if (LocaleCompare((const char *) tag,"despeckle") == 0)
{
Image
*despeckle_image;
/*
Despeckle image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
ThrowMSLException(OptionError,"UnrecognizedAttribute",keyword);
}
despeckle_image=DespeckleImage(msl_info->image[n],
msl_info->exception);
if (despeckle_image == (Image *) NULL)
break;
msl_info->image[n]=DestroyImage(msl_info->image[n]);
msl_info->image[n]=despeckle_image;
break;
}
if (LocaleCompare((const char *) tag,"display") == 0)
{
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
default:
{
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
}
}
(void) DisplayImages(msl_info->image_info[n],msl_info->image[n],
msl_info->exception);
break;
}
if (LocaleCompare((const char *) tag,"draw") == 0)
{
char
text[MagickPathExtent];
/*
Annotate image.
*/
if (msl_info->image[n] == (Image *) NULL)
{
ThrowMSLException(OptionError,"NoImagesDefined",
(const char *) tag);
break;
}
draw_info=CloneDrawInfo(msl_info->image_info[n],
msl_info->draw_info[n]);
angle=0.0;
current=draw_info->affine;
GetAffineMatrix(&affine);
if (attributes != (const xmlChar **) NULL)
for (i=0; (attributes[i] != (const xmlChar *) NULL); i++)
{
keyword=(const char *) attributes[i++];
attribute=InterpretImageProperties(msl_info->image_info[n],
msl_info->attributes[n],(const char *) attributes[i],
exception);
CloneString(&value,attribute);
attribute=DestroyString(attribute);
switch (*keyword)
{
case 'A':
case 'a':
{
if (LocaleCompare(keyword,"affine") == 0)
{
char
*p;
p=value;
draw_info->affine.sx=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.rx=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.ry=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.sy=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.tx=StringToDouble(p,&p);
if (*p ==',')
p++;
draw_info->affine.ty=StringToDouble(p,&p);
break;
}
if (LocaleCompare(keyword,"align") == 0)
{
option=ParseCommandOption(MagickAlignOptions,MagickFalse,
value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedAlignType",
value);
draw_info->align=(AlignType) option;
break;
}
if (LocaleCompare(keyword,"antialias") == 0)
{
option=ParseCommandOption(MagickBooleanOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedBooleanType",
value);
draw_info->stroke_antialias=(MagickBooleanType) option;
draw_info->text_antialias=(MagickBooleanType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'D':
case 'd':
{
if (LocaleCompare(keyword,"density") == 0)
{
CloneString(&draw_info->density,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'E':
case 'e':
{
if (LocaleCompare(keyword,"encoding") == 0)
{
CloneString(&draw_info->encoding,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'F':
case 'f':
{
if (LocaleCompare(keyword, "fill") == 0)
{
(void) QueryColorCompliance(value,AllCompliance,
&draw_info->fill,exception);
break;
}
if (LocaleCompare(keyword,"family") == 0)
{
CloneString(&draw_info->family,value);
break;
}
if (LocaleCompare(keyword,"font") == 0)
{
CloneString(&draw_info->font,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'G':
case 'g':
{
if (LocaleCompare(keyword,"geometry") == 0)
{
flags=ParsePageGeometry(msl_info->image[n],value,
&geometry,exception);
if ((flags & HeightValue) == 0)
geometry.height=geometry.width;
break;
}
if (LocaleCompare(keyword,"gravity") == 0)
{
option=ParseCommandOption(MagickGravityOptions,
MagickFalse,value);
if (option < 0)
ThrowMSLException(OptionError,"UnrecognizedGravityType",
value);
draw_info->gravity=(GravityType) option;
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'P':
case 'p':
{
if (LocaleCompare(keyword,"points") == 0)
{
if (LocaleCompare(draw_info->primitive,"path") == 0)
{
(void) ConcatenateString(&draw_info->primitive," '");
ConcatenateString(&draw_info->primitive,value);
(void) ConcatenateString(&draw_info->primitive,"'");
}
else
{
(void) ConcatenateString(&draw_info->primitive," ");
ConcatenateString(&draw_info->primitive,value);
}
break;
}
if (LocaleCompare(keyword,"pointsize") == 0)
{
draw_info->pointsize=StringToDouble(value,
(char **) NULL);
break;
}
if (LocaleCompare(keyword,"primitive") == 0)
{
CloneString(&draw_info->primitive,value);
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'R':
case 'r':
{
if (LocaleCompare(keyword,"rotate") == 0)
{
angle=StringToDouble(value,(char **) NULL);
affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
break;
}
ThrowMSLException(OptionError,"UnrecognizedAttribute",
keyword);
break;
}
case 'S':
case 's':
{
if (LocaleCompare(keyword,"scale") == 0)
{
flags=ParseGeometry(value,&geometry_info);
if ((flags & SigmaValue) == 0)
geometry_info.sigma=1.0;
affine.sx=geometry_info.rho;
affine.sy=geometry_info.sigma;
break;
}
if (LocaleCompare(keyword,"skewX") == 0)
{
angle=StringToDouble(value,(char **) NULL);
affine.ry=cos(DegreesToRadians(fmod(angle,360.0)));
break;
}
if (LocaleCompare(keyword,"skewY") == 0)
{
angle=StringToDouble(value,(char **) NULL