root/ImageMagick/trunk/magick/coder.c

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