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