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 L i s t %
140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 % DestroyTypeList() deallocates memory associated with the font list.
144 % The format of the DestroyTypeList method is:
146 % void DestroyTypeList(void)
149 MagickExport void DestroyTypeList(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 % L i s t T y p e I n f o %
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 % ListTypeInfo() lists the fonts to a file.
833 % The format of the ListTypeInfo method is:
835 % MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
837 % A description of each parameter follows.
839 % o file: An pointer to a FILE.
841 % o exception: return any errors or warnings in this structure.
844 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
847 weight[MaxTextExtent];
866 if (file == (FILE *) NULL)
869 type_info=GetTypeInfoList("*",&number_fonts,exception);
870 if (type_info == (const TypeInfo **) NULL)
873 path=(const char *) NULL;
874 for (i=0; i < (long) number_fonts; i++)
876 if (type_info[i]->stealth != MagickFalse)
878 if (((path == (const char *) NULL) ||
879 (LocaleCompare(path,type_info[i]->path) != 0)) &&
880 (type_info[i]->path != (char *) NULL))
881 (void) fprintf(file,"\nPath: %s\n",type_info[i]->path);
882 path=type_info[i]->path;
884 if (type_info[i]->name != (char *) NULL)
885 name=type_info[i]->name;
887 if (type_info[i]->family != (char *) NULL)
888 family=type_info[i]->family;
889 style=MagickOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
890 stretch=MagickOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
892 if (type_info[i]->glyphs != (char *) NULL)
893 glyphs=type_info[i]->glyphs;
894 (void) FormatMagickString(weight,MaxTextExtent,"%lu",type_info[i]->weight);
895 (void) fprintf(file," Font: %s\n",name);
896 (void) fprintf(file," family: %s\n",family);
897 (void) fprintf(file," style: %s\n",style);
898 (void) fprintf(file," stretch: %s\n",stretch);
899 (void) fprintf(file," weight: %s\n",weight);
900 (void) fprintf(file," glyphs: %s\n",glyphs);
903 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912 + L o a d T y p e L i s t %
916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
918 % LoadTypeList() loads the type configuration file which provides a mapping
919 % between type attributes and a type name.
921 % The format of the LoadTypeList method is:
923 % MagickBooleanType LoadTypeList(const char *xml,const char *filename,
924 % const unsigned long depth,ExceptionInfo *exception)
926 % A description of each parameter follows:
928 % o xml: The type list in XML format.
930 % o filename: The type list filename.
932 % o depth: depth of <include /> statements.
934 % o exception: return any errors or warnings in this structure.
938 static void *DestroyTypeNode(void *type_info)
943 p=(TypeInfo *) type_info;
944 if (p->path != (char *) NULL)
945 p->path=DestroyString(p->path);
946 if (p->name != (char *) NULL)
947 p->name=DestroyString(p->name);
948 if (p->description != (char *) NULL)
949 p->description=DestroyString(p->description);
950 if (p->family != (char *) NULL)
951 p->family=DestroyString(p->family);
952 if (p->encoding != (char *) NULL)
953 p->encoding=DestroyString(p->encoding);
954 if (p->foundry != (char *) NULL)
955 p->foundry=DestroyString(p->foundry);
956 if (p->format != (char *) NULL)
957 p->format=DestroyString(p->format);
958 if (p->metrics != (char *) NULL)
959 p->metrics=DestroyString(p->metrics);
960 if (p->glyphs != (char *) NULL)
961 p->glyphs=DestroyString(p->glyphs);
962 return(RelinquishMagickMemory(p));
965 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
966 const unsigned long depth,ExceptionInfo *exception)
969 font_path[MaxTextExtent],
970 keyword[MaxTextExtent],
983 Load the type map file.
985 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
986 "Loading type configure file \"%s\" ...",filename);
987 if (xml == (const char *) NULL)
989 if (type_list == (SplayTreeInfo *) NULL)
991 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
993 if (type_list == (SplayTreeInfo *) NULL)
995 ThrowFileException(exception,ResourceLimitError,
996 "MemoryAllocationFailed",filename);
1001 type_info=(TypeInfo *) NULL;
1002 token=AcquireString(xml);
1003 #if defined(__WINDOWS__)
1005 Determine the Ghostscript font path.
1008 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
1009 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
1011 for (q=(char *) xml; *q != '\0'; )
1016 GetMagickToken(q,&q,token);
1019 (void) CopyMagickString(keyword,token,MaxTextExtent);
1020 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1025 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1026 GetMagickToken(q,&q,token);
1029 if (LocaleNCompare(keyword,"<!--",4) == 0)
1034 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1035 GetMagickToken(q,&q,token);
1038 if (LocaleCompare(keyword,"<include") == 0)
1043 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1045 (void) CopyMagickString(keyword,token,MaxTextExtent);
1046 GetMagickToken(q,&q,token);
1049 GetMagickToken(q,&q,token);
1050 if (LocaleCompare(keyword,"file") == 0)
1053 (void) ThrowMagickException(exception,GetMagickModule(),
1054 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
1058 path[MaxTextExtent],
1065 GetPathComponent(filename,HeadPath,path);
1067 (void) ConcatenateMagickString(path,DirectorySeparator,
1069 if (*token == *DirectorySeparator)
1070 (void) CopyMagickString(path,token,MaxTextExtent);
1072 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1073 sans_exception=AcquireExceptionInfo();
1074 xml=FileToString(path,~0,sans_exception);
1075 sans_exception=DestroyExceptionInfo(sans_exception);
1076 if (xml != (char *) NULL)
1078 status=LoadTypeList(xml,path,depth+1,exception);
1079 xml=(char *) RelinquishMagickMemory(xml);
1086 if (LocaleCompare(keyword,"<type") == 0)
1091 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
1092 if (type_info == (TypeInfo *) NULL)
1093 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1094 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
1095 type_info->path=ConstantString(filename);
1096 type_info->signature=MagickSignature;
1099 if (type_info == (TypeInfo *) NULL)
1101 if (LocaleCompare(keyword,"/>") == 0)
1103 status=AddValueToSplayTree(type_list,type_info->name,type_info);
1104 if (status == MagickFalse)
1105 (void) ThrowMagickException(exception,GetMagickModule(),
1106 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
1107 type_info=(TypeInfo *) NULL;
1109 GetMagickToken(q,(const char **) NULL,token);
1112 GetMagickToken(q,&q,token);
1113 GetMagickToken(q,&q,token);
1119 if (LocaleCompare((char *) keyword,"encoding") == 0)
1121 type_info->encoding=ConstantString(token);
1129 if (LocaleCompare((char *) keyword,"face") == 0)
1131 type_info->face=(unsigned long) atol(token);
1134 if (LocaleCompare((char *) keyword,"family") == 0)
1136 type_info->family=ConstantString(token);
1139 if (LocaleCompare((char *) keyword,"format") == 0)
1141 type_info->format=ConstantString(token);
1144 if (LocaleCompare((char *) keyword,"foundry") == 0)
1146 type_info->foundry=ConstantString(token);
1149 if (LocaleCompare((char *) keyword,"fullname") == 0)
1151 type_info->description=ConstantString(token);
1159 if (LocaleCompare((char *) keyword,"glyphs") == 0)
1164 path=ConstantString(token);
1165 #if defined(__WINDOWS__)
1166 if (strchr(path,'@') != (char *) NULL)
1167 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1169 if (IsPathAccessible(path) == MagickFalse)
1174 path=DestroyString(path);
1175 GetPathComponent(filename,HeadPath,font_path);
1176 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1178 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1179 path=ConstantString(font_path);
1181 type_info->glyphs=path;
1189 if (LocaleCompare((char *) keyword,"metrics") == 0)
1194 path=ConstantString(token);
1195 #if defined(__WINDOWS__)
1196 if (strchr(path,'@') != (char *) NULL)
1197 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1199 if (IsPathAccessible(path) == MagickFalse)
1204 path=DestroyString(path);
1205 GetPathComponent(filename,HeadPath,font_path);
1206 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1208 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1209 path=ConstantString(font_path);
1211 type_info->metrics=path;
1219 if (LocaleCompare((char *) keyword,"name") == 0)
1221 type_info->name=ConstantString(token);
1229 if (LocaleCompare((char *) keyword,"stealth") == 0)
1231 type_info->stealth=IsMagickTrue(token);
1234 if (LocaleCompare((char *) keyword,"stretch") == 0)
1236 type_info->stretch=(StretchType) ParseMagickOption(
1237 MagickStretchOptions,MagickFalse,token);
1240 if (LocaleCompare((char *) keyword,"style") == 0)
1242 type_info->style=(StyleType) ParseMagickOption(MagickStyleOptions,
1251 if (LocaleCompare((char *) keyword,"weight") == 0)
1253 type_info->weight=(unsigned long) atol(token);
1254 if (LocaleCompare(token,"bold") == 0)
1255 type_info->weight=700;
1256 if (LocaleCompare(token,"normal") == 0)
1257 type_info->weight=400;
1266 token=(char *) RelinquishMagickMemory(token);
1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275 % L o a d T y p e L i s t s %
1279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281 % LoadTypeList() loads one or more type configuration files which provides a
1282 % mapping between type attributes and a type name.
1284 % The format of the LoadTypeLists method is:
1286 % MagickBooleanType LoadTypeLists(const char *filename,
1287 % ExceptionInfo *exception)
1289 % A description of each parameter follows:
1291 % o filename: the font file name.
1293 % o exception: return any errors or warnings in this structure.
1296 static MagickBooleanType LoadTypeLists(const char *filename,
1297 ExceptionInfo *exception)
1299 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1300 return(LoadTypeList(TypeMap,"built-in",0,exception));
1304 path[MaxTextExtent];
1317 options=GetConfigureOptions(filename,exception);
1318 option=(const StringInfo *) GetNextValueInLinkedList(options);
1319 while (option != (const StringInfo *) NULL)
1321 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1322 status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1323 GetStringInfoPath(option),0,exception);
1324 option=(const StringInfo *) GetNextValueInLinkedList(options);
1326 options=DestroyConfigureOptions(options);
1327 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1328 if (font_path != (char *) NULL)
1334 Search MAGICK_FONT_PATH.
1336 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",font_path,
1337 DirectorySeparator,filename);
1338 option=FileToString(path,~0,exception);
1339 if (option != (void *) NULL)
1341 status|=LoadTypeList(option,path,0,exception);
1342 option=DestroyString(option);
1344 font_path=DestroyString(font_path);
1346 if ((type_list == (SplayTreeInfo *) NULL) ||
1347 (GetNumberOfNodesInSplayTree(type_list) == 0))
1348 status|=LoadTypeList(TypeMap,"built-in",0,exception);
1349 return(status != 0 ? MagickTrue : MagickFalse);