]> granicus.if.org Git - imagemagick/blob - magick/type.c
(no commit message)
[imagemagick] / magick / 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 "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/client.h"
45 #include "magick/configure.h"
46 #include "magick/draw.h"
47 #include "magick/exception.h"
48 #include "magick/exception-private.h"
49 #include "magick/hashmap.h"
50 #include "magick/log.h"
51 #include "magick/memory_.h"
52 #include "magick/option.h"
53 #include "magick/semaphore.h"
54 #include "magick/splay-tree.h"
55 #include "magick/string_.h"
56 #include "magick/type.h"
57 #include "magick/token.h"
58 #include "magick/utility.h"
59 #include "magick/xml-tree.h"
60 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
61 # include "fontconfig/fontconfig.h"
62 #if (FC_VERSION < 20209)
63 #undef FC_WEIGHT_LIGHT
64 #define FC_WIDTH                  "width"    /* Int */
65 #define FC_WIDTH_ULTRACONDENSED    50
66 #define FC_WIDTH_EXTRACONDENSED    63
67 #define FC_WIDTH_CONDENSED         75
68 #define FC_WIDTH_SEMICONDENSED     87
69 #define FC_WIDTH_NORMAL            100
70 #define FC_WIDTH_SEMIEXPANDED      113
71 #define FC_WIDTH_EXPANDED          125
72 #define FC_WIDTH_EXTRAEXPANDED     150
73 #define FC_WIDTH_ULTRAEXPANDED     200
74
75 #define FC_WEIGHT_THIN             0
76 #define FC_WEIGHT_EXTRALIGHT       40
77 #define FC_WEIGHT_ULTRALIGHT       FC_WEIGHT_EXTRALIGHT
78 #define FC_WEIGHT_LIGHT            50
79 #define FC_WEIGHT_BOOK             75
80 #define FC_WEIGHT_REGULAR          80
81 #define FC_WEIGHT_NORMAL           FC_WEIGHT_REGULAR
82 #define FC_WEIGHT_MEDIUM           100
83 #define FC_WEIGHT_DEMIBOLD         180
84 #define FC_WEIGHT_SEMIBOLD         FC_WEIGHT_DEMIBOLD
85 #define FC_WEIGHT_BOLD             200
86 #define FC_WEIGHT_EXTRABOLD        205
87 #define FC_WEIGHT_ULTRABOLD        FC_WEIGHT_EXTRABOLD
88 #define FC_WEIGHT_BLACK            210
89 #define FC_WEIGHT_HEAVY            FC_WEIGHT_BLACK
90 #endif
91 #endif
92 #if defined(__WINDOWS__)
93 # include "magick/nt-feature.h"
94 #endif
95 \f
96 /*
97   Define declarations.
98 */
99 #define MagickTypeFilename  "type.xml"
100 \f
101 /*
102   Declare type map.
103 */
104 static const char
105   *TypeMap = (const char *)
106     "<?xml version=\"1.0\"?>"
107     "<typemap>"
108     "  <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
109     "  <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
110     "</typemap>";
111 \f
112 /*
113   Static declarations.
114 */
115 static SemaphoreInfo
116   *type_semaphore = (SemaphoreInfo *) NULL;
117
118 static volatile MagickBooleanType
119   instantiate_type = MagickFalse;
120
121 static SplayTreeInfo
122   *type_list = (SplayTreeInfo *) NULL;
123 \f
124 /*
125   Forward declarations.
126 */
127 static MagickBooleanType
128   InitializeTypeList(ExceptionInfo *),
129   LoadTypeLists(const char *,ExceptionInfo *);
130 \f
131 /*
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133 %                                                                             %
134 %                                                                             %
135 %                                                                             %
136 +   G e t T y p e I n f o                                                     %
137 %                                                                             %
138 %                                                                             %
139 %                                                                             %
140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 %
142 %  GetTypeInfo searches the type list for the specified name and if found
143 %  returns attributes for that type.
144 %
145 %  The format of the GetTypeInfo method is:
146 %
147 %      const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
148 %
149 %  A description of each parameter follows:
150 %
151 %    o name: the type name.
152 %
153 %    o exception: return any errors or warnings in this structure.
154 %
155 */
156 MagickExport const TypeInfo *GetTypeInfo(const char *name,
157   ExceptionInfo *exception)
158 {
159   assert(exception != (ExceptionInfo *) NULL);
160   if ((type_list == (SplayTreeInfo *) NULL) ||
161       (instantiate_type == MagickFalse))
162     if (InitializeTypeList(exception) == MagickFalse)
163       return((const TypeInfo *) NULL);
164   if ((type_list == (SplayTreeInfo *) NULL) ||
165       (GetNumberOfNodesInSplayTree(type_list) == 0))
166     return((const TypeInfo *) NULL);
167   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
168     {
169       ResetSplayTreeIterator(type_list);
170       return((const TypeInfo *) GetNextValueInSplayTree(type_list));
171     }
172   return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
173 }
174 \f
175 /*
176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
177 %                                                                             %
178 %                                                                             %
179 %                                                                             %
180 +   G e t T y p e I n f o B y F a m i l y                                     %
181 %                                                                             %
182 %                                                                             %
183 %                                                                             %
184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185 %
186 %  GetTypeInfoByFamily() searches the type list for the specified family and if
187 %  found returns attributes for that type.
188 %
189 %  Type substitution and scoring algorithm contributed by Bob Friesenhahn.
190 %
191 %  The format of the GetTypeInfoByFamily method is:
192 %
193 %      const TypeInfo *GetTypeInfoByFamily(const char *family,
194 %        const StyleType style,const StretchType stretch,
195 %        const unsigned long weight,ExceptionInfo *exception)
196 %
197 %  A description of each parameter follows:
198 %
199 %    o family: the type family.
200 %
201 %    o style: the type style.
202 %
203 %    o stretch: the type stretch.
204 %
205 %    o weight: the type weight.
206 %
207 %    o exception: return any errors or warnings in this structure.
208 %
209 */
210
211 static inline unsigned long MagickMax(const unsigned long x,
212   const unsigned long y)
213 {
214   if (x > y)
215     return(x);
216   return(y);
217 }
218
219 static inline unsigned long MagickMin(const unsigned long x,
220   const unsigned long 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 unsigned long 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   long
242     range;
243
244   register const TypeInfo
245     *p;
246
247   register long
248     i;
249
250   static 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   unsigned long
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   (void) 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   (void) 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   (void) 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-((long) MagickMax(MagickMin(weight,900),p->weight)-
361         (long) MagickMin(MagickMin(weight,900),p->weight))))/800;
362     if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
363       score+=8;
364     else
365       {
366         range=(long) UltraExpandedStretch-(long) NormalStretch;
367         score+=(8*(range-((long) MagickMax(stretch,p->stretch)-
368           (long) 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   (void) 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 %        unsigned long *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   unsigned long *number_fonts,ExceptionInfo *exception)
461 {
462   const TypeInfo
463     **fonts;
464
465   register const TypeInfo
466     *p;
467
468   register long
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 != (unsigned long *) 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   (void) 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   (void) UnlockSemaphoreInfo(type_semaphore);
499   qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
500   fonts[i]=(TypeInfo *) NULL;
501   *number_fonts=(unsigned long) 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,unsigned long *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,unsigned long *number_fonts,
553   ExceptionInfo *exception)
554 {
555   char
556     **fonts;
557
558   register const TypeInfo
559     *p;
560
561   register long
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 != (unsigned long *) 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   (void) 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   (void) UnlockSemaphoreInfo(type_semaphore);
592   qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
593   fonts[i]=(char *) NULL;
594   *number_fonts=(unsigned long) 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 long
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 < (long) 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       (void) LockSemaphoreInfo(type_semaphore);
777       if ((type_list == (SplayTreeInfo *) NULL) &&
778           (instantiate_type == MagickFalse))
779         {
780           (void) LoadTypeLists(MagickTypeFilename,exception);
781 #if defined(__WINDOWS__)
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       (void) 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 long
835     i;
836
837   unsigned long
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 < (long) 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) fprintf(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=MagickOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
864     stretch=MagickOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
865     glyphs="unknown";
866     if (type_info[i]->glyphs != (char *) NULL)
867       glyphs=type_info[i]->glyphs;
868     (void) FormatMagickString(weight,MaxTextExtent,"%lu",type_info[i]->weight);
869     (void) fprintf(file,"  Font: %s\n",name);
870     (void) fprintf(file,"    family: %s\n",family);
871     (void) fprintf(file,"    style: %s\n",style);
872     (void) fprintf(file,"    stretch: %s\n",stretch);
873     (void) fprintf(file,"    weight: %s\n",weight);
874     (void) fprintf(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 unsigned long 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 unsigned long 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(__WINDOWS__)
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=(unsigned long) atol(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(__WINDOWS__)
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               }
1155             type_info->glyphs=path;
1156             break;
1157           }
1158         break;
1159       }
1160       case 'M':
1161       case 'm':
1162       {
1163         if (LocaleCompare((char *) keyword,"metrics") == 0)
1164           {
1165             char
1166               *path;
1167
1168             path=ConstantString(token);
1169 #if defined(__WINDOWS__)
1170             if (strchr(path,'@') != (char *) NULL)
1171               SubstituteString(&path,"@ghostscript_font_path@",font_path);
1172 #endif
1173             if (IsPathAccessible(path) == MagickFalse)
1174               {
1175                 /*
1176                   Relative path.
1177                 */
1178                 path=DestroyString(path);
1179                 GetPathComponent(filename,HeadPath,font_path);
1180                 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1181                   MaxTextExtent);
1182                 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1183                 path=ConstantString(font_path);
1184               }
1185             type_info->metrics=path;
1186             break;
1187           }
1188         break;
1189       }
1190       case 'N':
1191       case 'n':
1192       {
1193         if (LocaleCompare((char *) keyword,"name") == 0)
1194           {
1195             type_info->name=ConstantString(token);
1196             break;
1197           }
1198         break;
1199       }
1200       case 'S':
1201       case 's':
1202       {
1203         if (LocaleCompare((char *) keyword,"stealth") == 0)
1204           {
1205             type_info->stealth=IsMagickTrue(token);
1206             break;
1207           }
1208         if (LocaleCompare((char *) keyword,"stretch") == 0)
1209           {
1210             type_info->stretch=(StretchType) ParseMagickOption(
1211               MagickStretchOptions,MagickFalse,token);
1212             break;
1213           }
1214         if (LocaleCompare((char *) keyword,"style") == 0)
1215           {
1216             type_info->style=(StyleType) ParseMagickOption(MagickStyleOptions,
1217               MagickFalse,token);
1218             break;
1219           }
1220         break;
1221       }
1222       case 'W':
1223       case 'w':
1224       {
1225         if (LocaleCompare((char *) keyword,"weight") == 0)
1226           {
1227             type_info->weight=(unsigned long) atol(token);
1228             if (LocaleCompare(token,"bold") == 0)
1229               type_info->weight=700;
1230             if (LocaleCompare(token,"normal") == 0)
1231               type_info->weight=400;
1232             break;
1233           }
1234         break;
1235       }
1236       default:
1237         break;
1238     }
1239   }
1240   token=(char *) RelinquishMagickMemory(token);
1241   return(status);
1242 }
1243 \f
1244 /*
1245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246 %                                                                             %
1247 %                                                                             %
1248 %                                                                             %
1249 %  L o a d T y p e L i s t s                                                  %
1250 %                                                                             %
1251 %                                                                             %
1252 %                                                                             %
1253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254 %
1255 %  LoadTypeList() loads one or more type configuration files which provides a
1256 %  mapping between type attributes and a type name.
1257 %
1258 %  The format of the LoadTypeLists method is:
1259 %
1260 %      MagickBooleanType LoadTypeLists(const char *filename,
1261 %        ExceptionInfo *exception)
1262 %
1263 %  A description of each parameter follows:
1264 %
1265 %    o filename: the font file name.
1266 %
1267 %    o exception: return any errors or warnings in this structure.
1268 %
1269 */
1270 static MagickBooleanType LoadTypeLists(const char *filename,
1271   ExceptionInfo *exception)
1272 {
1273 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1274   return(LoadTypeList(TypeMap,"built-in",0,exception));
1275 #else
1276   char
1277     *font_path,
1278     path[MaxTextExtent];
1279
1280   const StringInfo
1281     *option;
1282
1283   LinkedListInfo
1284     *options;
1285
1286   MagickStatusType
1287     status;
1288
1289   status=MagickFalse;
1290   *path='\0';
1291   options=GetConfigureOptions(filename,exception);
1292   option=(const StringInfo *) GetNextValueInLinkedList(options);
1293   while (option != (const StringInfo *) NULL)
1294   {
1295     (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1296     status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1297       GetStringInfoPath(option),0,exception);
1298     option=(const StringInfo *) GetNextValueInLinkedList(options);
1299   }
1300   options=DestroyConfigureOptions(options);
1301   font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1302   if (font_path != (char *) NULL)
1303     {
1304       char
1305         *option;
1306
1307       /*
1308         Search MAGICK_FONT_PATH.
1309       */
1310       (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",font_path,
1311         DirectorySeparator,filename);
1312       option=FileToString(path,~0,exception);
1313       if (option != (void *) NULL)
1314         {
1315           status|=LoadTypeList(option,path,0,exception);
1316           option=DestroyString(option);
1317         }
1318       font_path=DestroyString(font_path);
1319     }
1320   if ((type_list == (SplayTreeInfo *) NULL) ||
1321       (GetNumberOfNodesInSplayTree(type_list) == 0))
1322     status|=LoadTypeList(TypeMap,"built-in",0,exception);
1323   return(status != 0 ? MagickTrue : MagickFalse);
1324 #endif
1325 }
1326 \f
1327 /*
1328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329 %                                                                             %
1330 %                                                                             %
1331 %                                                                             %
1332 +   T y p e C o m p o n e n t G e n e s i s                                   %
1333 %                                                                             %
1334 %                                                                             %
1335 %                                                                             %
1336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 %
1338 %  TypeComponentGenesis() instantiates the type component.
1339 %
1340 %  The format of the TypeComponentGenesis method is:
1341 %
1342 %      MagickBooleanType TypeComponentGenesis(void)
1343 %
1344 */
1345 MagickExport MagickBooleanType TypeComponentGenesis(void)
1346 {
1347   assert(type_semaphore == (SemaphoreInfo *) NULL);
1348   type_semaphore=AllocateSemaphoreInfo();
1349   return(MagickTrue);
1350 }
1351 \f
1352 /*
1353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1354 %                                                                             %
1355 %                                                                             %
1356 %                                                                             %
1357 +   T y p e C o m p o n e n t T e r m i n u s                                 %
1358 %                                                                             %
1359 %                                                                             %
1360 %                                                                             %
1361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1362 %
1363 %  TypeComponentTerminus() destroy type component.
1364 %
1365 %  The format of the TypeComponentTerminus method is:
1366 %
1367 %      void TypeComponentTerminus(void)
1368 %
1369 */
1370 MagickExport void TypeComponentTerminus(void)
1371 {
1372   if (type_semaphore == (SemaphoreInfo *) NULL)
1373     AcquireSemaphoreInfo(&type_semaphore);
1374   (void) LockSemaphoreInfo(type_semaphore);
1375   if (type_list != (SplayTreeInfo *) NULL)
1376     type_list=DestroySplayTree(type_list);
1377   instantiate_type=MagickFalse;
1378   (void) UnlockSemaphoreInfo(type_semaphore);
1379   DestroySemaphoreInfo(&type_semaphore);
1380 }