type.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                        TTTTT  Y   Y  PPPP   EEEEE                           %
00007 %                          T     Y Y   P   P  E                               %
00008 %                          T      Y    PPPP   EEE                             %
00009 %                          T      Y    P      E                               %
00010 %                          T      Y    P      EEEEE                           %
00011 %                                                                             %
00012 %                                                                             %
00013 %                       MagickCore Image Type Methods                         %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 May 2001                                    %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2007 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
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"    /* Int */
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   Define declarations.
00098 */
00099 #define MagickTypeFilename  "type.xml"
00100 
00101 /*
00102   Declare type map.
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   Static declarations.
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   Forward declarations.
00126 */
00127 static MagickBooleanType
00128   InitializeTypeList(ExceptionInfo *),
00129   LoadTypeLists(const char *,ExceptionInfo *);
00130 
00131 /*
00132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00133 %                                                                             %
00134 %                                                                             %
00135 %                                                                             %
00136 +   D e s t r o y T y p e L i s t                                             %
00137 %                                                                             %
00138 %                                                                             %
00139 %                                                                             %
00140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00141 %
00142 %  DestroyTypeList() deallocates memory associated with the font list.
00143 %
00144 %  The format of the DestroyTypeList method is:
00145 %
00146 %      DestroyTypeList(void)
00147 %
00148 */
00149 MagickExport void DestroyTypeList(void)
00150 {
00151   AcquireSemaphoreInfo(&type_semaphore);
00152   if (type_list != (SplayTreeInfo *) NULL)
00153     type_list=DestroySplayTree(type_list);
00154   instantiate_type=MagickFalse;
00155   RelinquishSemaphoreInfo(type_semaphore);
00156   DestroySemaphoreInfo(&type_semaphore);
00157 }
00158 
00159 /*
00160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00161 %                                                                             %
00162 %                                                                             %
00163 %                                                                             %
00164 +   G e t T y p e I n f o                                                     %
00165 %                                                                             %
00166 %                                                                             %
00167 %                                                                             %
00168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00169 %
00170 %  GetTypeInfo searches the type list for the specified name and if found
00171 %  returns attributes for that type.
00172 %
00173 %  The format of the GetTypeInfo method is:
00174 %
00175 %      const TypeInfo *GetTypeInfo(const char *name,ExceptionInfo *exception)
00176 %
00177 %  A description of each parameter follows:
00178 %
00179 %    o name: the type name.
00180 %
00181 %    o exception: return any errors or warnings in this structure.
00182 %
00183 */
00184 MagickExport const TypeInfo *GetTypeInfo(const char *name,
00185   ExceptionInfo *exception)
00186 {
00187   assert(exception != (ExceptionInfo *) NULL);
00188   if ((type_list == (SplayTreeInfo *) NULL) ||
00189       (instantiate_type == MagickFalse))
00190     if (InitializeTypeList(exception) == MagickFalse)
00191       return((const TypeInfo *) NULL);
00192   if ((type_list == (SplayTreeInfo *) NULL) ||
00193       (GetNumberOfNodesInSplayTree(type_list) == 0))
00194     return((const TypeInfo *) NULL);
00195   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
00196     {
00197       ResetSplayTreeIterator(type_list);
00198       return((const TypeInfo *) GetNextValueInSplayTree(type_list));
00199     }
00200   return((const TypeInfo *) GetValueFromSplayTree(type_list,name));
00201 }
00202 
00203 /*
00204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00205 %                                                                             %
00206 %                                                                             %
00207 %                                                                             %
00208 +   G e t T y p e I n f o B y F a m i l y                                     %
00209 %                                                                             %
00210 %                                                                             %
00211 %                                                                             %
00212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00213 %
00214 %  GetTypeInfoByFamily() searches the type list for the specified family and if
00215 %  found returns attributes for that type.
00216 %
00217 %  Type substitution and scoring algorithm contributed by Bob Friesenhahn.
00218 %
00219 %  The format of the GetTypeInfoByFamily method is:
00220 %
00221 %      const TypeInfo *GetTypeInfoByFamily(const char *family,
00222 %        const StyleType style,const StretchType stretch,
00223 %        const unsigned long weight,ExceptionInfo *exception)
00224 %
00225 %  A description of each parameter follows:
00226 %
00227 %    o family: the type family.
00228 %
00229 %    o style: the type style.
00230 %
00231 %    o stretch: the type stretch.
00232 %
00233 %    o weight: the type weight.
00234 %
00235 %    o exception: return any errors or warnings in this structure.
00236 %
00237 */
00238 
00239 static inline unsigned long MagickMax(const unsigned long x,
00240   const unsigned long y)
00241 {
00242   if (x > y)
00243     return(x);
00244   return(y);
00245 }
00246 
00247 static inline unsigned long MagickMin(const unsigned long x,
00248   const unsigned long y)
00249 {
00250   if (x < y)
00251     return(x);
00252   return(y);
00253 }
00254 
00255 MagickExport const TypeInfo *GetTypeInfoByFamily(const char *family,
00256   const StyleType style,const StretchType stretch,const unsigned long weight,
00257   ExceptionInfo *exception)
00258 {
00259   typedef struct _Fontmap
00260   {
00261     const char
00262       *name,
00263       *substitute;
00264   } Fontmap;
00265 
00266   const TypeInfo
00267     *type_info;
00268 
00269   long
00270     range;
00271 
00272   register const TypeInfo
00273     *p;
00274 
00275   register long
00276     i;
00277 
00278   static Fontmap
00279     fontmap[] =
00280     {
00281       { "fixed", "courier" },
00282       { "modern","courier" },
00283       { "monotype corsiva", "courier" },
00284       { "news gothic", "helvetica" },
00285       { "system", "courier" },
00286       { "terminal", "courier" },
00287       { "wingdings", "symbol" },
00288       { NULL, NULL }
00289     };
00290 
00291   unsigned long
00292     max_score,
00293     score;
00294 
00295   /*
00296     Check for an exact type match.
00297   */
00298   (void) GetTypeInfo("*",exception);
00299   if (type_list == (SplayTreeInfo *) NULL)
00300     return((TypeInfo *) NULL);
00301   AcquireSemaphoreInfo(&type_semaphore);
00302   ResetSplayTreeIterator(type_list);
00303   type_info=(const TypeInfo *) NULL;
00304   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00305   while (p != (const TypeInfo *) NULL)
00306   {
00307     if (p->family == (char *) NULL)
00308       {
00309         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00310         continue;
00311       }
00312     if (family == (const char *) NULL)
00313       {
00314         if ((LocaleCompare(p->family,"arial") != 0) &&
00315             (LocaleCompare(p->family,"helvetica") != 0))
00316           {
00317             p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00318             continue;
00319           }
00320       }
00321     else
00322       if (LocaleCompare(p->family,family) != 0)
00323         {
00324           p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00325           continue;
00326         }
00327     if ((style != UndefinedStyle) && (style != AnyStyle) && (p->style != style))
00328       {
00329         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00330         continue;
00331       }
00332     if ((stretch != UndefinedStretch) && (stretch != AnyStretch) &&
00333         (p->stretch != stretch))
00334       {
00335         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00336         continue;
00337       }
00338     if ((weight != 0) && (p->weight != weight))
00339       {
00340         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00341         continue;
00342       }
00343     type_info=p;
00344     break;
00345   }
00346   RelinquishSemaphoreInfo(type_semaphore);
00347   if (type_info != (const TypeInfo *) NULL)
00348     return(type_info);
00349   /*
00350     Check for types in the same family.
00351   */
00352   max_score=0;
00353   AcquireSemaphoreInfo(&type_semaphore);
00354   ResetSplayTreeIterator(type_list);
00355   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00356   while (p != (const TypeInfo *) NULL)
00357   {
00358     if (p->family == (char *) NULL)
00359       {
00360         p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00361         continue;
00362       }
00363     if (family == (const char *) NULL)
00364       {
00365         if ((LocaleCompare(p->family,"arial") != 0) &&
00366             (LocaleCompare(p->family,"helvetica") != 0))
00367           {
00368             p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00369             continue;
00370           }
00371       }
00372     else
00373       if (LocaleCompare(p->family,family) != 0)
00374         {
00375           p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00376           continue;
00377         }
00378     score=0;
00379     if ((style == UndefinedStyle) || (style == AnyStyle) || (p->style == style))
00380       score+=32;
00381     else
00382       if (((style == ItalicStyle) || (style == ObliqueStyle)) &&
00383           ((p->style == ItalicStyle) || (p->style == ObliqueStyle)))
00384         score+=25;
00385     if (weight == 0)
00386       score+=16;
00387     else
00388       score+=(16*(800-((long) MagickMax(MagickMin(weight,900),p->weight)-
00389         (long) MagickMin(MagickMin(weight,900),p->weight))))/800;
00390     if ((stretch == UndefinedStretch) || (stretch == AnyStretch))
00391       score+=8;
00392     else
00393       {
00394         range=(long) UltraExpandedStretch-(long) NormalStretch;
00395         score+=(8*(range-((long) MagickMax(stretch,p->stretch)-
00396           (long) MagickMin(stretch,p->stretch))))/range;
00397       }
00398     if (score > max_score)
00399       {
00400         max_score=score;
00401         type_info=p;
00402       }
00403     p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00404   }
00405   RelinquishSemaphoreInfo(type_semaphore);
00406   if (type_info != (const TypeInfo *) NULL)
00407     return(type_info);
00408   /*
00409     Check for table-based substitution match.
00410   */
00411   for (i=0; fontmap[i].name != (char *) NULL; i++)
00412   {
00413     if (family == (const char *) NULL)
00414       {
00415         if ((LocaleCompare(fontmap[i].name,"arial") != 0) &&
00416             (LocaleCompare(fontmap[i].name,"helvetica") != 0))
00417           continue;
00418       }
00419     else
00420       if (LocaleCompare(fontmap[i].name,family) != 0)
00421         continue;
00422     type_info=GetTypeInfoByFamily(fontmap[i].substitute,style,stretch,weight,
00423       exception);
00424     break;
00425   }
00426   if (type_info != (const TypeInfo *) NULL)
00427     {
00428       (void) ThrowMagickException(exception,GetMagickModule(),TypeError,
00429         "FontSubstitutionRequired","`%s'",type_info->family);
00430       return(type_info);
00431     }
00432   if (family != (const char *) NULL)
00433     type_info=GetTypeInfoByFamily((const char *) NULL,style,stretch,weight,
00434       exception);
00435   return(type_info);
00436 }
00437 
00438 /*
00439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00440 %                                                                             %
00441 %                                                                             %
00442 %                                                                             %
00443 %   G e t T y p e I n f o L i s t                                             %
00444 %                                                                             %
00445 %                                                                             %
00446 %                                                                             %
00447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00448 %
00449 %  GetTypeInfoList() returns any fonts that match the specified pattern.
00450 %
00451 %  The format of the GetTypeInfoList function is:
00452 %
00453 %      const TypeInfo **GetTypeInfoList(const char *pattern,
00454 %        unsigned long *number_fonts,ExceptionInfo *exception)
00455 %
00456 %  A description of each parameter follows:
00457 %
00458 %    o pattern: Specifies a pointer to a text string containing a pattern.
00459 %
00460 %    o number_fonts:  This integer returns the number of types in the list.
00461 %
00462 %    o exception: return any errors or warnings in this structure.
00463 %
00464 */
00465 
00466 #if defined(__cplusplus) || defined(c_plusplus)
00467 extern "C" {
00468 #endif
00469 
00470 static int TypeInfoCompare(const void *x,const void *y)
00471 {
00472   const TypeInfo
00473     **p,
00474     **q;
00475 
00476   p=(const TypeInfo **) x,
00477   q=(const TypeInfo **) y;
00478   if (LocaleCompare((*p)->path,(*q)->path) == 0)
00479     return(LocaleCompare((*p)->name,(*q)->name));
00480   return(LocaleCompare((*p)->path,(*q)->path));
00481 }
00482 
00483 #if defined(__cplusplus) || defined(c_plusplus)
00484 }
00485 #endif
00486 
00487 MagickExport const TypeInfo **GetTypeInfoList(const char *pattern,
00488   unsigned long *number_fonts,ExceptionInfo *exception)
00489 {
00490   const TypeInfo
00491     **fonts;
00492 
00493   register const TypeInfo
00494     *p;
00495 
00496   register long
00497     i;
00498 
00499   /*
00500     Allocate type list.
00501   */
00502   assert(pattern != (char *) NULL);
00503   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00504   assert(number_fonts != (unsigned long *) NULL);
00505   *number_fonts=0;
00506   p=GetTypeInfo("*",exception);
00507   if (p == (const TypeInfo *) NULL)
00508     return((const TypeInfo **) NULL);
00509   fonts=(const TypeInfo **) AcquireQuantumMemory((size_t)
00510     GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
00511   if (fonts == (const TypeInfo **) NULL)
00512     return((const TypeInfo **) NULL);
00513   /*
00514     Generate type list.
00515   */
00516   AcquireSemaphoreInfo(&type_semaphore);
00517   ResetSplayTreeIterator(type_list);
00518   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00519   for (i=0; p != (const TypeInfo *) NULL; )
00520   {
00521     if ((p->stealth == MagickFalse) &&
00522         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00523       fonts[i++]=p;
00524     p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00525   }
00526   RelinquishSemaphoreInfo(type_semaphore);
00527   qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeInfoCompare);
00528   fonts[i]=(TypeInfo *) NULL;
00529   *number_fonts=(unsigned long) i;
00530   return(fonts);
00531 }
00532 
00533 /*
00534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00535 %                                                                             %
00536 %                                                                             %
00537 %                                                                             %
00538 %   G e t T y p e L i s t                                                     %
00539 %                                                                             %
00540 %                                                                             %
00541 %                                                                             %
00542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00543 %
00544 %  GetTypeList() returns any fonts that match the specified pattern.
00545 %
00546 %  The format of the GetTypeList function is:
00547 %
00548 %      char **GetTypeList(const char *pattern,unsigned long *number_fonts,
00549 %        ExceptionInfo *exception)
00550 %
00551 %  A description of each parameter follows:
00552 %
00553 %    o pattern: Specifies a pointer to a text string containing a pattern.
00554 %
00555 %    o number_fonts:  This integer returns the number of fonts in the list.
00556 %
00557 %    o exception: return any errors or warnings in this structure.
00558 %
00559 */
00560 
00561 #if defined(__cplusplus) || defined(c_plusplus)
00562 extern "C" {
00563 #endif
00564 
00565 static int TypeCompare(const void *x,const void *y)
00566 {
00567   register const char
00568     **p,
00569     **q;
00570 
00571   p=(const char **) x;
00572   q=(const char **) y;
00573   return(LocaleCompare(*p,*q));
00574 }
00575 
00576 #if defined(__cplusplus) || defined(c_plusplus)
00577 }
00578 #endif
00579 
00580 MagickExport char **GetTypeList(const char *pattern,unsigned long *number_fonts,
00581   ExceptionInfo *exception)
00582 {
00583   char
00584     **fonts;
00585 
00586   register const TypeInfo
00587     *p;
00588 
00589   register long
00590     i;
00591 
00592   /*
00593     Allocate type list.
00594   */
00595   assert(pattern != (char *) NULL);
00596   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00597   assert(number_fonts != (unsigned long *) NULL);
00598   *number_fonts=0;
00599   p=GetTypeInfo("*",exception);
00600   if (p == (const TypeInfo *) NULL)
00601     return((char **) NULL);
00602   fonts=(char **) AcquireQuantumMemory((size_t)
00603     GetNumberOfNodesInSplayTree(type_list)+1UL,sizeof(*fonts));
00604   if (fonts == (char **) NULL)
00605     return((char **) NULL);
00606   /*
00607     Generate type list.
00608   */
00609   AcquireSemaphoreInfo(&type_semaphore);
00610   ResetSplayTreeIterator(type_list);
00611   p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00612   for (i=0; p != (const TypeInfo *) NULL; )
00613   {
00614     if ((p->stealth == MagickFalse) &&
00615         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00616       fonts[i++]=ConstantString(p->name);
00617     p=(const TypeInfo *) GetNextValueInSplayTree(type_list);
00618   }
00619   RelinquishSemaphoreInfo(type_semaphore);
00620   qsort((void *) fonts,(size_t) i,sizeof(*fonts),TypeCompare);
00621   fonts[i]=(char *) NULL;
00622   *number_fonts=(unsigned long) i;
00623   return(fonts);
00624 }
00625 
00626 /*
00627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00628 %                                                                             %
00629 %                                                                             %
00630 %                                                                             %
00631 +   I n i t i a l i z e T y p e L i s t                                       %
00632 %                                                                             %
00633 %                                                                             %
00634 %                                                                             %
00635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00636 %
00637 %  InitializeTypeList() initializes the type list.
00638 %
00639 %  The format of the InitializeTypeList method is:
00640 %
00641 %      MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
00642 %
00643 %  A description of each parameter follows.
00644 %
00645 %    o exception: return any errors or warnings in this structure.
00646 %
00647 */
00648 
00649 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
00650 MagickExport MagickBooleanType LoadFontConfigFonts(SplayTreeInfo *type_list,
00651   ExceptionInfo *exception)
00652 {
00653   char
00654     extension[MaxTextExtent],
00655     name[MaxTextExtent];
00656 
00657   FcChar8
00658     *family,
00659     *file,
00660     *style;
00661 
00662   FcConfig
00663     *font_config;
00664 
00665   FcFontSet
00666     *font_set;
00667 
00668   FcObjectSet
00669     *object_set;
00670 
00671   FcPattern
00672     *pattern;
00673 
00674   FcResult
00675     status;
00676 
00677   int
00678     slant,
00679     width,
00680     weight;
00681 
00682   register long
00683     i;
00684 
00685   TypeInfo
00686     *type_info;
00687 
00688   /*
00689     Load system fonts.
00690   */
00691   (void) exception;
00692   font_config=FcInitLoadConfigAndFonts();
00693   if (font_config == (FcConfig *) NULL)
00694     return(MagickFalse);
00695   font_set=(FcFontSet *) NULL;
00696   object_set=FcObjectSetBuild(FC_FAMILY,FC_STYLE,FC_SLANT,FC_WIDTH,FC_WEIGHT,
00697     FC_FILE,(char *) NULL);
00698   if (object_set != (FcObjectSet *) NULL)
00699     {
00700       pattern=FcPatternCreate();
00701       if (pattern != (FcPattern *) NULL)
00702         {
00703           font_set=FcFontList(0,pattern,object_set);
00704           FcPatternDestroy(pattern);
00705         }
00706       FcObjectSetDestroy(object_set);
00707     }
00708   if (font_set == (FcFontSet *) NULL)
00709     {
00710       FcConfigDestroy(font_config);
00711       return(MagickFalse);
00712     }
00713   for (i=0; i < (long) font_set->nfont; i++)
00714   {
00715     status=FcPatternGetString(font_set->fonts[i],FC_FAMILY,0,&family);
00716     if (status != FcResultMatch)
00717       continue;
00718     status=FcPatternGetString(font_set->fonts[i],FC_FILE,0,&file);
00719     if (status != FcResultMatch)
00720       continue;
00721     *extension='\0';
00722     GetPathComponent((const char *) file,ExtensionPath,extension);
00723     if ((*extension != '\0') && (LocaleCompare(extension,"gz") == 0))
00724       continue;
00725     type_info=(TypeInfo *) AcquireMagickMemory(sizeof(*type_info));
00726     if (type_info == (TypeInfo *) NULL)
00727       continue;
00728     (void) ResetMagickMemory(type_info,0,sizeof(*type_info));
00729     type_info->path=ConstantString("System Fonts");
00730     type_info->signature=MagickSignature;
00731     (void) CopyMagickString(name,(const char *) family,MaxTextExtent);
00732     (void) ConcatenateMagickString(name," ",MaxTextExtent);
00733     status=FcPatternGetString(font_set->fonts[i],FC_STYLE,0,&style);
00734     if (status == FcResultMatch)
00735       (void) ConcatenateMagickString(name,(const char *) style,MaxTextExtent);
00736     type_info->name=ConstantString(name);
00737     (void) SubstituteString(&type_info->name," ","-");
00738     (void) SubstituteString(&type_info->name,"-L-","-");
00739     (void) SubstituteString(&type_info->name,"semicondensed","SemiCondensed");
00740     type_info->family=ConstantString((const char *) family);
00741     (void) SubstituteString(&type_info->family," L","");
00742     status=FcPatternGetInteger(font_set->fonts[i],FC_SLANT,0,&slant);
00743     type_info->style=NormalStyle;
00744     if (slant == FC_SLANT_ITALIC)
00745       type_info->style=ItalicStyle;
00746     if (slant == FC_SLANT_OBLIQUE)
00747       type_info->style=ObliqueStyle;
00748     status=FcPatternGetInteger(font_set->fonts[i],FC_WIDTH,0,&width);
00749     type_info->stretch=NormalStretch;
00750     if (width >= FC_WIDTH_ULTRACONDENSED)
00751       type_info->stretch=UltraCondensedStretch;
00752     if (width >= FC_WIDTH_EXTRACONDENSED)
00753       type_info->stretch=ExtraCondensedStretch;
00754     if (width >= FC_WIDTH_CONDENSED)
00755       type_info->stretch=CondensedStretch;
00756     if (width >= FC_WIDTH_SEMICONDENSED)
00757       type_info->stretch=SemiCondensedStretch;
00758     if (width >= FC_WIDTH_NORMAL)
00759       type_info->stretch=NormalStretch;
00760     if (width >= FC_WIDTH_SEMIEXPANDED)
00761       type_info->stretch=SemiExpandedStretch;
00762     if (width >= FC_WIDTH_EXPANDED)
00763       type_info->stretch=ExpandedStretch;
00764     if (width >= FC_WIDTH_EXTRAEXPANDED)
00765       type_info->stretch=ExtraExpandedStretch;
00766     if (width >= FC_WIDTH_ULTRAEXPANDED)
00767       type_info->stretch=UltraExpandedStretch;
00768     type_info->weight=400;
00769     status=FcPatternGetInteger(font_set->fonts[i],FC_WEIGHT,0,&weight);
00770     if (weight >= FC_WEIGHT_THIN)
00771       type_info->weight=100;
00772     if (weight >= FC_WEIGHT_EXTRALIGHT)
00773       type_info->weight=200;
00774     if (weight >= FC_WEIGHT_LIGHT)
00775       type_info->weight=300;
00776     if (weight >= FC_WEIGHT_NORMAL)
00777       type_info->weight=400;
00778     if (weight >= FC_WEIGHT_MEDIUM)
00779       type_info->weight=500;
00780     if (weight >= FC_WEIGHT_DEMIBOLD)
00781       type_info->weight=600;
00782     if (weight >= FC_WEIGHT_BOLD)
00783       type_info->weight=700;
00784     if (weight >= FC_WEIGHT_EXTRABOLD)
00785       type_info->weight=800;
00786     if (weight >= FC_WEIGHT_BLACK)
00787       type_info->weight=900;
00788     type_info->glyphs=ConstantString((const char *) file);
00789     (void) AddValueToSplayTree(type_list,type_info->name,type_info);
00790   }
00791   FcFontSetDestroy(font_set);
00792   FcConfigDestroy(font_config);
00793   return(MagickTrue);
00794 }
00795 #endif
00796 
00797 static MagickBooleanType InitializeTypeList(ExceptionInfo *exception)
00798 {
00799   if ((type_list == (SplayTreeInfo *) NULL) &&
00800       (instantiate_type == MagickFalse))
00801     {
00802       AcquireSemaphoreInfo(&type_semaphore);
00803       if ((type_list == (SplayTreeInfo *) NULL) &&
00804           (instantiate_type == MagickFalse))
00805         {
00806           (void) LoadTypeLists(MagickTypeFilename,exception);
00807 #if defined(__WINDOWS__)
00808           (void) NTLoadTypeLists(type_list,exception);
00809 #endif
00810 #if defined(MAGICKCORE_FONTCONFIG_DELEGATE)
00811           (void) LoadFontConfigFonts(type_list,exception);
00812 #endif
00813           instantiate_type=MagickTrue;
00814         }
00815       RelinquishSemaphoreInfo(type_semaphore);
00816     }
00817   return(type_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
00818 }
00819 
00820 /*
00821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00822 %                                                                             %
00823 %                                                                             %
00824 %                                                                             %
00825 %  L i s t T y p e I n f o                                                    %
00826 %                                                                             %
00827 %                                                                             %
00828 %                                                                             %
00829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00830 %
00831 %  ListTypeInfo() lists the fonts to a file.
00832 %
00833 %  The format of the ListTypeInfo method is:
00834 %
00835 %      MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
00836 %
00837 %  A description of each parameter follows.
00838 %
00839 %    o file:  An pointer to a FILE.
00840 %
00841 %    o exception: return any errors or warnings in this structure.
00842 %
00843 */
00844 MagickExport MagickBooleanType ListTypeInfo(FILE *file,ExceptionInfo *exception)
00845 {
00846   char
00847     weight[MaxTextExtent];
00848 
00849   const char
00850     *family,
00851     *glyphs,
00852     *name,
00853     *path,
00854     *stretch,
00855     *style;
00856 
00857   const TypeInfo
00858     **type_info;
00859 
00860   register long
00861     i;
00862 
00863   unsigned long
00864     number_fonts;
00865 
00866   if (file == (FILE *) NULL)
00867     file=stdout;
00868   number_fonts=0;
00869   type_info=GetTypeInfoList("*",&number_fonts,exception);
00870   if (type_info == (const TypeInfo **) NULL)
00871     return(MagickFalse);
00872   *weight='\0';
00873   path=(const char *) NULL;
00874   for (i=0; i < (long) number_fonts; i++)
00875   {
00876     if (type_info[i]->stealth != MagickFalse)
00877       continue;
00878     if (((path == (const char *) NULL) ||
00879          (LocaleCompare(path,type_info[i]->path) != 0)) &&
00880          (type_info[i]->path != (char *) NULL))
00881       (void) fprintf(file,"\nPath: %s\n",type_info[i]->path);
00882     path=type_info[i]->path;
00883     name="unknown";
00884     if (type_info[i]->name != (char *) NULL)
00885       name=type_info[i]->name;
00886     family="unknown";
00887     if (type_info[i]->family != (char *) NULL)
00888       family=type_info[i]->family;
00889     style=MagickOptionToMnemonic(MagickStyleOptions,type_info[i]->style);
00890     stretch=MagickOptionToMnemonic(MagickStretchOptions,type_info[i]->stretch);
00891     glyphs="unknown";
00892     if (type_info[i]->glyphs != (char *) NULL)
00893       glyphs=type_info[i]->glyphs;
00894     (void) FormatMagickString(weight,MaxTextExtent,"%lu",type_info[i]->weight);
00895     (void) fprintf(file,"  Font: %s\n",name);
00896     (void) fprintf(file,"    family: %s\n",family);
00897     (void) fprintf(file,"    style: %s\n",style);
00898     (void) fprintf(file,"    stretch: %s\n",stretch);
00899     (void) fprintf(file,"    weight: %s\n",weight);
00900     (void) fprintf(file,"    glyphs: %s\n",glyphs);
00901   }
00902   (void) fflush(file);
00903   type_info=(const TypeInfo **) RelinquishMagickMemory((void *) type_info);
00904   return(MagickTrue);
00905 }
00906 
00907 /*
00908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00909 %                                                                             %
00910 %                                                                             %
00911 %                                                                             %
00912 +   L o a d T y p e L i s t                                                   %
00913 %                                                                             %
00914 %                                                                             %
00915 %                                                                             %
00916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00917 %
00918 %  LoadTypeList() loads the type configuration file which provides a mapping
00919 %  between type attributes and a type name.
00920 %
00921 %  The format of the LoadTypeList method is:
00922 %
00923 %      MagickBooleanType LoadTypeList(const char *xml,const char *filename,
00924 %        const unsigned long depth,ExceptionInfo *exception)
00925 %
00926 %  A description of each parameter follows:
00927 %
00928 %    o xml:  The type list in XML format.
00929 %
00930 %    o filename:  The type list filename.
00931 %
00932 %    o depth: depth of <include /> statements.
00933 %
00934 %    o exception: return any errors or warnings in this structure.
00935 %
00936 */
00937 
00938 static void *DestroyTypeNode(void *type_info)
00939 {
00940   register TypeInfo
00941     *p;
00942 
00943   p=(TypeInfo *) type_info;
00944   if (p->path != (char *) NULL)
00945     p->path=DestroyString(p->path);
00946   if (p->name != (char *) NULL)
00947     p->name=DestroyString(p->name);
00948   if (p->description != (char *) NULL)
00949     p->description=DestroyString(p->description);
00950   if (p->family != (char *) NULL)
00951     p->family=DestroyString(p->family);
00952   if (p->encoding != (char *) NULL)
00953     p->encoding=DestroyString(p->encoding);
00954   if (p->foundry != (char *) NULL)
00955     p->foundry=DestroyString(p->foundry);
00956   if (p->format != (char *) NULL)
00957     p->format=DestroyString(p->format);
00958   if (p->metrics != (char *) NULL)
00959     p->metrics=DestroyString(p->metrics);
00960   if (p->glyphs != (char *) NULL)
00961     p->glyphs=DestroyString(p->glyphs);
00962   return(RelinquishMagickMemory(p));
00963 }
00964 
00965 static MagickBooleanType LoadTypeList(const char *xml,const char *filename,
00966   const unsigned long depth,ExceptionInfo *exception)
00967 {
00968   char
00969     font_path[MaxTextExtent],
00970     keyword[MaxTextExtent],
00971     *token;
00972 
00973   const char
00974     *q;
00975 
00976   MagickBooleanType
00977     status;
00978 
00979   TypeInfo
00980     *type_info;
00981 
00982   /*
00983     Load the type map file.
00984   */
00985   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00986     "Loading type configure file \"%s\" ...",filename);
00987   if (xml == (const char *) NULL)
00988     return(MagickFalse);
00989   if (type_list == (SplayTreeInfo *) NULL)
00990     {
00991       type_list=NewSplayTree(CompareSplayTreeString,(void *(*)(void *)) NULL,
00992         DestroyTypeNode);
00993       if (type_list == (SplayTreeInfo *) NULL)
00994         {
00995           ThrowFileException(exception,ResourceLimitError,
00996             "MemoryAllocationFailed",filename);
00997           return(MagickFalse);
00998         }
00999     }
01000   status=MagickTrue;
01001   type_info=(TypeInfo *) NULL;
01002   token=AcquireString(xml);
01003 #if defined(__WINDOWS__)
01004   /*
01005     Determine the Ghostscript font path.
01006   */
01007   *font_path='\0';
01008   if (NTGhostscriptFonts(font_path,MaxTextExtent-2))
01009     (void) ConcatenateMagickString(font_path,DirectorySeparator,MaxTextExtent);
01010 #endif
01011   for (q=(char *) xml; *q != '\0'; )
01012   {
01013     /*
01014       Interpret XML.
01015     */
01016     GetMagickToken(q,&q,token);
01017     if (*token == '\0')
01018       break;
01019     (void) CopyMagickString(keyword,token,MaxTextExtent);
01020     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
01021       {
01022         /*
01023           Doctype element.
01024         */
01025         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
01026           GetMagickToken(q,&q,token);
01027         continue;
01028       }
01029     if (LocaleNCompare(keyword,"<!--",4) == 0)
01030       {
01031         /*
01032           Comment element.
01033         */
01034         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
01035           GetMagickToken(q,&q,token);
01036         continue;
01037       }
01038     if (LocaleCompare(keyword,"<include") == 0)
01039       {
01040         /*
01041           Include element.
01042         */
01043         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
01044         {
01045           (void) CopyMagickString(keyword,token,MaxTextExtent);
01046           GetMagickToken(q,&q,token);
01047           if (*token != '=')
01048             continue;
01049           GetMagickToken(q,&q,token);
01050           if (LocaleCompare(keyword,"file") == 0)
01051