/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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 *) "" "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; /* 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 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,"",2) != 0) && (*q != '\0')) GetMagickToken(q,&q,token); continue; } if (LocaleNCompare(keyword,"