]> granicus.if.org Git - imagemagick/blob - MagickCore/type.c
(no commit message)
[imagemagick] / MagickCore / type.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                        TTTTT  Y   Y  PPPP   EEEEE                           %
7 %                          T     Y Y   P   P  E                               %
8 %                          T      Y    PPPP   EEE                             %
9 %                          T      Y    P      E                               %
10 %                          T      Y    P      EEEEE                           %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore Image Type Methods                         %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 May 2001                                    %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2007 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 "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/client.h"
45 #include "MagickCore/configure.h"
46 #include "MagickCore/draw.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/hashmap.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/nt-feature.h"
53 #include "MagickCore/nt-base-private.h"
54 #include "MagickCore/option.h"
55 #include "MagickCore/semaphore.h"
56 #include "MagickCore/splay-tree.h"
57 #include "MagickCore/string_.h"
58 #include "MagickCore/string-private.h"
59 #include "MagickCore/type.h"
60 #include "MagickCore/type-private.h"
61 #include "MagickCore/token.h"
62 #include "MagickCore/utility.h"
63 #include "MagickCore/utility-private.h"
64 #include "MagickCore/xml-tree.h"
65 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
66 # include "fontconfig/fontconfig.h"
67 #if (FC_VERSION < 20209)
68 #undef FC_WEIGHT_LIGHT
69 #define FC_WIDTH                  "width"    /* Int */
70 #define FC_WIDTH_ULTRACONDENSED    50
71 #define FC_WIDTH_EXTRACONDENSED    63
72 #define FC_WIDTH_CONDENSED         75
73 #define FC_WIDTH_SEMICONDENSED     87
74 #define FC_WIDTH_NORMAL            100
75 #define FC_WIDTH_SEMIEXPANDED      113
76 #define FC_WIDTH_EXPANDED          125
77 #define FC_WIDTH_EXTRAEXPANDED     150
78 #define FC_WIDTH_ULTRAEXPANDED     200
79
80 #define FC_WEIGHT_THIN             0
81 #define FC_WEIGHT_EXTRALIGHT       40
82 #define FC_WEIGHT_ULTRALIGHT       FC_WEIGHT_EXTRALIGHT
83 #define FC_WEIGHT_LIGHT            50
84 #define FC_WEIGHT_BOOK             75
85 #define FC_WEIGHT_REGULAR          80
86 #define FC_WEIGHT_NORMAL           FC_WEIGHT_REGULAR
87 #define FC_WEIGHT_MEDIUM           100
88 #define FC_WEIGHT_DEMIBOLD         180
89 #define FC_WEIGHT_SEMIBOLD         FC_WEIGHT_DEMIBOLD
90 #define FC_WEIGHT_BOLD             200
91 #define FC_WEIGHT_EXTRABOLD        205
92 #define FC_WEIGHT_ULTRABOLD        FC_WEIGHT_EXTRABOLD
93 #define FC_WEIGHT_BLACK            210
94 #define FC_WEIGHT_HEAVY            FC_WEIGHT_BLACK
95 #endif
96 #endif
97 \f
98 /*
99   Define declarations.
100 */
101 #define MagickTypeFilename  "type.xml"
102 \f
103 /*
104   Declare type map.
105 */
106 static const char
107   *TypeMap = (const char *)
108     "<?xml version=\"1.0\"?>"
109     "<typemap>"
110     "  <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
111     "  <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
112     "</typemap>";
113 \f
114 /*
115   Static declarations.
116 */
117 static SemaphoreInfo
118   *type_semaphore = (SemaphoreInfo *) NULL;
119
120 static volatile MagickBooleanType
121   instantiate_type = MagickFalse;
122
123 static SplayTreeInfo
124   *type_list = (SplayTreeInfo *) NULL;
125 \f
126 /*
127   Forward declarations.
128 */
129 static MagickBooleanType
130   InitializeTypeList(ExceptionInfo *),
131   LoadTypeLists(const char *,ExceptionInfo *);
132 \f
133 /*
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 %                                                                             %
136 %                                                                             %
137 %                                                                             %
138 +   G e t T y p e I n f o                                                     %
139 %                                                                             %
140 %                                                                             %
141 %                                                                             %
142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 %
144 %  GetTypeInfo searches the type list for the specified name and if found
145 %  returns attributes for that type.
146 %
147 %  The format of the GetTypeInfo method is:
148 %
149 %      const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
150 %
151 %  A description of each parameter follows:
152 %
153 %    o name: the type name.
154 %
155 %    o exception: return any errors or warnings in this structure.
156 %
157 */
158 MagickExport const TypeInfo *GetTypeInfo(const char *name,
159   ExceptionInfo *exception)
160 {
161   assert(exception != (ExceptionInfo *) NULL);
162   if ((type_list == (SplayTreeInfo *) NULL) ||
163       (instantiate_type == MagickFalse))
164     if (InitializeTypeList(exception) == MagickFalse)
165       return((const TypeInfo *) NULL);
166   if ((type_list == (SplayTreeInfo *) NULL) ||
167       (GetNumberOfNodesInSplayTree(type_list) == 0))
168     return((const TypeInfo *) NULL);
169   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
170     {
171       ResetSplayTreeIterator(type_list);
172       return((const TypeInfo *) GetNextValueInSplayTree(type_list));
173     }
174   return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
175 }
176 \f
177 /*
178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 %                                                                             %
180 %                                                                             %
181 %                                                                             %
182 +   G e t T y p e I n f o B y F a m i l y                                     %
183 %                                                                             %
184 %                                                                             %
185 %                                                                             %
186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 %
188 %  GetTypeInfoByFamily() searches the type list for the specified family and if
189 %  found returns attributes for that type.
190 %
191 %  Type substitution and scoring algorithm contributed by Bob Friesenhahn.
192 %
193 %  The format of the GetTypeInfoByFamily method is:
194 %
195 %      const TypeInfo *GetTypeInfoByFamily(const char *family,
196 %        const StyleType style,const StretchType stretch,
197 %        const size_t weight,ExceptionInfo *exception)
198 %
199 %  A description of each parameter follows:
200 %
201 %    o family: the type family.
202 %
203 %    o style: the type style.
204 %
205 %    o stretch: the type stretch.
206 %
207 %    o weight: the type weight.
208 %
209 %    o exception: return any errors or warnings in this structure.
210 %
211 */
212
213 static inline size_t MagickMax(const size_t x,const size_t y)
214 {
215   if (x > y)
216     return(x);
217   return(y);
218 }
219
220 static inline size_t MagickMin(const size_t x,const size_t y)
221 {
222   if (x < y)
223     return(x);
224   return(y);
225 }
226
227 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
228   const StyleType style,const StretchType stretch,const size_t weight,
229   ExceptionInfo *exception)
230 {
231   typedef struct _Fontmap
232   {
233     const char
234       *name,
235       *substitute;
236   } Fontmap;
237
238   const TypeInfo
239     *type_info;
240
241   register const TypeInfo
242     *p;
243
244   register ssize_t
245     i;
246
247   ssize_t
248     range;
249
250   static const Fontmap
251     fontmap[] =
252     {
253       { "fixed", "courier" },
254       { "modern","courier" },
255       { "monotype corsiva", "courier" },
256       { "news gothic", "helvetica" },
257       { "system", "courier" },
258       { "terminal", "courier" },
259       { "wingdings", "symbol" },
260       { NULL, NULL }
261     };
262
263   size_t
264     max_score,
265     score;
266
267   /*
268     Check for an exact type match.
269   */
270   (void) GetTypeInfo("*",exception);
271   if (type_list == (SplayTreeInfo *) NULL)
272     return((TypeInfo *) NULL);
273   LockSemaphoreInfo(type_semaphore);
274   ResetSplayTreeIterator(type_list);
275   type_info=(const TypeInfo *) NULL;
276   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
277   while (p != (const TypeInfo *) NULL)
278   {
279     if (p->family == (char *) NULL)
280       {
281         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
282         continue;
283       }
284     if (family == (const char *) NULL)
285       {
286         if ((LocaleCompare(p->family,"arial") != 0) &&
287             (LocaleCompare(p->family,"helvetica") != 0))
288           {
289             p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
290             continue;
291           }
292       }
293     else
294       if (LocaleCompare(p->family,family) != 0)
295         {
296           p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
297           continue;
298         }
299     if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
300       {
301         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
302         continue;
303       }
304     if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
305         (p->stretch != stretch))
306       {
307         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
308         continue;
309       }
310     if ((weight != 0) && (p->weight != weight))
311       {
312         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
313         continue;
314       }
315     type_info=p;
316     break;
317   }
318   UnlockSemaphoreInfo(type_semaphore);
319   if (type_info != (const TypeInfo *) NULL)
320     return(type_info);
321   /*
322     Check for types in the same family.
323   */
324   max_score=0;
325   LockSemaphoreInfo(type_semaphore);
326   ResetSplayTreeIterator(type_list);
327   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
328   while (p != (const TypeInfo *) NULL)
329   {
330     if (p->family == (char *) NULL)
331       {
332         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
333         continue;
334       }
335     if (family == (const char *) NULL)
336       {
337         if ((LocaleCompare(p->family,"arial") != 0) &&
338             (LocaleCompare(p->family,"helvetica") != 0))
339           {
340             p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
341             continue;
342           }
343       }
344     else
345       if (LocaleCompare(p->family,family) != 0)
346         {
347           p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
348           continue;
349         }
350     score=0;
351     if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
352       score+=32;
353     else
354       if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
355           ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
356         score+=25;
357     if (weight == 0)
358       score+=16;
359     else
360       score+=(16*(800-((ssize_t) MagickMax(MagickMin(weight,900),p->weight)-
361         (ssize_t) MagickMin(MagickMin(weight,900),p->weight))))/800;
362     if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
363       score+=8;
364     else
365       {
366         range=(ssize_t) UltraExpandedStretch-(ssize_t) NormalStretch;
367         score+=(8*(range-((ssize_t) MagickMax(stretch,p->stretch)-
368           (ssize_t) MagickMin(stretch,p->stretch))))/range;
369       }
370     if (score > max_score)
371       {
372         max_score=score;
373         type_info=p;
374       }
375     p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
376   }
377   UnlockSemaphoreInfo(type_semaphore);
378   if (type_info != (const TypeInfo *) NULL)
379     return(type_info);
380   /*
381     Check for table-based substitution match.
382   */
383   for (i=0; fontmap[i].name != (char *) NULL; i++)
384   {
385     if (family == (const char *) NULL)
386       {
387         if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
388             (LocaleCompare(fontmap[i].name,"helvetica") != 0))
389           continue;
390       }
391     else
392       if (LocaleCompare(fontmap[i].name,family) != 0)
393         continue;
394     type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
395       exception);
396     break;
397   }
398   if (type_info != (const TypeInfo *) NULL)
399     {
400       (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
401         "FontSubstitutionRequired","'%s'",type_info->family);
402       return(type_info);
403     }
404   if (family != (const char *) NULL)
405     type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
406       exception);
407   return(type_info);
408 }
409 \f
410 /*
411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
412 %                                                                             %
413 %                                                                             %
414 %                                                                             %
415 %   G e t T y p e I n f o L i s t                                             %
416 %                                                                             %
417 %                                                                             %
418 %                                                                             %
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 %
421 %  GetTypeInfoList() returns any fonts that match the specified pattern.
422 %
423 %  The format of the GetTypeInfoList function is:
424 %
425 %      const TypeInfo **GetTypeInfoList(const char *pattern,
426 %        size_t *number_fonts,ExceptionInfo *exception)
427 %
428 %  A description of each parameter follows:
429 %
430 %    o pattern: Specifies a pointer to a text string containing a pattern.
431 %
432 %    o number_fonts:  This integer returns the number of types in the list.
433 %
434 %    o exception: return any errors or warnings in this structure.
435 %
436 */
437
438 #if defined(__cplusplus) || defined(c_plusplus)
439 extern "C" {
440 #endif
441
442 static int TypeInfoCompare(const void *x,const void *y)
443 {
444   const TypeInfo
445     **p,
446     **q;
447
448   p=(const TypeInfo **) x,
449   q=(const TypeInfo **) y;
450   if (LocaleCompare((*p)->path,(*q)->path) == 0)
451     return(LocaleCompare((*p)->name,(*q)->name));
452   return(LocaleCompare((*p)->path,(*q)->path));
453 }
454
455 #if defined(__cplusplus) || defined(c_plusplus)
456 }
457 #endif
458
459 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
460   size_t *number_fonts,ExceptionInfo *exception)
461 {
462   const TypeInfo
463     **fonts;
464
465   register const TypeInfo
466     *p;
467
468   register ssize_t
469     i;
470
471   /*
472     Allocate type list.
473   */
474   assert(pattern != (char *) NULL);
475   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
476   assert(number_fonts != (size_t *) NULL);
477   *number_fonts=0;
478   p=GetTypeInfo("*",exception);
479   if (p == (const TypeInfo *) NULL)
480     return((const TypeInfo **) NULL);
481   fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
482     GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
483   if (fonts == (const TypeInfo **) NULL)
484     return((const TypeInfo **) NULL);
485   /*
486     Generate type list.
487   */
488   LockSemaphoreInfo(type_semaphore);
489   ResetSplayTreeIterator(type_list);
490   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
491   for (i=0; p != (const TypeInfo *) NULL; )
492   {
493     if ((p->stealth == MagickFalse) &&
494         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
495       fonts[i++]=p;
496     p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
497   }
498   UnlockSemaphoreInfo(type_semaphore);
499   qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
500   fonts[i]=(TypeInfo *) NULL;
501   *number_fonts=(size_t) i;
502   return(fonts);
503 }
504 \f
505 /*
506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 %                                                                             %
508 %                                                                             %
509 %                                                                             %
510 %   G e t T y p e L i s t                                                     %
511 %                                                                             %
512 %                                                                             %
513 %                                                                             %
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 %
516 %  GetTypeList() returns any fonts that match the specified pattern.
517 %
518 %  The format of the GetTypeList function is:
519 %
520 %      char **GetTypeList(const char *pattern,size_t *number_fonts,
521 %        ExceptionInfo *exception)
522 %
523 %  A description of each parameter follows:
524 %
525 %    o pattern: Specifies a pointer to a text string containing a pattern.
526 %
527 %    o number_fonts:  This integer returns the number of fonts in the list.
528 %
529 %    o exception: return any errors or warnings in this structure.
530 %
531 */
532
533 #if defined(__cplusplus) || defined(c_plusplus)
534 extern "C" {
535 #endif
536
537 static int TypeCompare(const void *x,const void *y)
538 {
539   register const char
540     **p,
541     **q;
542
543   p=(const char **) x;
544   q=(const char **) y;
545   return(LocaleCompare(*p,*q));
546 }
547
548 #if defined(__cplusplus) || defined(c_plusplus)
549 }
550 #endif
551
552 MagickExport char **GetTypeList(const char *pattern,size_t *number_fonts,
553   ExceptionInfo *exception)
554 {
555   char
556     **fonts;
557
558   register const TypeInfo
559     *p;
560
561   register ssize_t
562     i;
563
564   /*
565     Allocate type list.
566   */
567   assert(pattern != (char *) NULL);
568   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
569   assert(number_fonts != (size_t *) NULL);
570   *number_fonts=0;
571   p=GetTypeInfo("*",exception);
572   if (p == (const TypeInfo *) NULL)
573     return((char **) NULL);
574   fonts=(char **) AcquireQuantumMemory((size_t)
575     GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
576   if (fonts == (char **) NULL)
577     return((char **) NULL);
578   /*
579     Generate type list.
580   */
581   LockSemaphoreInfo(type_semaphore);
582   ResetSplayTreeIterator(type_list);
583   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
584   for (i=0; p != (const TypeInfo *) NULL; )
585   {
586     if ((p->stealth == MagickFalse) &&
587         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
588       fonts[i++]=ConstantString(p->name);
589     p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
590   }
591   UnlockSemaphoreInfo(type_semaphore);
592   qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
593   fonts[i]=(char *) NULL;
594   *number_fonts=(size_t) i;
595   return(fonts);
596 }
597 \f
598 /*
599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
600 %                                                                             %
601 %                                                                             %
602 %                                                                             %
603 +   I n i t i a l i z e T y p e L i s t                                       %
604 %                                                                             %
605 %                                                                             %
606 %                                                                             %
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 %
609 %  InitializeTypeList() initializes the type list.
610 %
611 %  The format of the InitializeTypeList method is:
612 %
613 %      MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
614 %
615 %  A description of each parameter follows.
616 %
617 %    o exception: return any errors or warnings in this structure.
618 %
619 */
620
621 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
622 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
623   ExceptionInfo *exception)
624 {
625   char
626     extension[MaxTextExtent],
627     name[MaxTextExtent];
628
629   FcChar8
630     *family,
631     *file,
632     *style;
633
634   FcConfig
635     *font_config;
636
637   FcFontSet
638     *font_set;
639
640   FcObjectSet
641     *object_set;
642
643   FcPattern
644     *pattern;
645
646   FcResult
647     status;
648
649   int
650     slant,
651     width,
652     weight;
653
654   register ssize_t
655     i;
656
657   TypeInfo
658     *type_info;
659
660   /*
661     Load system fonts.
662   */
663   (void) exception;
664   font_config=FcInitLoadConfigAndFonts();
665   if (font_config == (FcConfig *) NULL)
666     return(MagickFalse);
667   font_set=(FcFontSet *) NULL;
668   object_set=FcObjectSetBuild(FC_FAMILY,FC_STYLE,FC_SLANT,FC_WIDTH,FC_WEIGHT,
669     FC_FILE,(char *) NULL);
670   if (object_set != (FcObjectSet *) NULL)
671     {
672       pattern=FcPatternCreate();
673       if (pattern != (FcPattern *) NULL)
674         {
675           font_set=FcFontList(0,pattern,object_set);
676           FcPatternDestroy(pattern);
677         }
678       FcObjectSetDestroy(object_set);
679     }
680   if (font_set == (FcFontSet *) NULL)
681     {
682       FcConfigDestroy(font_config);
683       return(MagickFalse);
684     }
685   for (i=0; i < (ssize_t) font_set->nfont; i++)
686   {
687     status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
688     if (status != FcResultMatch)
689       continue;
690     status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
691     if (status != FcResultMatch)
692       continue;
693     *extension='\0';
694     GetPathComponent((const char *) file,ExtensionPath,extension);
695     if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
696       continue;
697     type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
698     if (type_info == (TypeInfo *) NULL)
699       continue;
700     (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
701     type_info->path=ConstantString("System Fonts");
702     type_info->signature=MagickSignature;
703     (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
704     (void) ConcatenateMagickString(name," ",MaxTextExtent);
705     status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
706     if (status == FcResultMatch)
707       (void) ConcatenateMagickString(name,(const char *) style,MaxTextExtent);
708     type_info->name=ConstantString(name);
709     (void) SubstituteString(&type_info->name," ","-");
710     (void) SubstituteString(&type_info->name,"-L-","-");
711     (void) SubstituteString(&type_info->name,"semicondensed","SemiCondensed");
712     type_info->family=ConstantString((const char *) family);
713     (void) SubstituteString(&type_info->family," L","");
714     status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
715     type_info->style=NormalStyle;
716     if (slant == FC_SLANT_ITALIC)
717       type_info->style=ItalicStyle;
718     if (slant == FC_SLANT_OBLIQUE)
719       type_info->style=ObliqueStyle;
720     status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
721     type_info->stretch=NormalStretch;
722     if (width >= FC_WIDTH_ULTRACONDENSED)
723       type_info->stretch=UltraCondensedStretch;
724     if (width >= FC_WIDTH_EXTRACONDENSED)
725       type_info->stretch=ExtraCondensedStretch;
726     if (width >= FC_WIDTH_CONDENSED)
727       type_info->stretch=CondensedStretch;
728     if (width >= FC_WIDTH_SEMICONDENSED)
729       type_info->stretch=SemiCondensedStretch;
730     if (width >= FC_WIDTH_NORMAL)
731       type_info->stretch=NormalStretch;
732     if (width >= FC_WIDTH_SEMIEXPANDED)
733       type_info->stretch=SemiExpandedStretch;
734     if (width >= FC_WIDTH_EXPANDED)
735       type_info->stretch=ExpandedStretch;
736     if (width >= FC_WIDTH_EXTRAEXPANDED)
737       type_info->stretch=ExtraExpandedStretch;
738     if (width >= FC_WIDTH_ULTRAEXPANDED)
739       type_info->stretch=UltraExpandedStretch;
740     type_info->weight=400;
741     status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
742     if (weight >= FC_WEIGHT_THIN)
743       type_info->weight=100;
744     if (weight >= FC_WEIGHT_EXTRALIGHT)
745       type_info->weight=200;
746     if (weight >= FC_WEIGHT_LIGHT)
747       type_info->weight=300;
748     if (weight >= FC_WEIGHT_NORMAL)
749       type_info->weight=400;
750     if (weight >= FC_WEIGHT_MEDIUM)
751       type_info->weight=500;
752     if (weight >= FC_WEIGHT_DEMIBOLD)
753       type_info->weight=600;
754     if (weight >= FC_WEIGHT_BOLD)
755       type_info->weight=700;
756     if (weight >= FC_WEIGHT_EXTRABOLD)
757       type_info->weight=800;
758     if (weight >= FC_WEIGHT_BLACK)
759       type_info->weight=900;
760     type_info->glyphs=ConstantString((const char *) file);
761     (void) AddValueToSplayTree(type_list,type_info->name,type_info);
762   }
763   FcFontSetDestroy(font_set);
764   FcConfigDestroy(font_config);
765   return(MagickTrue);
766 }
767 #endif
768
769 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
770 {
771   if ((type_list == (SplayTreeInfo *) NULL) &&
772       (instantiate_type == MagickFalse))
773     {
774       if (type_semaphore == (SemaphoreInfo *) NULL)
775         AcquireSemaphoreInfo(&type_semaphore);
776       LockSemaphoreInfo(type_semaphore);
777       if ((type_list == (SplayTreeInfo *) NULL) &&
778           (instantiate_type == MagickFalse))
779         {
780           (void) LoadTypeLists(MagickTypeFilename,exception);
781 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
782           (void) NTLoadTypeLists(type_list,exception);
783 #endif
784 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
785           (void) LoadFontConfigFonts(type_list,exception);
786 #endif
787           instantiate_type=MagickTrue;
788         }
789       UnlockSemaphoreInfo(type_semaphore);
790     }
791   return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
792 }
793 \f
794 /*
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %                                                                             %
797 %                                                                             %
798 %                                                                             %
799 %  L i s t T y p e I n f o                                                    %
800 %                                                                             %
801 %                                                                             %
802 %                                                                             %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 %
805 %  ListTypeInfo() lists the fonts to a file.
806 %
807 %  The format of the ListTypeInfo method is:
808 %
809 %      MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
810 %
811 %  A description of each parameter follows.
812 %
813 %    o file:  An pointer to a FILE.
814 %
815 %    o exception: return any errors or warnings in this structure.
816 %
817 */
818 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
819 {
820   char
821     weight[MaxTextExtent];
822
823   const char
824     *family,
825     *glyphs,
826     *name,
827     *path,
828     *stretch,
829     *style;
830
831   const TypeInfo
832     **type_info;
833
834   register ssize_t
835     i;
836
837   size_t
838     number_fonts;
839
840   if (file == (FILE *) NULL)
841     file=stdout;
842   number_fonts=0;
843   type_info=GetTypeInfoList("*",&number_fonts,exception);
844   if (type_info == (const TypeInfo **) NULL)
845     return(MagickFalse);
846   *weight='\0';
847   path=(const char *) NULL;
848   for (i=0; i < (ssize_t) number_fonts; i++)
849   {
850     if (type_info[i]->stealth != MagickFalse)
851       continue;
852     if (((path == (const char *) NULL) ||
853          (LocaleCompare(path,type_info[i]->path) != 0)) &&
854          (type_info[i]->path != (char *) NULL))
855       (void) FormatLocaleFile(file,"\nPath: %s\n",type_info[i]->path);
856     path=type_info[i]->path;
857     name="unknown";
858     if (type_info[i]->name != (char *) NULL)
859       name=type_info[i]->name;
860     family="unknown";
861     if (type_info[i]->family != (char *) NULL)
862       family=type_info[i]->family;
863     style=CommandOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
864     stretch=CommandOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
865     glyphs="unknown";
866     if (type_info[i]->glyphs != (char *) NULL)
867       glyphs=type_info[i]->glyphs;
868     (void) FormatLocaleString(weight,MaxTextExtent,"%.20g",(double)
869       type_info[i]->weight);
870     (void) FormatLocaleFile(file,"  Font: %s\n",name);
871     (void) FormatLocaleFile(file,"    family: %s\n",family);
872     (void) FormatLocaleFile(file,"    style: %s\n",style);
873     (void) FormatLocaleFile(file,"    stretch: %s\n",stretch);
874     (void) FormatLocaleFile(file,"    weight: %s\n",weight);
875     (void) FormatLocaleFile(file,"    glyphs: %s\n",glyphs);
876   }
877   (void) fflush(file);
878   type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
879   return(MagickTrue);
880 }
881 \f
882 /*
883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
884 %                                                                             %
885 %                                                                             %
886 %                                                                             %
887 +   L o a d T y p e L i s t                                                   %
888 %                                                                             %
889 %                                                                             %
890 %                                                                             %
891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
892 %
893 %  LoadTypeList() loads the type configuration file which provides a mapping
894 %  between type attributes and a type name.
895 %
896 %  The format of the LoadTypeList method is:
897 %
898 %      MagickBooleanType LoadTypeList(const char *xml,const char *filename,
899 %        const size_t depth,ExceptionInfo *exception)
900 %
901 %  A description of each parameter follows:
902 %
903 %    o xml:  The type list in XML format.
904 %
905 %    o filename:  The type list filename.
906 %
907 %    o depth: depth of <include /> statements.
908 %
909 %    o exception: return any errors or warnings in this structure.
910 %
911 */
912
913 static void *DestroyTypeNode(void *type_info)
914 {
915   register TypeInfo
916     *p;
917
918   p=(TypeInfo *) type_info;
919   if (p->path != (char *) NULL)
920     p->path=DestroyString(p->path);
921   if (p->name != (char *) NULL)
922     p->name=DestroyString(p->name);
923   if (p->description != (char *) NULL)
924     p->description=DestroyString(p->description);
925   if (p->family != (char *) NULL)
926     p->family=DestroyString(p->family);
927   if (p->encoding != (char *) NULL)
928     p->encoding=DestroyString(p->encoding);
929   if (p->foundry != (char *) NULL)
930     p->foundry=DestroyString(p->foundry);
931   if (p->format != (char *) NULL)
932     p->format=DestroyString(p->format);
933   if (p->metrics != (char *) NULL)
934     p->metrics=DestroyString(p->metrics);
935   if (p->glyphs != (char *) NULL)
936     p->glyphs=DestroyString(p->glyphs);
937   return(RelinquishMagickMemory(p));
938 }
939
940 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
941   const size_t depth,ExceptionInfo *exception)
942 {
943   char
944     font_path[MaxTextExtent],
945     keyword[MaxTextExtent],
946     *token;
947
948   const char
949     *q;
950
951   MagickBooleanType
952     status;
953
954   TypeInfo
955     *type_info;
956
957   /*
958     Load the type map file.
959   */
960   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
961     "Loading type configure file \"%s\" ...",filename);
962   if (xml == (const char *) NULL)
963     return(MagickFalse);
964   if (type_list == (SplayTreeInfo *) NULL)
965     {
966       type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
967         DestroyTypeNode);
968       if (type_list == (SplayTreeInfo *) NULL)
969         {
970           ThrowFileException(exception,ResourceLimitError,
971             "MemoryAllocationFailed",filename);
972           return(MagickFalse);
973         }
974     }
975   status=MagickTrue;
976   type_info=(TypeInfo *) NULL;
977   token=AcquireString(xml);
978 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
979   /*
980     Determine the Ghostscript font path.
981   */
982   *font_path='\0';
983   if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
984     (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
985 #endif
986   for (q=(char *) xml; *q != '\0'; )
987   {
988     /*
989       Interpret XML.
990     */
991     GetMagickToken(q,&q,token);
992     if (*token == '\0')
993       break;
994     (void) CopyMagickString(keyword,token,MaxTextExtent);
995     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
996       {
997         /*
998           Doctype element.
999         */
1000         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1001           GetMagickToken(q,&q,token);
1002         continue;
1003       }
1004     if (LocaleNCompare(keyword,"<!--",4) == 0)
1005       {
1006         /*
1007           Comment element.
1008         */
1009         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1010           GetMagickToken(q,&q,token);
1011         continue;
1012       }
1013     if (LocaleCompare(keyword,"<include") == 0)
1014       {
1015         /*
1016           Include element.
1017         */
1018         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1019         {
1020           (void) CopyMagickString(keyword,token,MaxTextExtent);
1021           GetMagickToken(q,&q,token);
1022           if (*token != '=')
1023             continue;
1024           GetMagickToken(q,&q,token);
1025           if (LocaleCompare(keyword,"file") == 0)
1026             {
1027               if (depth > 200)
1028                 (void) ThrowMagickException(exception,GetMagickModule(),
1029                   ConfigureError,"IncludeNodeNestedTooDeeply","'%s'",token);
1030               else
1031                 {
1032                   char
1033                     path[MaxTextExtent],
1034                     *xml;
1035
1036                   ExceptionInfo
1037                     *sans_exception;
1038
1039                   *path='\0';
1040                   GetPathComponent(filename,HeadPath,path);
1041                   if (*path != '\0')
1042                     (void) ConcatenateMagickString(path,DirectorySeparator,
1043                       MaxTextExtent);
1044                   if (*token == *DirectorySeparator)
1045                     (void) CopyMagickString(path,token,MaxTextExtent);
1046                   else
1047                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
1048                   sans_exception=AcquireExceptionInfo();
1049                   xml=FileToString(path,~0,sans_exception);
1050                   sans_exception=DestroyExceptionInfo(sans_exception);
1051                   if (xml != (char *) NULL)
1052                     {
1053                       status=LoadTypeList(xml,path,depth+1,exception);
1054                       xml=(char *) RelinquishMagickMemory(xml);
1055                     }
1056                 }
1057             }
1058         }
1059         continue;
1060       }
1061     if (LocaleCompare(keyword,"<type") == 0)
1062       {
1063         /*
1064           Type element.
1065         */
1066         type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
1067         if (type_info == (TypeInfo *) NULL)
1068           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1069         (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
1070         type_info->path=ConstantString(filename);
1071         type_info->signature=MagickSignature;
1072         continue;
1073       }
1074     if (type_info == (TypeInfo *) NULL)
1075       continue;
1076     if (LocaleCompare(keyword,"/>") == 0)
1077       {
1078         status=AddValueToSplayTree(type_list,type_info->name,type_info);
1079         if (status == MagickFalse)
1080           (void) ThrowMagickException(exception,GetMagickModule(),
1081             ResourceLimitError,"MemoryAllocationFailed","'%s'",type_info->name);
1082         type_info=(TypeInfo *) NULL;
1083       }
1084     GetMagickToken(q,(const char **) NULL,token);
1085     if (*token != '=')
1086       continue;
1087     GetMagickToken(q,&q,token);
1088     GetMagickToken(q,&q,token);
1089     switch (*keyword)
1090     {
1091       case 'E':
1092       case 'e':
1093       {
1094         if (LocaleCompare((char *) keyword,"encoding") == 0)
1095           {
1096             type_info->encoding=ConstantString(token);
1097             break;
1098           }
1099         break;
1100       }
1101       case 'F':
1102       case 'f':
1103       {
1104         if (LocaleCompare((char *) keyword,"face") == 0)
1105           {
1106             type_info->face=StringToUnsignedLong(token);
1107             break;
1108           }
1109         if (LocaleCompare((char *) keyword,"family") == 0)
1110           {
1111             type_info->family=ConstantString(token);
1112             break;
1113           }
1114         if (LocaleCompare((char *) keyword,"format") == 0)
1115           {
1116             type_info->format=ConstantString(token);
1117             break;
1118           }
1119         if (LocaleCompare((char *) keyword,"foundry") == 0)
1120           {
1121             type_info->foundry=ConstantString(token);
1122             break;
1123           }
1124         if (LocaleCompare((char *) keyword,"fullname") == 0)
1125           {
1126             type_info->description=ConstantString(token);
1127             break;
1128           }
1129         break;
1130       }
1131       case 'G':
1132       case 'g':
1133       {
1134         if (LocaleCompare((char *) keyword,"glyphs") == 0)
1135           {
1136             char
1137               *path;
1138
1139             path=ConstantString(token);
1140 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1141             if (strchr(path,'@') != (char *) NULL)
1142               SubstituteString(&path,"@ghostscript_font_path@",font_path);
1143 #endif
1144             if (IsPathAccessible(path) == MagickFalse)
1145               {
1146                 /*
1147                   Relative path.
1148                 */
1149                 path=DestroyString(path);
1150                 GetPathComponent(filename,HeadPath,font_path);
1151                 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1152                   MaxTextExtent);
1153                 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1154                 path=ConstantString(font_path);
1155                 if (IsPathAccessible(path) == MagickFalse)
1156                   {
1157                     path=DestroyString(path);
1158                     path=ConstantString(token);
1159                   }
1160               }
1161             type_info->glyphs=path;
1162             break;
1163           }
1164         break;
1165       }
1166       case 'M':
1167       case 'm':
1168       {
1169         if (LocaleCompare((char *) keyword,"metrics") == 0)
1170           {
1171             char
1172               *path;
1173
1174             path=ConstantString(token);
1175 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1176             if (strchr(path,'@') != (char *) NULL)
1177               SubstituteString(&path,"@ghostscript_font_path@",font_path);
1178 #endif
1179             if (IsPathAccessible(path) == MagickFalse)
1180               {
1181                 /*
1182                   Relative path.
1183                 */
1184                 path=DestroyString(path);
1185                 GetPathComponent(filename,HeadPath,font_path);
1186                 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1187                   MaxTextExtent);
1188                 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1189                 path=ConstantString(font_path);
1190               }
1191             type_info->metrics=path;
1192             break;
1193           }
1194         break;
1195       }
1196       case 'N':
1197       case 'n':
1198       {
1199         if (LocaleCompare((char *) keyword,"name") == 0)
1200           {
1201             type_info->name=ConstantString(token);
1202             break;
1203           }
1204         break;
1205       }
1206       case 'S':
1207       case 's':
1208       {
1209         if (LocaleCompare((char *) keyword,"stealth") == 0)
1210           {
1211             type_info->stealth=IsStringTrue(token);
1212             break;
1213           }
1214         if (LocaleCompare((char *) keyword,"stretch") == 0)
1215           {
1216             type_info->stretch=(StretchType) ParseCommandOption(
1217               MagickStretchOptions,MagickFalse,token);
1218             break;
1219           }
1220         if (LocaleCompare((char *) keyword,"style") == 0)
1221           {
1222             type_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1223               MagickFalse,token);
1224             break;
1225           }
1226         break;
1227       }
1228       case 'W':
1229       case 'w':
1230       {
1231         if (LocaleCompare((char *) keyword,"weight") == 0)
1232           {
1233             type_info->weight=StringToUnsignedLong(token);
1234             if (LocaleCompare(token,"bold") == 0)
1235               type_info->weight=700;
1236             if (LocaleCompare(token,"normal") == 0)
1237               type_info->weight=400;
1238             break;
1239           }
1240         break;
1241       }
1242       default:
1243         break;
1244     }
1245   }
1246   token=(char *) RelinquishMagickMemory(token);
1247   return(status);
1248 }
1249 \f
1250 /*
1251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 %                                                                             %
1253 %                                                                             %
1254 %                                                                             %
1255 %  L o a d T y p e L i s t s                                                  %
1256 %                                                                             %
1257 %                                                                             %
1258 %                                                                             %
1259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260 %
1261 %  LoadTypeList() loads one or more type configuration files which provides a
1262 %  mapping between type attributes and a type name.
1263 %
1264 %  The format of the LoadTypeLists method is:
1265 %
1266 %      MagickBooleanType LoadTypeLists(const char *filename,
1267 %        ExceptionInfo *exception)
1268 %
1269 %  A description of each parameter follows:
1270 %
1271 %    o filename: the font file name.
1272 %
1273 %    o exception: return any errors or warnings in this structure.
1274 %
1275 */
1276 static MagickBooleanType LoadTypeLists(const char *filename,
1277   ExceptionInfo *exception)
1278 {
1279 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1280   return(LoadTypeList(TypeMap,"built-in",0,exception));
1281 #else
1282   char
1283     *font_path,
1284     path[MaxTextExtent];
1285
1286   const StringInfo
1287     *option;
1288
1289   LinkedListInfo
1290     *options;
1291
1292   MagickStatusType
1293     status;
1294
1295   status=MagickFalse;
1296   *path='\0';
1297   options=GetConfigureOptions(filename,exception);
1298   option=(const StringInfo *) GetNextValueInLinkedList(options);
1299   while (option != (const StringInfo *) NULL)
1300   {
1301     (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1302     status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1303       GetStringInfoPath(option),0,exception);
1304     option=(const StringInfo *) GetNextValueInLinkedList(options);
1305   }
1306   options=DestroyConfigureOptions(options);
1307   font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1308   if (font_path != (char *) NULL)
1309     {
1310       char
1311         *option;
1312
1313       /*
1314         Search MAGICK_FONT_PATH.
1315       */
1316       (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",font_path,
1317         DirectorySeparator,filename);
1318       option=FileToString(path,~0,exception);
1319       if (option != (void *) NULL)
1320         {
1321           status|=LoadTypeList(option,path,0,exception);
1322           option=DestroyString(option);
1323         }
1324       font_path=DestroyString(font_path);
1325     }
1326   if ((type_list == (SplayTreeInfo *) NULL) ||
1327       (GetNumberOfNodesInSplayTree(type_list) == 0))
1328     status|=LoadTypeList(TypeMap,"built-in",0,exception);
1329   return(status != 0 ? MagickTrue : MagickFalse);
1330 #endif
1331 }
1332 \f
1333 /*
1334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1335 %                                                                             %
1336 %                                                                             %
1337 %                                                                             %
1338 +   T y p e C o m p o n e n t G e n e s i s                                   %
1339 %                                                                             %
1340 %                                                                             %
1341 %                                                                             %
1342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1343 %
1344 %  TypeComponentGenesis() instantiates the type component.
1345 %
1346 %  The format of the TypeComponentGenesis method is:
1347 %
1348 %      MagickBooleanType TypeComponentGenesis(void)
1349 %
1350 */
1351 MagickPrivate MagickBooleanType TypeComponentGenesis(void)
1352 {
1353   AcquireSemaphoreInfo(&type_semaphore);
1354   return(MagickTrue);
1355 }
1356 \f
1357 /*
1358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1359 %                                                                             %
1360 %                                                                             %
1361 %                                                                             %
1362 +   T y p e C o m p o n e n t T e r m i n u s                                 %
1363 %                                                                             %
1364 %                                                                             %
1365 %                                                                             %
1366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1367 %
1368 %  TypeComponentTerminus() destroy type component.
1369 %
1370 %  The format of the TypeComponentTerminus method is:
1371 %
1372 %      void TypeComponentTerminus(void)
1373 %
1374 */
1375 MagickPrivate void TypeComponentTerminus(void)
1376 {
1377   if (type_semaphore == (SemaphoreInfo *) NULL)
1378     AcquireSemaphoreInfo(&type_semaphore);
1379   LockSemaphoreInfo(type_semaphore);
1380   if (type_list != (SplayTreeInfo *) NULL)
1381     type_list=DestroySplayTree(type_list);
1382   instantiate_type=MagickFalse;
1383   UnlockSemaphoreInfo(type_semaphore);
1384   DestroySemaphoreInfo(&type_semaphore);
1385 }