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