00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "magick/studio.h"
00043 #include "magick/blob.h"
00044 #include "magick/client.h"
00045 #include "magick/configure.h"
00046 #include "magick/draw.h"
00047 #include "magick/exception.h"
00048 #include "magick/exception-private.h"
00049 #include "magick/hashmap.h"
00050 #include "magick/log.h"
00051 #include "magick/memory_.h"
00052 #include "magick/option.h"
00053 #include "magick/semaphore.h"
00054 #include "magick/splay-tree.h"
00055 #include "magick/string_.h"
00056 #include "magick/type.h"
00057 #include "magick/token.h"
00058 #include "magick/utility.h"
00059 #include "magick/xml-tree.h"
00060 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
00061 # include "fontconfig/fontconfig.h"
00062 #if (FC_VERSION < 20209)
00063 #undef FC_WEIGHT_LIGHT
00064 #define FC_WIDTH "width"
00065 #define FC_WIDTH_ULTRACONDENSED 50
00066 #define FC_WIDTH_EXTRACONDENSED 63
00067 #define FC_WIDTH_CONDENSED 75
00068 #define FC_WIDTH_SEMICONDENSED 87
00069 #define FC_WIDTH_NORMAL 100
00070 #define FC_WIDTH_SEMIEXPANDED 113
00071 #define FC_WIDTH_EXPANDED 125
00072 #define FC_WIDTH_EXTRAEXPANDED 150
00073 #define FC_WIDTH_ULTRAEXPANDED 200
00074
00075 #define FC_WEIGHT_THIN 0
00076 #define FC_WEIGHT_EXTRALIGHT 40
00077 #define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
00078 #define FC_WEIGHT_LIGHT 50
00079 #define FC_WEIGHT_BOOK 75
00080 #define FC_WEIGHT_REGULAR 80
00081 #define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
00082 #define FC_WEIGHT_MEDIUM 100
00083 #define FC_WEIGHT_DEMIBOLD 180
00084 #define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
00085 #define FC_WEIGHT_BOLD 200
00086 #define FC_WEIGHT_EXTRABOLD 205
00087 #define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
00088 #define FC_WEIGHT_BLACK 210
00089 #define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
00090 #endif
00091 #endif
00092 #if defined(__WINDOWS__)
00093 # include "magick/nt-feature.h"
00094 #endif
00095
00096
00097
00098
00099 #define MagickTypeFilename "type.xml"
00100
00101
00102
00103
00104 static const char
00105 *TypeMap = (const char *)
00106 "<?xml version=\"1.0\"?>"
00107 "<typemap>"
00108 " <type stealth=\"True\" name=\"fixed\" family=\"helvetica\"/>"
00109 " <type stealth=\"True\" name=\"helvetica\" family=\"helvetica\"/>"
00110 "</typemap>";
00111
00112
00113
00114
00115 static SemaphoreInfo
00116 *type_semaphore = (SemaphoreInfo *) NULL;
00117
00118 static volatile MagickBooleanType
00119 instantiate_type = MagickFalse;
00120
00121 static SplayTreeInfo
00122 *type_list = (SplayTreeInfo *) NULL;
00123
00124
00125
00126
00127 static MagickBooleanType
00128 InitializeTypeList(ExceptionInfo *),
00129 LoadTypeLists(const char *,ExceptionInfo *);
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 MagickExport const TypeInfo *GetTypeInfo(const char *name,
00157 ExceptionInfo *exception)
00158 {
00159 assert(exception != (ExceptionInfo *) NULL);
00160 if ((type_list == (SplayTreeInfo *) NULL) ||
00161 (instantiate_type == MagickFalse))
00162 if (InitializeTypeList(exception) == MagickFalse)
00163 return((const TypeInfo *) NULL);
00164 if ((type_list == (SplayTreeInfo *) NULL) ||
00165 (GetNumberOfNodesInSplayTree(type_list) == 0))
00166 return((const TypeInfo *) NULL);
00167 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
00168 {
00169 ResetSplayTreeIterator(type_list);
00170 return((const TypeInfo *) GetNextValueInSplayTree(type_list));
00171 }
00172 return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 static inline unsigned long MagickMax(const unsigned long x,
00212 const unsigned long y)
00213 {
00214 if (x > y)
00215 return(x);
00216 return(y);
00217 }
00218
00219 static inline unsigned long MagickMin(const unsigned long x,
00220 const unsigned long y)
00221 {
00222 if (x < y)
00223 return(x);
00224 return(y);
00225 }
00226
00227 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
00228 const StyleType style,const StretchType stretch,const unsigned long weight,
00229 ExceptionInfo *exception)
00230 {
00231 typedef struct _Fontmap
00232 {
00233 const char
00234 *name,
00235 *substitute;
00236 } Fontmap;
00237
00238 const TypeInfo
00239 *type_info;
00240
00241 long
00242 range;
00243
00244 register const TypeInfo
00245 *p;
00246
00247 register long
00248 i;
00249
00250 static Fontmap
00251 fontmap[] =
00252 {
00253 { "fixed", "courier" },
00254 { "modern","courier" },
00255 { "monotype corsiva", "courier" },
00256 { "news gothic", "helvetica" },
00257 { "system", "courier" },
00258 { "terminal", "courier" },
00259 { "wingdings", "symbol" },
00260 { NULL, NULL }
00261 };
00262
00263 unsigned long
00264 max_score,
00265 score;
00266
00267
00268
00269
00270 (void) GetTypeInfo("*",exception);
00271 if (type_list == (SplayTreeInfo *) NULL)
00272 return((TypeInfo *) NULL);
00273 (void) LockSemaphoreInfo(type_semaphore);
00274 ResetSplayTreeIterator(type_list);
00275 type_info=(const TypeInfo *) NULL;
00276 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00277 while (p != (const TypeInfo *) NULL)
00278 {
00279 if (p->family == (char *) NULL)
00280 {
00281 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00282 continue;
00283 }
00284 if (family == (const char *) NULL)
00285 {
00286 if ((LocaleCompare(p->family,"arial") != 0) &&
00287 (LocaleCompare(p->family,"helvetica") != 0))
00288 {
00289 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00290 continue;
00291 }
00292 }
00293 else
00294 if (LocaleCompare(p->family,family) != 0)
00295 {
00296 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00297 continue;
00298 }
00299 if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
00300 {
00301 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00302 continue;
00303 }
00304 if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
00305 (p->stretch != stretch))
00306 {
00307 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00308 continue;
00309 }
00310 if ((weight != 0) && (p->weight != weight))
00311 {
00312 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00313 continue;
00314 }
00315 type_info=p;
00316 break;
00317 }
00318 (void) UnlockSemaphoreInfo(type_semaphore);
00319 if (type_info != (const TypeInfo *) NULL)
00320 return(type_info);
00321
00322
00323
00324 max_score=0;
00325 (void) LockSemaphoreInfo(type_semaphore);
00326 ResetSplayTreeIterator(type_list);
00327 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00328 while (p != (const TypeInfo *) NULL)
00329 {
00330 if (p->family == (char *) NULL)
00331 {
00332 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00333 continue;
00334 }
00335 if (family == (const char *) NULL)
00336 {
00337 if ((LocaleCompare(p->family,"arial") != 0) &&
00338 (LocaleCompare(p->family,"helvetica") != 0))
00339 {
00340 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00341 continue;
00342 }
00343 }
00344 else
00345 if (LocaleCompare(p->family,family) != 0)
00346 {
00347 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00348 continue;
00349 }
00350 score=0;
00351 if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
00352 score+=32;
00353 else
00354 if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
00355 ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
00356 score+=25;
00357 if (weight == 0)
00358 score+=16;
00359 else
00360 score+=(16*(800-((long) MagickMax(MagickMin(weight,900),p->weight)-
00361 (long) MagickMin(MagickMin(weight,900),p->weight))))/800;
00362 if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
00363 score+=8;
00364 else
00365 {
00366 range=(long) UltraExpandedStretch-(long) NormalStretch;
00367 score+=(8*(range-((long) MagickMax(stretch,p->stretch)-
00368 (long) MagickMin(stretch,p->stretch))))/range;
00369 }
00370 if (score > max_score)
00371 {
00372 max_score=score;
00373 type_info=p;
00374 }
00375 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00376 }
00377 (void) UnlockSemaphoreInfo(type_semaphore);
00378 if (type_info != (const TypeInfo *) NULL)
00379 return(type_info);
00380
00381
00382
00383 for (i=0; fontmap[i].name != (char *) NULL; i++)
00384 {
00385 if (family == (const char *) NULL)
00386 {
00387 if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
00388 (LocaleCompare(fontmap[i].name,"helvetica") != 0))
00389 continue;
00390 }
00391 else
00392 if (LocaleCompare(fontmap[i].name,family) != 0)
00393 continue;
00394 type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
00395 exception);
00396 break;
00397 }
00398 if (type_info != (const TypeInfo *) NULL)
00399 {
00400 (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
00401 "FontSubstitutionRequired","`%s'",type_info->family);
00402 return(type_info);
00403 }
00404 if (family != (const char *) NULL)
00405 type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
00406 exception);
00407 return(type_info);
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 #if defined(__cplusplus) || defined(c_plusplus)
00439 extern "C" {
00440 #endif
00441
00442 static int TypeInfoCompare(const void *x,const void *y)
00443 {
00444 const TypeInfo
00445 **p,
00446 **q;
00447
00448 p=(const TypeInfo **) x,
00449 q=(const TypeInfo **) y;
00450 if (LocaleCompare((*p)->path,(*q)->path) == 0)
00451 return(LocaleCompare((*p)->name,(*q)->name));
00452 return(LocaleCompare((*p)->path,(*q)->path));
00453 }
00454
00455 #if defined(__cplusplus) || defined(c_plusplus)
00456 }
00457 #endif
00458
00459 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
00460 unsigned long *number_fonts,ExceptionInfo *exception)
00461 {
00462 const TypeInfo
00463 **fonts;
00464
00465 register const TypeInfo
00466 *p;
00467
00468 register long
00469 i;
00470
00471
00472
00473
00474 assert(pattern != (char *) NULL);
00475 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00476 assert(number_fonts != (unsigned long *) NULL);
00477 *number_fonts=0;
00478 p=GetTypeInfo("*",exception);
00479 if (p == (const TypeInfo *) NULL)
00480 return((const TypeInfo **) NULL);
00481 fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
00482 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
00483 if (fonts == (const TypeInfo **) NULL)
00484 return((const TypeInfo **) NULL);
00485
00486
00487
00488 (void) LockSemaphoreInfo(type_semaphore);
00489 ResetSplayTreeIterator(type_list);
00490 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00491 for (i=0; p != (const TypeInfo *) NULL; )
00492 {
00493 if ((p->stealth == MagickFalse) &&
00494 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00495 fonts[i++]=p;
00496 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00497 }
00498 (void) UnlockSemaphoreInfo(type_semaphore);
00499 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
00500 fonts[i]=(TypeInfo *) NULL;
00501 *number_fonts=(unsigned long) i;
00502 return(fonts);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 #if defined(__cplusplus) || defined(c_plusplus)
00534 extern "C" {
00535 #endif
00536
00537 static int TypeCompare(const void *x,const void *y)
00538 {
00539 register const char
00540 **p,
00541 **q;
00542
00543 p=(const char **) x;
00544 q=(const char **) y;
00545 return(LocaleCompare(*p,*q));
00546 }
00547
00548 #if defined(__cplusplus) || defined(c_plusplus)
00549 }
00550 #endif
00551
00552 MagickExport char **GetTypeList(const char *pattern,unsigned long *number_fonts,
00553 ExceptionInfo *exception)
00554 {
00555 char
00556 **fonts;
00557
00558 register const TypeInfo
00559 *p;
00560
00561 register long
00562 i;
00563
00564
00565
00566
00567 assert(pattern != (char *) NULL);
00568 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00569 assert(number_fonts != (unsigned long *) NULL);
00570 *number_fonts=0;
00571 p=GetTypeInfo("*",exception);
00572 if (p == (const TypeInfo *) NULL)
00573 return((char **) NULL);
00574 fonts=(char **) AcquireQuantumMemory((size_t)
00575 GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
00576 if (fonts == (char **) NULL)
00577 return((char **) NULL);
00578
00579
00580
00581 (void) LockSemaphoreInfo(type_semaphore);
00582 ResetSplayTreeIterator(type_list);
00583 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00584 for (i=0; p != (const TypeInfo *) NULL; )
00585 {
00586 if ((p->stealth == MagickFalse) &&
00587 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00588 fonts[i++]=ConstantString(p->name);
00589 p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00590 }
00591 (void) UnlockSemaphoreInfo(type_semaphore);
00592 qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
00593 fonts[i]=(char *) NULL;
00594 *number_fonts=(unsigned long) i;
00595 return(fonts);
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
00622 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
00623 ExceptionInfo *exception)
00624 {
00625 char
00626 extension[MaxTextExtent],
00627 name[MaxTextExtent];
00628
00629 FcChar8
00630 *family,
00631 *file,
00632 *style;
00633
00634 FcConfig
00635 *font_config;
00636
00637 FcFontSet
00638 *font_set;
00639
00640 FcObjectSet
00641 *object_set;
00642
00643 FcPattern
00644 *pattern;
00645
00646 FcResult
00647 status;
00648
00649 int
00650 slant,
00651 width,
00652 weight;
00653
00654 register long
00655 i;
00656
00657 TypeInfo
00658 *type_info;
00659
00660
00661
00662
00663 (void) exception;
00664 font_config=FcInitLoadConfigAndFonts();
00665 if (font_config == (FcConfig *) NULL)
00666 return(MagickFalse);
00667 font_set=(FcFontSet *) NULL;
00668 object_set=FcObjectSetBuild(FC_FAMILY,FC_STYLE,FC_SLANT,FC_WIDTH,FC_WEIGHT,
00669 FC_FILE,(char *) NULL);
00670 if (object_set != (FcObjectSet *) NULL)
00671 {
00672 pattern=FcPatternCreate();
00673 if (pattern != (FcPattern *) NULL)
00674 {
00675 font_set=FcFontList(0,pattern,object_set);
00676 FcPatternDestroy(pattern);
00677 }
00678 FcObjectSetDestroy(object_set);
00679 }
00680 if (font_set == (FcFontSet *) NULL)
00681 {
00682 FcConfigDestroy(font_config);
00683 return(MagickFalse);
00684 }
00685 for (i=0; i < (long) font_set->nfont; i++)
00686 {
00687 status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
00688 if (status != FcResultMatch)
00689 continue;
00690 status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
00691 if (status != FcResultMatch)
00692 continue;
00693 *extension='\0';
00694 GetPathComponent((const char *) file,ExtensionPath,extension);
00695 if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
00696 continue;
00697 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
00698 if (type_info == (TypeInfo *) NULL)
00699 continue;
00700 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
00701 type_info->path=ConstantString("System Fonts");
00702 type_info->signature=MagickSignature;
00703 (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
00704 (void) ConcatenateMagickString(name," ",MaxTextExtent);
00705 status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
00706 if (status == FcResultMatch)
00707 (void) ConcatenateMagickString(name,(const char *) style,MaxTextExtent);
00708 type_info->name=ConstantString(name);
00709 (void) SubstituteString(&type_info->name," ","-");
00710 (void) SubstituteString(&type_info->name,"-L-","-");
00711 (void) SubstituteString(&type_info->name,"semicondensed","SemiCondensed");
00712 type_info->family=ConstantString((const char *) family);
00713 (void) SubstituteString(&type_info->family," L","");
00714 status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
00715 type_info->style=NormalStyle;
00716 if (slant == FC_SLANT_ITALIC)
00717 type_info->style=ItalicStyle;
00718 if (slant == FC_SLANT_OBLIQUE)
00719 type_info->style=ObliqueStyle;
00720 status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
00721 type_info->stretch=NormalStretch;
00722 if (width >= FC_WIDTH_ULTRACONDENSED)
00723 type_info->stretch=UltraCondensedStretch;
00724 if (width >= FC_WIDTH_EXTRACONDENSED)
00725 type_info->stretch=ExtraCondensedStretch;
00726 if (width >= FC_WIDTH_CONDENSED)
00727 type_info->stretch=CondensedStretch;
00728 if (width >= FC_WIDTH_SEMICONDENSED)
00729 type_info->stretch=SemiCondensedStretch;
00730 if (width >= FC_WIDTH_NORMAL)
00731 type_info->stretch=NormalStretch;
00732 if (width >= FC_WIDTH_SEMIEXPANDED)
00733 type_info->stretch=SemiExpandedStretch;
00734 if (width >= FC_WIDTH_EXPANDED)
00735 type_info->stretch=ExpandedStretch;
00736 if (width >= FC_WIDTH_EXTRAEXPANDED)
00737 type_info->stretch=ExtraExpandedStretch;
00738 if (width >= FC_WIDTH_ULTRAEXPANDED)
00739 type_info->stretch=UltraExpandedStretch;
00740 type_info->weight=400;
00741 status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
00742 if (weight >= FC_WEIGHT_THIN)
00743 type_info->weight=100;
00744 if (weight >= FC_WEIGHT_EXTRALIGHT)
00745 type_info->weight=200;
00746 if (weight >= FC_WEIGHT_LIGHT)
00747 type_info->weight=300;
00748 if (weight >= FC_WEIGHT_NORMAL)
00749 type_info->weight=400;
00750 if (weight >= FC_WEIGHT_MEDIUM)
00751 type_info->weight=500;
00752 if (weight >= FC_WEIGHT_DEMIBOLD)
00753 type_info->weight=600;
00754 if (weight >= FC_WEIGHT_BOLD)
00755 type_info->weight=700;
00756 if (weight >= FC_WEIGHT_EXTRABOLD)
00757 type_info->weight=800;
00758 if (weight >= FC_WEIGHT_BLACK)
00759 type_info->weight=900;
00760 type_info->glyphs=ConstantString((const char *) file);
00761 (void) AddValueToSplayTree(type_list,type_info->name,type_info);
00762 }
00763 FcFontSetDestroy(font_set);
00764 FcConfigDestroy(font_config);
00765 return(MagickTrue);
00766 }
00767 #endif
00768
00769 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
00770 {
00771 if ((type_list == (SplayTreeInfo *) NULL) &&
00772 (instantiate_type == MagickFalse))
00773 {
00774 if (type_semaphore == (SemaphoreInfo *) NULL)
00775 AcquireSemaphoreInfo(&type_semaphore);
00776 (void) LockSemaphoreInfo(type_semaphore);
00777 if ((type_list == (SplayTreeInfo *) NULL) &&
00778 (instantiate_type == MagickFalse))
00779 {
00780 (void) LoadTypeLists(MagickTypeFilename,exception);
00781 #if defined(__WINDOWS__)
00782 (void) NTLoadTypeLists(type_list,exception);
00783 #endif
00784 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
00785 (void) LoadFontConfigFonts(type_list,exception);
00786 #endif
00787 instantiate_type=MagickTrue;
00788 }
00789 (void) UnlockSemaphoreInfo(type_semaphore);
00790 }
00791 return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
00819 {
00820 char
00821 weight[MaxTextExtent];
00822
00823 const char
00824 *family,
00825 *glyphs,
00826 *name,
00827 *path,
00828 *stretch,
00829 *style;
00830
00831 const TypeInfo
00832 **type_info;
00833
00834 register long
00835 i;
00836
00837 unsigned long
00838 number_fonts;
00839
00840 if (file == (FILE *) NULL)
00841 file=stdout;
00842 number_fonts=0;
00843 type_info=GetTypeInfoList("*",&number_fonts,exception);
00844 if (type_info == (const TypeInfo **) NULL)
00845 return(MagickFalse);
00846 *weight='\0';
00847 path=(const char *) NULL;
00848 for (i=0; i < (long) number_fonts; i++)
00849 {
00850 if (type_info[i]->stealth != MagickFalse)
00851 continue;
00852 if (((path == (const char *) NULL) ||
00853 (LocaleCompare(path,type_info[i]->path) != 0)) &&
00854 (type_info[i]->path != (char *) NULL))
00855 (void) fprintf(file,"\nPath: %s\n",type_info[i]->path);
00856 path=type_info[i]->path;
00857 name="unknown";
00858 if (type_info[i]->name != (char *) NULL)
00859 name=type_info[i]->name;
00860 family="unknown";
00861 if (type_info[i]->family != (char *) NULL)
00862 family=type_info[i]->family;
00863 style=MagickOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
00864 stretch=MagickOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
00865 glyphs="unknown";
00866 if (type_info[i]->glyphs != (char *) NULL)
00867 glyphs=type_info[i]->glyphs;
00868 (void) FormatMagickString(weight,MaxTextExtent,"%lu",type_info[i]->weight);
00869 (void) fprintf(file," Font: %s\n",name);
00870 (void) fprintf(file," family: %s\n",family);
00871 (void) fprintf(file," style: %s\n",style);
00872 (void) fprintf(file," stretch: %s\n",stretch);
00873 (void) fprintf(file," weight: %s\n",weight);
00874 (void) fprintf(file," glyphs: %s\n",glyphs);
00875 }
00876 (void) fflush(file);
00877 type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
00878 return(MagickTrue);
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 static void *DestroyTypeNode(void *type_info)
00913 {
00914 register TypeInfo
00915 *p;
00916
00917 p=(TypeInfo *) type_info;
00918 if (p->path != (char *) NULL)
00919 p->path=DestroyString(p->path);
00920 if (p->name != (char *) NULL)
00921 p->name=DestroyString(p->name);
00922 if (p->description != (char *) NULL)
00923 p->description=DestroyString(p->description);
00924 if (p->family != (char *) NULL)
00925 p->family=DestroyString(p->family);
00926 if (p->encoding != (char *) NULL)
00927 p->encoding=DestroyString(p->encoding);
00928 if (p->foundry != (char *) NULL)
00929 p->foundry=DestroyString(p->foundry);
00930 if (p->format != (char *) NULL)
00931 p->format=DestroyString(p->format);
00932 if (p->metrics != (char *) NULL)
00933 p->metrics=DestroyString(p->metrics);
00934 if (p->glyphs != (char *) NULL)
00935 p->glyphs=DestroyString(p->glyphs);
00936 return(RelinquishMagickMemory(p));
00937 }
00938
00939 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
00940 const unsigned long depth,ExceptionInfo *exception)
00941 {
00942 char
00943 font_path[MaxTextExtent],
00944 keyword[MaxTextExtent],
00945 *token;
00946
00947 const char
00948 *q;
00949
00950 MagickBooleanType
00951 status;
00952
00953 TypeInfo
00954 *type_info;
00955
00956
00957
00958
00959 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00960 "Loading type configure file \"%s\" ...",filename);
00961 if (xml == (const char *) NULL)
00962 return(MagickFalse);
00963 if (type_list == (SplayTreeInfo *) NULL)
00964 {
00965 type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
00966 DestroyTypeNode);
00967 if (type_list == (SplayTreeInfo *) NULL)
00968 {
00969 ThrowFileException(exception,ResourceLimitError,
00970 "MemoryAllocationFailed",filename);
00971 return(MagickFalse);
00972 }
00973 }
00974 status=MagickTrue;
00975 type_info=(TypeInfo *) NULL;
00976 token=AcquireString(xml);
00977 #if defined(__WINDOWS__)
00978
00979
00980
00981 *font_path='\0';
00982 if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
00983 (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
00984 #endif
00985 for (q=(char *) xml; *q != '\0'; )
00986 {
00987
00988
00989
00990 GetMagickToken(q,&q,token);
00991 if (*token == '\0')
00992 break;
00993 (void) CopyMagickString(keyword,token,MaxTextExtent);
00994 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
00995 {
00996
00997
00998
00999 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
01000 GetMagickToken(q,&q,token);
01001 continue;
01002 }
01003 if (LocaleNCompare(keyword,"<!--",4) == 0)
01004 {
01005
01006
01007
01008 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
01009 GetMagickToken(q,&q,token);
01010 continue;
01011 }
01012 if (LocaleCompare(keyword,"<include") == 0)
01013 {
01014
01015
01016
01017 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
01018 {
01019 (void) CopyMagickString(keyword,token,MaxTextExtent);
01020 GetMagickToken(q,&q,token);
01021 if (*token != '=')
01022 continue;
01023 GetMagickToken(q,&q,token);
01024 if (LocaleCompare(keyword,"file") == 0)
01025 {
01026 if (depth > 200)
01027 (void) ThrowMagickException(exception,GetMagickModule(),
01028 ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
01029 else
01030 {
01031 char
01032 path[MaxTextExtent],
01033 *xml;
01034
01035 ExceptionInfo
01036 *sans_exception;
01037
01038 *path='\0';
01039 GetPathComponent(filename,HeadPath,path);
01040 if (*path != '\0')
01041 (void) ConcatenateMagickString(path,DirectorySeparator,
01042 MaxTextExtent);
01043 if (*token == *DirectorySeparator)
01044 (void) CopyMagickString(path,token,MaxTextExtent);
01045 else
01046 (void) ConcatenateMagickString(path,token,MaxTextExtent);
01047 sans_exception=AcquireExceptionInfo();
01048 xml=FileToString(path,~0,sans_exception);
01049 sans_exception=DestroyExceptionInfo(sans_exception);
01050 if (xml != (char *) NULL)
01051 {
01052 status=LoadTypeList(xml,path,depth+1,exception);
01053 xml=(char *) RelinquishMagickMemory(xml);
01054 }
01055 }
01056 }
01057 }
01058 continue;
01059 }
01060 if (LocaleCompare(keyword,"<type") == 0)
01061 {
01062
01063
01064
01065 type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
01066 if (type_info == (TypeInfo *) NULL)
01067 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01068 (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
01069 type_info->path=ConstantString(filename);
01070 type_info->signature=MagickSignature;
01071 continue;
01072 }
01073 if (type_info == (TypeInfo *) NULL)
01074 continue;
01075 if (LocaleCompare(keyword,"/>") == 0)
01076 {
01077 status=AddValueToSplayTree(type_list,type_info->name,type_info);
01078 if (status == MagickFalse)
01079 (void) ThrowMagickException(exception,GetMagickModule(),
01080 ResourceLimitError,"MemoryAllocationFailed","`%s'",type_info->name);
01081 type_info=(TypeInfo *) NULL;
01082 }
01083 GetMagickToken(q,(const char **) NULL,token);
01084 if (*token != '=')
01085 continue;
01086 GetMagickToken(q,&q,token);
01087 GetMagickToken(q,&q,token);
01088 switch (*keyword)
01089 {
01090 case 'E':
01091 case 'e':
01092 {
01093 if (LocaleCompare((char *) keyword,"encoding") == 0)
01094 {
01095 type_info->encoding=ConstantString(token);
01096 break;
01097 }
01098 break;
01099 }
01100 case 'F':
01101 case 'f':
01102 {
01103 if (LocaleCompare((char *) keyword,"face") == 0)
01104 {
01105 type_info->face=(unsigned long) atol(token);
01106 break;
01107 }
01108 if (LocaleCompare((char *) keyword,"family") == 0)
01109 {
01110 type_info->family=ConstantString(token);
01111 break;
01112 }
01113 if (LocaleCompare((char *) keyword,"format") == 0)
01114 {
01115 type_info->format=ConstantString(token);
01116 break;
01117 }
01118 if (LocaleCompare((char *) keyword,"foundry") == 0)
01119 {
01120 type_info->foundry=ConstantString(token);
01121 break;
01122 }
01123 if (LocaleCompare((char *) keyword,"fullname") == 0)
01124 {
01125 type_info->description=ConstantString(token);
01126 break;
01127 }
01128 break;
01129 }
01130 case 'G':
01131 case 'g':
01132 {
01133 if (LocaleCompare((char *) keyword,"glyphs") == 0)
01134 {
01135 char
01136 *path;
01137
01138 path=ConstantString(token);
01139 #if defined(__WINDOWS__)
01140 if (strchr(path,'@') != (char *) NULL)
01141 SubstituteString(&path,"@ghostscript_font_path@",font_path);
01142 #endif
01143 if (IsPathAccessible(path) == MagickFalse)
01144 {
01145
01146
01147
01148 path=DestroyString(path);
01149 GetPathComponent(filename,HeadPath,font_path);
01150 (void) ConcatenateMagickString(font_path,DirectorySeparator,
01151 MaxTextExtent);
01152 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
01153 path=ConstantString(font_path);
01154 }
01155 type_info->glyphs=path;
01156 break;
01157 }
01158 break;
01159 }
01160 case 'M':
01161 case 'm':
01162 {
01163 if (LocaleCompare((char *) keyword,"metrics") == 0)
01164 {
01165 char
01166 *path;
01167
01168 path=ConstantString(token);
01169 #if defined(__WINDOWS__)
01170 if (strchr(path,'@') != (char *) NULL)
01171 SubstituteString(&path,"@ghostscript_font_path@",font_path);
01172 #endif
01173 if (IsPathAccessible(path) == MagickFalse)
01174 {
01175
01176
01177
01178 path=DestroyString(path);
01179 GetPathComponent(filename,HeadPath,font_path);
01180 (void) ConcatenateMagickString(font_path,DirectorySeparator,
01181 MaxTextExtent);
01182 (void) ConcatenateMagickString(font_path,token,MaxTextExtent);
01183 path=ConstantString(font_path);
01184 }
01185 type_info->metrics=path;
01186 break;
01187 }
01188 break;
01189 }
01190 case 'N':
01191 case 'n':
01192 {
01193 if (LocaleCompare((char *) keyword,"name") == 0)
01194 {
01195 type_info->name=ConstantString(token);
01196 break;
01197 }
01198 break;
01199 }
01200 case 'S':
01201 case 's':
01202 {
01203 if (LocaleCompare((char *) keyword,"stealth") == 0)
01204 {
01205 type_info->stealth=IsMagickTrue(token);
01206 break;
01207 }
01208 if (LocaleCompare((char *) keyword,"stretch") == 0)
01209 {
01210 type_info->stretch=(StretchType) ParseMagickOption(
01211 MagickStretchOptions,MagickFalse,token);
01212 break;
01213 }
01214 if (LocaleCompare((char *) keyword,"style") == 0)
01215 {
01216 type_info->style=(StyleType) ParseMagickOption(MagickStyleOptions,
01217 MagickFalse,token);
01218 break;
01219 }
01220 break;
01221 }
01222 case 'W':
01223 case 'w':
01224 {
01225 if (LocaleCompare((char *) keyword,"weight") == 0)
01226 {
01227 type_info->weight=(unsigned long) atol(token);
01228 if (LocaleCompare(token,"bold") == 0)
01229 type_info->weight=700;
01230 if (LocaleCompare(token,"normal") == 0)
01231 type_info->weight=400;
01232 break;
01233 }
01234 break;
01235 }
01236 default:
01237 break;
01238 }
01239 }
01240 token=(char *) RelinquishMagickMemory(token);
01241 return(status);
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 static MagickBooleanType LoadTypeLists(const char *filename,
01271 ExceptionInfo *exception)
01272 {
01273 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
01274 return(LoadTypeList(TypeMap,"built-in",0,exception));
01275 #else
01276 char
01277 *font_path,
01278 path[MaxTextExtent];
01279
01280 const StringInfo
01281 *option;
01282
01283 LinkedListInfo
01284 *options;
01285
01286 MagickStatusType
01287 status;
01288
01289 status=MagickFalse;
01290 *path='\0';
01291 options=GetConfigureOptions(filename,exception);
01292 option=(const StringInfo *) GetNextValueInLinkedList(options);
01293 while (option != (const StringInfo *) NULL)
01294 {
01295 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
01296 status|=LoadTypeList((const char *) GetStringInfoDatum(option),
01297 GetStringInfoPath(option),0,exception);
01298 option=(const StringInfo *) GetNextValueInLinkedList(options);
01299 }
01300 options=DestroyConfigureOptions(options);
01301 font_path=GetEnvironmentValue("MAGICK_FONT_PATH");
01302 if (font_path != (char *) NULL)
01303 {
01304 char
01305 *option;
01306
01307
01308
01309
01310 (void) FormatMagickString(path,MaxTextExtent,"%s%s%s",font_path,
01311 DirectorySeparator,filename);
01312 option=FileToString(path,~0,exception);
01313 if (option != (void *) NULL)
01314 {
01315 status|=LoadTypeList(option,path,0,exception);
01316 option=DestroyString(option);
01317 }
01318 font_path=DestroyString(font_path);
01319 }
01320 if ((type_list == (SplayTreeInfo *) NULL) ||
01321 (GetNumberOfNodesInSplayTree(type_list) == 0))
01322 status|=LoadTypeList(TypeMap,"built-in",0,exception);
01323 return(status != 0 ? MagickTrue : MagickFalse);
01324 #endif
01325 }
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345 MagickExport MagickBooleanType TypeComponentGenesis(void)
01346 {
01347 AcquireSemaphoreInfo(&type_semaphore);
01348 return(MagickTrue);
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369 MagickExport void TypeComponentTerminus(void)
01370 {
01371 if (type_semaphore == (SemaphoreInfo *) NULL)
01372 AcquireSemaphoreInfo(&type_semaphore);
01373 (void) LockSemaphoreInfo(type_semaphore);
01374 if (type_list != (SplayTreeInfo *) NULL)
01375 type_list=DestroySplayTree(type_list);
01376 instantiate_type=MagickFalse;
01377 (void) UnlockSemaphoreInfo(type_semaphore);
01378 DestroySemaphoreInfo(&type_semaphore);
01379 }