blob: 134b79d35311be947705d6cb653465637e17c414 [file] [log] [blame]
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% CCCC OOO DDDD EEEEE RRRR %
% C O O D D E R R %
% C O O D D EEE RRRR %
% C O O D D E R R %
% CCCC OOO DDDD EEEEE R R %
% %
% %
% MagickCore Image Coder Methods %
% %
% Software Design %
% John Cristy %
% May 2001 %
% %
% %
% Copyright 1999-2009 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 %
% %
% http://www.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 "magick/studio.h"
#include "magick/blob.h"
#include "magick/client.h"
#include "magick/coder.h"
#include "magick/configure.h"
#include "magick/draw.h"
#include "magick/exception.h"
#include "magick/exception-private.h"
#include "magick/hashmap.h"
#include "magick/log.h"
#include "magick/memory_.h"
#include "magick/option.h"
#include "magick/semaphore.h"
#include "magick/string_.h"
#include "magick/splay-tree.h"
#include "magick/token.h"
#include "magick/utility.h"
#include "magick/xml-tree.h"
/*
Define declarations.
*/
#define MagickCoderFilename "coder.xml"
/*
Declare coder map.
*/
static const char
*CoderMap = (const char *)
"<?xml version=\"1.0\"?>"
"<codermap>"
" <coder magick=\"3FR\" name=\"DNG\" />"
" <coder magick=\"8BIM\" name=\"META\" />"
" <coder magick=\"8BIMTEXT\" name=\"META\" />"
" <coder magick=\"8BIMWTEXT\" name=\"META\" />"
" <coder magick=\"A\" name=\"RAW\" />"
" <coder magick=\"AI\" name=\"PDF\" />"
" <coder magick=\"AFM\" name=\"TTF\" />"
" <coder magick=\"APP1JPEG\" name=\"META\" />"
" <coder magick=\"APP1\" name=\"META\" />"
" <coder magick=\"ARW\" name=\"DNG\" />"
" <coder magick=\"BIE\" name=\"JBIG\" />"
" <coder magick=\"BMP2\" name=\"BMP\" />"
" <coder magick=\"BMP3\" name=\"BMP\" />"
" <coder magick=\"B\" name=\"GRAY\" />"
" <coder magick=\"BRF\" name=\"BRAILLE\" />"
" <coder magick=\"CMYKA\" name=\"CMYK\" />"
" <coder magick=\"C\" name=\"GRAY\" />"
" <coder magick=\"CAL\" name=\"CALS\" />"
" <coder magick=\"CR2\" name=\"DNG\" />"
" <coder magick=\"CRW\" name=\"DNG\" />"
" <coder magick=\"CUR\" name=\"ICON\" />"
" <coder magick=\"DCR\" name=\"DNG\" />"
" <coder magick=\"DCX\" name=\"PCX\" />"
" <coder magick=\"DFONT\" name=\"TTF\" />"
" <coder magick=\"EMF\" name=\"EMF\" />"
" <coder magick=\"EPDF\" name=\"PDF\" />"
" <coder magick=\"EPI\" name=\"PS\" />"
" <coder magick=\"EPS2\" name=\"PS2\" />"
" <coder magick=\"EPS3\" name=\"PS3\" />"
" <coder magick=\"EPSF\" name=\"PS\" />"
" <coder magick=\"EPSI\" name=\"PS\" />"
" <coder magick=\"EPS\" name=\"PS\" />"
" <coder magick=\"EPT2\" name=\"EPT\" />"
" <coder magick=\"EPT3\" name=\"EPT\" />"
" <coder magick=\"ERF\" name=\"DNG\" />"
" <coder magick=\"EXIF\" name=\"META\" />"
" <coder magick=\"FILE\" name=\"URL\" />"
" <coder magick=\"FRACTAL\" name=\"PLASMA\" />"
" <coder magick=\"FTP\" name=\"URL\" />"
" <coder magick=\"FTS\" name=\"FITS\" />"
" <coder magick=\"G3\" name=\"FAX\" />"
" <coder magick=\"GIF87\" name=\"GIF\" />"
" <coder magick=\"G\" name=\"GRAY\" />"
" <coder magick=\"GRANITE\" name=\"MAGICK\" />"
" <coder magick=\"GROUP4\" name=\"TIFF\" />"
" <coder magick=\"H\" name=\"MAGICK\" />"
" <coder magick=\"HTM\" name=\"HTML\" />"
" <coder magick=\"HTTP\" name=\"URL\" />"
" <coder magick=\"ICB\" name=\"TGA\" />"
" <coder magick=\"ICC\" name=\"META\" />"
" <coder magick=\"ICM\" name=\"META\" />"
" <coder magick=\"ICO\" name=\"ICON\" />"
" <coder magick=\"IMPLICIT\" name=\"***\" />"
" <coder magick=\"IPTC\" name=\"META\" />"
" <coder magick=\"IPTCTEXT\" name=\"META\" />"
" <coder magick=\"IPTCWTEXT\" name=\"META\" />"
" <coder magick=\"ISOBRL\" name=\"BRAILLE\" />"
" <coder magick=\"JBG\" name=\"JBIG\" />"
" <coder magick=\"JNG\" name=\"PNG\" />"
" <coder magick=\"JPC\" name=\"JP2\" />"
" <coder magick=\"JPG\" name=\"JPEG\" />"
" <coder magick=\"JPX\" name=\"JP2\" />"
" <coder magick=\"K\" name=\"GRAY\" />"
" <coder magick=\"K25\" name=\"DNG\" />"
" <coder magick=\"KDC\" name=\"DNG\" />"
" <coder magick=\"LOGO\" name=\"MAGICK\" />"
" <coder magick=\"M2V\" name=\"MPEG\" />"
" <coder magick=\"M4V\" name=\"MPEG\" />"
" <coder magick=\"M\" name=\"GRAY\" />"
" <coder magick=\"MNG\" name=\"PNG\" />"
" <coder magick=\"MOV\" name=\"MPEG\" />"
" <coder magick=\"MPG\" name=\"MPEG\" />"
" <coder magick=\"MP4\" name=\"MPEG\" />"
" <coder magick=\"MPRI\" name=\"MPR\" />"
" <coder magick=\"MRW\" name=\"DNG\" />"
" <coder magick=\"MSVG\" name=\"SVG\" />"
" <coder magick=\"NEF\" name=\"DNG\" />"
" <coder magick=\"NETSCAPE\" name=\"MAGICK\" />"
" <coder magick=\"O\" name=\"GRAY\" />"
" <coder magick=\"ORF\" name=\"DNG\" />"
" <coder magick=\"OTF\" name=\"TTF\" />"
" <coder magick=\"P7\" name=\"PNM\" />"
" <coder magick=\"PAL\" name=\"UYVY\" />"
" <coder magick=\"PAM\" name=\"PNM\" />"
" <coder magick=\"PBM\" name=\"PNM\" />"
" <coder magick=\"PCDS\" name=\"PCD\" />"
" <coder magick=\"PCT\" name=\"PICT\" />"
" <coder magick=\"PDFA\" name=\"PDF\" />"
" <coder magick=\"PEF\" name=\"DNG\" />"
" <coder magick=\"PFA\" name=\"TTF\" />"
" <coder magick=\"PFB\" name=\"TTF\" />"
" <coder magick=\"PFM\" name=\"PNM\" />"
" <coder magick=\"PGM\" name=\"PNM\" />"
" <coder magick=\"PGX\" name=\"JP2\" />"
" <coder magick=\"PICON\" name=\"XPM\" />"
" <coder magick=\"PJPEG\" name=\"JPEG\" />"
" <coder magick=\"PM\" name=\"XPM\" />"
" <coder magick=\"PNG24\" name=\"PNG\" />"
" <coder magick=\"PNG32\" name=\"PNG\" />"
" <coder magick=\"PNG8\" name=\"PNG\" />"
" <coder magick=\"PPM\" name=\"PNM\" />"
" <coder magick=\"PTIF\" name=\"TIFF\" />"
" <coder magick=\"RADIAL-GRADIENT\" name=\"GRADIENT\" />"
" <coder magick=\"RAF\" name=\"DNG\" />"
" <coder magick=\"RAS\" name=\"SUN\" />"
" <coder magick=\"RGBA\" name=\"RGB\" />"
" <coder magick=\"RGBO\" name=\"RGB\" />"
" <coder magick=\"R\" name=\"GRAY\" />"
" <coder magick=\"ROSE\" name=\"MAGICK\" />"
" <coder magick=\"SHTML\" name=\"HTML\" />"
" <coder magick=\"SR2\" name=\"DNG\" />"
" <coder magick=\"SRF\" name=\"DNG\" />"
" <coder magick=\"SVGZ\" name=\"SVG\" />"
" <coder magick=\"TEXT\" name=\"TXT\" />"
" <coder magick=\"TIFF64\" name=\"TIFF\" />"
" <coder magick=\"TIF\" name=\"TIFF\" />"
" <coder magick=\"TTC\" name=\"TTF\" />"
" <coder magick=\"UBRL\" name=\"BRAILLE\" />"
" <coder magick=\"VDA\" name=\"TGA\" />"
" <coder magick=\"VST\" name=\"TGA\" />"
" <coder magick=\"WMFWIN32\" name=\"EMF\" />"
" <coder magick=\"WMV\" name=\"MPEG\" />"
" <coder magick=\"X3F\" name=\"DNG\" />"
" <coder magick=\"XTRNARRAY\" name=\"XTRN\" />"
" <coder magick=\"XTRNBLOB\" name=\"XTRN\" />"
" <coder magick=\"XTRNBSTR\" name=\"XTRN\" />"
" <coder magick=\"XTRNFILE\" name=\"XTRN\" />"
" <coder magick=\"XTRNIMAGE\" name=\"XTRN\" />"
" <coder magick=\"XTRNSTREAM\" name=\"XTRN\" />"
" <coder magick=\"XV\" name=\"VIFF\" />"
" <coder magick=\"Y\" name=\"GRAY\" />"
" <coder magick=\"YCbCrA\" name=\"YCbCr\" />"
"</codermap>";
/*
Static declarations.
*/
static SemaphoreInfo
*coder_semaphore = (SemaphoreInfo *) NULL;
static SplayTreeInfo
*coder_list = (SplayTreeInfo *) NULL;
static volatile MagickBooleanType
instantiate_coder = MagickFalse;
/*
Forward declarations.
*/
static MagickBooleanType
InitializeCoderList(ExceptionInfo *),
LoadCoderLists(const char *,ExceptionInfo *);
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ D e s t r o y C o d e r L i s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DestroyCoderList() deallocates memory associated with the font list.
%
% The format of the DestroyCoderList method is:
%
% DestroyCoderList(void)
%
*/
MagickExport void DestroyCoderList(void)
{
AcquireSemaphoreInfo(&coder_semaphore);
if (coder_list != (SplayTreeInfo *) NULL)
coder_list=DestroySplayTree(coder_list);
instantiate_coder=MagickFalse;
RelinquishSemaphoreInfo(coder_semaphore);
DestroySemaphoreInfo(&coder_semaphore);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ G e t C o d e r I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetCoderInfo searches the coder list for the specified name and if found
% returns attributes for that coder.
%
% The format of the GetCoderInfo method is:
%
% const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o name: the coder name.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport const CoderInfo *GetCoderInfo(const char *name,
ExceptionInfo *exception)
{
assert(exception != (ExceptionInfo *) NULL);
if ((coder_list == (SplayTreeInfo *) NULL) ||
(instantiate_coder == MagickFalse))
if (InitializeCoderList(exception) == MagickFalse)
return((const CoderInfo *) NULL);
if ((coder_list == (SplayTreeInfo *) NULL) ||
(GetNumberOfNodesInSplayTree(coder_list) == 0))
return((const CoderInfo *) NULL);
if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
{
ResetSplayTreeIterator(coder_list);
return((const CoderInfo *) GetNextValueInSplayTree(coder_list));
}
return((const CoderInfo *) GetValueFromSplayTree(coder_list,name));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t C o d e r I n f o L i s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetCoderInfoList() returns any coder_map that match the specified pattern.
% The format of the GetCoderInfoList function is:
%
% const CoderInfo **GetCoderInfoList(const char *pattern,
% unsigned long *number_coders,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o pattern: Specifies a pointer to a text string containing a pattern.
%
% o number_coders: This integer returns the number of coders in the list.
%
% o exception: return any errors or warnings in this structure.
%
*/
static int CoderInfoCompare(const void *x,const void *y)
{
const CoderInfo
**p,
**q;
p=(const CoderInfo **) x,
q=(const CoderInfo **) y;
if (LocaleCompare((*p)->path,(*q)->path) == 0)
return(LocaleCompare((*p)->name,(*q)->name));
return(LocaleCompare((*p)->path,(*q)->path));
}
MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
unsigned long *number_coders,ExceptionInfo *exception)
{
const CoderInfo
**coder_map;
register const CoderInfo
*p;
register long
i;
/*
Allocate coder list.
*/
assert(pattern != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
assert(number_coders != (unsigned long *) NULL);
*number_coders=0;
p=GetCoderInfo("*",exception);
if (p == (const CoderInfo *) NULL)
return((const CoderInfo **) NULL);
coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
if (coder_map == (const CoderInfo **) NULL)
return((const CoderInfo **) NULL);
/*
Generate coder list.
*/
AcquireSemaphoreInfo(&coder_semaphore);
ResetSplayTreeIterator(coder_list);
p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
for (i=0; p != (const CoderInfo *) NULL; )
{
if ((p->stealth == MagickFalse) &&
(GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
coder_map[i++]=p;
p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
}
RelinquishSemaphoreInfo(coder_semaphore);
qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
coder_map[i]=(CoderInfo *) NULL;
*number_coders=(unsigned long) i;
return(coder_map);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% G e t C o d e r L i s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% GetCoderList() returns any coder_map that match the specified pattern.
%
% The format of the GetCoderList function is:
%
% char **GetCoderList(const char *pattern,unsigned long *number_coders,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o pattern: Specifies a pointer to a text string containing a pattern.
%
% o number_coders: This integer returns the number of coders in the list.
%
% o exception: return any errors or warnings in this structure.
%
*/
static int CoderCompare(const void *x,const void *y)
{
register const char
**p,
**q;
p=(const char **) x;
q=(const char **) y;
return(LocaleCompare(*p,*q));
}
MagickExport char **GetCoderList(const char *pattern,
unsigned long *number_coders,ExceptionInfo *exception)
{
char
**coder_map;
register const CoderInfo
*p;
register long
i;
/*
Allocate coder list.
*/
assert(pattern != (char *) NULL);
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
assert(number_coders != (unsigned long *) NULL);
*number_coders=0;
p=GetCoderInfo("*",exception);
if (p == (const CoderInfo *) NULL)
return((char **) NULL);
coder_map=(char **) AcquireQuantumMemory((size_t)
GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
if (coder_map == (char **) NULL)
return((char **) NULL);
/*
Generate coder list.
*/
AcquireSemaphoreInfo(&coder_semaphore);
ResetSplayTreeIterator(coder_list);
p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
for (i=0; p != (const CoderInfo *) NULL; )
{
if ((p->stealth == MagickFalse) &&
(GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
coder_map[i++]=ConstantString(p->name);
p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
}
RelinquishSemaphoreInfo(coder_semaphore);
qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
coder_map[i]=(char *) NULL;
*number_coders=(unsigned long) i;
return(coder_map);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ I n i t i a l i z e C o d e r L i s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% InitializeCoderList() initializes the coder list.
%
% The format of the InitializeCoderList method is:
%
% MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
%
% A description of each parameter follows.
%
% o exception: return any errors or warnings in this structure.
%
*/
static MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
{
if ((coder_list == (SplayTreeInfo *) NULL) &&
(instantiate_coder == MagickFalse))
{
AcquireSemaphoreInfo(&coder_semaphore);
if ((coder_list == (SplayTreeInfo *) NULL) &&
(instantiate_coder == MagickFalse))
{
(void) LoadCoderLists(MagickCoderFilename,exception);
instantiate_coder=MagickTrue;
}
RelinquishSemaphoreInfo(coder_semaphore);
}
return(coder_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% L i s t C o d e r I n f o %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ListCoderInfo() lists the coder info to a file.
%
% The format of the ListCoderInfo coder is:
%
% MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
%
% A description of each parameter follows.
%
% o file: An pointer to a FILE.
%
% o exception: return any errors or warnings in this structure.
%
*/
MagickExport MagickBooleanType ListCoderInfo(FILE *file,
ExceptionInfo *exception)
{
const char
*path;
const CoderInfo
**coder_info;
long
j;
register long
i;
unsigned long
number_coders;
if (file == (const FILE *) NULL)
file=stdout;
coder_info=GetCoderInfoList("*",&number_coders,exception);
if (coder_info == (const CoderInfo **) NULL)
return(MagickFalse);
path=(const char *) NULL;
for (i=0; i < (long) number_coders; i++)
{
if (coder_info[i]->stealth != MagickFalse)
continue;
if ((path == (const char *) NULL) ||
(LocaleCompare(path,coder_info[i]->path) != 0))
{
if (coder_info[i]->path != (char *) NULL)
(void) fprintf(file,"\nPath: %s\n\n",coder_info[i]->path);
(void) fprintf(file,"Magick Coder\n");
(void) fprintf(file,"-------------------------------------------------"
"------------------------------\n");
}
path=coder_info[i]->path;
(void) fprintf(file,"%s",coder_info[i]->magick);
for (j=(long) strlen(coder_info[i]->magick); j <= 11; j++)
(void) fprintf(file," ");
if (coder_info[i]->name != (char *) NULL)
(void) fprintf(file,"%s",coder_info[i]->name);
(void) fprintf(file,"\n");
}
coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
(void) fflush(file);
return(MagickTrue);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ L o a d C o d e r L i s t %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% LoadCoderList() loads the coder configuration file which provides a
% mapping between coder attributes and a coder name.
%
% The format of the LoadCoderList coder is:
%
% MagickBooleanType LoadCoderList(const char *xml,const char *filename,
% const unsigned long depth,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o xml: The coder list in XML format.
%
% o filename: The coder list filename.
%
% o depth: depth of <include /> statements.
%
% o exception: return any errors or warnings in this structure.
%
*/
static void *DestroyCoderNode(void *coder_info)
{
register CoderInfo
*p;
p=(CoderInfo *) coder_info;
if (p->path != (char *) NULL)
p->path=DestroyString(p->path);
if (p->name != (char *) NULL)
p->name=DestroyString(p->name);
if (p->magick != (char *) NULL)
p->magick=DestroyString(p->magick);
return(RelinquishMagickMemory(p));
}
static MagickBooleanType LoadCoderList(const char *xml,const char *filename,
const unsigned long depth,ExceptionInfo *exception)
{
char
keyword[MaxTextExtent],
*token;
const char
*q;
CoderInfo
*coder_info;
MagickBooleanType
status;
/*
Load the coder map file.
*/
(void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
"Loading coder configuration file \"%s\" ...",filename);
if (xml == (const char *) NULL)
return(MagickFalse);
if (coder_list == (SplayTreeInfo *) NULL)
{
coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
DestroyCoderNode);
if (coder_list == (SplayTreeInfo *) NULL)
{
ThrowFileException(exception,ResourceLimitError,
"MemoryAllocationFailed",filename);
return(MagickFalse);
}
}
status=MagickTrue;
coder_info=(CoderInfo *) NULL;
token=AcquireString(xml);
for (q=(char *) xml; *q != '\0'; )
{
/*
Interpret XML.
*/
GetMagickToken(q,&q,token);
if (*token == '\0')
break;
(void) CopyMagickString(keyword,token,MaxTextExtent);
if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
{
/*
Doctype element.
*/
while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
GetMagickToken(q,&q,token);
continue;
}
if (LocaleNCompare(keyword,"<!--",4) == 0)
{
/*
Comment element.
*/
while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
GetMagickToken(q,&q,token);
continue;
}
if (LocaleCompare(keyword,"<include") == 0)
{
/*
Include element.
*/
while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
{
(void) CopyMagickString(keyword,token,MaxTextExtent);
GetMagickToken(q,&q,token);
if (*token != '=')
continue;
GetMagickToken(q,&q,token);
if (LocaleCompare(keyword,"file") == 0)
{
if (depth > 200)
(void) ThrowMagickException(exception,GetMagickModule(),
ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
else
{
char
path[MaxTextExtent],
*xml;
GetPathComponent(filename,HeadPath,path);
if (*path != '\0')
(void) ConcatenateMagickString(path,DirectorySeparator,
MaxTextExtent);
if (*token == *DirectorySeparator)
(void) CopyMagickString(path,token,MaxTextExtent);
else
(void) ConcatenateMagickString(path,token,MaxTextExtent);
xml=FileToString(path,~0,exception);
if (xml != (char *) NULL)
{
status=LoadCoderList(xml,path,depth+1,exception);
xml=(char *) RelinquishMagickMemory(xml);
}
}
}
}
continue;
}
if (LocaleCompare(keyword,"<coder") == 0)
{
/*
Coder element.
*/
coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
if (coder_info == (CoderInfo *) NULL)
ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
(void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
coder_info->path=ConstantString(filename);
coder_info->signature=MagickSignature;
continue;
}
if (coder_info == (CoderInfo *) NULL)
continue;
if (LocaleCompare(keyword,"/>") == 0)
{
status=AddValueToSplayTree(coder_list,ConstantString(
coder_info->magick),coder_info);
if (status == MagickFalse)
(void) ThrowMagickException(exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","`%s'",
coder_info->magick);
coder_info=(CoderInfo *) NULL;
}
GetMagickToken(q,(const char **) NULL,token);
if (*token != '=')
continue;
GetMagickToken(q,&q,token);
GetMagickToken(q,&q,token);
switch (*keyword)
{
case 'M':
case 'm':
{
if (LocaleCompare((char *) keyword,"magick") == 0)
{
coder_info->magick=ConstantString(token);
break;
}
break;
}
case 'N':
case 'n':
{
if (LocaleCompare((char *) keyword,"name") == 0)
{
coder_info->name=ConstantString(token);
break;
}
break;
}
case 'S':
case 's':
{
if (LocaleCompare((char *) keyword,"stealth") == 0)
{
coder_info->stealth=IsMagickTrue(token);
break;
}
break;
}
default:
break;
}
}
token=(char *) RelinquishMagickMemory(token);
return(status);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% L o a d C o d e r L i s t s %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% LoadCoderLists() loads one or more coder configuration file which
% provides a mapping between coder attributes and a coder name.
%
% The format of the LoadCoderLists coder is:
%
% MagickBooleanType LoadCoderLists(const char *filename,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o filename: the font file name.
%
% o exception: return any errors or warnings in this structure.
%
*/
static MagickBooleanType LoadCoderLists(const char *filename,
ExceptionInfo *exception)
{
#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
return(LoadCoderList(CoderMap,"built-in",0,exception));
#else
const StringInfo
*option;
LinkedListInfo
*options;
MagickStatusType
status;
status=MagickFalse;
options=GetConfigureOptions(filename,exception);
option=(const StringInfo *) GetNextValueInLinkedList(options);
while (option != (const StringInfo *) NULL)
{
status|=LoadCoderList((const char *) GetStringInfoDatum(option),
GetStringInfoPath(option),0,exception);
option=(const StringInfo *) GetNextValueInLinkedList(options);
}
options=DestroyConfigureOptions(options);
if ((coder_list == (SplayTreeInfo *) NULL) ||
(GetNumberOfNodesInSplayTree(coder_list) == 0))
status|=LoadCoderList(CoderMap,"built-in",0,exception);
return(status != 0 ? MagickTrue : MagickFalse);
#endif
}