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/type.h"
57 #include "magick/token.h"
58 #include "magick/utility.h"
59 #include "magick/xml-tree.h"
60 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
61 # include "fontconfig/fontconfig.h"
62 #if (FC_VERSION < 20209)
63 #undef FC_WEIGHT_LIGHT
64 #define FC_WIDTH "width" /* Int */
65 #define FC_WIDTH_ULTRACONDENSED 50
66 #define FC_WIDTH_EXTRACONDENSED 63
67 #define FC_WIDTH_CONDENSED 75
68 #define FC_WIDTH_SEMICONDENSED 87
69 #define FC_WIDTH_NORMAL 100
70 #define FC_WIDTH_SEMIEXPANDED 113
71 #define FC_WIDTH_EXPANDED 125
72 #define FC_WIDTH_EXTRAEXPANDED 150
73 #define FC_WIDTH_ULTRAEXPANDED 200
75 #define FC_WEIGHT_THIN 0
76 #define FC_WEIGHT_EXTRALIGHT 40
77 #define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
78 #define FC_WEIGHT_LIGHT 50
79 #define FC_WEIGHT_BOOK 75
80 #define FC_WEIGHT_REGULAR 80
81 #define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
82 #define FC_WEIGHT_MEDIUM 100
83 #define FC_WEIGHT_DEMIBOLD 180
84 #define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
85 #define FC_WEIGHT_BOLD 200
86 #define FC_WEIGHT_EXTRABOLD 205
87 #define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
88 #define FC_WEIGHT_BLACK 210
89 #define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
92 #if defined(__WINDOWS__)
93 # include "magick/nt-feature.h"
99 #define MagickTypeFilename "type.xml"
105 *TypeMap = (const char *)
106 "<?xml version=\"1.0\"?>"
108 " <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
109 " <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
116 *type_semaphore = (SemaphoreInfo *) NULL;
118 static volatile MagickBooleanType
119 instantiate_type = MagickFalse;
122 *type_list = (SplayTreeInfo *) NULL;
125 Forward declarations.
127 static MagickBooleanType
128 InitializeTypeList(ExceptionInfo *),
129 LoadTypeLists(const char *,ExceptionInfo *);
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 + D e s t r o y T y p e F a c i l i t y %
140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 % DestroyTypeFacility() destroy type facility.
144 % The format of the DestroyTypeFacility method is:
146 % void DestroyTypeFacility(void)
149 MagickExport void DestroyTypeFacility(void)
151 AcquireSemaphoreInfo(&type_semaphore);
152 if (type_list != (SplayTreeInfo *) NULL)
153 type_list=DestroySplayTree(type_list);
154 instantiate_type=MagickFalse;
155 RelinquishSemaphoreInfo(type_semaphore);
156 DestroySemaphoreInfo(&type_semaphore);
160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 + G e t T y p e I n f o %
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 % GetTypeInfo searches the type list for the specified name and if found
171 % returns attributes for that type.
173 % The format of the GetTypeInfo method is:
175 % const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
177 % A description of each parameter follows:
179 % o name: the type name.
181 % o exception: return any errors or warnings in this structure.
184 MagickExport const TypeInfo *GetTypeInfo(const char *name,
185 ExceptionInfo *exception)
187 assert(exception != (ExceptionInfo *) NULL);
188 if ((type_list == (SplayTreeInfo *) NULL) ||
189 (instantiate_type == MagickFalse))
190 if (InitializeTypeList(exception) == MagickFalse)
191 return((const TypeInfo *) NULL);
192 if ((type_list == (SplayTreeInfo *) NULL) ||
193 (GetNumberOfNodesInSplayTree(type_list) == 0))
194 return((const TypeInfo *) NULL);
195 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
197 ResetSplayTreeIterator(type_list);
198 return((const TypeInfo *) GetNextValueInSplayTree(type_list));
200 return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 + G e t T y p e I n f o B y F a m i l y %
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214 % GetTypeInfoByFamily() searches the type list for the specified family and if
215 % found returns attributes for that type.
217 % Type substitution and scoring algorithm contributed by Bob Friesenhahn.
219 % The format of the GetTypeInfoByFamily method is:
221 % const TypeInfo *GetTypeInfoByFamily(const char *family,
222 % const StyleType style,const StretchType stretch,
223 % const unsigned long weight,ExceptionInfo *exception)
225 % A description of each parameter follows:
227 % o family: the type family.
229 % o style: the type style.
231 % o stretch: the type stretch.
233 % o weight: the type weight.
235 % o exception: return any errors or warnings in this structure.
239 static inline unsigned long MagickMax(const unsigned long x,
240 const unsigned long y)
247 static inline unsigned long MagickMin(const unsigned long x,
248 const unsigned long y)
255 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
256 const StyleType style,const StretchType stretch,const unsigned long weight,
257 ExceptionInfo *exception)
259 typedef struct _Fontmap
272 register const TypeInfo
281 { "fixed", "courier" },
282 { "modern","courier" },
283 { "monotype corsiva", "courier" },
284 { "news gothic", "helvetica" },
285 { "system", "courier" },
286 { "terminal", "courier" },
287 { "wingdings", "symbol" },
296 Check for an exact type match.
298 (void) GetTypeInfo("*",exception);
299 if (type_list == (SplayTreeInfo *) NULL)
300 return((TypeInfo *) NULL);
301 AcquireSemaphoreInfo(&type_semaphore);
302 ResetSplayTreeIterator(type_list);
303 type_info=(const TypeInfo *) NULL;
304 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
305 while (p != (const TypeInfo *) NULL)
307 if (p->family == (char *) NULL)
309 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
312 if (family == (const char *) NULL)
314 if ((LocaleCompare(p->family,"arial") != 0) &&
315 (LocaleCompare(p->family,"helvetica") != 0))
317 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
322 if (LocaleCompare(p->family,family) != 0)
324 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
327 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
329 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
332 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
333 (p->stretch != stretch))
335 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
338 if ((weight != 0) && (p->weight != weight))
340 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
346 RelinquishSemaphoreInfo(type_semaphore);
347 if (type_info != (const TypeInfo *) NULL)
350 Check for types in the same family.
353 AcquireSemaphoreInfo(&type_semaphore);
354 ResetSplayTreeIterator(type_list);
355 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
356 while (p != (const TypeInfo *) NULL)
358 if (p->family == (char *) NULL)
360 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
363 if (family == (const char *) NULL)
365 if ((LocaleCompare(p->family,"arial") != 0) &&
366 (LocaleCompare(p->family,"helvetica") != 0))
368 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
373 if (LocaleCompare(p->family,family) != 0)
375 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
379 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
382 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
383 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
388 score+=(16*(800-((long) MagickMax(MagickMin(weight,900),p->weight)-
389 (long) MagickMin(MagickMin(weight,900),p->weight))))/800;
390 if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
394 range=(long) UltraExpandedStretch-(long) NormalStretch;
395 score+=(8*(range-((long) MagickMax(stretch,p->stretch)-
396 (long) MagickMin(stretch,p->stretch))))/range;
398 if (score > max_score)
403 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
405 RelinquishSemaphoreInfo(type_semaphore);
406 if (type_info != (const TypeInfo *) NULL)
409 Check for table-based substitution match.
411 for (i=0; fontmap[i].name != (char *) NULL; i++)
413 if (family == (const char *) NULL)
415 if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
416 (LocaleCompare(fontmap[i].name,"helvetica") != 0))
420 if (LocaleCompare(fontmap[i].name,family) != 0)
422 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
426 if (type_info != (const TypeInfo *) NULL)
428 (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
429 "FontSubstitutionRequired","`%s'",type_info->family);
432 if (family != (const char *) NULL)
433 type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 % G e t T y p e I n f o L i s t %
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 % GetTypeInfoList() returns any fonts that match the specified pattern.
451 % The format of the GetTypeInfoList function is:
453 % const TypeInfo **GetTypeInfoList(const char *pattern,
454 % unsigned long *number_fonts,ExceptionInfo *exception)
456 % A description of each parameter follows:
458 % o pattern: Specifies a pointer to a text string containing a pattern.
460 % o number_fonts: This integer returns the number of types in the list.
462 % o exception: return any errors or warnings in this structure.
466 #if defined(__cplusplus) || defined(c_plusplus)
470 static int TypeInfoCompare(const void *x,const void *y)
476 p=(const TypeInfo **) x,
477 q=(const TypeInfo **) y;
478 if (LocaleCompare((*p)->path,(*q)->path) == 0)
479 return(LocaleCompare((*p)->name,(*q)->name));
480 return(LocaleCompare((*p)->path,(*q)->path));
483 #if defined(__cplusplus) || defined(c_plusplus)
487 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
488 unsigned long *number_fonts,ExceptionInfo *exception)
493 register const TypeInfo
502 assert(pattern != (char *) NULL);
503 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
504 assert(number_fonts != (unsigned long *) NULL);
506 p=GetTypeInfo("*",exception);
507 if (p == (const TypeInfo *) NULL)
508 return((const TypeInfo **) NULL);
509 fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
510 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
511 if (fonts == (const TypeInfo **) NULL)
512 return((const TypeInfo **) NULL);
516 AcquireSemaphoreInfo(&type_semaphore);
517 ResetSplayTreeIterator(type_list);
518 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
519 for (i=0; p != (const TypeInfo *) NULL; )
521 if ((p->stealth == MagickFalse) &&
522 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
524 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
526 RelinquishSemaphoreInfo(type_semaphore);
527 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
528 fonts[i]=(TypeInfo *) NULL;
529 *number_fonts=(unsigned long) i;
534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
538 % G e t T y p e L i s t %
542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 % GetTypeList() returns any fonts that match the specified pattern.
546 % The format of the GetTypeList function is:
548 % char **GetTypeList(const char *pattern,unsigned long *number_fonts,
549 % ExceptionInfo *exception)
551 % A description of each parameter follows:
553 % o pattern: Specifies a pointer to a text string containing a pattern.
555 % o number_fonts: This integer returns the number of fonts in the list.
557 % o exception: return any errors or warnings in this structure.
561 #if defined(__cplusplus) || defined(c_plusplus)
565 static int TypeCompare(const void *x,const void *y)
573 return(LocaleCompare(*p,*q));
576 #if defined(__cplusplus) || defined(c_plusplus)
580 MagickExport char **GetTypeList(const char *pattern,unsigned long *number_fonts,
581 ExceptionInfo *exception)
586 register const TypeInfo
595 assert(pattern != (char *) NULL);
596 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
597 assert(number_fonts != (unsigned long *) NULL);
599 p=GetTypeInfo("*",exception);
600 if (p == (const TypeInfo *) NULL)
601 return((char **) NULL);
602 fonts=(char **) AcquireQuantumMemory((size_t)
603 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
604 if (fonts == (char **) NULL)
605 return((char **) NULL);
609 AcquireSemaphoreInfo(&type_semaphore);
610 ResetSplayTreeIterator(type_list);
611 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
612 for (i=0; p != (const TypeInfo *) NULL; )
614 if ((p->stealth == MagickFalse) &&
615 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
616 fonts[i++]=ConstantString(p->name);
617 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
619 RelinquishSemaphoreInfo(type_semaphore);
620 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
621 fonts[i]=(char *) NULL;
622 *number_fonts=(unsigned long) i;
627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631 + I n i t i a l i z e T y p e L i s t %
635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637 % InitializeTypeList() initializes the type list.
639 % The format of the InitializeTypeList method is:
641 % MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
643 % A description of each parameter follows.
645 % o exception: return any errors or warnings in this structure.
649 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
650 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
651 ExceptionInfo *exception)
654 extension[MaxTextExtent],
692 font_config=FcInitLoadConfigAndFonts();
693 if (font_config == (FcConfig *) NULL)
695 font_set=(FcFontSet *) NULL;
696 object_set=FcObjectSetBuild(FC_FAMILY,FC_STYLE,FC_SLANT,FC_WIDTH,FC_WEIGHT,
697 FC_FILE,(char *) NULL);
698 if (object_set != (FcObjectSet *) NULL)
700 pattern=FcPatternCreate();
701 if (pattern != (FcPattern *) NULL)
703 font_set=FcFontList(0,pattern,object_set);
704 FcPatternDestroy(pattern);
706 FcObjectSetDestroy(object_set);
708 if (font_set == (FcFontSet *) NULL)
710 FcConfigDestroy(font_config);
713 for (i=0; i < (long) font_set->nfont; i++)
715 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
716 if (status != FcResultMatch)
718 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
719 if (status != FcResultMatch)
722 GetPathComponent((const char *) file,ExtensionPath,extension);
723 if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
725 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
726 if (type_info == (TypeInfo *) NULL)
728 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
729 type_info->path=ConstantString("System Fonts");
730 type_info->signature=MagickSignature;
731 (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
732 (void) ConcatenateMagickString(name," ",MaxTextExtent);
733 status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
734 if (status == FcResultMatch)
735 (void) ConcatenateMagickString(name,(const char *) style,MaxTextExtent);
736 type_info->name=ConstantString(name);
737 (void) SubstituteString(&type_info->name," ","-");
738 (void) SubstituteString(&type_info->name,"-L-","-");
739 (void) SubstituteString(&type_info->name,"semicondensed","SemiCondensed");
740 type_info->family=ConstantString((const char *) family);
741 (void) SubstituteString(&type_info->family," L","");
742 status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
743 type_info->style=NormalStyle;
744 if (slant == FC_SLANT_ITALIC)
745 type_info->style=ItalicStyle;
746 if (slant == FC_SLANT_OBLIQUE)
747 type_info->style=ObliqueStyle;
748 status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
749 type_info->stretch=NormalStretch;
750 if (width >= FC_WIDTH_ULTRACONDENSED)
751 type_info->stretch=UltraCondensedStretch;
752 if (width >= FC_WIDTH_EXTRACONDENSED)
753 type_info->stretch=ExtraCondensedStretch;
754 if (width >= FC_WIDTH_CONDENSED)
755 type_info->stretch=CondensedStretch;
756 if (width >= FC_WIDTH_SEMICONDENSED)
757 type_info->stretch=SemiCondensedStretch;
758 if (width >= FC_WIDTH_NORMAL)
759 type_info->stretch=NormalStretch;
760 if (width >= FC_WIDTH_SEMIEXPANDED)
761 type_info->stretch=SemiExpandedStretch;
762 if (width >= FC_WIDTH_EXPANDED)
763 type_info->stretch=ExpandedStretch;
764 if (width >= FC_WIDTH_EXTRAEXPANDED)
765 type_info->stretch=ExtraExpandedStretch;
766 if (width >= FC_WIDTH_ULTRAEXPANDED)
767 type_info->stretch=UltraExpandedStretch;
768 type_info->weight=400;
769 status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
770 if (weight >= FC_WEIGHT_THIN)
771 type_info->weight=100;
772 if (weight >= FC_WEIGHT_EXTRALIGHT)
773 type_info->weight=200;
774 if (weight >= FC_WEIGHT_LIGHT)
775 type_info->weight=300;
776 if (weight >= FC_WEIGHT_NORMAL)
777 type_info->weight=400;
778 if (weight >= FC_WEIGHT_MEDIUM)
779 type_info->weight=500;
780 if (weight >= FC_WEIGHT_DEMIBOLD)
781 type_info->weight=600;
782 if (weight >= FC_WEIGHT_BOLD)
783 type_info->weight=700;
784 if (weight >= FC_WEIGHT_EXTRABOLD)
785 type_info->weight=800;
786 if (weight >= FC_WEIGHT_BLACK)
787 type_info->weight=900;
788 type_info->glyphs=ConstantString((const char *) file);
789 (void) AddValueToSplayTree(type_list,type_info->name,type_info);
791 FcFontSetDestroy(font_set);
792 FcConfigDestroy(font_config);
797 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
799 if ((type_list == (SplayTreeInfo *) NULL) &&
800 (instantiate_type == MagickFalse))
802 AcquireSemaphoreInfo(&type_semaphore);
803 if ((type_list == (SplayTreeInfo *) NULL) &&
804 (instantiate_type == MagickFalse))
806 (void) LoadTypeLists(MagickTypeFilename,exception);
807 #if defined(__WINDOWS__)
808 (void) NTLoadTypeLists(type_list,exception);
810 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
811 (void) LoadFontConfigFonts(type_list,exception);
813 instantiate_type=MagickTrue;
815 RelinquishSemaphoreInfo(type_semaphore);
817 return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 + I n s t a n t i a t e T y p e F a c i l i t y %
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 % InstantiateTypeFacility() instantiates the type facility.
833 % The format of the InstantiateTypeFacility method is:
835 % MagickBooleanType InstantiateTypeFacility(void)
838 MagickExport MagickBooleanType InstantiateTypeFacility(void)
840 AcquireSemaphoreInfo(&type_semaphore);
841 RelinquishSemaphoreInfo(type_semaphore);
846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 % L i s t T y p e I n f o %
854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 % ListTypeInfo() lists the fonts to a file.
858 % The format of the ListTypeInfo method is:
860 % MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
862 % A description of each parameter follows.
864 % o file: An pointer to a FILE.
866 % o exception: return any errors or warnings in this structure.
869 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
872 weight[MaxTextExtent];
891 if (file == (FILE *) NULL)
894 type_info=GetTypeInfoList("*",&number_fonts,exception);
895 if (type_info == (const TypeInfo **) NULL)
898 path=(const char *) NULL;
899 for (i=0; i < (long) number_fonts; i++)
901 if (type_info[i]->stealth != MagickFalse)
903 if (((path == (const char *) NULL) ||
904 (LocaleCompare(path,type_info[i]->path) != 0)) &&
905 (type_info[i]->path != (char *) NULL))
906 (void) fprintf(file,"\nPath: %s\n",type_info[i]->path);
907 path=type_info[i]->path;
909 if (type_info[i]->name != (char *) NULL)
910 name=type_info[i]->name;
912 if (type_info[i]->family != (char *) NULL)
913 family=type_info[i]->family;
914 style=MagickOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
915 stretch=MagickOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
917 if (type_info[i]->glyphs != (char *) NULL)
918 glyphs=type_info[i]->glyphs;
919 (void) FormatMagickString(weight,MaxTextExtent,"%lu",type_info[i]->weight);
920 (void) fprintf(file," Font: %s\n",name);
921 (void) fprintf(file," family: %s\n",family);
922 (void) fprintf(file," style: %s\n",style);
923 (void) fprintf(file," stretch: %s\n",stretch);
924 (void) fprintf(file," weight: %s\n",weight);
925 (void) fprintf(file," glyphs: %s\n",glyphs);
928 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
937 + L o a d T y p e L i s t %
941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
943 % LoadTypeList() loads the type configuration file which provides a mapping
944 % between type attributes and a type name.
946 % The format of the LoadTypeList method is:
948 % MagickBooleanType LoadTypeList(const char *xml,const char *filename,
949 % const unsigned long depth,ExceptionInfo *exception)
951 % A description of each parameter follows:
953 % o xml: The type list in XML format.
955 % o filename: The type list filename.
957 % o depth: depth of <include /> statements.
959 % o exception: return any errors or warnings in this structure.
963 static void *DestroyTypeNode(void *type_info)
968 p=(TypeInfo *) type_info;
969 if (p->path != (char *) NULL)
970 p->path=DestroyString(p->path);
971 if (p->name != (char *) NULL)
972 p->name=DestroyString(p->name);
973 if (p->description != (char *) NULL)
974 p->description=DestroyString(p->description);
975 if (p->family != (char *) NULL)
976 p->family=DestroyString(p->family);
977 if (p->encoding != (char *) NULL)
978 p->encoding=DestroyString(p->encoding);
979 if (p->foundry != (char *) NULL)
980 p->foundry=DestroyString(p->foundry);
981 if (p->format != (char *) NULL)
982 p->format=DestroyString(p->format);
983 if (p->metrics != (char *) NULL)
984 p->metrics=DestroyString(p->metrics);
985 if (p->glyphs != (char *) NULL)
986 p->glyphs=DestroyString(p->glyphs);
987 return(RelinquishMagickMemory(p));
990 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
991 const unsigned long depth,ExceptionInfo *exception)
994 font_path[MaxTextExtent],
995 keyword[MaxTextExtent],
1008 Load the type map file.
1010 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1011 "Loading type configure file \"%s\" ...",filename);
1012 if (xml == (const char *) NULL)
1013 return(MagickFalse);
1014 if (type_list == (SplayTreeInfo *) NULL)
1016 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
1018 if (type_list == (SplayTreeInfo *) NULL)
1020 ThrowFileException(exception,ResourceLimitError,
1021 "MemoryAllocationFailed",filename);
1022 return(MagickFalse);
1026 type_info=(TypeInfo *) NULL;
1027 token=AcquireString(xml);
1028 #if defined(__WINDOWS__)
1030 Determine the Ghostscript font path.
1033 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
1034 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
1036 for (q=(char *) xml; *q != '\0'; )
1041 GetMagickToken(q,&q,token);
1044 (void) CopyMagickString(keyword,token,MaxTextExtent);
1045 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1050 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1051 GetMagickToken(q,&q,token);
1054 if (LocaleNCompare(keyword,"<!--",4) == 0)
1059 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1060 GetMagickToken(q,&q,token);
1063 if (LocaleCompare(keyword,"<include") == 0)
1068 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1070 (void) CopyMagickString(keyword,token,MaxTextExtent);
1071 GetMagickToken(q,&q,token);
1074 GetMagickToken(q,&q,token);
1075 if (LocaleCompare(keyword,"file") == 0)
1078 (void) ThrowMagickException(exception,GetMagickModule(),
1079 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
1083 path[MaxTextExtent],
1090 GetPathComponent(filename,HeadPath,path);
1092 (void) ConcatenateMagickString(path,DirectorySeparator,
1094 if (*token == *DirectorySeparator)
1095 (void) CopyMagickString(path,token,MaxTextExtent);
1097 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1098 sans_exception=AcquireExceptionInfo();
1099 xml=FileToString(path,~0,sans_exception);
1100 sans_exception=DestroyExceptionInfo(sans_exception);
1101 if (xml != (char *) NULL)
1103 status=LoadTypeList(xml,path,depth+1,exception);
1104 xml=(char *) RelinquishMagickMemory(xml);
1111 if (LocaleCompare(keyword,"<type") == 0)
1116 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
1117 if (type_info == (TypeInfo *) NULL)
1118 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1119 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
1120 type_info->path=ConstantString(filename);
1121 type_info->signature=MagickSignature;
1124 if (type_info == (TypeInfo *) NULL)
1126 if (LocaleCompare(keyword,"/>") == 0)
1128 status=AddValueToSplayTree(type_list,type_info->name,type_info);
1129 if (status == MagickFalse)
1130 (void) ThrowMagickException(exception,GetMagickModule(),
1131 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
1132 type_info=(TypeInfo *) NULL;
1134 GetMagickToken(q,(const char **) NULL,token);
1137 GetMagickToken(q,&q,token);
1138 GetMagickToken(q,&q,token);
1144 if (LocaleCompare((char *) keyword,"encoding") == 0)
1146 type_info->encoding=ConstantString(token);
1154 if (LocaleCompare((char *) keyword,"face") == 0)
1156 type_info->face=(unsigned long) atol(token);
1159 if (LocaleCompare((char *) keyword,"family") == 0)
1161 type_info->family=ConstantString(token);
1164 if (LocaleCompare((char *) keyword,"format") == 0)
1166 type_info->format=ConstantString(token);
1169 if (LocaleCompare((char *) keyword,"foundry") == 0)
1171 type_info->foundry=ConstantString(token);
1174 if (LocaleCompare((char *) keyword,"fullname") == 0)
1176 type_info->description=ConstantString(token);
1184 if (LocaleCompare((char *) keyword,"glyphs") == 0)
1189 path=ConstantString(token);
1190 #if defined(__WINDOWS__)
1191 if (strchr(path,'@') != (char *) NULL)
1192 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1194 if (IsPathAccessible(path) == MagickFalse)
1199 path=DestroyString(path);
1200 GetPathComponent(filename,HeadPath,font_path);
1201 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1203 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1204 path=ConstantString(font_path);
1206 type_info->glyphs=path;
1214 if (LocaleCompare((char *) keyword,"metrics") == 0)
1219 path=ConstantString(token);
1220 #if defined(__WINDOWS__)
1221 if (strchr(path,'@') != (char *) NULL)
1222 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1224 if (IsPathAccessible(path) == MagickFalse)
1229 path=DestroyString(path);
1230 GetPathComponent(filename,HeadPath,font_path);
1231 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1233 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1234 path=ConstantString(font_path);
1236 type_info->metrics=path;
1244 if (LocaleCompare((char *) keyword,"name") == 0)
1246 type_info->name=ConstantString(token);
1254 if (LocaleCompare((char *) keyword,"stealth") == 0)
1256 type_info->stealth=IsMagickTrue(token);
1259 if (LocaleCompare((char *) keyword,"stretch") == 0)
1261 type_info->stretch=(StretchType) ParseMagickOption(
1262 MagickStretchOptions,MagickFalse,token);
1265 if (LocaleCompare((char *) keyword,"style") == 0)
1267 type_info->style=(StyleType) ParseMagickOption(MagickStyleOptions,
1276 if (LocaleCompare((char *) keyword,"weight") == 0)
1278 type_info->weight=(unsigned long) atol(token);
1279 if (LocaleCompare(token,"bold") == 0)
1280 type_info->weight=700;
1281 if (LocaleCompare(token,"normal") == 0)
1282 type_info->weight=400;
1291 token=(char *) RelinquishMagickMemory(token);
1296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1300 % L o a d T y p e L i s t s %
1304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1306 % LoadTypeList() loads one or more type configuration files which provides a
1307 % mapping between type attributes and a type name.
1309 % The format of the LoadTypeLists method is:
1311 % MagickBooleanType LoadTypeLists(const char *filename,
1312 % ExceptionInfo *exception)
1314 % A description of each parameter follows:
1316 % o filename: the font file name.
1318 % o exception: return any errors or warnings in this structure.
1321 static MagickBooleanType LoadTypeLists(const char *filename,
1322 ExceptionInfo *exception)
1324 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1325 return(LoadTypeList(TypeMap,"built-in",0,exception));
1329 path[MaxTextExtent];
1342 options=GetConfigureOptions(filename,exception);
1343 option=(const StringInfo *) GetNextValueInLinkedList(options);
1344 while (option != (const StringInfo *) NULL)
1346 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1347 status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1348 GetStringInfoPath(option),0,exception);
1349 option=(const StringInfo *) GetNextValueInLinkedList(options);
1351 options=DestroyConfigureOptions(options);
1352 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1353 if (font_path != (char *) NULL)
1359 Search MAGICK_FONT_PATH.
1361 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",font_path,
1362 DirectorySeparator,filename);
1363 option=FileToString(path,~0,exception);
1364 if (option != (void *) NULL)
1366 status|=LoadTypeList(option,path,0,exception);
1367 option=DestroyString(option);
1369 font_path=DestroyString(font_path);
1371 if ((type_list == (SplayTreeInfo *) NULL) ||
1372 (GetNumberOfNodesInSplayTree(type_list) == 0))
1373 status|=LoadTypeList(TypeMap,"built-in",0,exception);
1374 return(status != 0 ? MagickTrue : MagickFalse);