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/nt-base-private.h"
53 #include "MagickCore/option.h"
54 #include "MagickCore/semaphore.h"
55 #include "MagickCore/splay-tree.h"
56 #include "MagickCore/string_.h"
57 #include "MagickCore/string-private.h"
58 #include "MagickCore/type.h"
59 #include "MagickCore/type-private.h"
60 #include "MagickCore/token.h"
61 #include "MagickCore/utility.h"
62 #include "MagickCore/utility-private.h"
63 #include "MagickCore/xml-tree.h"
64 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
65 # include "fontconfig/fontconfig.h"
66 #if (FC_VERSION < 20209)
67 #undef FC_WEIGHT_LIGHT
68 #define FC_WIDTH "width" /* Int */
69 #define FC_WIDTH_ULTRACONDENSED 50
70 #define FC_WIDTH_EXTRACONDENSED 63
71 #define FC_WIDTH_CONDENSED 75
72 #define FC_WIDTH_SEMICONDENSED 87
73 #define FC_WIDTH_NORMAL 100
74 #define FC_WIDTH_SEMIEXPANDED 113
75 #define FC_WIDTH_EXPANDED 125
76 #define FC_WIDTH_EXTRAEXPANDED 150
77 #define FC_WIDTH_ULTRAEXPANDED 200
79 #define FC_WEIGHT_THIN 0
80 #define FC_WEIGHT_EXTRALIGHT 40
81 #define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
82 #define FC_WEIGHT_LIGHT 50
83 #define FC_WEIGHT_BOOK 75
84 #define FC_WEIGHT_REGULAR 80
85 #define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
86 #define FC_WEIGHT_MEDIUM 100
87 #define FC_WEIGHT_DEMIBOLD 180
88 #define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
89 #define FC_WEIGHT_BOLD 200
90 #define FC_WEIGHT_EXTRABOLD 205
91 #define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
92 #define FC_WEIGHT_BLACK 210
93 #define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
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 size_t 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 size_t MagickMax(const size_t x,const size_t y)
219 static inline size_t MagickMin(const size_t x,const size_t y)
226 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
227 const StyleType style,const StretchType stretch,const size_t weight,
228 ExceptionInfo *exception)
230 typedef struct _Fontmap
240 register const TypeInfo
252 { "fixed", "courier" },
253 { "modern","courier" },
254 { "monotype corsiva", "courier" },
255 { "news gothic", "helvetica" },
256 { "system", "courier" },
257 { "terminal", "courier" },
258 { "wingdings", "symbol" },
267 Check for an exact type match.
269 (void) GetTypeInfo("*",exception);
270 if (type_list == (SplayTreeInfo *) NULL)
271 return((TypeInfo *) NULL);
272 LockSemaphoreInfo(type_semaphore);
273 ResetSplayTreeIterator(type_list);
274 type_info=(const TypeInfo *) NULL;
275 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
276 while (p != (const TypeInfo *) NULL)
278 if (p->family == (char *) NULL)
280 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
283 if (family == (const char *) NULL)
285 if ((LocaleCompare(p->family,"arial") != 0) &&
286 (LocaleCompare(p->family,"helvetica") != 0))
288 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
293 if (LocaleCompare(p->family,family) != 0)
295 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
298 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
300 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
303 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
304 (p->stretch != stretch))
306 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
309 if ((weight != 0) && (p->weight != weight))
311 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
317 UnlockSemaphoreInfo(type_semaphore);
318 if (type_info != (const TypeInfo *) NULL)
321 Check for types in the same family.
324 LockSemaphoreInfo(type_semaphore);
325 ResetSplayTreeIterator(type_list);
326 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
327 while (p != (const TypeInfo *) NULL)
329 if (p->family == (char *) NULL)
331 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
334 if (family == (const char *) NULL)
336 if ((LocaleCompare(p->family,"arial") != 0) &&
337 (LocaleCompare(p->family,"helvetica") != 0))
339 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
344 if (LocaleCompare(p->family,family) != 0)
346 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
350 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
353 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
354 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
359 score+=(16*(800-((ssize_t) MagickMax(MagickMin(weight,900),p->weight)-
360 (ssize_t) MagickMin(MagickMin(weight,900),p->weight))))/800;
361 if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
365 range=(ssize_t) UltraExpandedStretch-(ssize_t) NormalStretch;
366 score+=(8*(range-((ssize_t) MagickMax(stretch,p->stretch)-
367 (ssize_t) MagickMin(stretch,p->stretch))))/range;
369 if (score > max_score)
374 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
376 UnlockSemaphoreInfo(type_semaphore);
377 if (type_info != (const TypeInfo *) NULL)
380 Check for table-based substitution match.
382 for (i=0; fontmap[i].name != (char *) NULL; i++)
384 if (family == (const char *) NULL)
386 if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
387 (LocaleCompare(fontmap[i].name,"helvetica") != 0))
391 if (LocaleCompare(fontmap[i].name,family) != 0)
393 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
397 if (type_info != (const TypeInfo *) NULL)
399 (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
400 "FontSubstitutionRequired","`%s'",type_info->family);
403 if (family != (const char *) NULL)
404 type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
414 % G e t T y p e I n f o L i s t %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420 % GetTypeInfoList() returns any fonts that match the specified pattern.
422 % The format of the GetTypeInfoList function is:
424 % const TypeInfo **GetTypeInfoList(const char *pattern,
425 % size_t *number_fonts,ExceptionInfo *exception)
427 % A description of each parameter follows:
429 % o pattern: Specifies a pointer to a text string containing a pattern.
431 % o number_fonts: This integer returns the number of types in the list.
433 % o exception: return any errors or warnings in this structure.
437 #if defined(__cplusplus) || defined(c_plusplus)
441 static int TypeInfoCompare(const void *x,const void *y)
447 p=(const TypeInfo **) x,
448 q=(const TypeInfo **) y;
449 if (LocaleCompare((*p)->path,(*q)->path) == 0)
450 return(LocaleCompare((*p)->name,(*q)->name));
451 return(LocaleCompare((*p)->path,(*q)->path));
454 #if defined(__cplusplus) || defined(c_plusplus)
458 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
459 size_t *number_fonts,ExceptionInfo *exception)
464 register const TypeInfo
473 assert(pattern != (char *) NULL);
474 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
475 assert(number_fonts != (size_t *) NULL);
477 p=GetTypeInfo("*",exception);
478 if (p == (const TypeInfo *) NULL)
479 return((const TypeInfo **) NULL);
480 fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
481 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
482 if (fonts == (const TypeInfo **) NULL)
483 return((const TypeInfo **) NULL);
487 LockSemaphoreInfo(type_semaphore);
488 ResetSplayTreeIterator(type_list);
489 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
490 for (i=0; p != (const TypeInfo *) NULL; )
492 if ((p->stealth == MagickFalse) &&
493 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
495 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
497 UnlockSemaphoreInfo(type_semaphore);
498 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
499 fonts[i]=(TypeInfo *) NULL;
500 *number_fonts=(size_t) i;
505 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509 % G e t T y p e L i s t %
513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 % GetTypeList() returns any fonts that match the specified pattern.
517 % The format of the GetTypeList function is:
519 % char **GetTypeList(const char *pattern,size_t *number_fonts,
520 % ExceptionInfo *exception)
522 % A description of each parameter follows:
524 % o pattern: Specifies a pointer to a text string containing a pattern.
526 % o number_fonts: This integer returns the number of fonts in the list.
528 % o exception: return any errors or warnings in this structure.
532 #if defined(__cplusplus) || defined(c_plusplus)
536 static int TypeCompare(const void *x,const void *y)
544 return(LocaleCompare(*p,*q));
547 #if defined(__cplusplus) || defined(c_plusplus)
551 MagickExport char **GetTypeList(const char *pattern,size_t *number_fonts,
552 ExceptionInfo *exception)
557 register const TypeInfo
566 assert(pattern != (char *) NULL);
567 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
568 assert(number_fonts != (size_t *) NULL);
570 p=GetTypeInfo("*",exception);
571 if (p == (const TypeInfo *) NULL)
572 return((char **) NULL);
573 fonts=(char **) AcquireQuantumMemory((size_t)
574 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
575 if (fonts == (char **) NULL)
576 return((char **) NULL);
580 LockSemaphoreInfo(type_semaphore);
581 ResetSplayTreeIterator(type_list);
582 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
583 for (i=0; p != (const TypeInfo *) NULL; )
585 if ((p->stealth == MagickFalse) &&
586 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
587 fonts[i++]=ConstantString(p->name);
588 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
590 UnlockSemaphoreInfo(type_semaphore);
591 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
592 fonts[i]=(char *) NULL;
593 *number_fonts=(size_t) i;
598 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602 + I n i t i a l i z e T y p e L i s t %
606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608 % InitializeTypeList() initializes the type list.
610 % The format of the InitializeTypeList method is:
612 % MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
614 % A description of each parameter follows.
616 % o exception: return any errors or warnings in this structure.
620 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
621 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
622 ExceptionInfo *exception)
625 extension[MaxTextExtent],
663 font_config=FcInitLoadConfigAndFonts();
664 if (font_config == (FcConfig *) NULL)
666 font_set=(FcFontSet *) NULL;
667 object_set=FcObjectSetBuild(FC_FAMILY,FC_STYLE,FC_SLANT,FC_WIDTH,FC_WEIGHT,
668 FC_FILE,(char *) NULL);
669 if (object_set != (FcObjectSet *) NULL)
671 pattern=FcPatternCreate();
672 if (pattern != (FcPattern *) NULL)
674 font_set=FcFontList(0,pattern,object_set);
675 FcPatternDestroy(pattern);
677 FcObjectSetDestroy(object_set);
679 if (font_set == (FcFontSet *) NULL)
681 FcConfigDestroy(font_config);
684 for (i=0; i < (ssize_t) font_set->nfont; i++)
686 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
687 if (status != FcResultMatch)
689 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
690 if (status != FcResultMatch)
693 GetPathComponent((const char *) file,ExtensionPath,extension);
694 if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
696 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
697 if (type_info == (TypeInfo *) NULL)
699 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
700 type_info->path=ConstantString("System Fonts");
701 type_info->signature=MagickSignature;
702 (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
703 (void) ConcatenateMagickString(name," ",MaxTextExtent);
704 status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
705 if (status == FcResultMatch)
706 (void) ConcatenateMagickString(name,(const char *) style,MaxTextExtent);
707 type_info->name=ConstantString(name);
708 (void) SubstituteString(&type_info->name," ","-");
709 (void) SubstituteString(&type_info->name,"-L-","-");
710 (void) SubstituteString(&type_info->name,"semicondensed","SemiCondensed");
711 type_info->family=ConstantString((const char *) family);
712 (void) SubstituteString(&type_info->family," L","");
713 status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
714 type_info->style=NormalStyle;
715 if (slant == FC_SLANT_ITALIC)
716 type_info->style=ItalicStyle;
717 if (slant == FC_SLANT_OBLIQUE)
718 type_info->style=ObliqueStyle;
719 status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
720 type_info->stretch=NormalStretch;
721 if (width >= FC_WIDTH_ULTRACONDENSED)
722 type_info->stretch=UltraCondensedStretch;
723 if (width >= FC_WIDTH_EXTRACONDENSED)
724 type_info->stretch=ExtraCondensedStretch;
725 if (width >= FC_WIDTH_CONDENSED)
726 type_info->stretch=CondensedStretch;
727 if (width >= FC_WIDTH_SEMICONDENSED)
728 type_info->stretch=SemiCondensedStretch;
729 if (width >= FC_WIDTH_NORMAL)
730 type_info->stretch=NormalStretch;
731 if (width >= FC_WIDTH_SEMIEXPANDED)
732 type_info->stretch=SemiExpandedStretch;
733 if (width >= FC_WIDTH_EXPANDED)
734 type_info->stretch=ExpandedStretch;
735 if (width >= FC_WIDTH_EXTRAEXPANDED)
736 type_info->stretch=ExtraExpandedStretch;
737 if (width >= FC_WIDTH_ULTRAEXPANDED)
738 type_info->stretch=UltraExpandedStretch;
739 type_info->weight=400;
740 status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
741 if (weight >= FC_WEIGHT_THIN)
742 type_info->weight=100;
743 if (weight >= FC_WEIGHT_EXTRALIGHT)
744 type_info->weight=200;
745 if (weight >= FC_WEIGHT_LIGHT)
746 type_info->weight=300;
747 if (weight >= FC_WEIGHT_NORMAL)
748 type_info->weight=400;
749 if (weight >= FC_WEIGHT_MEDIUM)
750 type_info->weight=500;
751 if (weight >= FC_WEIGHT_DEMIBOLD)
752 type_info->weight=600;
753 if (weight >= FC_WEIGHT_BOLD)
754 type_info->weight=700;
755 if (weight >= FC_WEIGHT_EXTRABOLD)
756 type_info->weight=800;
757 if (weight >= FC_WEIGHT_BLACK)
758 type_info->weight=900;
759 type_info->glyphs=ConstantString((const char *) file);
760 (void) AddValueToSplayTree(type_list,type_info->name,type_info);
762 FcFontSetDestroy(font_set);
763 FcConfigDestroy(font_config);
768 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
770 if ((type_list == (SplayTreeInfo *) NULL) &&
771 (instantiate_type == MagickFalse))
773 if (type_semaphore == (SemaphoreInfo *) NULL)
774 AcquireSemaphoreInfo(&type_semaphore);
775 LockSemaphoreInfo(type_semaphore);
776 if ((type_list == (SplayTreeInfo *) NULL) &&
777 (instantiate_type == MagickFalse))
779 (void) LoadTypeLists(MagickTypeFilename,exception);
780 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
781 (void) NTLoadTypeLists(type_list,exception);
783 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
784 (void) LoadFontConfigFonts(type_list,exception);
786 instantiate_type=MagickTrue;
788 UnlockSemaphoreInfo(type_semaphore);
790 return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798 % L i s t T y p e I n f o %
802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 % ListTypeInfo() lists the fonts to a file.
806 % The format of the ListTypeInfo method is:
808 % MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
810 % A description of each parameter follows.
812 % o file: An pointer to a FILE.
814 % o exception: return any errors or warnings in this structure.
817 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
820 weight[MaxTextExtent];
839 if (file == (FILE *) NULL)
842 type_info=GetTypeInfoList("*",&number_fonts,exception);
843 if (type_info == (const TypeInfo **) NULL)
846 path=(const char *) NULL;
847 for (i=0; i < (ssize_t) number_fonts; i++)
849 if (type_info[i]->stealth != MagickFalse)
851 if (((path == (const char *) NULL) ||
852 (LocaleCompare(path,type_info[i]->path) != 0)) &&
853 (type_info[i]->path != (char *) NULL))
854 (void) FormatLocaleFile(file,"\nPath: %s\n",type_info[i]->path);
855 path=type_info[i]->path;
857 if (type_info[i]->name != (char *) NULL)
858 name=type_info[i]->name;
860 if (type_info[i]->family != (char *) NULL)
861 family=type_info[i]->family;
862 style=CommandOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
863 stretch=CommandOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
865 if (type_info[i]->glyphs != (char *) NULL)
866 glyphs=type_info[i]->glyphs;
867 (void) FormatLocaleString(weight,MaxTextExtent,"%.20g",(double)
868 type_info[i]->weight);
869 (void) FormatLocaleFile(file," Font: %s\n",name);
870 (void) FormatLocaleFile(file," family: %s\n",family);
871 (void) FormatLocaleFile(file," style: %s\n",style);
872 (void) FormatLocaleFile(file," stretch: %s\n",stretch);
873 (void) FormatLocaleFile(file," weight: %s\n",weight);
874 (void) FormatLocaleFile(file," glyphs: %s\n",glyphs);
877 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886 + L o a d T y p e L i s t %
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
892 % LoadTypeList() loads the type configuration file which provides a mapping
893 % between type attributes and a type name.
895 % The format of the LoadTypeList method is:
897 % MagickBooleanType LoadTypeList(const char *xml,const char *filename,
898 % const size_t depth,ExceptionInfo *exception)
900 % A description of each parameter follows:
902 % o xml: The type list in XML format.
904 % o filename: The type list filename.
906 % o depth: depth of <include /> statements.
908 % o exception: return any errors or warnings in this structure.
912 static void *DestroyTypeNode(void *type_info)
917 p=(TypeInfo *) type_info;
918 if (p->path != (char *) NULL)
919 p->path=DestroyString(p->path);
920 if (p->name != (char *) NULL)
921 p->name=DestroyString(p->name);
922 if (p->description != (char *) NULL)
923 p->description=DestroyString(p->description);
924 if (p->family != (char *) NULL)
925 p->family=DestroyString(p->family);
926 if (p->encoding != (char *) NULL)
927 p->encoding=DestroyString(p->encoding);
928 if (p->foundry != (char *) NULL)
929 p->foundry=DestroyString(p->foundry);
930 if (p->format != (char *) NULL)
931 p->format=DestroyString(p->format);
932 if (p->metrics != (char *) NULL)
933 p->metrics=DestroyString(p->metrics);
934 if (p->glyphs != (char *) NULL)
935 p->glyphs=DestroyString(p->glyphs);
936 return(RelinquishMagickMemory(p));
939 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
940 const size_t depth,ExceptionInfo *exception)
943 font_path[MaxTextExtent],
944 keyword[MaxTextExtent],
957 Load the type map file.
959 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
960 "Loading type configure file \"%s\" ...",filename);
961 if (xml == (const char *) NULL)
963 if (type_list == (SplayTreeInfo *) NULL)
965 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
967 if (type_list == (SplayTreeInfo *) NULL)
969 ThrowFileException(exception,ResourceLimitError,
970 "MemoryAllocationFailed",filename);
975 type_info=(TypeInfo *) NULL;
976 token=AcquireString(xml);
977 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
979 Determine the Ghostscript font path.
982 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
983 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
985 for (q=(char *) xml; *q != '\0'; )
990 GetMagickToken(q,&q,token);
993 (void) CopyMagickString(keyword,token,MaxTextExtent);
994 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
999 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1000 GetMagickToken(q,&q,token);
1003 if (LocaleNCompare(keyword,"<!--",4) == 0)
1008 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1009 GetMagickToken(q,&q,token);
1012 if (LocaleCompare(keyword,"<include") == 0)
1017 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1019 (void) CopyMagickString(keyword,token,MaxTextExtent);
1020 GetMagickToken(q,&q,token);
1023 GetMagickToken(q,&q,token);
1024 if (LocaleCompare(keyword,"file") == 0)
1027 (void) ThrowMagickException(exception,GetMagickModule(),
1028 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
1032 path[MaxTextExtent],
1039 GetPathComponent(filename,HeadPath,path);
1041 (void) ConcatenateMagickString(path,DirectorySeparator,
1043 if (*token == *DirectorySeparator)
1044 (void) CopyMagickString(path,token,MaxTextExtent);
1046 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1047 sans_exception=AcquireExceptionInfo();
1048 xml=FileToString(path,~0,sans_exception);
1049 sans_exception=DestroyExceptionInfo(sans_exception);
1050 if (xml != (char *) NULL)
1052 status=LoadTypeList(xml,path,depth+1,exception);
1053 xml=(char *) RelinquishMagickMemory(xml);
1060 if (LocaleCompare(keyword,"<type") == 0)
1065 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
1066 if (type_info == (TypeInfo *) NULL)
1067 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1068 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
1069 type_info->path=ConstantString(filename);
1070 type_info->signature=MagickSignature;
1073 if (type_info == (TypeInfo *) NULL)
1075 if (LocaleCompare(keyword,"/>") == 0)
1077 status=AddValueToSplayTree(type_list,type_info->name,type_info);
1078 if (status == MagickFalse)
1079 (void) ThrowMagickException(exception,GetMagickModule(),
1080 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
1081 type_info=(TypeInfo *) NULL;
1083 GetMagickToken(q,(const char **) NULL,token);
1086 GetMagickToken(q,&q,token);
1087 GetMagickToken(q,&q,token);
1093 if (LocaleCompare((char *) keyword,"encoding") == 0)
1095 type_info->encoding=ConstantString(token);
1103 if (LocaleCompare((char *) keyword,"face") == 0)
1105 type_info->face=StringToUnsignedLong(token);
1108 if (LocaleCompare((char *) keyword,"family") == 0)
1110 type_info->family=ConstantString(token);
1113 if (LocaleCompare((char *) keyword,"format") == 0)
1115 type_info->format=ConstantString(token);
1118 if (LocaleCompare((char *) keyword,"foundry") == 0)
1120 type_info->foundry=ConstantString(token);
1123 if (LocaleCompare((char *) keyword,"fullname") == 0)
1125 type_info->description=ConstantString(token);
1133 if (LocaleCompare((char *) keyword,"glyphs") == 0)
1138 path=ConstantString(token);
1139 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1140 if (strchr(path,'@') != (char *) NULL)
1141 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1143 if (IsPathAccessible(path) == MagickFalse)
1148 path=DestroyString(path);
1149 GetPathComponent(filename,HeadPath,font_path);
1150 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1152 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1153 path=ConstantString(font_path);
1154 if (IsPathAccessible(path) == MagickFalse)
1156 path=DestroyString(path);
1157 path=ConstantString(token);
1160 type_info->glyphs=path;
1168 if (LocaleCompare((char *) keyword,"metrics") == 0)
1173 path=ConstantString(token);
1174 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1175 if (strchr(path,'@') != (char *) NULL)
1176 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1178 if (IsPathAccessible(path) == MagickFalse)
1183 path=DestroyString(path);
1184 GetPathComponent(filename,HeadPath,font_path);
1185 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1187 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1188 path=ConstantString(font_path);
1190 type_info->metrics=path;
1198 if (LocaleCompare((char *) keyword,"name") == 0)
1200 type_info->name=ConstantString(token);
1208 if (LocaleCompare((char *) keyword,"stealth") == 0)
1210 type_info->stealth=IsMagickTrue(token);
1213 if (LocaleCompare((char *) keyword,"stretch") == 0)
1215 type_info->stretch=(StretchType) ParseCommandOption(
1216 MagickStretchOptions,MagickFalse,token);
1219 if (LocaleCompare((char *) keyword,"style") == 0)
1221 type_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1230 if (LocaleCompare((char *) keyword,"weight") == 0)
1232 type_info->weight=StringToUnsignedLong(token);
1233 if (LocaleCompare(token,"bold") == 0)
1234 type_info->weight=700;
1235 if (LocaleCompare(token,"normal") == 0)
1236 type_info->weight=400;
1245 token=(char *) RelinquishMagickMemory(token);
1250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1254 % L o a d T y p e L i s t s %
1258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260 % LoadTypeList() loads one or more type configuration files which provides a
1261 % mapping between type attributes and a type name.
1263 % The format of the LoadTypeLists method is:
1265 % MagickBooleanType LoadTypeLists(const char *filename,
1266 % ExceptionInfo *exception)
1268 % A description of each parameter follows:
1270 % o filename: the font file name.
1272 % o exception: return any errors or warnings in this structure.
1275 static MagickBooleanType LoadTypeLists(const char *filename,
1276 ExceptionInfo *exception)
1278 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1279 return(LoadTypeList(TypeMap,"built-in",0,exception));
1283 path[MaxTextExtent];
1296 options=GetConfigureOptions(filename,exception);
1297 option=(const StringInfo *) GetNextValueInLinkedList(options);
1298 while (option != (const StringInfo *) NULL)
1300 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1301 status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1302 GetStringInfoPath(option),0,exception);
1303 option=(const StringInfo *) GetNextValueInLinkedList(options);
1305 options=DestroyConfigureOptions(options);
1306 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1307 if (font_path != (char *) NULL)
1313 Search MAGICK_FONT_PATH.
1315 (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",font_path,
1316 DirectorySeparator,filename);
1317 option=FileToString(path,~0,exception);
1318 if (option != (void *) NULL)
1320 status|=LoadTypeList(option,path,0,exception);
1321 option=DestroyString(option);
1323 font_path=DestroyString(font_path);
1325 if ((type_list == (SplayTreeInfo *) NULL) ||
1326 (GetNumberOfNodesInSplayTree(type_list) == 0))
1327 status|=LoadTypeList(TypeMap,"built-in",0,exception);
1328 return(status != 0 ? MagickTrue : MagickFalse);
1333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 + T y p e C o m p o n e n t G e n e s i s %
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1343 % TypeComponentGenesis() instantiates the type component.
1345 % The format of the TypeComponentGenesis method is:
1347 % MagickBooleanType TypeComponentGenesis(void)
1350 MagickPrivate MagickBooleanType TypeComponentGenesis(void)
1352 AcquireSemaphoreInfo(&type_semaphore);
1357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1361 + T y p e C o m p o n e n t T e r m i n u s %
1365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1367 % TypeComponentTerminus() destroy type component.
1369 % The format of the TypeComponentTerminus method is:
1371 % void TypeComponentTerminus(void)
1374 MagickPrivate void TypeComponentTerminus(void)
1376 if (type_semaphore == (SemaphoreInfo *) NULL)
1377 AcquireSemaphoreInfo(&type_semaphore);
1378 LockSemaphoreInfo(type_semaphore);
1379 if (type_list != (SplayTreeInfo *) NULL)
1380 type_list=DestroySplayTree(type_list);
1381 instantiate_type=MagickFalse;
1382 UnlockSemaphoreInfo(type_semaphore);
1383 DestroySemaphoreInfo(&type_semaphore);