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