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/image-private.h"
50#include "MagickCore/linked-list.h"
51#include "MagickCore/log.h"
52#include "MagickCore/memory_.h"
53#include "MagickCore/memory-private.h"
54#include "MagickCore/nt-feature.h"
55#include "MagickCore/nt-base-private.h"
56#include "MagickCore/option.h"
57#include "MagickCore/semaphore.h"
58#include "MagickCore/splay-tree.h"
59#include "MagickCore/string_.h"
60#include "MagickCore/string-private.h"
61#include "MagickCore/type.h"
62#include "MagickCore/type-private.h"
63#include "MagickCore/token.h"
64#include "MagickCore/utility.h"
65#include "MagickCore/utility-private.h"
66#include "MagickCore/xml-tree.h"
67#include "MagickCore/xml-tree-private.h"
68#if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
69# include "fontconfig/fontconfig.h"
70#if (FC_VERSION < 20209)
72#define FC_WIDTH "width"
73#define FC_WIDTH_ULTRACONDENSED 50
74#define FC_WIDTH_EXTRACONDENSED 63
75#define FC_WIDTH_CONDENSED 75
76#define FC_WIDTH_SEMICONDENSED 87
77#define FC_WIDTH_NORMAL 100
78#define FC_WIDTH_SEMIEXPANDED 113
79#define FC_WIDTH_EXPANDED 125
80#define FC_WIDTH_EXTRAEXPANDED 150
81#define FC_WIDTH_ULTRAEXPANDED 200
83#define FC_WEIGHT_THIN 0
84#define FC_WEIGHT_EXTRALIGHT 40
85#define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
86#define FC_WEIGHT_LIGHT 50
87#define FC_WEIGHT_BOOK 75
88#define FC_WEIGHT_REGULAR 80
89#define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
90#define FC_WEIGHT_MEDIUM 100
91#define FC_WEIGHT_DEMIBOLD 180
92#define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
93#define FC_WEIGHT_BOLD 200
94#define FC_WEIGHT_EXTRABOLD 205
95#define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
96#define FC_WEIGHT_BLACK 210
97#define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
100#if defined(MAGICKCORE_WINDOWS_SUPPORT)
101# include "MagickCore/nt-feature.h"
107#define MagickTypeFilename "type.xml"
114 "<?xml version=\"1.0\"?>"
116 " <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
117 " <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
127 *type_cache = (SplayTreeInfo *) NULL;
132static MagickBooleanType
133 IsTypeTreeInstantiated(ExceptionInfo *),
134 LoadTypeCache(SplayTreeInfo *,
const char *,
const char *,
const size_t,
164static void *DestroyTypeNode(
void *type_info)
169 p=(TypeInfo *) type_info;
170 if (p->path != (
char *) NULL)
171 p->path=DestroyString(p->path);
172 if (p->name != (
char *) NULL)
173 p->name=DestroyString(p->name);
174 if (p->description != (
char *) NULL)
175 p->description=DestroyString(p->description);
176 if (p->family != (
char *) NULL)
177 p->family=DestroyString(p->family);
178 if (p->encoding != (
char *) NULL)
179 p->encoding=DestroyString(p->encoding);
180 if (p->foundry != (
char *) NULL)
181 p->foundry=DestroyString(p->foundry);
182 if (p->format != (
char *) NULL)
183 p->format=DestroyString(p->format);
184 if (p->metrics != (
char *) NULL)
185 p->metrics=DestroyString(p->metrics);
186 if (p->glyphs != (
char *) NULL)
187 p->glyphs=DestroyString(p->glyphs);
188 return(RelinquishMagickMemory(p));
191static SplayTreeInfo *AcquireTypeCache(
const char *filename,
192 ExceptionInfo *exception)
197 cache=NewSplayTree(CompareSplayTreeString,(
void *(*)(
void *)) NULL,
199 if (cache == (SplayTreeInfo *) NULL)
200 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
201#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
205 path[MagickPathExtent];
214 options=GetConfigureOptions(filename,exception);
215 option=(
const StringInfo *) GetNextValueInLinkedList(options);
216 while (option != (
const StringInfo *) NULL)
218 (void) CopyMagickString(path,GetStringInfoPath(option),MagickPathExtent);
219 (void) LoadTypeCache(cache,(
const char *) GetStringInfoDatum(option),
220 GetStringInfoPath(option),0,exception);
221 option=(
const StringInfo *) GetNextValueInLinkedList(options);
223 options=DestroyConfigureOptions(options);
224 font_path=GetEnvironmentValue(
"MAGICK_FONT_PATH");
225 if (font_path != (
char *) NULL)
233 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s%s",font_path,
234 DirectorySeparator,filename);
235 xml=FileToString(path,~0UL,exception);
236 if (xml != (
void *) NULL)
238 (void) LoadTypeCache(cache,xml,path,0,exception);
239 xml=DestroyString(xml);
241 font_path=DestroyString(font_path);
245 magick_unreferenced(filename);
247 if (GetNumberOfNodesInSplayTree(cache) == 0)
248 (void) LoadTypeCache(cache,TypeMap,
"built-in",0,exception);
277MagickExport
const TypeInfo *GetTypeInfo(
const char *name,
278 ExceptionInfo *exception)
280 assert(exception != (ExceptionInfo *) NULL);
281 if (IsTypeTreeInstantiated(exception) == MagickFalse)
282 return((
const TypeInfo *) NULL);
283 if ((name == (
const char *) NULL) || (LocaleCompare(name,
"*") == 0))
284 return((
const TypeInfo *) GetRootValueFromSplayTree(type_cache));
285 return((
const TypeInfo *) GetValueFromSplayTree(type_cache,name));
323MagickExport
const TypeInfo *GetTypeInfoByFamily(
const char *family,
324 const StyleType style,
const StretchType stretch,
const size_t weight,
325 ExceptionInfo *exception)
327 typedef struct _Fontmap
350 {
"fixed",
"courier" },
351 {
"modern",
"courier" },
352 {
"monotype corsiva",
"courier" },
353 {
"news gothic",
"helvetica" },
354 {
"system",
"courier" },
355 {
"terminal",
"courier" },
356 {
"wingdings",
"symbol" }
362 (void) GetTypeInfo(
"*",exception);
363 if (type_cache == (SplayTreeInfo *) NULL)
364 return((TypeInfo *) NULL);
365 font_weight=(size_t) (weight == 0 ? 400 : weight);
366 LockSemaphoreInfo(type_semaphore);
367 ResetSplayTreeIterator(type_cache);
368 type_info=(
const TypeInfo *) NULL;
369 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
370 while (p != (
const TypeInfo *) NULL)
372 if (p->family == (
char *) NULL)
374 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
377 if (family == (
const char *) NULL)
379 if ((LocaleCompare(p->family,
"arial") != 0) &&
380 (LocaleCompare(p->family,
"helvetica") != 0))
382 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
387 if (LocaleCompare(p->family,family) != 0)
389 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
392 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
394 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
397 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
398 (p->stretch != stretch))
400 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
403 if (p->weight != font_weight)
405 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
411 UnlockSemaphoreInfo(type_semaphore);
412 if (type_info != (
const TypeInfo *) NULL)
418 LockSemaphoreInfo(type_semaphore);
419 ResetSplayTreeIterator(type_cache);
420 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
421 while (p != (
const TypeInfo *) NULL)
423 if (p->family == (
char *) NULL)
425 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
428 if (family == (
const char *) NULL)
430 if ((LocaleCompare(p->family,
"arial") != 0) &&
431 (LocaleCompare(p->family,
"helvetica") != 0))
433 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
438 if (LocaleCompare(p->family,family) != 0)
440 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
444 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
447 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
448 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
450 score+=(size_t) ((16L*(800L-((ssize_t) MagickMax(MagickMin(font_weight,900),
451 p->weight)-(ssize_t) MagickMin(MagickMin(font_weight,900),p->weight))))/
453 if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
457 range=(ssize_t) UltraExpandedStretch-(ssize_t) NormalStretch;
458 score+=(size_t) ((ssize_t) (8L*(range-((ssize_t) MagickMax(stretch,
459 p->stretch)-(ssize_t) MagickMin(stretch,p->stretch))))/range);
461 if (score > max_score)
466 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
468 UnlockSemaphoreInfo(type_semaphore);
469 if (type_info != (
const TypeInfo *) NULL)
474 for (i=0; i < (ssize_t) (
sizeof(fontmap)/
sizeof(fontmap[0])); i++)
476 if (family == (
const char *) NULL)
478 if ((LocaleCompare(fontmap[i].name,
"arial") != 0) &&
479 (LocaleCompare(fontmap[i].name,
"helvetica") != 0))
483 if (LocaleCompare(fontmap[i].name,family) != 0)
485 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
489 if (type_info != (
const TypeInfo *) NULL)
491 (void) ThrowMagickException(exception,GetMagickModule(),TypeWarning,
492 "FontSubstitutionRequired",
"`%s'",type_info->family);
495 if (family != (
const char *) NULL)
496 type_info=GetTypeInfoByFamily((
const char *) NULL,style,stretch,weight,
529#if defined(__cplusplus) || defined(c_plusplus)
533static int TypeInfoCompare(
const void *x,
const void *y)
539 p=(
const TypeInfo **) x,
540 q=(
const TypeInfo **) y;
541 if (LocaleCompare((*p)->path,(*q)->path) == 0)
542 return(LocaleCompare((*p)->name,(*q)->name));
543 return(LocaleCompare((*p)->path,(*q)->path));
546#if defined(__cplusplus) || defined(c_plusplus)
550MagickExport
const TypeInfo **GetTypeInfoList(
const char *pattern,
551 size_t *number_fonts,ExceptionInfo *exception)
565 assert(pattern != (
char *) NULL);
566 assert(number_fonts != (
size_t *) NULL);
567 if (IsEventLogging() != MagickFalse)
568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
570 p=GetTypeInfo(
"*",exception);
571 if (p == (
const TypeInfo *) NULL)
572 return((
const TypeInfo **) NULL);
573 fonts=(
const TypeInfo **) AcquireQuantumMemory((
size_t)
574 GetNumberOfNodesInSplayTree(type_cache)+1UL,
sizeof(*fonts));
575 if (fonts == (
const TypeInfo **) NULL)
576 return((
const TypeInfo **) NULL);
580 LockSemaphoreInfo(type_semaphore);
581 ResetSplayTreeIterator(type_cache);
582 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
583 for (i=0; p != (
const TypeInfo *) NULL; )
585 if ((p->stealth == MagickFalse) &&
586 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
588 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
590 UnlockSemaphoreInfo(type_semaphore);
591 qsort((
void *) fonts,(
size_t) i,
sizeof(*fonts),TypeInfoCompare);
592 fonts[i]=(TypeInfo *) NULL;
593 *number_fonts=(size_t) i;
625#if defined(__cplusplus) || defined(c_plusplus)
629static int TypeCompare(
const void *x,
const void *y)
637 return(LocaleCompare(*p,*q));
640#if defined(__cplusplus) || defined(c_plusplus)
644MagickExport
char **GetTypeList(
const char *pattern,
size_t *number_fonts,
645 ExceptionInfo *exception)
659 assert(pattern != (
char *) NULL);
660 assert(number_fonts != (
size_t *) NULL);
661 if (IsEventLogging() != MagickFalse)
662 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
664 p=GetTypeInfo(
"*",exception);
665 if (p == (
const TypeInfo *) NULL)
666 return((
char **) NULL);
667 fonts=(
char **) AcquireQuantumMemory((
size_t)
668 GetNumberOfNodesInSplayTree(type_cache)+1UL,
sizeof(*fonts));
669 if (fonts == (
char **) NULL)
670 return((
char **) NULL);
674 LockSemaphoreInfo(type_semaphore);
675 ResetSplayTreeIterator(type_cache);
676 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
677 for (i=0; p != (
const TypeInfo *) NULL; )
679 if ((p->stealth == MagickFalse) &&
680 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
681 fonts[i++]=ConstantString(p->name);
682 p=(
const TypeInfo *) GetNextValueInSplayTree(type_cache);
684 UnlockSemaphoreInfo(type_semaphore);
685 qsort((
void *) fonts,(
size_t) i,
sizeof(*fonts),TypeCompare);
686 fonts[i]=(
char *) NULL;
687 *number_fonts=(size_t) i;
715#if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
716MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_cache,
717 ExceptionInfo *exception)
719#if !defined(FC_FULLNAME)
720#define FC_FULLNAME "fullname"
724 extension[MagickPathExtent],
725 name[MagickPathExtent];
770 font_config=FcConfigGetCurrent();
771 if (font_config == (FcConfig *) NULL)
773 (void) FcConfigSetRescanInterval(font_config,0);
774 font_set=(FcFontSet *) NULL;
775 object_set=FcObjectSetBuild(FC_FULLNAME,FC_FAMILY,FC_STYLE,FC_SLANT,
776 FC_WIDTH,FC_WEIGHT,FC_FILE,FC_INDEX,(
char *) NULL);
777 if (object_set != (FcObjectSet *) NULL)
779 pattern=FcPatternCreate();
780 if (pattern != (FcPattern *) NULL)
782 font_set=FcFontList(font_config,pattern,object_set);
783 FcPatternDestroy(pattern);
785 FcObjectSetDestroy(object_set);
787 if (font_set == (FcFontSet *) NULL)
789 FcConfigDestroy(font_config);
792 for (i=0; i < (ssize_t) font_set->nfont; i++)
794 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
795 if (status != FcResultMatch)
797 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
798 if (status != FcResultMatch)
801 GetPathComponent((
const char *) file,ExtensionPath,extension);
802 if ((*extension !=
'\0') && (LocaleCompare(extension,
"gz") == 0))
804 type_info=(TypeInfo *) AcquireMagickMemory(
sizeof(*type_info));
805 if (type_info == (TypeInfo *) NULL)
807 (void) memset(type_info,0,
sizeof(*type_info));
808 type_info->path=ConstantString(
"System Fonts");
809 type_info->signature=MagickCoreSignature;
810 (void) CopyMagickString(name,
"Unknown",MagickPathExtent);
811 status=FcPatternGetString(font_set->fonts[i],FC_FULLNAME,0,&fullname);
812 if ((status == FcResultMatch) && (fullname != (FcChar8 *) NULL))
813 (void) CopyMagickString(name,(
const char *) fullname,MagickPathExtent);
816 if (family != (FcChar8 *) NULL)
817 (void) CopyMagickString(name,(
const char *) family,MagickPathExtent);
818 status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
819 if ((status == FcResultMatch) && (style != (FcChar8 *) NULL) &&
820 (LocaleCompare((
const char *) style,
"Regular") != 0))
822 (void) ConcatenateMagickString(name,
" ",MagickPathExtent);
823 (void) ConcatenateMagickString(name,(
const char *) style,
827 type_info->name=ConstantString(name);
828 (void) SubstituteString(&type_info->name,
" ",
"-");
829 type_info->family=ConstantString((
const char *) family);
830 status=FcPatternGetInteger(font_set->fonts[i],FC_INDEX,0,&index);
831 if (status == FcResultMatch)
832 type_info->face=(size_t) index;
833 status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
834 type_info->style=NormalStyle;
835 if (slant == FC_SLANT_ITALIC)
836 type_info->style=ItalicStyle;
837 if (slant == FC_SLANT_OBLIQUE)
838 type_info->style=ObliqueStyle;
839 status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
840 type_info->stretch=NormalStretch;
841 if (width >= FC_WIDTH_ULTRACONDENSED)
842 type_info->stretch=UltraCondensedStretch;
843 if (width >= FC_WIDTH_EXTRACONDENSED)
844 type_info->stretch=ExtraCondensedStretch;
845 if (width >= FC_WIDTH_CONDENSED)
846 type_info->stretch=CondensedStretch;
847 if (width >= FC_WIDTH_SEMICONDENSED)
848 type_info->stretch=SemiCondensedStretch;
849 if (width >= FC_WIDTH_NORMAL)
850 type_info->stretch=NormalStretch;
851 if (width >= FC_WIDTH_SEMIEXPANDED)
852 type_info->stretch=SemiExpandedStretch;
853 if (width >= FC_WIDTH_EXPANDED)
854 type_info->stretch=ExpandedStretch;
855 if (width >= FC_WIDTH_EXTRAEXPANDED)
856 type_info->stretch=ExtraExpandedStretch;
857 if (width >= FC_WIDTH_ULTRAEXPANDED)
858 type_info->stretch=UltraExpandedStretch;
859 type_info->weight=400;
860 status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
861 if (weight >= FC_WEIGHT_THIN)
862 type_info->weight=100;
863 if (weight >= FC_WEIGHT_EXTRALIGHT)
864 type_info->weight=200;
865 if (weight >= FC_WEIGHT_LIGHT)
866 type_info->weight=300;
867 if (weight >= FC_WEIGHT_NORMAL)
868 type_info->weight=400;
869 if (weight >= FC_WEIGHT_MEDIUM)
870 type_info->weight=500;
871 if (weight >= FC_WEIGHT_DEMIBOLD)
872 type_info->weight=600;
873 if (weight >= FC_WEIGHT_BOLD)
874 type_info->weight=700;
875 if (weight >= FC_WEIGHT_EXTRABOLD)
876 type_info->weight=800;
877 if (weight >= FC_WEIGHT_BLACK)
878 type_info->weight=900;
879 type_info->glyphs=ConstantString((
const char *) file);
880 (void) AddValueToSplayTree(type_cache,type_info->name,type_info);
882 FcFontSetDestroy(font_set);
883 FcConfigDestroy(font_config);
888static MagickBooleanType IsTypeTreeInstantiated(ExceptionInfo *exception)
890 if (type_cache == (SplayTreeInfo *) NULL)
893 ActivateSemaphoreInfo(&type_semaphore);
894 LockSemaphoreInfo(type_semaphore);
895 if (type_cache == (SplayTreeInfo *) NULL)
900 splay_tree=AcquireTypeCache(MagickTypeFilename,exception);
901#if defined(MAGICKCORE_WINDOWS_SUPPORT)
902 (void) NTAcquireTypeCache(splay_tree,exception);
904#if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
905 (void) LoadFontConfigFonts(splay_tree,exception);
907 type_cache=splay_tree;
909 UnlockSemaphoreInfo(type_semaphore);
911 return(type_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
938MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
958 if (file == (FILE *) NULL)
961 type_info=GetTypeInfoList(
"*",&number_fonts,exception);
962 if (type_info == (
const TypeInfo **) NULL)
964 path=(
const char *) NULL;
965 for (i=0; i < (ssize_t) number_fonts; i++)
967 if (type_info[i]->stealth != MagickFalse)
969 if (((path == (
const char *) NULL) ||
970 (LocaleCompare(path,type_info[i]->path) != 0)) &&
971 (type_info[i]->path != (
char *) NULL))
972 (void) FormatLocaleFile(file,
"\nPath: %s\n",type_info[i]->path);
973 path=type_info[i]->path;
975 if (type_info[i]->name != (
char *) NULL)
976 name=type_info[i]->name;
977 family=
"not defined";
978 if (type_info[i]->family != (
char *) NULL)
979 family=type_info[i]->family;
980 style=CommandOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
981 stretch=CommandOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
982 metrics=
"not defined";
983 if (type_info[i]->metrics != (
char *) NULL)
984 metrics=type_info[i]->metrics;
985 glyphs=
"not defined";
986 if (type_info[i]->glyphs != (
char *) NULL)
987 glyphs=type_info[i]->glyphs;
988 (void) FormatLocaleFile(file,
" Font: %s\n",name);
989 (void) FormatLocaleFile(file,
" family: %s\n",family);
990 (void) FormatLocaleFile(file,
" style: %s\n",style);
991 (void) FormatLocaleFile(file,
" stretch: %s\n",stretch);
992 (void) FormatLocaleFile(file,
" weight: %.17g\n",(
double)
993 type_info[i]->weight);
994 (void) FormatLocaleFile(file,
" metrics: %s\n",metrics);
995 (void) FormatLocaleFile(file,
" glyphs: %s\n",glyphs);
996 (void) FormatLocaleFile(file,
" index: %d\n",(
int)
1000 type_info=(
const TypeInfo **) RelinquishMagickMemory((
void *) type_info);
1035static inline MagickBooleanType SetTypeNodePath(
const char *filename,
1036 char *font_path,
const char *token,
char **target)
1041 path=ConstantString(token);
1042#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1043 if (strchr(path,
'@') != (
char *) NULL)
1044 SubstituteString(&path,
"@ghostscript_font_path@",font_path);
1046 if (IsPathAccessible(path) == MagickFalse)
1051 path=DestroyString(path);
1052 GetPathComponent(filename,HeadPath,font_path);
1053 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1055 (void) ConcatenateMagickString(font_path,token,MagickPathExtent);
1056 path=ConstantString(font_path);
1057#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1058 if (strchr(path,
'@') != (
char *) NULL)
1059 SubstituteString(&path,
"@ghostscript_font_path@",
"");
1061 if (IsPathAccessible(path) == MagickFalse)
1063 path=DestroyString(path);
1064 return(MagickFalse);
1072static MagickBooleanType LoadTypeCache(SplayTreeInfo *cache,
const char *xml,
1073 const char *filename,
const size_t depth,ExceptionInfo *exception)
1076 font_path[MagickPathExtent],
1077 keyword[MagickPathExtent],
1095 if (IsEventLogging() != MagickFalse)
1096 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1097 "Loading type configure file \"%s\" ...",filename);
1098 if (xml == (
const char *) NULL)
1099 return(MagickFalse);
1101 type_info=(TypeInfo *) NULL;
1102 token=AcquireString(xml);
1103 extent=strlen(token)+MagickPathExtent;
1104#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1109 if (NTGhostscriptFonts(font_path,MagickPathExtent-2) != MagickFalse)
1110 (void) ConcatenateMagickString(font_path,DirectorySeparator,
1113 for (q=(
char *) xml; *q !=
'\0'; )
1118 if (SkipXMLComment(&q) == MagickFalse)
1120 (void) ThrowMagickException(exception,GetMagickModule(),
1121 ConfigureError,
"UnterminatedComment",
"`%s'",filename);
1125 (void) GetNextToken(q,&q,extent,token);
1128 (void) CopyMagickString(keyword,token,MagickPathExtent);
1129 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
1131 if (SkipXMLDocType(&q) == MagickFalse)
1136 (void) ThrowMagickException(exception,GetMagickModule(),
1137 ConfigureError,
"UnterminatedDOCTYPE",
"`%s'",filename);
1143 if (LocaleCompare(keyword,
"<include") == 0)
1148 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
1150 (void) CopyMagickString(keyword,token,MagickPathExtent);
1151 (void) GetNextToken(q,&q,extent,token);
1154 (void) GetNextToken(q,&q,extent,token);
1155 if (LocaleCompare(keyword,
"file") == 0)
1157 if (depth >= MagickMaxRecursionDepth)
1158 (void) ThrowMagickException(exception,GetMagickModule(),
1159 ConfigureError,
"IncludeNodeNestedTooDeeply",
"`%s'",token);
1163 path[MagickPathExtent],
1170 GetPathComponent(filename,HeadPath,path);
1172 (void) ConcatenateMagickString(path,DirectorySeparator,
1174 if (*token == *DirectorySeparator)
1175 (void) CopyMagickString(path,token,MagickPathExtent);
1177 (
void) ConcatenateMagickString(path,token,MagickPathExtent);
1178 sans_exception=AcquireExceptionInfo();
1179 file_xml=FileToString(path,~0UL,sans_exception);
1180 sans_exception=DestroyExceptionInfo(sans_exception);
1181 if (file_xml != (
char *) NULL)
1183 if (LoadTypeCache(cache,file_xml,path,depth+1,exception) == MagickFalse)
1185 file_xml=(
char *) RelinquishMagickMemory(file_xml);
1186 if (status == MagickFalse)
1192 if (status == MagickFalse)
1196 if (LocaleCompare(keyword,
"<type") == 0)
1201 type_info=(TypeInfo *) AcquireCriticalMemory(
sizeof(*type_info));
1202 (void) memset(type_info,0,
sizeof(*type_info));
1203 type_info->path=ConstantString(filename);
1204 type_info->signature=MagickCoreSignature;
1207 if (type_info == (TypeInfo *) NULL)
1209 if ((LocaleCompare(keyword,
"/>") == 0) ||
1210 (LocaleCompare(keyword,
"</policy>") == 0))
1212 status=AddValueToSplayTree(cache,type_info->name,type_info);
1213 if (status == MagickFalse)
1214 (void) ThrowMagickException(exception,GetMagickModule(),
1215 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",type_info->name);
1216 type_info=(TypeInfo *) NULL;
1219 (void) GetNextToken(q,(
const char **) NULL,extent,token);
1222 (void) GetNextToken(q,&q,extent,token);
1223 (void) GetNextToken(q,&q,extent,token);
1229 if (LocaleCompare((
char *) keyword,
"encoding") == 0)
1231 type_info->encoding=ConstantString(token);
1239 if (LocaleCompare((
char *) keyword,
"face") == 0)
1241 type_info->face=StringToUnsignedLong(token);
1244 if (LocaleCompare((
char *) keyword,
"family") == 0)
1246 type_info->family=ConstantString(token);
1249 if (LocaleCompare((
char *) keyword,
"format") == 0)
1251 type_info->format=ConstantString(token);
1254 if (LocaleCompare((
char *) keyword,
"foundry") == 0)
1256 type_info->foundry=ConstantString(token);
1259 if (LocaleCompare((
char *) keyword,
"fullname") == 0)
1261 type_info->description=ConstantString(token);
1269 if (LocaleCompare((
char *) keyword,
"glyphs") == 0)
1271 if (SetTypeNodePath(filename,font_path,token,&type_info->glyphs) == MagickFalse)
1272 type_info=(TypeInfo *) DestroyTypeNode(type_info);
1280 if (LocaleCompare((
char *) keyword,
"metrics") == 0)
1282 if (SetTypeNodePath(filename,font_path,token,&type_info->metrics) == MagickFalse)
1283 type_info=(TypeInfo *) DestroyTypeNode(type_info);
1291 if (LocaleCompare((
char *) keyword,
"name") == 0)
1293 type_info->name=ConstantString(token);
1301 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
1303 type_info->stealth=IsStringTrue(token);
1306 if (LocaleCompare((
char *) keyword,
"stretch") == 0)
1308 type_info->stretch=(StretchType) ParseCommandOption(
1309 MagickStretchOptions,MagickFalse,token);
1312 if (LocaleCompare((
char *) keyword,
"style") == 0)
1314 type_info->style=(StyleType) ParseCommandOption(MagickStyleOptions,
1323 if (LocaleCompare((
char *) keyword,
"weight") == 0)
1328 weight=ParseCommandOption(MagickWeightOptions,MagickFalse,token);
1330 weight=(ssize_t) StringToUnsignedLong(token);
1331 type_info->weight=(size_t) weight;
1340 token=(
char *) RelinquishMagickMemory(token);
1362MagickPrivate MagickBooleanType TypeComponentGenesis(
void)
1365 type_semaphore=AcquireSemaphoreInfo();
1387MagickPrivate
void TypeComponentTerminus(
void)
1390 ActivateSemaphoreInfo(&type_semaphore);
1391 LockSemaphoreInfo(type_semaphore);
1392 if (type_cache != (SplayTreeInfo *) NULL)
1393 type_cache=DestroySplayTree(type_cache);
1394 UnlockSemaphoreInfo(type_semaphore);
1395 RelinquishSemaphoreInfo(&type_semaphore);