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