2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % TTTTT Y Y PPPP EEEEE %
13 % MagickCore Image Type Methods %
20 % Copyright 1999-2013 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-feature.h"
53 #include "MagickCore/nt-base-private.h"
54 #include "MagickCore/option.h"
55 #include "MagickCore/semaphore.h"
56 #include "MagickCore/splay-tree.h"
57 #include "MagickCore/string_.h"
58 #include "MagickCore/string-private.h"
59 #include "MagickCore/type.h"
60 #include "MagickCore/type-private.h"
61 #include "MagickCore/token.h"
62 #include "MagickCore/utility.h"
63 #include "MagickCore/utility-private.h"
64 #include "MagickCore/xml-tree.h"
65 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
66 # include "fontconfig/fontconfig.h"
67 #if (FC_VERSION < 20209)
68 #undef FC_WEIGHT_LIGHT
69 #define FC_WIDTH "width" /* Int */
70 #define FC_WIDTH_ULTRACONDENSED 50
71 #define FC_WIDTH_EXTRACONDENSED 63
72 #define FC_WIDTH_CONDENSED 75
73 #define FC_WIDTH_SEMICONDENSED 87
74 #define FC_WIDTH_NORMAL 100
75 #define FC_WIDTH_SEMIEXPANDED 113
76 #define FC_WIDTH_EXPANDED 125
77 #define FC_WIDTH_EXTRAEXPANDED 150
78 #define FC_WIDTH_ULTRAEXPANDED 200
80 #define FC_WEIGHT_THIN 0
81 #define FC_WEIGHT_EXTRALIGHT 40
82 #define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
83 #define FC_WEIGHT_LIGHT 50
84 #define FC_WEIGHT_BOOK 75
85 #define FC_WEIGHT_REGULAR 80
86 #define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
87 #define FC_WEIGHT_MEDIUM 100
88 #define FC_WEIGHT_DEMIBOLD 180
89 #define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
90 #define FC_WEIGHT_BOLD 200
91 #define FC_WEIGHT_EXTRABOLD 205
92 #define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
93 #define FC_WEIGHT_BLACK 210
94 #define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
101 #define MagickTypeFilename "type.xml"
107 *TypeMap = (const char *)
108 "<?xml version=\"1.0\"?>"
110 " <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
111 " <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
118 *type_semaphore = (SemaphoreInfo *) NULL;
120 static volatile MagickBooleanType
121 instantiate_type = MagickFalse;
124 *type_list = (SplayTreeInfo *) NULL;
127 Forward declarations.
129 static MagickBooleanType
130 InitializeTypeList(ExceptionInfo *),
131 LoadTypeLists(const char *,ExceptionInfo *);
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 + G e t T y p e I n f o %
142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144 % GetTypeInfo searches the type list for the specified name and if found
145 % returns attributes for that type.
147 % The format of the GetTypeInfo method is:
149 % const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
151 % A description of each parameter follows:
153 % o name: the type name.
155 % o exception: return any errors or warnings in this structure.
158 MagickExport const TypeInfo *GetTypeInfo(const char *name,
159 ExceptionInfo *exception)
161 assert(exception != (ExceptionInfo *) NULL);
162 if ((type_list == (SplayTreeInfo *) NULL) ||
163 (instantiate_type == MagickFalse))
164 if (InitializeTypeList(exception) == MagickFalse)
165 return((const TypeInfo *) NULL);
166 if ((type_list == (SplayTreeInfo *) NULL) ||
167 (GetNumberOfNodesInSplayTree(type_list) == 0))
168 return((const TypeInfo *) NULL);
169 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
171 ResetSplayTreeIterator(type_list);
172 return((const TypeInfo *) GetNextValueInSplayTree(type_list));
174 return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182 + G e t T y p e I n f o B y F a m i l y %
186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188 % GetTypeInfoByFamily() searches the type list for the specified family and if
189 % found returns attributes for that type.
191 % Type substitution and scoring algorithm contributed by Bob Friesenhahn.
193 % The format of the GetTypeInfoByFamily method is:
195 % const TypeInfo *GetTypeInfoByFamily(const char *family,
196 % const StyleType style,const StretchType stretch,
197 % const size_t weight,ExceptionInfo *exception)
199 % A description of each parameter follows:
201 % o family: the type family.
203 % o style: the type style.
205 % o stretch: the type stretch.
207 % o weight: the type weight.
209 % o exception: return any errors or warnings in this structure.
213 static inline size_t MagickMax(const size_t x,const size_t y)
220 static inline size_t MagickMin(const size_t x,const size_t y)
227 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
228 const StyleType style,const StretchType stretch,const size_t weight,
229 ExceptionInfo *exception)
231 typedef struct _Fontmap
241 register const TypeInfo
253 { "fixed", "courier" },
254 { "modern","courier" },
255 { "monotype corsiva", "courier" },
256 { "news gothic", "helvetica" },
257 { "system", "courier" },
258 { "terminal", "courier" },
259 { "wingdings", "symbol" },
268 Check for an exact type match.
270 (void) GetTypeInfo("*",exception);
271 if (type_list == (SplayTreeInfo *) NULL)
272 return((TypeInfo *) NULL);
273 LockSemaphoreInfo(type_semaphore);
274 ResetSplayTreeIterator(type_list);
275 type_info=(const TypeInfo *) NULL;
276 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
277 while (p != (const TypeInfo *) NULL)
279 if (p->family == (char *) NULL)
281 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
284 if (family == (const char *) NULL)
286 if ((LocaleCompare(p->family,"arial") != 0) &&
287 (LocaleCompare(p->family,"helvetica") != 0))
289 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
294 if (LocaleCompare(p->family,family) != 0)
296 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
299 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
301 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
304 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
305 (p->stretch != stretch))
307 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
310 if ((weight != 0) && (p->weight != weight))
312 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
318 UnlockSemaphoreInfo(type_semaphore);
319 if (type_info != (const TypeInfo *) NULL)
322 Check for types in the same family.
325 LockSemaphoreInfo(type_semaphore);
326 ResetSplayTreeIterator(type_list);
327 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
328 while (p != (const TypeInfo *) NULL)
330 if (p->family == (char *) NULL)
332 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
335 if (family == (const char *) NULL)
337 if ((LocaleCompare(p->family,"arial") != 0) &&
338 (LocaleCompare(p->family,"helvetica") != 0))
340 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
345 if (LocaleCompare(p->family,family) != 0)
347 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
351 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
354 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
355 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
360 score+=(16*(800-((ssize_t) MagickMax(MagickMin(weight,900),p->weight)-
361 (ssize_t) MagickMin(MagickMin(weight,900),p->weight))))/800;
362 if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
366 range=(ssize_t) UltraExpandedStretch-(ssize_t) NormalStretch;
367 score+=(8*(range-((ssize_t) MagickMax(stretch,p->stretch)-
368 (ssize_t) MagickMin(stretch,p->stretch))))/range;
370 if (score > max_score)
375 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
377 UnlockSemaphoreInfo(type_semaphore);
378 if (type_info != (const TypeInfo *) NULL)
381 Check for table-based substitution match.
383 for (i=0; fontmap[i].name != (char *) NULL; i++)
385 if (family == (const char *) NULL)
387 if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
388 (LocaleCompare(fontmap[i].name,"helvetica") != 0))
392 if (LocaleCompare(fontmap[i].name,family) != 0)
394 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
398 if (type_info != (const TypeInfo *) NULL)
400 (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
401 "FontSubstitutionRequired","`%s'",type_info->family);
404 if (family != (const char *) NULL)
405 type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 % G e t T y p e I n f o L i s t %
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421 % GetTypeInfoList() returns any fonts that match the specified pattern.
423 % The format of the GetTypeInfoList function is:
425 % const TypeInfo **GetTypeInfoList(const char *pattern,
426 % size_t *number_fonts,ExceptionInfo *exception)
428 % A description of each parameter follows:
430 % o pattern: Specifies a pointer to a text string containing a pattern.
432 % o number_fonts: This integer returns the number of types in the list.
434 % o exception: return any errors or warnings in this structure.
438 #if defined(__cplusplus) || defined(c_plusplus)
442 static int TypeInfoCompare(const void *x,const void *y)
448 p=(const TypeInfo **) x,
449 q=(const TypeInfo **) y;
450 if (LocaleCompare((*p)->path,(*q)->path) == 0)
451 return(LocaleCompare((*p)->name,(*q)->name));
452 return(LocaleCompare((*p)->path,(*q)->path));
455 #if defined(__cplusplus) || defined(c_plusplus)
459 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
460 size_t *number_fonts,ExceptionInfo *exception)
465 register const TypeInfo
474 assert(pattern != (char *) NULL);
475 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
476 assert(number_fonts != (size_t *) NULL);
478 p=GetTypeInfo("*",exception);
479 if (p == (const TypeInfo *) NULL)
480 return((const TypeInfo **) NULL);
481 fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
482 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
483 if (fonts == (const TypeInfo **) NULL)
484 return((const TypeInfo **) NULL);
488 LockSemaphoreInfo(type_semaphore);
489 ResetSplayTreeIterator(type_list);
490 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
491 for (i=0; p != (const TypeInfo *) NULL; )
493 if ((p->stealth == MagickFalse) &&
494 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
496 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
498 UnlockSemaphoreInfo(type_semaphore);
499 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
500 fonts[i]=(TypeInfo *) NULL;
501 *number_fonts=(size_t) i;
506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 % G e t T y p e L i s t %
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516 % GetTypeList() returns any fonts that match the specified pattern.
518 % The format of the GetTypeList function is:
520 % char **GetTypeList(const char *pattern,size_t *number_fonts,
521 % ExceptionInfo *exception)
523 % A description of each parameter follows:
525 % o pattern: Specifies a pointer to a text string containing a pattern.
527 % o number_fonts: This integer returns the number of fonts in the list.
529 % o exception: return any errors or warnings in this structure.
533 #if defined(__cplusplus) || defined(c_plusplus)
537 static int TypeCompare(const void *x,const void *y)
545 return(LocaleCompare(*p,*q));
548 #if defined(__cplusplus) || defined(c_plusplus)
552 MagickExport char **GetTypeList(const char *pattern,size_t *number_fonts,
553 ExceptionInfo *exception)
558 register const TypeInfo
567 assert(pattern != (char *) NULL);
568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
569 assert(number_fonts != (size_t *) NULL);
571 p=GetTypeInfo("*",exception);
572 if (p == (const TypeInfo *) NULL)
573 return((char **) NULL);
574 fonts=(char **) AcquireQuantumMemory((size_t)
575 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
576 if (fonts == (char **) NULL)
577 return((char **) NULL);
581 LockSemaphoreInfo(type_semaphore);
582 ResetSplayTreeIterator(type_list);
583 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
584 for (i=0; p != (const TypeInfo *) NULL; )
586 if ((p->stealth == MagickFalse) &&
587 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
588 fonts[i++]=ConstantString(p->name);
589 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
591 UnlockSemaphoreInfo(type_semaphore);
592 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
593 fonts[i]=(char *) NULL;
594 *number_fonts=(size_t) i;
599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 + I n i t i a l i z e T y p e L i s t %
607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 % InitializeTypeList() initializes the type list.
611 % The format of the InitializeTypeList method is:
613 % MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
615 % A description of each parameter follows.
617 % o exception: return any errors or warnings in this structure.
621 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
622 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
623 ExceptionInfo *exception)
625 #if !defined(FC_FULLNAME)
626 #define FC_FULLNAME "fullname"
630 extension[MaxTextExtent],
669 font_config=FcInitLoadConfigAndFonts();
670 if (font_config == (FcConfig *) NULL)
672 font_set=(FcFontSet *) NULL;
673 object_set=FcObjectSetBuild(FC_FULLNAME,FC_FAMILY,FC_STYLE,FC_SLANT,
674 FC_WIDTH,FC_WEIGHT,FC_FILE,(char *) NULL);
675 if (object_set != (FcObjectSet *) NULL)
677 pattern=FcPatternCreate();
678 if (pattern != (FcPattern *) NULL)
680 font_set=FcFontList(0,pattern,object_set);
681 FcPatternDestroy(pattern);
683 FcObjectSetDestroy(object_set);
685 if (font_set == (FcFontSet *) NULL)
687 FcConfigDestroy(font_config);
690 for (i=0; i < (ssize_t) font_set->nfont; i++)
692 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
693 if (status != FcResultMatch)
695 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
696 if (status != FcResultMatch)
699 GetPathComponent((const char *) file,ExtensionPath,extension);
700 if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
702 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
703 if (type_info == (TypeInfo *) NULL)
705 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
706 type_info->path=ConstantString("System Fonts");
707 type_info->signature=MagickSignature;
708 (void) CopyMagickString(name,"Unknown",MaxTextExtent);
709 status=FcPatternGetString(font_set->fonts[i],FC_FULLNAME,0,&fullname);
710 if ((status == FcResultMatch) && (fullname != (FcChar8 *) NULL))
711 (void) CopyMagickString(name,(const char *) fullname,MaxTextExtent);
714 if (family != (FcChar8 *) NULL)
715 (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
716 status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
717 if ((status == FcResultMatch) && (style != (FcChar8 *) NULL) &&
718 (LocaleCompare((const char *) style,"Regular") != 0))
720 (void) ConcatenateMagickString(name," ",MaxTextExtent);
721 (void) ConcatenateMagickString(name,(const char *) style,
725 type_info->name=ConstantString(name);
726 (void) SubstituteString(&type_info->name," ","-");
727 type_info->family=ConstantString((const char *) family);
728 status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
729 type_info->style=NormalStyle;
730 if (slant == FC_SLANT_ITALIC)
731 type_info->style=ItalicStyle;
732 if (slant == FC_SLANT_OBLIQUE)
733 type_info->style=ObliqueStyle;
734 status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
735 type_info->stretch=NormalStretch;
736 if (width >= FC_WIDTH_ULTRACONDENSED)
737 type_info->stretch=UltraCondensedStretch;
738 if (width >= FC_WIDTH_EXTRACONDENSED)
739 type_info->stretch=ExtraCondensedStretch;
740 if (width >= FC_WIDTH_CONDENSED)
741 type_info->stretch=CondensedStretch;
742 if (width >= FC_WIDTH_SEMICONDENSED)
743 type_info->stretch=SemiCondensedStretch;
744 if (width >= FC_WIDTH_NORMAL)
745 type_info->stretch=NormalStretch;
746 if (width >= FC_WIDTH_SEMIEXPANDED)
747 type_info->stretch=SemiExpandedStretch;
748 if (width >= FC_WIDTH_EXPANDED)
749 type_info->stretch=ExpandedStretch;
750 if (width >= FC_WIDTH_EXTRAEXPANDED)
751 type_info->stretch=ExtraExpandedStretch;
752 if (width >= FC_WIDTH_ULTRAEXPANDED)
753 type_info->stretch=UltraExpandedStretch;
754 type_info->weight=400;
755 status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
756 if (weight >= FC_WEIGHT_THIN)
757 type_info->weight=100;
758 if (weight >= FC_WEIGHT_EXTRALIGHT)
759 type_info->weight=200;
760 if (weight >= FC_WEIGHT_LIGHT)
761 type_info->weight=300;
762 if (weight >= FC_WEIGHT_NORMAL)
763 type_info->weight=400;
764 if (weight >= FC_WEIGHT_MEDIUM)
765 type_info->weight=500;
766 if (weight >= FC_WEIGHT_DEMIBOLD)
767 type_info->weight=600;
768 if (weight >= FC_WEIGHT_BOLD)
769 type_info->weight=700;
770 if (weight >= FC_WEIGHT_EXTRABOLD)
771 type_info->weight=800;
772 if (weight >= FC_WEIGHT_BLACK)
773 type_info->weight=900;
774 type_info->glyphs=ConstantString((const char *) file);
775 (void) AddValueToSplayTree(type_list,type_info->name,type_info);
777 FcFontSetDestroy(font_set);
778 FcConfigDestroy(font_config);
783 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
785 if ((type_list == (SplayTreeInfo *) NULL) &&
786 (instantiate_type == MagickFalse))
788 if (type_semaphore == (SemaphoreInfo *) NULL)
789 AcquireSemaphoreInfo(&type_semaphore);
790 LockSemaphoreInfo(type_semaphore);
791 if ((type_list == (SplayTreeInfo *) NULL) &&
792 (instantiate_type == MagickFalse))
794 (void) LoadTypeLists(MagickTypeFilename,exception);
795 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
796 (void) NTLoadTypeLists(type_list,exception);
798 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
799 (void) LoadFontConfigFonts(type_list,exception);
801 instantiate_type=MagickTrue;
803 UnlockSemaphoreInfo(type_semaphore);
805 return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
809 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
813 % L i s t T y p e I n f o %
817 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 % ListTypeInfo() lists the fonts to a file.
821 % The format of the ListTypeInfo method is:
823 % MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
825 % A description of each parameter follows.
827 % o file: An pointer to a FILE.
829 % o exception: return any errors or warnings in this structure.
832 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
835 weight[MaxTextExtent];
854 if (file == (FILE *) NULL)
857 type_info=GetTypeInfoList("*",&number_fonts,exception);
858 if (type_info == (const TypeInfo **) NULL)
861 path=(const char *) NULL;
862 for (i=0; i < (ssize_t) number_fonts; i++)
864 if (type_info[i]->stealth != MagickFalse)
866 if (((path == (const char *) NULL) ||
867 (LocaleCompare(path,type_info[i]->path) != 0)) &&
868 (type_info[i]->path != (char *) NULL))
869 (void) FormatLocaleFile(file,"\nPath: %s\n",type_info[i]->path);
870 path=type_info[i]->path;
872 if (type_info[i]->name != (char *) NULL)
873 name=type_info[i]->name;
875 if (type_info[i]->family != (char *) NULL)
876 family=type_info[i]->family;
877 style=CommandOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
878 stretch=CommandOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
880 if (type_info[i]->glyphs != (char *) NULL)
881 glyphs=type_info[i]->glyphs;
882 (void) FormatLocaleString(weight,MaxTextExtent,"%.20g",(double)
883 type_info[i]->weight);
884 (void) FormatLocaleFile(file," Font: %s\n",name);
885 (void) FormatLocaleFile(file," family: %s\n",family);
886 (void) FormatLocaleFile(file," style: %s\n",style);
887 (void) FormatLocaleFile(file," stretch: %s\n",stretch);
888 (void) FormatLocaleFile(file," weight: %s\n",weight);
889 (void) FormatLocaleFile(file," glyphs: %s\n",glyphs);
892 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 + L o a d T y p e L i s t %
905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907 % LoadTypeList() loads the type configuration file which provides a mapping
908 % between type attributes and a type name.
910 % The format of the LoadTypeList method is:
912 % MagickBooleanType LoadTypeList(const char *xml,const char *filename,
913 % const size_t depth,ExceptionInfo *exception)
915 % A description of each parameter follows:
917 % o xml: The type list in XML format.
919 % o filename: The type list filename.
921 % o depth: depth of <include /> statements.
923 % o exception: return any errors or warnings in this structure.
927 static void *DestroyTypeNode(void *type_info)
932 p=(TypeInfo *) type_info;
933 if (p->path != (char *) NULL)
934 p->path=DestroyString(p->path);
935 if (p->name != (char *) NULL)
936 p->name=DestroyString(p->name);
937 if (p->description != (char *) NULL)
938 p->description=DestroyString(p->description);
939 if (p->family != (char *) NULL)
940 p->family=DestroyString(p->family);
941 if (p->encoding != (char *) NULL)
942 p->encoding=DestroyString(p->encoding);
943 if (p->foundry != (char *) NULL)
944 p->foundry=DestroyString(p->foundry);
945 if (p->format != (char *) NULL)
946 p->format=DestroyString(p->format);
947 if (p->metrics != (char *) NULL)
948 p->metrics=DestroyString(p->metrics);
949 if (p->glyphs != (char *) NULL)
950 p->glyphs=DestroyString(p->glyphs);
951 return(RelinquishMagickMemory(p));
954 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
955 const size_t depth,ExceptionInfo *exception)
958 font_path[MaxTextExtent],
959 keyword[MaxTextExtent],
972 Load the type map file.
974 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
975 "Loading type configure file \"%s\" ...",filename);
976 if (xml == (const char *) NULL)
978 if (type_list == (SplayTreeInfo *) NULL)
980 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
982 if (type_list == (SplayTreeInfo *) NULL)
984 ThrowFileException(exception,ResourceLimitError,
985 "MemoryAllocationFailed",filename);
990 type_info=(TypeInfo *) NULL;
991 token=AcquireString(xml);
992 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
994 Determine the Ghostscript font path.
997 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
998 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
1000 for (q=(char *) xml; *q != '\0'; )
1005 GetMagickToken(q,&q,token);
1008 (void) CopyMagickString(keyword,token,MaxTextExtent);
1009 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1014 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1015 GetMagickToken(q,&q,token);
1018 if (LocaleNCompare(keyword,"<!--",4) == 0)
1023 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1024 GetMagickToken(q,&q,token);
1027 if (LocaleCompare(keyword,"<include") == 0)
1032 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1034 (void) CopyMagickString(keyword,token,MaxTextExtent);
1035 GetMagickToken(q,&q,token);
1038 GetMagickToken(q,&q,token);
1039 if (LocaleCompare(keyword,"file") == 0)
1042 (void) ThrowMagickException(exception,GetMagickModule(),
1043 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
1047 path[MaxTextExtent],
1054 GetPathComponent(filename,HeadPath,path);
1056 (void) ConcatenateMagickString(path,DirectorySeparator,
1058 if (*token == *DirectorySeparator)
1059 (void) CopyMagickString(path,token,MaxTextExtent);
1061 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1062 sans_exception=AcquireExceptionInfo();
1063 xml=FileToString(path,~0,sans_exception);
1064 sans_exception=DestroyExceptionInfo(sans_exception);
1065 if (xml != (char *) NULL)
1067 status=LoadTypeList(xml,path,depth+1,exception);
1068 xml=(char *) RelinquishMagickMemory(xml);
1075 if (LocaleCompare(keyword,"<type") == 0)
1080 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
1081 if (type_info == (TypeInfo *) NULL)
1082 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1083 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
1084 type_info->path=ConstantString(filename);
1085 type_info->signature=MagickSignature;
1088 if (type_info == (TypeInfo *) NULL)
1090 if (LocaleCompare(keyword,"/>") == 0)
1092 status=AddValueToSplayTree(type_list,type_info->name,type_info);
1093 if (status == MagickFalse)
1094 (void) ThrowMagickException(exception,GetMagickModule(),
1095 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
1096 type_info=(TypeInfo *) NULL;
1098 GetMagickToken(q,(const char **) NULL,token);
1101 GetMagickToken(q,&q,token);
1102 GetMagickToken(q,&q,token);
1108 if (LocaleCompare((char *) keyword,"encoding") == 0)
1110 type_info->encoding=ConstantString(token);
1118 if (LocaleCompare((char *) keyword,"face") == 0)
1120 type_info->face=StringToUnsignedLong(token);
1123 if (LocaleCompare((char *) keyword,"family") == 0)
1125 type_info->family=ConstantString(token);
1128 if (LocaleCompare((char *) keyword,"format") == 0)
1130 type_info->format=ConstantString(token);
1133 if (LocaleCompare((char *) keyword,"foundry") == 0)
1135 type_info->foundry=ConstantString(token);
1138 if (LocaleCompare((char *) keyword,"fullname") == 0)
1140 type_info->description=ConstantString(token);
1148 if (LocaleCompare((char *) keyword,"glyphs") == 0)
1153 path=ConstantString(token);
1154 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1155 if (strchr(path,'@') != (char *) NULL)
1156 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1158 if (IsPathAccessible(path) == MagickFalse)
1163 path=DestroyString(path);
1164 GetPathComponent(filename,HeadPath,font_path);
1165 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1167 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1168 path=ConstantString(font_path);
1169 if (IsPathAccessible(path) == MagickFalse)
1171 path=DestroyString(path);
1172 path=ConstantString(token);
1175 type_info->glyphs=path;
1183 if (LocaleCompare((char *) keyword,"metrics") == 0)
1188 path=ConstantString(token);
1189 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1190 if (strchr(path,'@') != (char *) NULL)
1191 SubstituteString(&path,"@ghostscript_font_path@",font_path);
1193 if (IsPathAccessible(path) == MagickFalse)
1198 path=DestroyString(path);
1199 GetPathComponent(filename,HeadPath,font_path);
1200 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1202 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
1203 path=ConstantString(font_path);
1205 type_info->metrics=path;
1213 if (LocaleCompare((char *) keyword,"name") == 0)
1215 type_info->name=ConstantString(token);
1223 if (LocaleCompare((char *) keyword,"stealth") == 0)
1225 type_info->stealth=IsStringTrue(token);
1228 if (LocaleCompare((char *) keyword,"stretch") == 0)
1230 type_info->stretch=(StretchType) ParseCommandOption(
1231 MagickStretchOptions,MagickFalse,token);
1234 if (LocaleCompare((char *) keyword,"style") == 0)
1236 type_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1245 if (LocaleCompare((char *) keyword,"weight") == 0)
1247 type_info->weight=StringToUnsignedLong(token);
1248 if (LocaleCompare(token,"bold") == 0)
1249 type_info->weight=700;
1250 if (LocaleCompare(token,"normal") == 0)
1251 type_info->weight=400;
1260 token=(char *) RelinquishMagickMemory(token);
1265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1269 % L o a d T y p e L i s t s %
1273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275 % LoadTypeList() loads one or more type configuration files which provides a
1276 % mapping between type attributes and a type name.
1278 % The format of the LoadTypeLists method is:
1280 % MagickBooleanType LoadTypeLists(const char *filename,
1281 % ExceptionInfo *exception)
1283 % A description of each parameter follows:
1285 % o filename: the font file name.
1287 % o exception: return any errors or warnings in this structure.
1290 static MagickBooleanType LoadTypeLists(const char *filename,
1291 ExceptionInfo *exception)
1293 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1294 return(LoadTypeList(TypeMap,"built-in",0,exception));
1298 path[MaxTextExtent];
1311 options=GetConfigureOptions(filename,exception);
1312 option=(const StringInfo *) GetNextValueInLinkedList(options);
1313 while (option != (const StringInfo *) NULL)
1315 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1316 status|=LoadTypeList((const char *) GetStringInfoDatum(option),
1317 GetStringInfoPath(option),0,exception);
1318 option=(const StringInfo *) GetNextValueInLinkedList(options);
1320 options=DestroyConfigureOptions(options);
1321 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
1322 if (font_path != (char *) NULL)
1328 Search MAGICK_FONT_PATH.
1330 (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",font_path,
1331 DirectorySeparator,filename);
1332 option=FileToString(path,~0,exception);
1333 if (option != (void *) NULL)
1335 status|=LoadTypeList(option,path,0,exception);
1336 option=DestroyString(option);
1338 font_path=DestroyString(font_path);
1340 if ((type_list == (SplayTreeInfo *) NULL) ||
1341 (GetNumberOfNodesInSplayTree(type_list) == 0))
1342 status|=LoadTypeList(TypeMap,"built-in",0,exception);
1343 return(status != 0 ? MagickTrue : MagickFalse);
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1352 + T y p e C o m p o n e n t G e n e s i s %
1356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358 % TypeComponentGenesis() instantiates the type component.
1360 % The format of the TypeComponentGenesis method is:
1362 % MagickBooleanType TypeComponentGenesis(void)
1365 MagickPrivate MagickBooleanType TypeComponentGenesis(void)
1367 AcquireSemaphoreInfo(&type_semaphore);
1372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1376 + T y p e C o m p o n e n t T e r m i n u s %
1380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 % TypeComponentTerminus() destroy type component.
1384 % The format of the TypeComponentTerminus method is:
1386 % void TypeComponentTerminus(void)
1389 MagickPrivate void TypeComponentTerminus(void)
1391 if (type_semaphore == (SemaphoreInfo *) NULL)
1392 AcquireSemaphoreInfo(&type_semaphore);
1393 LockSemaphoreInfo(type_semaphore);
1394 if (type_list != (SplayTreeInfo *) NULL)
1395 type_list=DestroySplayTree(type_list);
1396 instantiate_type=MagickFalse;
1397 UnlockSemaphoreInfo(type_semaphore);
1398 DestroySemaphoreInfo(&type_semaphore);