]> granicus.if.org Git - imagemagick/blob - magick/coder.c
(no commit message)
[imagemagick] / magick / coder.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                   CCCC   OOO   DDDD    EEEEE  RRRR                          %
7 %                  C      O   O  D   D   E      R   R                         %
8 %                  C      O   O  D   D   EEE    RRRR                          %
9 %                  C      O   O  D   D   E      R R                           %
10 %                   CCCC   OOO   DDDD    EEEEE  R  R                          %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Image Coder Methods                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 May 2001                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/client.h"
45 #include "magick/coder.h"
46 #include "magick/configure.h"
47 #include "magick/draw.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/hashmap.h"
51 #include "magick/log.h"
52 #include "magick/memory_.h"
53 #include "magick/option.h"
54 #include "magick/semaphore.h"
55 #include "magick/string_.h"
56 #include "magick/splay-tree.h"
57 #include "magick/token.h"
58 #include "magick/utility.h"
59 #include "magick/xml-tree.h"
60 \f
61 /*
62   Define declarations.
63 */
64 #define MagickCoderFilename  "coder.xml"
65 \f
66 /*
67   Static declarations.
68 */
69 typedef struct _CoderMapInfo
70 {
71   const char
72     *magick,
73     *name;
74 } CoderMapInfo;
75
76 static const CoderMapInfo
77   CoderMap[] =
78   {
79     { "3FR", "DNG" },
80     { "8BIM", "META" },
81     { "8BIMTEXT", "META" },
82     { "8BIMWTEXT", "META" },
83     { "AFM", "TTF" },
84     { "A", "RAW" },
85     { "AI", "PDF" },
86     { "APP1JPEG", "META" },
87     { "APP1", "META" },
88     { "ARW", "DNG" },
89     { "BIE", "JBIG" },
90     { "BMP2", "BMP" },
91     { "BMP3", "BMP" },
92     { "B", "RAW" },
93     { "BRF", "BRAILLE" },
94     { "BGR", "RGB" },
95     { "BRG", "RGB" },
96     { "CMYKA", "CMYK" },
97     { "C", "RAW" },
98     { "CAL", "CALS" },
99     { "CR2", "DNG" },
100     { "CRW", "DNG" },
101     { "CUR", "ICON" },
102     { "DCR", "DNG" },
103     { "DCX", "PCX" },
104     { "DFONT", "TTF" },
105     { "EPDF", "PDF" },
106     { "EPI", "PS" },
107     { "EPS2", "PS2" },
108     { "EPS3", "PS3" },
109     { "EPSF", "PS" },
110     { "EPSI", "PS" },
111     { "EPS", "PS" },
112     { "EPT2", "EPT" },
113     { "EPT3", "EPT" },
114     { "ERF", "DNG" },
115     { "EXIF", "META" },
116     { "FILE", "URL" },
117     { "FRACTAL", "PLASMA" },
118     { "FTP", "URL" },
119     { "FTS", "FITS" },
120     { "G3", "FAX" },
121     { "GIF87", "GIF" },
122     { "G", "RAW" },
123     { "GBR", "RGB" },
124     { "GRB", "RGB" },
125     { "GRANITE", "MAGICK" },
126     { "GROUP4", "TIFF" },
127     { "K25", "DNG" },
128     { "KDC", "DNG" },
129     { "H", "MAGICK" },
130     { "HTM", "HTML" },
131     { "HTTP", "URL" },
132     { "ICB", "TGA" },
133     { "ICC", "META" },
134     { "ICM", "META" },
135     { "ICO", "ICON" },
136     { "IMPLICIT", "***" },
137     { "IPTC", "META" },
138     { "IPTCTEXT", "META" },
139     { "IPTCWTEXT", "META" },
140     { "ISOBRL", "BRAILLE" },
141     { "JBG", "JBIG" },
142     { "JNG", "PNG" },
143     { "JPC", "JP2" },
144     { "JPG", "JPEG" },
145     { "JPX", "JP2" },
146     { "K", "RAW" },
147     { "LOGO", "MAGICK" },
148     { "M2V", "MPEG" },
149     { "M4V", "MPEG" },
150     { "M", "RAW" },
151     { "MNG", "PNG" },
152     { "MOV", "PNG" },
153     { "MP4", "MPEG" },
154     { "MPG", "MPEG" },
155     { "MPRI", "MPR" },
156     { "MRW", "DNG" },
157     { "MSVG", "SVG" },
158     { "NEF", "DNG" },
159     { "NETSCAPE", "MAGICK" },
160     { "O", "RAW" },
161     { "ORF", "DNG" },
162     { "OTF", "TTF" },
163     { "P7", "PNM" },
164     { "PAL", "UYVY" },
165     { "PAM", "PNM" },
166     { "PBM", "PNM" },
167     { "PCDS", "PCD" },
168     { "PDFA", "PDF" },
169     { "PEF", "DNG" },
170     { "PEF", "DNG" },
171     { "PFA", "TTF" },
172     { "PFB", "TTF" },
173     { "PFM", "PNM" },
174     { "PGM", "PNM" },
175     { "PGX", "JP2" },
176     { "PICON", "XPM" },
177     { "PJPEG", "JPEG" },
178     { "PM", "XPM" },
179     { "PNG24", "PNG" },
180     { "PNG32", "PNG" },
181     { "PNG8", "PNG" },
182     { "PPM", "PNM" },
183     { "PTIF", "TIFF" },
184     { "RADIAL-GRADIENT", "GRADIENT" },
185     { "RAF", "DNG" },
186     { "RAS", "SUN" },
187     { "RBG", "RGB" },
188     { "RGBA", "RGB" },
189     { "RGBO", "RGB" },
190     { "R", "RAW" },
191     { "ROSE", "MAGICK" },
192     { "SHTML", "HTML" },
193     { "SR2", "DNG" },
194     { "SRF", "DNG" },
195     { "SVGZ", "SVG" },
196     { "TEXT", "TXT" },
197     { "TIFF64", "TIFF" },
198     { "TIF", "TIFF" },
199     { "TTC", "TTF" },
200     { "UBRL", "BRAILLE" },
201     { "VDA", "TGA" },
202     { "VST", "TGA" },
203     { "WMV", "MPEG" },
204     { "WMFWIN32", "EMF" },
205     { "WMZ", "WMF" },
206     { "X3f", "DNG" },
207     { "XMP", "META" },
208     { "XTRNARRAY", "XTRN" },
209     { "XTRNBLOB", "XTRN" },
210     { "XTRNBSTR", "XTRN" },
211     { "XTRNFILE", "XTRN" },
212     { "XTRNIMAGE", "XTRN" },
213     { "XTRNSTREAM", "XTRN" },
214     { "XV", "VIFF" },
215     { "Y", "RAW" },
216     { "YCbCrA", "YCbCr" },
217     { (const char *) NULL, (const char *) NULL }
218  };
219
220 static SemaphoreInfo
221   *coder_semaphore = (SemaphoreInfo *) NULL;
222
223 static SplayTreeInfo
224   *coder_list = (SplayTreeInfo *) NULL;
225
226 static volatile MagickBooleanType
227   instantiate_coder = MagickFalse;
228 \f
229 /*
230   Forward declarations.
231 */
232 static MagickBooleanType
233   InitializeCoderList(ExceptionInfo *),
234   LoadCoderLists(const char *,ExceptionInfo *);
235 \f
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 %                                                                             %
239 %                                                                             %
240 %                                                                             %
241 +   D e s t r o y C o d e r C o m p o n e n t                                 %
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 %  DestroyCoderComponent() destroys the coder component.
248 %
249 %  The format of the DestroyCoderComponent method is:
250 %
251 %      DestroyCoderComponent(void)
252 %
253 */
254 MagickExport void DestroyCoderComponent(void)
255 {
256   AcquireSemaphoreInfo(&coder_semaphore);
257   if (coder_list != (SplayTreeInfo *) NULL)
258     coder_list=DestroySplayTree(coder_list);
259   instantiate_coder=MagickFalse;
260   RelinquishSemaphoreInfo(coder_semaphore);
261   DestroySemaphoreInfo(&coder_semaphore);
262 }
263 \f
264 /*
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266 %                                                                             %
267 %                                                                             %
268 %                                                                             %
269 +   G e t C o d e r I n f o                                                   %
270 %                                                                             %
271 %                                                                             %
272 %                                                                             %
273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274 %
275 %  GetCoderInfo searches the coder list for the specified name and if found
276 %  returns attributes for that coder.
277 %
278 %  The format of the GetCoderInfo method is:
279 %
280 %      const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
281 %
282 %  A description of each parameter follows:
283 %
284 %    o name: the coder name.
285 %
286 %    o exception: return any errors or warnings in this structure.
287 %
288 */
289 MagickExport const CoderInfo *GetCoderInfo(const char *name,
290   ExceptionInfo *exception)
291 {
292   assert(exception != (ExceptionInfo *) NULL);
293   if ((coder_list == (SplayTreeInfo *) NULL) ||
294       (instantiate_coder == MagickFalse))
295     if (InitializeCoderList(exception) == MagickFalse)
296       return((const CoderInfo *) NULL);
297   if ((coder_list == (SplayTreeInfo *) NULL) ||
298       (GetNumberOfNodesInSplayTree(coder_list) == 0))
299     return((const CoderInfo *) NULL);
300   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
301     {
302       ResetSplayTreeIterator(coder_list);
303       return((const CoderInfo *) GetNextValueInSplayTree(coder_list));
304     }
305   return((const CoderInfo *) GetValueFromSplayTree(coder_list,name));
306 }
307 \f
308 /*
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310 %                                                                             %
311 %                                                                             %
312 %                                                                             %
313 %   G e t C o d e r I n f o L i s t                                           %
314 %                                                                             %
315 %                                                                             %
316 %                                                                             %
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 %
319 %  GetCoderInfoList() returns any coder_map that match the specified pattern.
320 %  The format of the GetCoderInfoList function is:
321 %
322 %      const CoderInfo **GetCoderInfoList(const char *pattern,
323 %        unsigned long *number_coders,ExceptionInfo *exception)
324 %
325 %  A description of each parameter follows:
326 %
327 %    o pattern: Specifies a pointer to a text string containing a pattern.
328 %
329 %    o number_coders:  This integer returns the number of coders in the list.
330 %
331 %    o exception: return any errors or warnings in this structure.
332 %
333 */
334
335 static int CoderInfoCompare(const void *x,const void *y)
336 {
337   const CoderInfo
338     **p,
339     **q;
340
341   p=(const CoderInfo **) x,
342   q=(const CoderInfo **) y;
343   if (LocaleCompare((*p)->path,(*q)->path) == 0)
344     return(LocaleCompare((*p)->name,(*q)->name));
345   return(LocaleCompare((*p)->path,(*q)->path));
346 }
347
348 MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
349   unsigned long *number_coders,ExceptionInfo *exception)
350 {
351   const CoderInfo
352     **coder_map;
353
354   register const CoderInfo
355     *p;
356
357   register long
358     i;
359
360   /*
361     Allocate coder list.
362   */
363   assert(pattern != (char *) NULL);
364   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
365   assert(number_coders != (unsigned long *) NULL);
366   *number_coders=0;
367   p=GetCoderInfo("*",exception);
368   if (p == (const CoderInfo *) NULL)
369     return((const CoderInfo **) NULL);
370   coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
371     GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
372   if (coder_map == (const CoderInfo **) NULL)
373     return((const CoderInfo **) NULL);
374   /*
375     Generate coder list.
376   */
377   AcquireSemaphoreInfo(&coder_semaphore);
378   ResetSplayTreeIterator(coder_list);
379   p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
380   for (i=0; p != (const CoderInfo *) NULL; )
381   {
382     if ((p->stealth == MagickFalse) &&
383         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
384       coder_map[i++]=p;
385     p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
386   }
387   RelinquishSemaphoreInfo(coder_semaphore);
388   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
389   coder_map[i]=(CoderInfo *) NULL;
390   *number_coders=(unsigned long) i;
391   return(coder_map);
392 }
393 \f
394 /*
395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396 %                                                                             %
397 %                                                                             %
398 %                                                                             %
399 %   G e t C o d e r L i s t                                                   %
400 %                                                                             %
401 %                                                                             %
402 %                                                                             %
403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404 %
405 %  GetCoderList() returns any coder_map that match the specified pattern.
406 %
407 %  The format of the GetCoderList function is:
408 %
409 %      char **GetCoderList(const char *pattern,unsigned long *number_coders,
410 %        ExceptionInfo *exception)
411 %
412 %  A description of each parameter follows:
413 %
414 %    o pattern: Specifies a pointer to a text string containing a pattern.
415 %
416 %    o number_coders:  This integer returns the number of coders in the list.
417 %
418 %    o exception: return any errors or warnings in this structure.
419 %
420 */
421
422 static int CoderCompare(const void *x,const void *y)
423 {
424   register const char
425     **p,
426     **q;
427
428   p=(const char **) x;
429   q=(const char **) y;
430   return(LocaleCompare(*p,*q));
431 }
432
433 MagickExport char **GetCoderList(const char *pattern,
434   unsigned long *number_coders,ExceptionInfo *exception)
435 {
436   char
437     **coder_map;
438
439   register const CoderInfo
440     *p;
441
442   register long
443     i;
444
445   /*
446     Allocate coder list.
447   */
448   assert(pattern != (char *) NULL);
449   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
450   assert(number_coders != (unsigned long *) NULL);
451   *number_coders=0;
452   p=GetCoderInfo("*",exception);
453   if (p == (const CoderInfo *) NULL)
454     return((char **) NULL);
455   coder_map=(char **) AcquireQuantumMemory((size_t)
456     GetNumberOfNodesInSplayTree(coder_list)+1UL,sizeof(*coder_map));
457   if (coder_map == (char **) NULL)
458     return((char **) NULL);
459   /*
460     Generate coder list.
461   */
462   AcquireSemaphoreInfo(&coder_semaphore);
463   ResetSplayTreeIterator(coder_list);
464   p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
465   for (i=0; p != (const CoderInfo *) NULL; )
466   {
467     if ((p->stealth == MagickFalse) &&
468         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
469       coder_map[i++]=ConstantString(p->name);
470     p=(const CoderInfo *) GetNextValueInSplayTree(coder_list);
471   }
472   RelinquishSemaphoreInfo(coder_semaphore);
473   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
474   coder_map[i]=(char *) NULL;
475   *number_coders=(unsigned long) i;
476   return(coder_map);
477 }
478 \f
479 /*
480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 %                                                                             %
482 %                                                                             %
483 %                                                                             %
484 +   I n i t i a l i z e C o d e r L i s t                                     %
485 %                                                                             %
486 %                                                                             %
487 %                                                                             %
488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
489 %
490 %  InitializeCoderList() initializes the coder list.
491 %
492 %  The format of the InitializeCoderList method is:
493 %
494 %      MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
495 %
496 %  A description of each parameter follows.
497 %
498 %    o exception: return any errors or warnings in this structure.
499 %
500 */
501 static MagickBooleanType InitializeCoderList(ExceptionInfo *exception)
502 {
503   if ((coder_list == (SplayTreeInfo *) NULL) &&
504       (instantiate_coder == MagickFalse))
505     {
506       AcquireSemaphoreInfo(&coder_semaphore);
507       if ((coder_list == (SplayTreeInfo *) NULL) &&
508           (instantiate_coder == MagickFalse))
509         {
510           (void) LoadCoderLists(MagickCoderFilename,exception);
511           instantiate_coder=MagickTrue;
512         }
513       RelinquishSemaphoreInfo(coder_semaphore);
514     }
515   return(coder_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
516 }
517 \f
518 /*
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 %                                                                             %
521 %                                                                             %
522 %                                                                             %
523 +   I n s t a n t i a t e C o d e r C o m p o n e n t                         %
524 %                                                                             %
525 %                                                                             %
526 %                                                                             %
527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528 %
529 %  InstantiateCoderComponent() instantiates the coder component.
530 %
531 %  The format of the InstantiateCoderComponent method is:
532 %
533 %      MagickBooleanType InstantiateCoderComponent(void)
534 %
535 */
536 MagickExport MagickBooleanType InstantiateCoderComponent(void)
537 {
538   AcquireSemaphoreInfo(&coder_semaphore);
539   RelinquishSemaphoreInfo(coder_semaphore);
540   return(MagickTrue);
541 }
542 \f
543 /*
544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
545 %                                                                             %
546 %                                                                             %
547 %                                                                             %
548 %  L i s t C o d e r I n f o                                                  %
549 %                                                                             %
550 %                                                                             %
551 %                                                                             %
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553 %
554 %  ListCoderInfo() lists the coder info to a file.
555 %
556 %  The format of the ListCoderInfo coder is:
557 %
558 %      MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
559 %
560 %  A description of each parameter follows.
561 %
562 %    o file:  An pointer to a FILE.
563 %
564 %    o exception: return any errors or warnings in this structure.
565 %
566 */
567 MagickExport MagickBooleanType ListCoderInfo(FILE *file,
568   ExceptionInfo *exception)
569 {
570   const char
571     *path;
572
573   const CoderInfo
574     **coder_info;
575
576   long
577     j;
578
579   register long
580     i;
581
582   unsigned long
583     number_coders;
584
585   if (file == (const FILE *) NULL)
586     file=stdout;
587   coder_info=GetCoderInfoList("*",&number_coders,exception);
588   if (coder_info == (const CoderInfo **) NULL)
589     return(MagickFalse);
590   path=(const char *) NULL;
591   for (i=0; i < (long) number_coders; i++)
592   {
593     if (coder_info[i]->stealth != MagickFalse)
594       continue;
595     if ((path == (const char *) NULL) ||
596         (LocaleCompare(path,coder_info[i]->path) != 0))
597       {
598         if (coder_info[i]->path != (char *) NULL)
599           (void) fprintf(file,"\nPath: %s\n\n",coder_info[i]->path);
600         (void) fprintf(file,"Magick      Coder\n");
601         (void) fprintf(file,"-------------------------------------------------"
602           "------------------------------\n");
603       }
604     path=coder_info[i]->path;
605     (void) fprintf(file,"%s",coder_info[i]->magick);
606     for (j=(long) strlen(coder_info[i]->magick); j <= 11; j++)
607       (void) fprintf(file," ");
608     if (coder_info[i]->name != (char *) NULL)
609       (void) fprintf(file,"%s",coder_info[i]->name);
610     (void) fprintf(file,"\n");
611   }
612   coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
613   (void) fflush(file);
614   return(MagickTrue);
615 }
616 \f
617 /*
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %                                                                             %
620 %                                                                             %
621 %                                                                             %
622 +   L o a d C o d e r L i s t                                                 %
623 %                                                                             %
624 %                                                                             %
625 %                                                                             %
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 %
628 %  LoadCoderList() loads the coder configuration file which provides a
629 %  mapping between coder attributes and a coder name.
630 %
631 %  The format of the LoadCoderList coder is:
632 %
633 %      MagickBooleanType LoadCoderList(const char *xml,const char *filename,
634 %        const unsigned long depth,ExceptionInfo *exception)
635 %
636 %  A description of each parameter follows:
637 %
638 %    o xml:  The coder list in XML format.
639 %
640 %    o filename:  The coder list filename.
641 %
642 %    o depth: depth of <include /> statements.
643 %
644 %    o exception: return any errors or warnings in this structure.
645 %
646 */
647
648 static void *DestroyCoderNode(void *coder_info)
649 {
650   register CoderInfo
651     *p;
652
653   p=(CoderInfo *) coder_info;
654   if (p->exempt == MagickFalse)
655     {
656       if (p->path != (char *) NULL)
657         p->path=DestroyString(p->path);
658       if (p->name != (char *) NULL)
659         p->name=DestroyString(p->name);
660       if (p->magick != (char *) NULL)
661         p->magick=DestroyString(p->magick);
662     }
663   return(RelinquishMagickMemory(p));
664 }
665
666 static MagickBooleanType LoadCoderList(const char *xml,const char *filename,
667   const unsigned long depth,ExceptionInfo *exception)
668 {
669   char
670     keyword[MaxTextExtent],
671     *token;
672
673   const char
674     *q;
675
676   CoderInfo
677     *coder_info;
678
679   MagickBooleanType
680     status;
681
682   /*
683     Load the coder map file.
684   */
685   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
686     "Loading coder configuration file \"%s\" ...",filename);
687   if (xml == (const char *) NULL)
688     return(MagickFalse);
689   if (coder_list == (SplayTreeInfo *) NULL)
690     {
691       coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
692         DestroyCoderNode);
693       if (coder_list == (SplayTreeInfo *) NULL)
694         {
695           ThrowFileException(exception,ResourceLimitError,
696             "MemoryAllocationFailed",filename);
697           return(MagickFalse);
698         }
699     }
700   status=MagickTrue;
701   coder_info=(CoderInfo *) NULL;
702   token=AcquireString(xml);
703   for (q=(char *) xml; *q != '\0'; )
704   {
705     /*
706       Interpret XML.
707     */
708     GetMagickToken(q,&q,token);
709     if (*token == '\0')
710       break;
711     (void) CopyMagickString(keyword,token,MaxTextExtent);
712     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
713       {
714         /*
715           Doctype element.
716         */
717         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
718           GetMagickToken(q,&q,token);
719         continue;
720       }
721     if (LocaleNCompare(keyword,"<!--",4) == 0)
722       {
723         /*
724           Comment element.
725         */
726         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
727           GetMagickToken(q,&q,token);
728         continue;
729       }
730     if (LocaleCompare(keyword,"<include") == 0)
731       {
732         /*
733           Include element.
734         */
735         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
736         {
737           (void) CopyMagickString(keyword,token,MaxTextExtent);
738           GetMagickToken(q,&q,token);
739           if (*token != '=')
740             continue;
741           GetMagickToken(q,&q,token);
742           if (LocaleCompare(keyword,"file") == 0)
743             {
744               if (depth > 200)
745                 (void) ThrowMagickException(exception,GetMagickModule(),
746                   ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
747               else
748                 {
749                   char
750                     path[MaxTextExtent],
751                     *xml;
752
753                   GetPathComponent(filename,HeadPath,path);
754                   if (*path != '\0')
755                     (void) ConcatenateMagickString(path,DirectorySeparator,
756                       MaxTextExtent);
757                   if (*token == *DirectorySeparator)
758                     (void) CopyMagickString(path,token,MaxTextExtent);
759                   else
760                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
761                   xml=FileToString(path,~0,exception);
762                   if (xml != (char *) NULL)
763                     {
764                       status=LoadCoderList(xml,path,depth+1,exception);
765                       xml=(char *) RelinquishMagickMemory(xml);
766                     }
767                 }
768             }
769         }
770         continue;
771       }
772     if (LocaleCompare(keyword,"<coder") == 0)
773       {
774         /*
775           Coder element.
776         */
777         coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
778         if (coder_info == (CoderInfo *) NULL)
779           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
780         (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
781         coder_info->path=ConstantString(filename);
782         coder_info->exempt=MagickFalse;
783         coder_info->signature=MagickSignature;
784         continue;
785       }
786     if (coder_info == (CoderInfo *) NULL)
787       continue;
788     if (LocaleCompare(keyword,"/>") == 0)
789       {
790         status=AddValueToSplayTree(coder_list,ConstantString(
791           coder_info->magick),coder_info);
792         if (status == MagickFalse)
793           (void) ThrowMagickException(exception,GetMagickModule(),
794             ResourceLimitError,"MemoryAllocationFailed","`%s'",
795             coder_info->magick);
796         coder_info=(CoderInfo *) NULL;
797       }
798     GetMagickToken(q,(const char **) NULL,token);
799     if (*token != '=')
800       continue;
801     GetMagickToken(q,&q,token);
802     GetMagickToken(q,&q,token);
803     switch (*keyword)
804     {
805       case 'M':
806       case 'm':
807       {
808         if (LocaleCompare((char *) keyword,"magick") == 0)
809           {
810             coder_info->magick=ConstantString(token);
811             break;
812           }
813         break;
814       }
815       case 'N':
816       case 'n':
817       {
818         if (LocaleCompare((char *) keyword,"name") == 0)
819           {
820             coder_info->name=ConstantString(token);
821             break;
822           }
823         break;
824       }
825       case 'S':
826       case 's':
827       {
828         if (LocaleCompare((char *) keyword,"stealth") == 0)
829           {
830             coder_info->stealth=IsMagickTrue(token);
831             break;
832           }
833         break;
834       }
835       default:
836         break;
837     }
838   }
839   token=(char *) RelinquishMagickMemory(token);
840   return(status);
841 }
842 \f
843 /*
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845 %                                                                             %
846 %                                                                             %
847 %                                                                             %
848 %  L o a d C o d e r L i s t s                                                %
849 %                                                                             %
850 %                                                                             %
851 %                                                                             %
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853 %
854 %  LoadCoderLists() loads one or more coder configuration file which
855 %  provides a mapping between coder attributes and a coder name.
856 %
857 %  The format of the LoadCoderLists coder is:
858 %
859 %      MagickBooleanType LoadCoderLists(const char *filename,
860 %        ExceptionInfo *exception)
861 %
862 %  A description of each parameter follows:
863 %
864 %    o filename: the font file name.
865 %
866 %    o exception: return any errors or warnings in this structure.
867 %
868 */
869 static MagickBooleanType LoadCoderLists(const char *filename,
870   ExceptionInfo *exception)
871 {
872   const StringInfo
873     *option;
874
875   LinkedListInfo
876     *options;
877
878   MagickStatusType
879     status;
880
881   register const CoderMapInfo
882     *p;
883
884   /*
885     Load built-in coder map.
886   */
887   status=MagickFalse;
888   if (coder_list == (SplayTreeInfo *) NULL)
889     {
890       coder_list=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
891         DestroyCoderNode);
892       if (coder_list == (SplayTreeInfo *) NULL)
893         {
894           ThrowFileException(exception,ResourceLimitError,
895             "MemoryAllocationFailed",filename);
896           return(MagickFalse);
897         }
898     }
899   for (p=CoderMap; p->magick != (const char *) NULL; p++)
900   {
901     CoderInfo
902       *coder_info;
903
904     coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
905     if (coder_info == (CoderInfo *) NULL)
906       {
907         (void) ThrowMagickException(exception,GetMagickModule(),
908           ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
909         continue;
910       }
911     (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
912     coder_info->path=(char *) "[built-in]";
913     coder_info->magick=(char *) p->magick;
914     coder_info->name=(char *) p->name;
915     coder_info->exempt=MagickTrue;
916     coder_info->signature=MagickSignature;
917     status=AddValueToSplayTree(coder_list,ConstantString(coder_info->magick),
918       coder_info);
919     if (status == MagickFalse)
920       (void) ThrowMagickException(exception,GetMagickModule(),
921         ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
922   }
923   /*
924     Load external coder map.
925   */
926   options=GetConfigureOptions(filename,exception);
927   option=(const StringInfo *) GetNextValueInLinkedList(options);
928   while (option != (const StringInfo *) NULL)
929   {
930     status|=LoadCoderList((const char *) GetStringInfoDatum(option),
931       GetStringInfoPath(option),0,exception);
932     option=(const StringInfo *) GetNextValueInLinkedList(options);
933   }
934   options=DestroyConfigureOptions(options);
935   return(status != 0 ? MagickTrue : MagickFalse);
936 }