2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % TTTTT Y Y PPPP EEEEE %
13 % MagickCore Image Type Methods %
20 % Copyright 1999-2007 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
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
95 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
96 # include "MagickCore/nt-feature.h"
102 #define MagickTypeFilename "type.xml"
108 *TypeMap = (const char *)
109 "<?xml version=\"1.0\"?>"
111 " <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
112 " <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
119 *type_semaphore = (SemaphoreInfo *) NULL;
121 static volatile MagickBooleanType
122 instantiate_type = MagickFalse;
125 *type_list = (SplayTreeInfo *) NULL;
128 Forward declarations.
130 static MagickBooleanType
131 InitializeTypeList(ExceptionInfo *),
132 LoadTypeLists(const char *,ExceptionInfo *);
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 + G e t T y p e I n f o %
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145 % GetTypeInfo searches the type list for the specified name and if found
146 % returns attributes for that type.
148 % The format of the GetTypeInfo method is:
150 % const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
152 % A description of each parameter follows:
154 % o name: the type name.
156 % o exception: return any errors or warnings in this structure.
159 MagickExport const TypeInfo *GetTypeInfo(const char *name,
160 ExceptionInfo *exception)
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))
172 ResetSplayTreeIterator(type_list);
173 return((const TypeInfo *) GetNextValueInSplayTree(type_list));
175 return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
183 + G e t T y p e I n f o B y F a m i l y %
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189 % GetTypeInfoByFamily() searches the type list for the specified family and if
190 % found returns attributes for that type.
192 % Type substitution and scoring algorithm contributed by Bob Friesenhahn.
194 % The format of the GetTypeInfoByFamily method is:
196 % const TypeInfo *GetTypeInfoByFamily(const char *family,
197 % const StyleType style,const StretchType stretch,
198 % const size_t weight,ExceptionInfo *exception)
200 % A description of each parameter follows:
202 % o family: the type family.
204 % o style: the type style.
206 % o stretch: the type stretch.
208 % o weight: the type weight.
210 % o exception: return any errors or warnings in this structure.
214 static inline size_t MagickMax(const size_t x,
222 static inline size_t MagickMin(const size_t x,
230 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
231 const StyleType style,const StretchType stretch,const size_t weight,
232 ExceptionInfo *exception)
234 typedef struct _Fontmap
244 register const TypeInfo
256 { "fixed", "courier" },
257 { "modern","courier" },
258 { "monotype corsiva", "courier" },
259 { "news gothic", "helvetica" },
260 { "system", "courier" },
261 { "terminal", "courier" },
262 { "wingdings", "symbol" },
271 Check for an exact type match.
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)
282 if (p->family == (char *) NULL)
284 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
287 if (family == (const char *) NULL)
289 if ((LocaleCompare(p->family,"arial") != 0) &&
290 (LocaleCompare(p->family,"helvetica") != 0))
292 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
297 if (LocaleCompare(p->family,family) != 0)
299 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
302 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
304 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
307 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
308 (p->stretch != stretch))
310 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
313 if ((weight != 0) && (p->weight != weight))
315 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
321 UnlockSemaphoreInfo(type_semaphore);
322 if (type_info != (const TypeInfo *) NULL)
325 Check for types in the same family.
328 LockSemaphoreInfo(type_semaphore);
329 ResetSplayTreeIterator(type_list);
330 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
331 while (p != (const TypeInfo *) NULL)
333 if (p->family == (char *) NULL)
335 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
338 if (family == (const char *) NULL)
340 if ((LocaleCompare(p->family,"arial") != 0) &&
341 (LocaleCompare(p->family,"helvetica") != 0))
343 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
348 if (LocaleCompare(p->family,family) != 0)
350 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
354 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
357 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
358 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
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))
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;
373 if (score > max_score)
378 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
380 UnlockSemaphoreInfo(type_semaphore);
381 if (type_info != (const TypeInfo *) NULL)
384 Check for table-based substitution match.
386 for (i=0; fontmap[i].name != (char *) NULL; i++)
388 if (family == (const char *) NULL)
390 if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
391 (LocaleCompare(fontmap[i].name,"helvetica") != 0))
395 if (LocaleCompare(fontmap[i].name,family) != 0)
397 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
401 if (type_info != (const TypeInfo *) NULL)
403 (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
404 "FontSubstitutionRequired","`%s'",type_info->family);
407 if (family != (const char *) NULL)
408 type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418 % G e t T y p e I n f o L i s t %
422 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 % GetTypeInfoList() returns any fonts that match the specified pattern.
426 % The format of the GetTypeInfoList function is:
428 % const TypeInfo **GetTypeInfoList(const char *pattern,
429 % size_t *number_fonts,ExceptionInfo *exception)
431 % A description of each parameter follows:
433 % o pattern: Specifies a pointer to a text string containing a pattern.
435 % o number_fonts: This integer returns the number of types in the list.
437 % o exception: return any errors or warnings in this structure.
441 #if defined(__cplusplus) || defined(c_plusplus)
445 static int TypeInfoCompare(const void *x,const void *y)
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));
458 #if defined(__cplusplus) || defined(c_plusplus)
462 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
463 size_t *number_fonts,ExceptionInfo *exception)
468 register const TypeInfo
477 assert(pattern != (char *) NULL);
478 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
479 assert(number_fonts != (size_t *) NULL);
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);
491 LockSemaphoreInfo(type_semaphore);
492 ResetSplayTreeIterator(type_list);
493 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
494 for (i=0; p != (const TypeInfo *) NULL; )
496 if ((p->stealth == MagickFalse) &&
497 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
499 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
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;
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 % G e t T y p e L i s t %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 % GetTypeList() returns any fonts that match the specified pattern.
521 % The format of the GetTypeList function is:
523 % char **GetTypeList(const char *pattern,size_t *number_fonts,
524 % ExceptionInfo *exception)
526 % A description of each parameter follows:
528 % o pattern: Specifies a pointer to a text string containing a pattern.
530 % o number_fonts: This integer returns the number of fonts in the list.
532 % o exception: return any errors or warnings in this structure.
536 #if defined(__cplusplus) || defined(c_plusplus)
540 static int TypeCompare(const void *x,const void *y)
548 return(LocaleCompare(*p,*q));
551 #if defined(__cplusplus) || defined(c_plusplus)
555 MagickExport char **GetTypeList(const char *pattern,size_t *number_fonts,
556 ExceptionInfo *exception)
561 register const TypeInfo
570 assert(pattern != (char *) NULL);
571 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
572 assert(number_fonts != (size_t *) NULL);
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);
584 LockSemaphoreInfo(type_semaphore);
585 ResetSplayTreeIterator(type_list);
586 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
587 for (i=0; p != (const TypeInfo *) NULL; )
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);
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;
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606 + I n i t i a l i z e T y p e L i s t %
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 % InitializeTypeList() initializes the type list.
614 % The format of the InitializeTypeList method is:
616 % MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
618 % A description of each parameter follows.
620 % o exception: return any errors or warnings in this structure.
624 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
625 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
626 ExceptionInfo *exception)
629 extension[MaxTextExtent],
667 font_config=FcInitLoadConfigAndFonts();
668 if (font_config == (FcConfig *) NULL)
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)
675 pattern=FcPatternCreate();
676 if (pattern != (FcPattern *) NULL)
678 font_set=FcFontList(0,pattern,object_set);
679 FcPatternDestroy(pattern);
681 FcObjectSetDestroy(object_set);
683 if (font_set == (FcFontSet *) NULL)
685 FcConfigDestroy(font_config);
688 for (i=0; i < (ssize_t) font_set->nfont; i++)
690 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
691 if (status != FcResultMatch)
693 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
694 if (status != FcResultMatch)
697 GetPathComponent((const char *) file,ExtensionPath,extension);
698 if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
700 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
701 if (type_info == (TypeInfo *) NULL)
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);
766 FcFontSetDestroy(font_set);
767 FcConfigDestroy(font_config);
772 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
774 if ((type_list == (SplayTreeInfo *) NULL) &&
775 (instantiate_type == MagickFalse))
777 if (type_semaphore == (SemaphoreInfo *) NULL)
778 AcquireSemaphoreInfo(&type_semaphore);
779 LockSemaphoreInfo(type_semaphore);
780 if ((type_list == (SplayTreeInfo *) NULL) &&
781 (instantiate_type == MagickFalse))
783 (void) LoadTypeLists(MagickTypeFilename,exception);
784 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
785 (void) NTLoadTypeLists(type_list,exception);
787 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
788 (void) LoadFontConfigFonts(type_list,exception);
790 instantiate_type=MagickTrue;
792 UnlockSemaphoreInfo(type_semaphore);
794 return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 % L i s t T y p e I n f o %
806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 % ListTypeInfo() lists the fonts to a file.
810 % The format of the ListTypeInfo method is:
812 % MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
814 % A description of each parameter follows.
816 % o file: An pointer to a FILE.
818 % o exception: return any errors or warnings in this structure.
821 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
824 weight[MaxTextExtent];
843 if (file == (FILE *) NULL)
846 type_info=GetTypeInfoList("*",&number_fonts,exception);
847 if (type_info == (const TypeInfo **) NULL)
850 path=(const char *) NULL;
851 for (i=0; i < (ssize_t) number_fonts; i++)
853 if (type_info[i]->stealth != MagickFalse)
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;
861 if (type_info[i]->name != (char *) NULL)
862 name=type_info[i]->name;
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);
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);
881 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890 + L o a d T y p e L i s t %
894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 % LoadTypeList() loads the type configuration file which provides a mapping
897 % between type attributes and a type name.
899 % The format of the LoadTypeList method is:
901 % MagickBooleanType LoadTypeList(const char *xml,const char *filename,
902 % const size_t depth,ExceptionInfo *exception)
904 % A description of each parameter follows:
906 % o xml: The type list in XML format.
908 % o filename: The type list filename.
910 % o depth: depth of <include /> statements.
912 % o exception: return any errors or warnings in this structure.
916 static void *DestroyTypeNode(void *type_info)
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));
943 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
944 const size_t depth,ExceptionInfo *exception)
947 font_path[MaxTextExtent],
948 keyword[MaxTextExtent],
961 Load the type map file.
963 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
964 "Loading type configure file \"%s\" ...",filename);
965 if (xml == (const char *) NULL)
967 if (type_list == (SplayTreeInfo *) NULL)
969 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
971 if (type_list == (SplayTreeInfo *) NULL)
973 ThrowFileException(exception,ResourceLimitError,
974 "MemoryAllocationFailed",filename);
979 type_info=(TypeInfo *) NULL;
980 token=AcquireString(xml);
981 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
983 Determine the Ghostscript font path.
986 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
987 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
989 for (q=(char *) xml; *q != '\0'; )
994 GetMagickToken(q,&q,token);
997 (void) CopyMagickString(keyword,token,MaxTextExtent);
998 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1003 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1004 GetMagickToken(q,&q,token);
1007 if (LocaleNCompare(keyword,"<!--",4) == 0)
1012 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1013 GetMagickToken(q,&q,token);
1016 if (LocaleCompare(keyword,"<include") == 0)
1021 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1023 (void) CopyMagickString(keyword,token,MaxTextExtent);
1024 GetMagickToken(q,&q,token);
1027 GetMagickToken(q,&q,token);
1028 if (LocaleCompare(keyword,"file") == 0)
1031 (void) ThrowMagickException(exception,GetMagickModule(),
1032 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
1036 path[MaxTextExtent],
1043 GetPathComponent(filename,HeadPath,path);
1045 (void) ConcatenateMagickString(path,DirectorySeparator,
1047 if (*token == *DirectorySeparator)
1048 (void) CopyMagickString(path,token,MaxTextExtent);
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)
1056 status=LoadTypeList(xml,path,depth+1,exception);
1057 xml=(char *) RelinquishMagickMemory(xml);
1064 if (LocaleCompare(keyword,"<type") == 0)
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;
1077 if (type_info == (TypeInfo *) NULL)
1079 if (LocaleCompare(keyword,"/>") == 0)
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;
1087 GetMagickToken(q,(const char **) NULL,token);
1090 GetMagickToken(q,&q,token);
1091 GetMagickToken(q,&q,token);
1097 if (LocaleCompare((char *) keyword,"encoding") == 0)
1099 type_info->encoding=ConstantString(token);
1107 if (LocaleCompare((char *) keyword,"face") == 0)
1109 type_info->face=StringToUnsignedLong(token);
1112 if (LocaleCompare((char *) keyword,"family") == 0)
1114 type_info->family=ConstantString(token);
1117 if (LocaleCompare((char *) keyword,"format") == 0)
1119 type_info->format=ConstantString(token);
1122 if (LocaleCompare((char *) keyword,"foundry") == 0)
1124 type_info->foundry=ConstantString(token);
1127 if (LocaleCompare((char *) keyword,"fullname") == 0)
1129 type_info->description=ConstantString(token);
1137 if (LocaleCompare((char *) keyword,"glyphs") == 0)
1142 path=ConstantString(token);
1143 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1144 if (strchr(path,'@') != (char *) NULL)
1145 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1147 if (IsPathAccessible(path) == MagickFalse)
1152 path=DestroyString(path);
1153 GetPathComponent(filename,HeadPath,font_path);
1154 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1156 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1157 path=ConstantString(font_path);
1158 if (IsPathAccessible(path) == MagickFalse)
1160 path=DestroyString(path);
1161 path=ConstantString(token);
1164 type_info->glyphs=path;
1172 if (LocaleCompare((char *) keyword,"metrics") == 0)
1177 path=ConstantString(token);
1178 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1179 if (strchr(path,'@') != (char *) NULL)
1180 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1182 if (IsPathAccessible(path) == MagickFalse)
1187 path=DestroyString(path);
1188 GetPathComponent(filename,HeadPath,font_path);
1189 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1191 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1192 path=ConstantString(font_path);
1194 type_info->metrics=path;
1202 if (LocaleCompare((char *) keyword,"name") == 0)
1204 type_info->name=ConstantString(token);
1212 if (LocaleCompare((char *) keyword,"stealth") == 0)
1214 type_info->stealth=IsMagickTrue(token);
1217 if (LocaleCompare((char *) keyword,"stretch") == 0)
1219 type_info->stretch=(StretchType) ParseCommandOption(
1220 MagickStretchOptions,MagickFalse,token);
1223 if (LocaleCompare((char *) keyword,"style") == 0)
1225 type_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1234 if (LocaleCompare((char *) keyword,"weight") == 0)
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;
1249 token=(char *) RelinquishMagickMemory(token);
1254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1258 % L o a d T y p e L i s t s %
1262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 % LoadTypeList() loads one or more type configuration files which provides a
1265 % mapping between type attributes and a type name.
1267 % The format of the LoadTypeLists method is:
1269 % MagickBooleanType LoadTypeLists(const char *filename,
1270 % ExceptionInfo *exception)
1272 % A description of each parameter follows:
1274 % o filename: the font file name.
1276 % o exception: return any errors or warnings in this structure.
1279 static MagickBooleanType LoadTypeLists(const char *filename,
1280 ExceptionInfo *exception)
1282 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1283 return(LoadTypeList(TypeMap,"built-in",0,exception));
1287 path[MaxTextExtent];
1300 options=GetConfigureOptions(filename,exception);
1301 option=(const StringInfo *) GetNextValueInLinkedList(options);
1302 while (option != (const StringInfo *) NULL)
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);
1309 options=DestroyConfigureOptions(options);
1310 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1311 if (font_path != (char *) NULL)
1317 Search MAGICK_FONT_PATH.
1319 (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",font_path,
1320 DirectorySeparator,filename);
1321 option=FileToString(path,~0,exception);
1322 if (option != (void *) NULL)
1324 status|=LoadTypeList(option,path,0,exception);
1325 option=DestroyString(option);
1327 font_path=DestroyString(font_path);
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);
1337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341 + T y p e C o m p o n e n t G e n e s i s %
1345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1347 % TypeComponentGenesis() instantiates the type component.
1349 % The format of the TypeComponentGenesis method is:
1351 % MagickBooleanType TypeComponentGenesis(void)
1354 MagickPrivate MagickBooleanType TypeComponentGenesis(void)
1356 AcquireSemaphoreInfo(&type_semaphore);
1361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1365 + T y p e C o m p o n e n t T e r m i n u s %
1369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1371 % TypeComponentTerminus() destroy type component.
1373 % The format of the TypeComponentTerminus method is:
1375 % void TypeComponentTerminus(void)
1378 MagickPrivate void TypeComponentTerminus(void)
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);