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