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