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 "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/client.h"
45 #include "magick/configure.h"
46 #include "magick/draw.h"
47 #include "magick/exception.h"
48 #include "magick/exception-private.h"
49 #include "magick/hashmap.h"
50 #include "magick/log.h"
51 #include "magick/memory_.h"
52 #include "magick/option.h"
53 #include "magick/semaphore.h"
54 #include "magick/splay-tree.h"
55 #include "magick/string_.h"
56 #include "magick/string-private.h"
57 #include "magick/type.h"
58 #include "magick/token.h"
59 #include "magick/utility.h"
60 #include "magick/xml-tree.h"
61 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
62 # include "fontconfig/fontconfig.h"
63 #if (FC_VERSION < 20209)
64 #undef FC_WEIGHT_LIGHT
65 #define FC_WIDTH "width" /* Int */
66 #define FC_WIDTH_ULTRACONDENSED 50
67 #define FC_WIDTH_EXTRACONDENSED 63
68 #define FC_WIDTH_CONDENSED 75
69 #define FC_WIDTH_SEMICONDENSED 87
70 #define FC_WIDTH_NORMAL 100
71 #define FC_WIDTH_SEMIEXPANDED 113
72 #define FC_WIDTH_EXPANDED 125
73 #define FC_WIDTH_EXTRAEXPANDED 150
74 #define FC_WIDTH_ULTRAEXPANDED 200
76 #define FC_WEIGHT_THIN 0
77 #define FC_WEIGHT_EXTRALIGHT 40
78 #define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
79 #define FC_WEIGHT_LIGHT 50
80 #define FC_WEIGHT_BOOK 75
81 #define FC_WEIGHT_REGULAR 80
82 #define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
83 #define FC_WEIGHT_MEDIUM 100
84 #define FC_WEIGHT_DEMIBOLD 180
85 #define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
86 #define FC_WEIGHT_BOLD 200
87 #define FC_WEIGHT_EXTRABOLD 205
88 #define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
89 #define FC_WEIGHT_BLACK 210
90 #define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
93 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
94 # include "magick/nt-feature.h"
100 #define MagickTypeFilename "type.xml"
106 *TypeMap = (const char *)
107 "<?xml version=\"1.0\"?>"
109 " <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
110 " <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
117 *type_semaphore = (SemaphoreInfo *) NULL;
119 static volatile MagickBooleanType
120 instantiate_type = MagickFalse;
123 *type_list = (SplayTreeInfo *) NULL;
126 Forward declarations.
128 static MagickBooleanType
129 InitializeTypeList(ExceptionInfo *),
130 LoadTypeLists(const char *,ExceptionInfo *);
133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 + G e t T y p e I n f o %
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 % GetTypeInfo searches the type list for the specified name and if found
144 % returns attributes for that type.
146 % The format of the GetTypeInfo method is:
148 % const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
150 % A description of each parameter follows:
152 % o name: the type name.
154 % o exception: return any errors or warnings in this structure.
157 MagickExport const TypeInfo *GetTypeInfo(const char *name,
158 ExceptionInfo *exception)
160 assert(exception != (ExceptionInfo *) NULL);
161 if ((type_list == (SplayTreeInfo *) NULL) ||
162 (instantiate_type == MagickFalse))
163 if (InitializeTypeList(exception) == MagickFalse)
164 return((const TypeInfo *) NULL);
165 if ((type_list == (SplayTreeInfo *) NULL) ||
166 (GetNumberOfNodesInSplayTree(type_list) == 0))
167 return((const TypeInfo *) NULL);
168 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
170 ResetSplayTreeIterator(type_list);
171 return((const TypeInfo *) GetNextValueInSplayTree(type_list));
173 return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181 + G e t T y p e I n f o B y F a m i l y %
185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 % GetTypeInfoByFamily() searches the type list for the specified family and if
188 % found returns attributes for that type.
190 % Type substitution and scoring algorithm contributed by Bob Friesenhahn.
192 % The format of the GetTypeInfoByFamily method is:
194 % const TypeInfo *GetTypeInfoByFamily(const char *family,
195 % const StyleType style,const StretchType stretch,
196 % const unsigned long weight,ExceptionInfo *exception)
198 % A description of each parameter follows:
200 % o family: the type family.
202 % o style: the type style.
204 % o stretch: the type stretch.
206 % o weight: the type weight.
208 % o exception: return any errors or warnings in this structure.
212 static inline unsigned long MagickMax(const unsigned long x,
213 const unsigned long y)
220 static inline unsigned long MagickMin(const unsigned long x,
221 const unsigned long y)
228 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
229 const StyleType style,const StretchType stretch,const unsigned long weight,
230 ExceptionInfo *exception)
232 typedef struct _Fontmap
245 register const TypeInfo
254 { "fixed", "courier" },
255 { "modern","courier" },
256 { "monotype corsiva", "courier" },
257 { "news gothic", "helvetica" },
258 { "system", "courier" },
259 { "terminal", "courier" },
260 { "wingdings", "symbol" },
269 Check for an exact type match.
271 (void) GetTypeInfo("*",exception);
272 if (type_list == (SplayTreeInfo *) NULL)
273 return((TypeInfo *) NULL);
274 LockSemaphoreInfo(type_semaphore);
275 ResetSplayTreeIterator(type_list);
276 type_info=(const TypeInfo *) NULL;
277 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
278 while (p != (const TypeInfo *) NULL)
280 if (p->family == (char *) NULL)
282 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
285 if (family == (const char *) NULL)
287 if ((LocaleCompare(p->family,"arial") != 0) &&
288 (LocaleCompare(p->family,"helvetica") != 0))
290 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
295 if (LocaleCompare(p->family,family) != 0)
297 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
300 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
302 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
305 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
306 (p->stretch != stretch))
308 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
311 if ((weight != 0) && (p->weight != weight))
313 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
319 UnlockSemaphoreInfo(type_semaphore);
320 if (type_info != (const TypeInfo *) NULL)
323 Check for types in the same family.
326 LockSemaphoreInfo(type_semaphore);
327 ResetSplayTreeIterator(type_list);
328 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
329 while (p != (const TypeInfo *) NULL)
331 if (p->family == (char *) NULL)
333 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
336 if (family == (const char *) NULL)
338 if ((LocaleCompare(p->family,"arial") != 0) &&
339 (LocaleCompare(p->family,"helvetica") != 0))
341 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
346 if (LocaleCompare(p->family,family) != 0)
348 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
352 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
355 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
356 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
361 score+=(16*(800-((long) MagickMax(MagickMin(weight,900),p->weight)-
362 (long) MagickMin(MagickMin(weight,900),p->weight))))/800;
363 if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
367 range=(long) UltraExpandedStretch-(long) NormalStretch;
368 score+=(8*(range-((long) MagickMax(stretch,p->stretch)-
369 (long) MagickMin(stretch,p->stretch))))/range;
371 if (score > max_score)
376 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
378 UnlockSemaphoreInfo(type_semaphore);
379 if (type_info != (const TypeInfo *) NULL)
382 Check for table-based substitution match.
384 for (i=0; fontmap[i].name != (char *) NULL; i++)
386 if (family == (const char *) NULL)
388 if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
389 (LocaleCompare(fontmap[i].name,"helvetica") != 0))
393 if (LocaleCompare(fontmap[i].name,family) != 0)
395 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
399 if (type_info != (const TypeInfo *) NULL)
401 (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
402 "FontSubstitutionRequired","`%s'",type_info->family);
405 if (family != (const char *) NULL)
406 type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
416 % G e t T y p e I n f o L i s t %
420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422 % GetTypeInfoList() returns any fonts that match the specified pattern.
424 % The format of the GetTypeInfoList function is:
426 % const TypeInfo **GetTypeInfoList(const char *pattern,
427 % unsigned long *number_fonts,ExceptionInfo *exception)
429 % A description of each parameter follows:
431 % o pattern: Specifies a pointer to a text string containing a pattern.
433 % o number_fonts: This integer returns the number of types in the list.
435 % o exception: return any errors or warnings in this structure.
439 #if defined(__cplusplus) || defined(c_plusplus)
443 static int TypeInfoCompare(const void *x,const void *y)
449 p=(const TypeInfo **) x,
450 q=(const TypeInfo **) y;
451 if (LocaleCompare((*p)->path,(*q)->path) == 0)
452 return(LocaleCompare((*p)->name,(*q)->name));
453 return(LocaleCompare((*p)->path,(*q)->path));
456 #if defined(__cplusplus) || defined(c_plusplus)
460 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
461 unsigned long *number_fonts,ExceptionInfo *exception)
466 register const TypeInfo
475 assert(pattern != (char *) NULL);
476 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
477 assert(number_fonts != (unsigned long *) NULL);
479 p=GetTypeInfo("*",exception);
480 if (p == (const TypeInfo *) NULL)
481 return((const TypeInfo **) NULL);
482 fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
483 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
484 if (fonts == (const TypeInfo **) NULL)
485 return((const TypeInfo **) NULL);
489 LockSemaphoreInfo(type_semaphore);
490 ResetSplayTreeIterator(type_list);
491 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
492 for (i=0; p != (const TypeInfo *) NULL; )
494 if ((p->stealth == MagickFalse) &&
495 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
497 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
499 UnlockSemaphoreInfo(type_semaphore);
500 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
501 fonts[i]=(TypeInfo *) NULL;
502 *number_fonts=(unsigned long) i;
507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511 % G e t T y p e L i s t %
515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517 % GetTypeList() returns any fonts that match the specified pattern.
519 % The format of the GetTypeList function is:
521 % char **GetTypeList(const char *pattern,unsigned long *number_fonts,
522 % ExceptionInfo *exception)
524 % A description of each parameter follows:
526 % o pattern: Specifies a pointer to a text string containing a pattern.
528 % o number_fonts: This integer returns the number of fonts in the list.
530 % o exception: return any errors or warnings in this structure.
534 #if defined(__cplusplus) || defined(c_plusplus)
538 static int TypeCompare(const void *x,const void *y)
546 return(LocaleCompare(*p,*q));
549 #if defined(__cplusplus) || defined(c_plusplus)
553 MagickExport char **GetTypeList(const char *pattern,unsigned long *number_fonts,
554 ExceptionInfo *exception)
559 register const TypeInfo
568 assert(pattern != (char *) NULL);
569 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
570 assert(number_fonts != (unsigned long *) NULL);
572 p=GetTypeInfo("*",exception);
573 if (p == (const TypeInfo *) NULL)
574 return((char **) NULL);
575 fonts=(char **) AcquireQuantumMemory((size_t)
576 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
577 if (fonts == (char **) NULL)
578 return((char **) NULL);
582 LockSemaphoreInfo(type_semaphore);
583 ResetSplayTreeIterator(type_list);
584 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
585 for (i=0; p != (const TypeInfo *) NULL; )
587 if ((p->stealth == MagickFalse) &&
588 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
589 fonts[i++]=ConstantString(p->name);
590 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
592 UnlockSemaphoreInfo(type_semaphore);
593 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
594 fonts[i]=(char *) NULL;
595 *number_fonts=(unsigned long) i;
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 + I n i t i a l i z e T y p e L i s t %
608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 % InitializeTypeList() initializes the type list.
612 % The format of the InitializeTypeList method is:
614 % MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
616 % A description of each parameter follows.
618 % o exception: return any errors or warnings in this structure.
622 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
623 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
624 ExceptionInfo *exception)
627 extension[MaxTextExtent],
665 font_config=FcInitLoadConfigAndFonts();
666 if (font_config == (FcConfig *) NULL)
668 font_set=(FcFontSet *) NULL;
669 object_set=FcObjectSetBuild(FC_FAMILY,FC_STYLE,FC_SLANT,FC_WIDTH,FC_WEIGHT,
670 FC_FILE,(char *) NULL);
671 if (object_set != (FcObjectSet *) NULL)
673 pattern=FcPatternCreate();
674 if (pattern != (FcPattern *) NULL)
676 font_set=FcFontList(0,pattern,object_set);
677 FcPatternDestroy(pattern);
679 FcObjectSetDestroy(object_set);
681 if (font_set == (FcFontSet *) NULL)
683 FcConfigDestroy(font_config);
686 for (i=0; i < (long) font_set->nfont; i++)
688 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
689 if (status != FcResultMatch)
691 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
692 if (status != FcResultMatch)
695 GetPathComponent((const char *) file,ExtensionPath,extension);
696 if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
698 type_info=(TypeInfo *) AcquireAlignedMemory(1,sizeof(*type_info));
699 if (type_info == (TypeInfo *) NULL)
701 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
702 type_info->path=ConstantString("System Fonts");
703 type_info->signature=MagickSignature;
704 (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
705 (void) ConcatenateMagickString(name," ",MaxTextExtent);
706 status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
707 if (status == FcResultMatch)
708 (void) ConcatenateMagickString(name,(const char *) style,MaxTextExtent);
709 type_info->name=ConstantString(name);
710 (void) SubstituteString(&type_info->name," ","-");
711 (void) SubstituteString(&type_info->name,"-L-","-");
712 (void) SubstituteString(&type_info->name,"semicondensed","SemiCondensed");
713 type_info->family=ConstantString((const char *) family);
714 (void) SubstituteString(&type_info->family," L","");
715 status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
716 type_info->style=NormalStyle;
717 if (slant == FC_SLANT_ITALIC)
718 type_info->style=ItalicStyle;
719 if (slant == FC_SLANT_OBLIQUE)
720 type_info->style=ObliqueStyle;
721 status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
722 type_info->stretch=NormalStretch;
723 if (width >= FC_WIDTH_ULTRACONDENSED)
724 type_info->stretch=UltraCondensedStretch;
725 if (width >= FC_WIDTH_EXTRACONDENSED)
726 type_info->stretch=ExtraCondensedStretch;
727 if (width >= FC_WIDTH_CONDENSED)
728 type_info->stretch=CondensedStretch;
729 if (width >= FC_WIDTH_SEMICONDENSED)
730 type_info->stretch=SemiCondensedStretch;
731 if (width >= FC_WIDTH_NORMAL)
732 type_info->stretch=NormalStretch;
733 if (width >= FC_WIDTH_SEMIEXPANDED)
734 type_info->stretch=SemiExpandedStretch;
735 if (width >= FC_WIDTH_EXPANDED)
736 type_info->stretch=ExpandedStretch;
737 if (width >= FC_WIDTH_EXTRAEXPANDED)
738 type_info->stretch=ExtraExpandedStretch;
739 if (width >= FC_WIDTH_ULTRAEXPANDED)
740 type_info->stretch=UltraExpandedStretch;
741 type_info->weight=400;
742 status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
743 if (weight >= FC_WEIGHT_THIN)
744 type_info->weight=100;
745 if (weight >= FC_WEIGHT_EXTRALIGHT)
746 type_info->weight=200;
747 if (weight >= FC_WEIGHT_LIGHT)
748 type_info->weight=300;
749 if (weight >= FC_WEIGHT_NORMAL)
750 type_info->weight=400;
751 if (weight >= FC_WEIGHT_MEDIUM)
752 type_info->weight=500;
753 if (weight >= FC_WEIGHT_DEMIBOLD)
754 type_info->weight=600;
755 if (weight >= FC_WEIGHT_BOLD)
756 type_info->weight=700;
757 if (weight >= FC_WEIGHT_EXTRABOLD)
758 type_info->weight=800;
759 if (weight >= FC_WEIGHT_BLACK)
760 type_info->weight=900;
761 type_info->glyphs=ConstantString((const char *) file);
762 (void) AddValueToSplayTree(type_list,type_info->name,type_info);
764 FcFontSetDestroy(font_set);
765 FcConfigDestroy(font_config);
770 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
772 if ((type_list == (SplayTreeInfo *) NULL) &&
773 (instantiate_type == MagickFalse))
775 if (type_semaphore == (SemaphoreInfo *) NULL)
776 AcquireSemaphoreInfo(&type_semaphore);
777 LockSemaphoreInfo(type_semaphore);
778 if ((type_list == (SplayTreeInfo *) NULL) &&
779 (instantiate_type == MagickFalse))
781 (void) LoadTypeLists(MagickTypeFilename,exception);
782 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
783 (void) NTLoadTypeLists(type_list,exception);
785 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
786 (void) LoadFontConfigFonts(type_list,exception);
788 instantiate_type=MagickTrue;
790 UnlockSemaphoreInfo(type_semaphore);
792 return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
800 % L i s t T y p e I n f o %
804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 % ListTypeInfo() lists the fonts to a file.
808 % The format of the ListTypeInfo method is:
810 % MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
812 % A description of each parameter follows.
814 % o file: An pointer to a FILE.
816 % o exception: return any errors or warnings in this structure.
819 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
822 weight[MaxTextExtent];
841 if (file == (FILE *) NULL)
844 type_info=GetTypeInfoList("*",&number_fonts,exception);
845 if (type_info == (const TypeInfo **) NULL)
848 path=(const char *) NULL;
849 for (i=0; i < (long) number_fonts; i++)
851 if (type_info[i]->stealth != MagickFalse)
853 if (((path == (const char *) NULL) ||
854 (LocaleCompare(path,type_info[i]->path) != 0)) &&
855 (type_info[i]->path != (char *) NULL))
856 (void) fprintf(file,"\nPath: %s\n",type_info[i]->path);
857 path=type_info[i]->path;
859 if (type_info[i]->name != (char *) NULL)
860 name=type_info[i]->name;
862 if (type_info[i]->family != (char *) NULL)
863 family=type_info[i]->family;
864 style=MagickOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
865 stretch=MagickOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
867 if (type_info[i]->glyphs != (char *) NULL)
868 glyphs=type_info[i]->glyphs;
869 (void) FormatMagickString(weight,MaxTextExtent,"%lu",type_info[i]->weight);
870 (void) fprintf(file," Font: %s\n",name);
871 (void) fprintf(file," family: %s\n",family);
872 (void) fprintf(file," style: %s\n",style);
873 (void) fprintf(file," stretch: %s\n",stretch);
874 (void) fprintf(file," weight: %s\n",weight);
875 (void) fprintf(file," glyphs: %s\n",glyphs);
878 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887 + L o a d T y p e L i s t %
891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
893 % LoadTypeList() loads the type configuration file which provides a mapping
894 % between type attributes and a type name.
896 % The format of the LoadTypeList method is:
898 % MagickBooleanType LoadTypeList(const char *xml,const char *filename,
899 % const unsigned long depth,ExceptionInfo *exception)
901 % A description of each parameter follows:
903 % o xml: The type list in XML format.
905 % o filename: The type list filename.
907 % o depth: depth of <include /> statements.
909 % o exception: return any errors or warnings in this structure.
913 static void *DestroyTypeNode(void *type_info)
918 p=(TypeInfo *) type_info;
919 if (p->path != (char *) NULL)
920 p->path=DestroyString(p->path);
921 if (p->name != (char *) NULL)
922 p->name=DestroyString(p->name);
923 if (p->description != (char *) NULL)
924 p->description=DestroyString(p->description);
925 if (p->family != (char *) NULL)
926 p->family=DestroyString(p->family);
927 if (p->encoding != (char *) NULL)
928 p->encoding=DestroyString(p->encoding);
929 if (p->foundry != (char *) NULL)
930 p->foundry=DestroyString(p->foundry);
931 if (p->format != (char *) NULL)
932 p->format=DestroyString(p->format);
933 if (p->metrics != (char *) NULL)
934 p->metrics=DestroyString(p->metrics);
935 if (p->glyphs != (char *) NULL)
936 p->glyphs=DestroyString(p->glyphs);
937 return(RelinquishMagickMemory(p));
940 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
941 const unsigned long depth,ExceptionInfo *exception)
944 font_path[MaxTextExtent],
945 keyword[MaxTextExtent],
958 Load the type map file.
960 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
961 "Loading type configure file \"%s\" ...",filename);
962 if (xml == (const char *) NULL)
964 if (type_list == (SplayTreeInfo *) NULL)
966 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
968 if (type_list == (SplayTreeInfo *) NULL)
970 ThrowFileException(exception,ResourceLimitError,
971 "MemoryAllocationFailed",filename);
976 type_info=(TypeInfo *) NULL;
977 token=AcquireString(xml);
978 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
980 Determine the Ghostscript font path.
983 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
984 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
986 for (q=(char *) xml; *q != '\0'; )
991 GetMagickToken(q,&q,token);
994 (void) CopyMagickString(keyword,token,MaxTextExtent);
995 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1000 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1001 GetMagickToken(q,&q,token);
1004 if (LocaleNCompare(keyword,"<!--",4) == 0)
1009 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1010 GetMagickToken(q,&q,token);
1013 if (LocaleCompare(keyword,"<include") == 0)
1018 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1020 (void) CopyMagickString(keyword,token,MaxTextExtent);
1021 GetMagickToken(q,&q,token);
1024 GetMagickToken(q,&q,token);
1025 if (LocaleCompare(keyword,"file") == 0)
1028 (void) ThrowMagickException(exception,GetMagickModule(),
1029 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
1033 path[MaxTextExtent],
1040 GetPathComponent(filename,HeadPath,path);
1042 (void) ConcatenateMagickString(path,DirectorySeparator,
1044 if (*token == *DirectorySeparator)
1045 (void) CopyMagickString(path,token,MaxTextExtent);
1047 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1048 sans_exception=AcquireExceptionInfo();
1049 xml=FileToString(path,~0,sans_exception);
1050 sans_exception=DestroyExceptionInfo(sans_exception);
1051 if (xml != (char *) NULL)
1053 status=LoadTypeList(xml,path,depth+1,exception);
1054 xml=(char *) RelinquishMagickMemory(xml);
1061 if (LocaleCompare(keyword,"<type") == 0)
1066 type_info=(TypeInfo *) AcquireAlignedMemory(1,sizeof(*type_info));
1067 if (type_info == (TypeInfo *) NULL)
1068 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1069 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
1070 type_info->path=ConstantString(filename);
1071 type_info->signature=MagickSignature;
1074 if (type_info == (TypeInfo *) NULL)
1076 if (LocaleCompare(keyword,"/>") == 0)
1078 status=AddValueToSplayTree(type_list,type_info->name,type_info);
1079 if (status == MagickFalse)
1080 (void) ThrowMagickException(exception,GetMagickModule(),
1081 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
1082 type_info=(TypeInfo *) NULL;
1084 GetMagickToken(q,(const char **) NULL,token);
1087 GetMagickToken(q,&q,token);
1088 GetMagickToken(q,&q,token);
1094 if (LocaleCompare((char *) keyword,"encoding") == 0)
1096 type_info->encoding=ConstantString(token);
1104 if (LocaleCompare((char *) keyword,"face") == 0)
1106 type_info->face=StringToUnsignedLong(token);
1109 if (LocaleCompare((char *) keyword,"family") == 0)
1111 type_info->family=ConstantString(token);
1114 if (LocaleCompare((char *) keyword,"format") == 0)
1116 type_info->format=ConstantString(token);
1119 if (LocaleCompare((char *) keyword,"foundry") == 0)
1121 type_info->foundry=ConstantString(token);
1124 if (LocaleCompare((char *) keyword,"fullname") == 0)
1126 type_info->description=ConstantString(token);
1134 if (LocaleCompare((char *) keyword,"glyphs") == 0)
1139 path=ConstantString(token);
1140 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1141 if (strchr(path,'@') != (char *) NULL)
1142 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1144 if (IsPathAccessible(path) == MagickFalse)
1149 path=DestroyString(path);
1150 GetPathComponent(filename,HeadPath,font_path);
1151 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1153 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1154 path=ConstantString(font_path);
1156 type_info->glyphs=path;
1164 if (LocaleCompare((char *) keyword,"metrics") == 0)
1169 path=ConstantString(token);
1170 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1171 if (strchr(path,'@') != (char *) NULL)
1172 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1174 if (IsPathAccessible(path) == MagickFalse)
1179 path=DestroyString(path);
1180 GetPathComponent(filename,HeadPath,font_path);
1181 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1183 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1184 path=ConstantString(font_path);
1186 type_info->metrics=path;
1194 if (LocaleCompare((char *) keyword,"name") == 0)
1196 type_info->name=ConstantString(token);
1204 if (LocaleCompare((char *) keyword,"stealth") == 0)
1206 type_info->stealth=IsMagickTrue(token);
1209 if (LocaleCompare((char *) keyword,"stretch") == 0)
1211 type_info->stretch=(StretchType) ParseMagickOption(
1212 MagickStretchOptions,MagickFalse,token);
1215 if (LocaleCompare((char *) keyword,"style") == 0)
1217 type_info->style=(StyleType) ParseMagickOption(MagickStyleOptions,
1226 if (LocaleCompare((char *) keyword,"weight") == 0)
1228 type_info->weight=StringToUnsignedLong(token);
1229 if (LocaleCompare(token,"bold") == 0)
1230 type_info->weight=700;
1231 if (LocaleCompare(token,"normal") == 0)
1232 type_info->weight=400;
1241 token=(char *) RelinquishMagickMemory(token);
1246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1250 % L o a d T y p e L i s t s %
1254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1256 % LoadTypeList() loads one or more type configuration files which provides a
1257 % mapping between type attributes and a type name.
1259 % The format of the LoadTypeLists method is:
1261 % MagickBooleanType LoadTypeLists(const char *filename,
1262 % ExceptionInfo *exception)
1264 % A description of each parameter follows:
1266 % o filename: the font file name.
1268 % o exception: return any errors or warnings in this structure.
1271 static MagickBooleanType LoadTypeLists(const char *filename,
1272 ExceptionInfo *exception)
1274 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1275 return(LoadTypeList(TypeMap,"built-in",0,exception));
1279 path[MaxTextExtent];
1292 options=GetConfigureOptions(filename,exception);
1293 option=(const StringInfo *) GetNextValueInLinkedList(options);
1294 while (option != (const StringInfo *) NULL)
1296 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1297 status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1298 GetStringInfoPath(option),0,exception);
1299 option=(const StringInfo *) GetNextValueInLinkedList(options);
1301 options=DestroyConfigureOptions(options);
1302 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1303 if (font_path != (char *) NULL)
1309 Search MAGICK_FONT_PATH.
1311 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",font_path,
1312 DirectorySeparator,filename);
1313 option=FileToString(path,~0,exception);
1314 if (option != (void *) NULL)
1316 status|=LoadTypeList(option,path,0,exception);
1317 option=DestroyString(option);
1319 font_path=DestroyString(font_path);
1321 if ((type_list == (SplayTreeInfo *) NULL) ||
1322 (GetNumberOfNodesInSplayTree(type_list) == 0))
1323 status|=LoadTypeList(TypeMap,"built-in",0,exception);
1324 return(status != 0 ? MagickTrue : MagickFalse);
1329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333 + T y p e C o m p o n e n t G e n e s i s %
1337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1339 % TypeComponentGenesis() instantiates the type component.
1341 % The format of the TypeComponentGenesis method is:
1343 % MagickBooleanType TypeComponentGenesis(void)
1346 MagickExport MagickBooleanType TypeComponentGenesis(void)
1348 AcquireSemaphoreInfo(&type_semaphore);
1353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1357 + T y p e C o m p o n e n t T e r m i n u s %
1361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1363 % TypeComponentTerminus() destroy type component.
1365 % The format of the TypeComponentTerminus method is:
1367 % void TypeComponentTerminus(void)
1370 MagickExport void TypeComponentTerminus(void)
1372 if (type_semaphore == (SemaphoreInfo *) NULL)
1373 AcquireSemaphoreInfo(&type_semaphore);
1374 LockSemaphoreInfo(type_semaphore);
1375 if (type_list != (SplayTreeInfo *) NULL)
1376 type_list=DestroySplayTree(type_list);
1377 instantiate_type=MagickFalse;
1378 UnlockSemaphoreInfo(type_semaphore);
1379 DestroySemaphoreInfo(&type_semaphore);