root/ImageMagick/trunk/magick/coder.c

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