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