src/VFlib.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. STRPARAM
  2. VF_Init
  3. VF_GetVersion
  4. VF_ClearError
  5. VF_InstallFontDriver
  6. VF_FontDriverList
  7. VF_OpenFont1
  8. vf_openfont1
  9. VF_OpenFont2
  10. vf_openfont2
  11. open_font
  12. do_open_font
  13. VF_CloseFont
  14. VF_GetMetric1
  15. VF_GetMetric2
  16. VF_GetFontBoundingBox1
  17. VF_GetFontBoundingBox2
  18. VF_GetBitmap1
  19. VF_GetBitmap2
  20. VF_GetOutline
  21. VF_GetFontProp
  22. VF_QueryFontType
  23. id2font
  24. VF_DumpFontTable

   1 /*
   2  * VFlib.c - a main file for VFlib 
   3  *
   4  * Programmed by Hirotsugu Kakugawa
   5  *
   6  *  5 Mar 1997  VFlib 3.1.4
   7  * 20 Mar 1997  VFlib 3.1.5
   8  * 22 Mar 1997  VFlib 3.2
   9  *  1 Oct 1997  VFlib 3.2.6  Changed encoding & charset conversion module.
  10  *  4 Aug 1997  VFlib 3.3    Changed API.
  11  *  9 Jan 1998  VFlib 3.4    Changed vflibcap syntax. 
  12  * 17 Sep 1999  VFlib 3.6
  13  * 18 Oct 2001     Fixed memory leak.
  14  */
  15 
  16 /*
  17  * Copyright (C) 1996-2001 Hirotsugu Kakugawa. 
  18  * All rights reserved.
  19  *
  20  * This file is part of the VFlib Library.  This library is free
  21  * software; you can redistribute it and/or modify it under the terms of
  22  * the GNU Library General Public License as published by the Free
  23  * Software Foundation; either version 2 of the License, or (at your
  24  * option) any later version.  This library is distributed in the hope
  25  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  26  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  27  * PURPOSE.  See the GNU Library General Public License for more details.
  28  * You should have received a copy of the GNU Library General Public
  29  * License along with this library; if not, write to the Free Software
  30  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  31  */
  32 
  33 #include  "config.h"
  34 #include  <stdio.h>
  35 #include  <stdlib.h>
  36 #ifdef HAVE_UNISTD_H
  37 #  include <unistd.h>
  38 #endif
  39 #include  <ctype.h>
  40 #include  "VFlib-3_6.h"
  41 #include  "VFsys.h"
  42 #include  "consts.h"
  43 #include  "vflpaths.h"
  44 #include  "params.h"
  45 #include  "vflibcap.h"
  46 #include  "str.h"
  47 #include  "sexp.h"
  48 #include  "metric.h"
  49 #include  "bitmap.h"
  50 #include  "cache.h"
  51 #include  "ccv.h"
  52 
  53 
  54 Public int        vf_error;
  55 
  56 
  57 Private int       vf_initialized = 0;
  58 Private int       open_nesting = 0;
  59 
  60 Private VF_TABLE  font_class_table = NULL;
  61 Private VF_TABLE  font_id_table = NULL;
  62 
  63 struct s_font_class {
  64   char*    class_name;
  65   int      (*driver_entry)(VF_FONT,char*,char*,int,void*);
  66 };
  67 typedef struct s_font_class  *FONT_CLASS;
  68 
  69 Glocal int  vf_dbg_font_open    = 0;
  70 Glocal int  vf_dbg_font_search  = 0;
  71 Glocal int  vf_dbg_kpathsea     = 0;
  72 Glocal int  vf_dbg_vfcap        = 0;
  73 Glocal int  vf_dbg_parameters   = 0;
  74 Glocal int  vf_dbg_ccv          = 0;
  75 Glocal int  vf_dbg_ccv_map      = 0;
  76 Glocal int  vf_dbg_log          = 0;
  77 Glocal FILE*vf_dbg_log_fp       = NULL;
  78 #define     DEBUG_LOG_FILE      "__dbg.tmp"
  79 
  80 struct s_open_arg_pack1 {
  81   double  dpi_x, dpi_y;
  82   double  point_size;
  83   double  mag_x, mag_y;
  84 };
  85 struct s_open_arg_pack2 {
  86   int     pixel_size;
  87   double  mag_x, mag_y;
  88 };
  89 
  90 Private int  open_font(char *font_name, char *requested_font_class,
  91                        struct s_open_arg_pack1 *arg_mode1, 
  92                        struct s_open_arg_pack2 *arg_mode2);
  93 
  94 Private int  do_open_font(char *font_class_spec, 
  95                           char* font_name, int implicit, int mode, 
  96                           char *cache_key,
  97                           VF_FONT font);
  98 
  99 Private VF_FONT  id2font(int);
 100 
 101 extern int  vf_drv_init(void);
 102 
 103 #define STRPARAM(s)    if ((s) != NULL){ fprintf(vf_dbg_log_fp, "\"%s\"", s); \
     /* [<][>][^][v][top][bottom][index][help] */
 104                        } else { fprintf(vf_dbg_log_fp, "NULL"); }
 105 
 106 
 107 
 108 
 109 /**
 110  **   VF_Init
 111  **/
 112 Public int
 113 VF_Init(char *vflibcap_path, char *parameters)
     /* [<][>][^][v][top][bottom][index][help] */
 114 {
 115   if (vf_initialized != 0)
 116     return 0;
 117 
 118   vf_initialized  = 1;
 119   vf_error        = 0;
 120   open_nesting    = 0;
 121 
 122   /* Check Environment Variables for Debugging */
 123   if (getenv(VF_ENV_DEBUG_FONT_OPEN) != NULL)
 124     vf_dbg_font_open = 1;
 125   if (getenv(VF_ENV_DEBUG_FONT_SEARCH) != NULL)
 126     vf_dbg_font_search = 1;
 127   if (getenv(VF_ENV_DEBUG_KPATHSEA) != NULL)
 128     vf_dbg_kpathsea = 1;
 129   if (getenv(VF_ENV_DEBUG_VFLIBCAP) != NULL)
 130     vf_dbg_vfcap = 1;
 131   if (getenv(VF_ENV_DEBUG_PARAMETERS) != NULL)
 132     vf_dbg_parameters = 1;
 133   if (getenv(VF_ENV_DEBUG_CCV) != NULL)
 134     vf_dbg_ccv = 1;
 135   if (getenv(VF_ENV_DEBUG_CCV_MAPPING) != NULL)
 136     vf_dbg_ccv_map = 1;
 137 
 138   if (getenv(VF_ENV_DEBUG_LOG) != NULL){
 139     if ((vf_dbg_log = atoi(getenv(VF_ENV_DEBUG_LOG))) <= 0)
 140       vf_dbg_log = 1;
 141     if (vf_dbg_log > 1)
 142       vf_dbg_log_fp = fopen(DEBUG_LOG_FILE, "w");
 143     else
 144       vf_dbg_log_fp = stdout;
 145   }
 146 
 147   if (vf_dbg_log > 0){
 148     fprintf(vf_dbg_log_fp, "VF_Init(");
 149     STRPARAM(vflibcap_path);
 150     fprintf(vf_dbg_log_fp, ", ");
 151     STRPARAM(parameters);
 152     fprintf(vf_dbg_log_fp, ");\n");
 153   }
 154 
 155 
 156   /* Initialize File Stream Manager */
 157   if (vf_fm_init() < 0)
 158     return -1;
 159 
 160   /* Initialize 'vflibcap' Database System */
 161   if (vf_cap_init(vflibcap_path) < 0)
 162     return -1;
 163 
 164   /* set parameters (variable values for vflibcap) */
 165   if (vf_params_init(parameters) < 0)
 166     return -1;
 167 
 168   /* Initialize Code Conversion Module */
 169   vf_ccv_init();
 170 
 171   /* Create a Table for Opened Font Table */
 172   if (vf_defaults_init() < 0)
 173     return -1;
 174 
 175   /* Create a Table for Opened Font Table */
 176   if ((font_id_table = vf_table_create()) == NULL){
 177     vf_error = VF_ERR_NO_MEMORY;
 178     return -1;
 179   }
 180 
 181   /* Create a Table for Font Drivers */
 182   if ((font_class_table = vf_table_create()) == NULL){
 183     vf_error = VF_ERR_NO_MEMORY;
 184     return -1;
 185   }
 186 
 187   /* Call Initializer of Each Font Module (Install of Font Drivers) */ 
 188   vf_drv_init();
 189 
 190   return 0;
 191 }
 192 
 193 
 194 /**
 195  **   VF_Version
 196  **/
 197 Public char*
 198 VF_GetVersion(void)
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200   return VFLIB_VERSION;
 201 }
 202 
 203 
 204 /**
 205  **   VF_ClearError
 206  **/
 207 Public void
 208 VF_ClearError(void)
     /* [<][>][^][v][top][bottom][index][help] */
 209 {
 210   vf_error = 0;
 211 }
 212 
 213 
 214 /**
 215  **   VF_InstallFontDriver
 216  **/
 217 Public int
 218 VF_InstallFontDriver(char *class_name,
     /* [<][>][^][v][top][bottom][index][help] */
 219                      int(*driver_entry)(VF_FONT,char*,char*,int,void*))
 220 {
 221   int         id;
 222   FONT_CLASS  fclass;
 223 
 224   vf_error = 0;
 225 
 226 #if 0
 227   printf("** New font class: %s\n", class_name); 
 228 #endif
 229 
 230   /* Check if a driver of the same name is installed or not. */
 231   if ((font_class_table->get_obj_by_key)(font_class_table, class_name, 
 232                                          strlen(class_name)+1) != NULL){
 233     vf_error = VF_ERR_USED_CLASS_NAME;
 234     return -1;
 235   }
 236 
 237   /* Create font class object. */
 238   ALLOC_IF_ERR(fclass, struct s_font_class){
 239     vf_error = VF_ERR_NO_MEMORY;
 240     return -1;
 241   }
 242   if ((fclass->class_name = vf_strdup(class_name)) == NULL){
 243     vf_error = VF_ERR_NO_MEMORY;
 244     vf_free(fclass);
 245     return -1;
 246   }
 247   fclass->driver_entry = driver_entry;
 248 
 249   /* Install font class object to font driver table. */
 250   if ((id = (font_class_table->put)(font_class_table, fclass, 
 251                                     class_name, strlen(class_name)+1)) < 0){
 252     vf_error = VF_ERR_NO_MEMORY;
 253     vf_free(fclass->class_name);
 254     vf_free(fclass);
 255     return -1;
 256   }
 257 
 258   return id;
 259 }
 260 
 261 
 262 /**
 263  **   VF_FontDriverList
 264  **/
 265 Public char**
 266 VF_FontDriverList(void)
     /* [<][>][^][v][top][bottom][index][help] */
 267 {
 268   int        n, i, j;
 269   char       **drv_list;
 270   FONT_CLASS fclass;
 271 
 272   vf_error = 0;
 273 
 274   /* Obtain the number of installed font drivers. */
 275   n = (font_class_table->get_nelements)(font_class_table);
 276 
 277   ALLOCN_IF_ERR(drv_list, char*, n+1){
 278     vf_error = VF_ERR_NO_MEMORY;
 279     return NULL;
 280   }
 281   
 282   j = 0;
 283   for (i = 0; j < n; i++){
 284     fclass 
 285       = (FONT_CLASS)(font_class_table->get_obj_by_id)(font_class_table, i);
 286     if (fclass == NULL)
 287       continue;
 288     if ((drv_list[j] = vf_strdup(fclass->class_name)) == NULL){
 289       vf_error = VF_ERR_NO_MEMORY;
 290       for (j--; j >= 0; j--)
 291         vf_free(drv_list[j]);
 292       vf_free(drv_list);
 293       return NULL;
 294     }
 295     j++;
 296   }
 297   drv_list[j] = NULL;
 298 
 299   return drv_list;
 300 }
 301 
 302 
 303 /**
 304  **   VF_OpenFont1
 305  **/
 306 Public int
 307 VF_OpenFont1(char *font_name,
     /* [<][>][^][v][top][bottom][index][help] */
 308              double dpi_x, double dpi_y, double point_size, 
 309              double mag_x, double mag_y)
 310 {
 311   if (vf_dbg_font_open == 1){
 312     printf(">>Font Open: VF_OpenFont1(%s, %.2f, %.2f, %.2f, %.3f, %.3f);\n",
 313            font_name, dpi_x, dpi_y, point_size, mag_x, mag_y);
 314   }
 315 
 316   if (vf_dbg_log > 0){
 317     if (vf_dbg_log > 1)
 318       fprintf(vf_dbg_log_fp, "VF_OpenFont1(\"%s\", %f, %f, %f, %f, %f);\n", 
 319               font_name, dpi_x, dpi_y, point_size, mag_x, mag_y);
 320     else
 321       fprintf(vf_dbg_log_fp, "VF_OpenFont1(\"%s\", %f, %f, %f, %f, %f);\n", 
 322               font_name, dpi_x, dpi_y, point_size, mag_x, mag_y);
 323   }
 324 
 325   return  vf_openfont1(font_name, NULL, 
 326                        dpi_x, dpi_y, point_size, mag_x, mag_y);
 327 }
 328 
 329 Glocal int
 330 vf_openfont1(char *font_name,
     /* [<][>][^][v][top][bottom][index][help] */
 331              char *requested_font_class, 
 332              double dpi_x, double dpi_y, double point_size, 
 333              double mag_x, double mag_y)
 334 {
 335   struct s_open_arg_pack1  arg1;
 336   
 337   vf_error = 0;
 338 
 339   /* Pack argments */
 340   arg1.dpi_x = dpi_x;
 341   arg1.dpi_y = dpi_y;
 342   arg1.point_size = point_size;
 343   arg1.mag_x = mag_x;
 344   arg1.mag_y = mag_y;
 345 
 346   return open_font(font_name, requested_font_class, &arg1, NULL);
 347 }
 348 
 349 
 350 /**
 351  **   VF_OpenFont2
 352  **/
 353 Public int
 354 VF_OpenFont2(char *font_name,
     /* [<][>][^][v][top][bottom][index][help] */
 355              int pixel_size, 
 356              double mag_x, double mag_y)
 357 {
 358   if (vf_dbg_font_open == 1){
 359     printf(">>Font Open: VF_OpenFont2(\"%s\", %d, %.3f, %.3f);\n",
 360            font_name, pixel_size, mag_x, mag_y);
 361   }
 362 
 363   if (vf_dbg_log > 0){
 364     fprintf(vf_dbg_log_fp, "VF_OpenFont2(\"%s\", %d, %f, %f);\n", 
 365             font_name, pixel_size, mag_x, mag_y);
 366   }
 367 
 368   return  vf_openfont2(font_name, NULL, 
 369                        pixel_size, mag_x, mag_y);
 370 }
 371 
 372 Glocal int
 373 vf_openfont2(char *font_name,
     /* [<][>][^][v][top][bottom][index][help] */
 374              char *requested_font_class, 
 375              int pixel_size, 
 376              double mag_x, double mag_y)
 377 {
 378   struct s_open_arg_pack2  arg2;
 379   
 380   vf_error = 0;
 381 
 382   /* Pack argments */
 383   arg2.pixel_size = pixel_size;
 384   arg2.mag_x = mag_x;
 385   arg2.mag_y = mag_y;
 386 
 387   return open_font(font_name, requested_font_class, NULL, &arg2);
 388 }
 389 
 390 
 391 
 392 Private int
 393 open_font(char *font_name,
     /* [<][>][^][v][top][bottom][index][help] */
 394           char *requested_font_class, 
 395           struct s_open_arg_pack1 *arg_mode1, 
 396           struct s_open_arg_pack2 *arg_mode2)
 397 {
 398   VF_FONT  font = NULL;
 399   int      font_id, mode;
 400   char     *class, *ext, key[1024];
 401   SEXP_ALIST  exh;
 402   SEXP_LIST   ife, pair;
 403 
 404   font = NULL;
 405 
 406   /* Check nesting of font opens. */
 407   open_nesting++;
 408   if (open_nesting > VF_MAX_OPEN_NESTING){
 409     fprintf(stderr, "VFlib: too many nesting levels for font open.\n"); 
 410     vf_error = VF_ERR_OPEN_NESTING;
 411     goto Error;
 412   }
 413 
 414   /* Check if the same font is opened. */
 415   if (arg_mode1 != NULL){          /* mode 1: high-resolution oriented mode */
 416     mode = 1;
 417     sprintf(key, "<%s,%d,%s,%d,%d,%d,%d,%d>", 
 418             (requested_font_class != NULL) ? requested_font_class : "_",
 419             mode, font_name,
 420             toint(arg_mode1->dpi_x*100), toint(arg_mode1->dpi_y*100),
 421             toint(arg_mode1->point_size*100),
 422             toint(arg_mode1->mag_x*100), toint(arg_mode1->mag_y*100));
 423   } else if (arg_mode2 != NULL){   /* mode 2: low-resolution oriented mode */
 424     mode = 2;
 425     sprintf(key, "<%s,%d,%s,%d,%d,%d>", 
 426             (requested_font_class != NULL) ? requested_font_class : "_",
 427             mode, font_name,
 428             arg_mode2->pixel_size,
 429             toint(arg_mode2->mag_x*100), toint(arg_mode2->mag_y*100));
 430   } else {
 431     fprintf(stderr, "VFlib internal error: Cannot happen in %s\n", 
 432             "open_font()");
 433     abort();
 434   }
 435   font_id = (font_id_table->get_id_by_key)(font_id_table, 
 436                                            key, strlen(key)+1);
 437   if (font_id >= 0){ 
 438     /* Share the same font object. */
 439     (font_id_table->link_by_id)(font_id_table, font_id);
 440     goto Found;
 441   }
 442 
 443   /* Make a skeleton font object. */
 444   ALLOC_IF_ERR(font, struct vf_s_font){
 445     vf_error = VF_ERR_NO_MEMORY;
 446     goto Error;
 447   }
 448   if (mode == 1){
 449     font->font_name  = NULL;
 450     font->mode       = 1;
 451     font->point_size = arg_mode1->point_size;
 452     font->pixel_size = -1;
 453     font->mag_x      = arg_mode1->mag_x;
 454     font->mag_y      = arg_mode1->mag_y;
 455     font->dpi_x      = arg_mode1->dpi_x;
 456     font->dpi_y      = arg_mode1->dpi_y;
 457   } else if (mode == 2){
 458     font->mode       = 2;
 459     font->point_size = -1;
 460     font->pixel_size = arg_mode2->pixel_size;
 461     font->mag_x      = arg_mode2->mag_x;
 462     font->mag_y      = arg_mode2->mag_y;
 463     font->dpi_x      = -1;
 464     font->dpi_y      = -1;
 465   } else {
 466     fprintf(stderr, "VFlib internal error: Cannot happen in %s\n", 
 467             "open_font()");
 468     abort();
 469   }
 470 
 471   font->font_type       = 0;
 472   font->get_metric1     = NULL;
 473   font->get_metric2     = NULL;
 474   font->get_fontbbx1    = NULL;
 475   font->get_fontbbx2    = NULL;
 476   font->get_bitmap1     = NULL;
 477   font->get_bitmap2     = NULL;
 478   font->get_outline     = NULL;
 479   font->get_font_prop   = NULL;
 480   font->query_font_type = NULL;
 481   font->close           = NULL;
 482 
 483   /* If 'requested_font_class' is given, we open a font by calling the 
 484      corresponding font driver directly. */
 485   if (requested_font_class != NULL){
 486     /* try to open as an explicit font */
 487     if ((font_id = do_open_font(requested_font_class, 
 488                                 font_name, 0, mode, key, font)) >= 0)
 489       goto Found;
 490     if (vf_error != VF_ERR_NO_FONT_ENTRY)
 491       goto Error;
 492     /* try to open as an implicit font */
 493     vf_error = 0;
 494     if ((font_id = do_open_font(requested_font_class, 
 495                                 font_name, 1, mode, key, font)) >= 0)
 496       goto Found;
 497     goto Error;
 498   }
 499 
 500   /* Try to open as an explicit font. */
 501   if (vf_dbg_font_open == 1)
 502     printf(">>Font Open: Try to open an explicit font %s.\n", font_name);
 503   font_id = do_open_font(NULL, font_name, 0, mode, key, font);
 504   if (font_id >= 0)      /* Opened as an explicit font. */
 505     goto Found;
 506 
 507   /* If it is not an explicit font, clear error code and try to
 508      open as an implicit font. */
 509   if (vf_error != VF_ERR_NO_FONT_ENTRY)
 510     goto Error;
 511 
 512   /* Search an implicit font. */
 513   if (vf_dbg_font_open == 1)
 514     printf(">>Font Open: Try to open an implicit font %s.\n", font_name);
 515 
 516   /* First, try to make use of extension hint. */
 517   for (exh = vf_extension_hints; vf_sexp_consp(exh); exh = vf_sexp_cdr(exh)){
 518     pair = vf_sexp_car(exh);
 519     if (!vf_sexp_consp(pair) 
 520         || ((ext = vf_sexp_get_cstring(vf_sexp_car(pair))) == NULL)
 521         || ((class = vf_sexp_get_cstring(vf_sexp_cadr(pair))) == NULL))
 522       continue;
 523     if (strlen(font_name) > strlen(ext)){
 524       if (strcmp(ext, &font_name[strlen(font_name)-strlen(ext)]) == 0){
 525         if (vf_dbg_font_open == 1)
 526           printf(">>Font Open: Try font class '%s' by hint '%s'\n", 
 527                  class, ext);
 528         vf_error = 0;
 529         font_id = do_open_font(class, font_name, 1, mode, key, font);
 530         if (font_id >= 0)    /* Font is found. */
 531           goto Found;
 532       }     
 533     }
 534   }
 535   if (vf_dbg_font_open == 1)
 536     printf(">>Extension hint does not work. Try other classes.\n");
 537 
 538   /* Next, try other implict classes not in extension hints. */
 539   ife = NULL;
 540   for (ife = vf_implicit_font_classes; 
 541        vf_sexp_consp(ife); 
 542        ife = vf_sexp_cdr(ife)){
 543     for (exh = vf_extension_hints; 
 544          vf_sexp_consp(exh);
 545          exh = vf_sexp_cdr(exh)){
 546       ext = vf_sexp_get_cstring(vf_sexp_caar(exh));
 547       if (strcmp(ext, vf_sexp_get_cstring(vf_sexp_car(ife))) == 0)
 548         break;       /* Skip this font class since it is checked already. */
 549     }
 550     if (vf_sexp_consp(exh))
 551       continue;
 552 
 553     if (vf_dbg_font_open == 1)
 554       printf(">>  ==> Trying %s\n", 
 555              vf_sexp_get_cstring(vf_sexp_car(ife)));
 556     vf_error = 0;
 557     font_id = do_open_font(vf_sexp_get_cstring(vf_sexp_car(ife)),
 558                            font_name, 1, mode, key, font);
 559     if (font_id >= 0)     /* Font is found. */
 560       goto Found;
 561   }
 562 
 563   /* The font is not opened as an implicit font. Open error. */
 564   vf_error = VF_ERR_NO_FONT_IMP;
 565 Error:
 566   if (font != NULL)
 567     vf_free(font);
 568   if (vf_dbg_font_open == 1)
 569     printf(">>Font Open Failure: %s\n", font_name);
 570   open_nesting--;
 571   return -1;
 572 
 573 
 574   /* The font is opened. */
 575 Found:
 576   vf_error = 0;
 577   if (vf_dbg_font_open == 1)
 578     printf(">>Font Open Success: %s fid=%d\n", font_name, font_id);
 579   if ((font != NULL) && (font->font_name == NULL)){
 580     font->font_name = vf_strdup(font_name);
 581   }
 582   open_nesting--;
 583   return font_id;
 584 }
 585 
 586 Private int
 587 do_open_font(char *font_class_spec, 
     /* [<][>][^][v][top][bottom][index][help] */
 588              char *font_name, int implicit, int mode, 
 589              char *cache_key,
 590              VF_FONT font)
 591 {
 592   int           font_id, font_class_id;
 593   char         *class_name;
 594   SEXP          entry, s;
 595   FONT_CLASS    fclass;
 596 
 597   /* Obtain font class name. */
 598   if (implicit == 1){       /* open for implicit font. */
 599     entry = NULL;
 600     if ((class_name = font_class_spec) == NULL){
 601       vf_error = VF_ERR_CLASS_UNKNOWN;
 602       goto Error;
 603     }
 604   } else {                  /* open for explicit font. */
 605     if ((entry = vf_cap_GetFontEntry(font_name)) == 0){
 606       vf_error = VF_ERR_NO_FONT_ENTRY;
 607       goto Error;
 608     }
 609     class_name = NULL;
 610     for (s = vf_sexp_cddr(entry); vf_sexp_consp(s); s = vf_sexp_cdr(s)){
 611       if (strcmp(vf_sexp_get_cstring(vf_sexp_caar(s)), 
 612                  VF_CAPE_FONT_CLASS) == 0){
 613         if (vf_sexp_stringp(vf_sexp_car(vf_sexp_cdar(s))))
 614           class_name = vf_sexp_get_cstring(vf_sexp_car(vf_sexp_cdar(s)));
 615         break;
 616       }
 617     }
 618     if (class_name == NULL){
 619       vf_error = VF_ERR_CLASS_UNKNOWN;
 620       goto Error;
 621     }
 622     if ((font_class_spec != NULL) 
 623         && (strcmp(font_class_spec, class_name) != 0)){ 
 624       /* class name mismatch. */
 625       if (vf_dbg_font_open == 1)
 626         printf(">>%s: fontname: %s   requested class is %s but %s\n", 
 627                "Font Open: Font class name mismatch",
 628                font_name, font_class_spec, class_name);
 629       vf_error = VF_ERR_NO_FONT_ENTRY;
 630       goto Error;
 631     }
 632   }
 633 
 634   /* Get font class object for the font class. */
 635   if ((fclass 
 636        = (font_class_table->get_obj_by_key)(font_class_table, class_name,
 637                                             strlen(class_name)+1)) == NULL){
 638     if (vf_dbg_font_open == 1)
 639       printf(">>Font Open: Unknown font class '%s'\n", class_name);
 640     vf_error = VF_ERR_NO_FONT_CLASS;
 641     goto Error;
 642   }
 643   if (vf_dbg_font_open == 1)
 644     printf(">>Font Open: entry=%s class=%s\n", font_name, class_name);
 645 
 646   /* Get font class object id. */
 647   if ((font_class_id 
 648        = (font_class_table->get_id_by_key)(font_class_table, class_name,
 649                                            strlen(class_name)+1)) < 0){
 650     vf_error = VF_ERR_NO_FONT_CLASS;
 651     goto Error;
 652   }
 653   font->font_class = font_class_id;
 654 
 655   /* Call font open procedure in a font driver.
 656      For an implicit font, the driver searches a font. */
 657   if ((fclass->driver_entry)(font, class_name, 
 658                              font_name, implicit, entry) < 0){
 659     goto Error;
 660   }
 661 
 662   /* If a font is opened, install the font object. */
 663   if ((font_id = (font_id_table->put)(font_id_table, font, 
 664                                       cache_key, strlen(cache_key)+1)) < 0){
 665     vf_error = VF_ERR_NO_MEMORY;
 666     goto Error;
 667   }
 668 
 669   /* Font is Opened. */
 670   if (entry != NULL)
 671     vf_sexp_free(&entry);
 672   return font_id;
 673 
 674 
 675 Error:
 676   if (entry != NULL)
 677     vf_sexp_free(&entry);
 678   return -1;
 679 }
 680 
 681 
 682 /**
 683  **   VF_CloseFont
 684  **/
 685 Public int
 686 VF_CloseFont(int font_id)
     /* [<][>][^][v][top][bottom][index][help] */
 687 {
 688   VF_FONT  font;
 689   int   v;
 690 
 691   vf_error = 0;
 692 
 693   if (vf_dbg_log > 0){
 694     fprintf(vf_dbg_log_fp, "VF_CloseFont(%d);\n", font_id);
 695   }
 696 
 697   /* Obtain a font object for given font id. */ 
 698   if ((font = id2font(font_id)) == NULL)
 699     return -1;
 700 
 701   /* Discard cache */
 702   (void)id2font(-1);
 703 
 704   /* Unlink the font object. If link count is not zero, close is deferred. */
 705   if ((font_id_table->unlink_by_id)(font_id_table, font_id) >= 1)
 706     return 0;
 707 
 708   /* No one use the font object. Do close it. */
 709   v = (font->close)(font);
 710 
 711   vf_free(font->font_name);
 712   vf_free(font);
 713 
 714   return v;
 715 }
 716 
 717 
 718 /**
 719  **   VF_GetMetric1
 720  **/
 721 Public VF_METRIC1
 722 VF_GetMetric1(int font_id, long code_point, VF_METRIC1 metric1,
     /* [<][>][^][v][top][bottom][index][help] */
 723               double mag_x, double mag_y)
 724 {
 725   VF_FONT    font;
 726   VF_METRIC1 met1;
 727   int        val;
 728 
 729   vf_error = 0;
 730 
 731 
 732   /* Obtain a font object for given font id. */ 
 733   if ((font = id2font(font_id)) == NULL)
 734     return NULL;
 735 
 736   /* Check if this font is opened as mode 1. */
 737   if (font->mode != 1){
 738     vf_error = VF_ERR_ILL_MODE;
 739     return NULL;
 740   }
 741 
 742   /* Check if this operation is supported by a font driver. */ 
 743   if (font->get_metric1 == NULL){
 744     vf_error = VF_ERR_NOT_SUPPORTED_OP;
 745     return NULL;
 746   }
 747 
 748   /* Allocate metric object if not given. */
 749   if ((met1 = metric1) == NULL){
 750     if ((met1 = vf_alloc_metric1()) == NULL){
 751       vf_error = VF_ERR_NO_MEMORY;
 752       return NULL;
 753     }
 754   }
 755 
 756   /* Call a font driver's procedure. */
 757   val = (font->get_metric1)(font, code_point, met1, mag_x, mag_y);
 758   if (val < 0){
 759     if (metric1 == NULL)
 760       vf_free(met1);
 761     return NULL;
 762   }
 763   
 764   return met1;
 765 }
 766 
 767 /**
 768  **   VF_GetMetric2
 769  **/
 770 Public VF_METRIC2
 771 VF_GetMetric2(int font_id, long code_point, VF_METRIC2 metric2,
     /* [<][>][^][v][top][bottom][index][help] */
 772               double mag_x, double mag_y)
 773 {
 774   VF_FONT    font;
 775   VF_METRIC2 met2;
 776   int        val;
 777 
 778   vf_error = 0;
 779 
 780   /* Obtain a font object for given font id. */ 
 781   if ((font = id2font(font_id)) == NULL)
 782     return NULL;
 783 
 784   /* Check if this font is opened as mode 2. */
 785   if (font->mode != 2){
 786     vf_error = VF_ERR_ILL_MODE;
 787     return NULL;
 788   }
 789 
 790   /* Check if this operation is supported by a font driver. */ 
 791   if (font->get_metric1 == NULL){
 792     vf_error = VF_ERR_NOT_SUPPORTED_OP;
 793     return NULL;
 794   }
 795 
 796   /* Allocate metric object if not given. */
 797   if ((met2 = metric2) == NULL){
 798     if ((met2 = vf_alloc_metric2()) == NULL){
 799       vf_error = VF_ERR_NO_MEMORY;
 800       return NULL;
 801     }
 802   }
 803 
 804   /* Call a font driver's procedure. */
 805   val = (font->get_metric2)(font, code_point, met2, mag_x, mag_y);
 806   if (val < 0){
 807     if (metric2 == NULL)
 808       vf_free(met2);
 809     return NULL;
 810   }
 811   
 812   return met2;
 813 }
 814 
 815 /**
 816  **   VF_GetFontBoundingBox1
 817  **/
 818 Public int
 819 VF_GetFontBoundingBox1(int font_id, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 820                        double *width_p, double *height_p,
 821                        double *xoff_p, double *yoff_p)
 822 {
 823   VF_FONT   font;
 824   double    d1, d2, d3, d4;
 825 
 826   vf_error = 0;
 827 
 828   /* Obtain a font object for given font id. */ 
 829   if ((font = id2font(font_id)) == NULL)
 830     return -1;
 831 
 832   /* Check if this font is opened as mode 1. */
 833   if (font->mode != 1){
 834     vf_error = VF_ERR_ILL_MODE;
 835     return -1;
 836   }
 837 
 838   /* Check if this operation is supported by a font driver. */ 
 839   if (font->get_fontbbx1 == NULL){
 840     vf_error = VF_ERR_NOT_SUPPORTED_OP;
 841     return -1;
 842   }
 843 
 844   if (width_p == NULL)
 845     width_p = &d1;
 846   if (height_p == NULL)
 847     height_p = &d2;
 848   if (xoff_p == NULL)
 849     xoff_p = &d3;
 850   if (yoff_p == NULL)
 851     yoff_p = &d4;
 852   *width_p = *height_p = *xoff_p = *yoff_p = 0;
 853 
 854   /* Call a font driver's procedure. */
 855   return (font->get_fontbbx1)(font, mag_x, mag_y,
 856                               width_p, height_p, xoff_p, yoff_p);
 857 }
 858 
 859 /**
 860  **   VF_GetFontBoundingBox2
 861  **/
 862 Public int
 863 VF_GetFontBoundingBox2(int font_id, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 864                        int *width_p, int *height_p,
 865                        int *xoff_p, int *yoff_p)
 866 {
 867   VF_FONT   font;
 868   int    d1, d2, d3, d4;
 869 
 870   vf_error = 0;
 871 
 872   /* Obtain a font object for given font id. */ 
 873   if ((font = id2font(font_id)) == NULL)
 874     return -1;
 875 
 876   /* Check if this font is opened as mode 2. */
 877   if (font->mode != 2){
 878     vf_error = VF_ERR_ILL_MODE;
 879     return -1;
 880   }
 881 
 882   /* Check if this operation is supported by a font driver. */ 
 883   if (font->get_fontbbx2 == NULL){
 884     vf_error = VF_ERR_NOT_SUPPORTED_OP;
 885     return -1;
 886   }
 887 
 888   if (width_p == NULL)
 889     width_p = &d1;
 890   if (height_p == NULL)
 891     height_p = &d2;
 892   if (xoff_p == NULL)
 893     xoff_p = &d3;
 894   if (yoff_p == NULL)
 895     yoff_p = &d4;
 896   *width_p = *height_p = *xoff_p = *yoff_p = 0;
 897 
 898   /* Call a font driver's procedure. */
 899   return (font->get_fontbbx2)(font, mag_x, mag_y,
 900                               width_p, height_p, xoff_p, yoff_p);
 901 }
 902 
 903 
 904 /**
 905  ** VF_GetBitmap1
 906  **/
 907 Public VF_BITMAP
 908 VF_GetBitmap1(int font_id, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 909               double mag_x, double mag_y)
 910 {
 911   VF_FONT   font;
 912 
 913   vf_error = 0;
 914 
 915   if (vf_dbg_log > 0){
 916     if (vf_dbg_log > 1)
 917       fprintf(vf_dbg_log_fp, 
 918               "VF_DumpBitmap(VF_GetBitmap1(%d, 0x%lx, %f, %f));\n",
 919               font_id, code_point, mag_x, mag_y);
 920     else 
 921       fprintf(vf_dbg_log_fp, "VF_GetBitmap1(%d, 0x%lx, %f, %f);\n",
 922               font_id, code_point, mag_x, mag_y);
 923   }
 924 
 925   /* Obtain a font object for given font id. */ 
 926   if ((font = id2font(font_id)) == NULL)
 927     return NULL;
 928 
 929   /* Check if this font is opened as mode 1. */
 930   if (font->mode != 1){
 931     vf_error = VF_ERR_ILL_MODE;
 932     return NULL;
 933   }
 934 
 935   /* Check if this operation is supported by a font driver. */ 
 936   if (font->get_bitmap1 == NULL){
 937     vf_error = VF_ERR_NOT_SUPPORTED_OP;
 938     return NULL;
 939   }
 940 
 941   /* Call a font driver's procedure. */
 942   return (font->get_bitmap1)(font, code_point, mag_x, mag_y);
 943 }
 944 
 945 
 946 /**
 947  **   VF_GetBitmap2
 948  **/
 949 Public VF_BITMAP
 950 VF_GetBitmap2(int font_id, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 951               double mag_x, double mag_y)
 952 {
 953   VF_FONT   font;
 954 
 955   vf_error = 0;
 956 
 957   if (vf_dbg_log > 0){
 958     if (vf_dbg_log > 1)
 959       fprintf(vf_dbg_log_fp, 
 960               "VF_DumpBitmap(VF_GetBitmap2(%d, 0x%lx, %f, %f));\n",
 961               font_id, code_point, mag_x, mag_y);
 962     else 
 963       fprintf(vf_dbg_log_fp, "VF_GetBitmap2(%d, 0x%lx, %f, %f);\n",
 964               font_id, code_point, mag_x, mag_y);
 965   }
 966 
 967   /* Obtain a font object for given font id. */ 
 968   if ((font = id2font(font_id)) == NULL)
 969     return NULL;
 970 
 971   /* Check if this font is opened as mode 2. */
 972   if (font->mode != 2){
 973     vf_error = VF_ERR_ILL_MODE;
 974     return NULL;
 975   }
 976 
 977   /* Check if this operation is supported by a font driver. */ 
 978   if (font->get_bitmap2 == NULL){
 979     vf_error = VF_ERR_NOT_SUPPORTED_OP;
 980     return NULL;
 981   }
 982 
 983   /* Call a font driver's procedure. */
 984   return (font->get_bitmap2)(font, code_point, mag_x, mag_y);
 985 }
 986 
 987 
 988 /**
 989  **   VF_GetOutline
 990  **/
 991 Public VF_OUTLINE
 992 VF_GetOutline(int font_id, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 993               double mag_x, double mag_y)
 994 {
 995   VF_FONT  font;
 996 
 997   vf_error = 0;
 998 
 999   /* Obtain a font object for given font id. */ 
1000   if ((font = id2font(font_id)) == NULL)
1001     return NULL;
1002 
1003   /* Check if this font is opened as mode 1. */
1004   if (font->mode != 1){
1005     vf_error = VF_ERR_ILL_MODE;
1006     return NULL;
1007   }
1008 
1009   /* Check if this operation is supported by a font driver. */ 
1010   if (font->get_outline == NULL){
1011     vf_error = VF_ERR_NOT_SUPPORTED_OP;
1012     return NULL;
1013   }
1014 
1015   /* Call a font driver's procedure. */
1016   return (font->get_outline)(font, code_point, mag_x, mag_y);
1017 }
1018 
1019 
1020 /**
1021  **   VF_GetFontProp
1022  **/
1023 Public char*
1024 VF_GetFontProp(int font_id, char *prop_name)
     /* [<][>][^][v][top][bottom][index][help] */
1025 {
1026   VF_FONT  font;
1027 
1028   vf_error = 0;
1029 
1030   /* Obtain a font object for given font id. */ 
1031   if ((font = id2font(font_id)) == NULL)
1032     return NULL;
1033 
1034   /* Check if this operation is supported by a font driver. */ 
1035   if (font->get_font_prop == NULL){
1036     vf_error = VF_ERR_NOT_SUPPORTED_OP;
1037     return NULL;
1038   }
1039 
1040   /* Call a font driver's procedure. */
1041   return (font->get_font_prop)(font, prop_name);
1042 }
1043 
1044 
1045 /**
1046  **   VF_QueryFontType
1047  **/
1048 Public int
1049 VF_QueryFontType(int font_id, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
1050 {
1051   VF_FONT  font;
1052 
1053   vf_error = 0;
1054 
1055   /* Obtain a font object for given font id. */ 
1056   if ((font = id2font(font_id)) == NULL)
1057     return -1;
1058 
1059   switch (font->font_type){
1060   case VF_FONT_TYPE_BITMAP:
1061   case VF_FONT_TYPE_OUTLINE:
1062     return font->font_type;
1063   default:
1064   case VF_FONT_TYPE_UNDEF:
1065     /* Check if this operation is supported by a font driver. */ 
1066     if (font->query_font_type == NULL){
1067       vf_error = VF_ERR_NOT_SUPPORTED_OP;
1068       return -1;
1069     }
1070     /* Call a font driver's procedure. */
1071     return (font->query_font_type)(font, code_point);
1072   }
1073 
1074   return -1;
1075 }
1076 
1077 
1078 
1079 /* font ID  ==>  font obj */
1080 
1081 Private VF_FONT
1082 id2font(int font_id)
     /* [<][>][^][v][top][bottom][index][help] */
1083 {
1084   VF_FONT           font;
1085   static VF_FONT    last_font    = NULL;  /* 1st cache */
1086   static int        last_font_id = -1;  
1087 
1088   if (font_id < 0){
1089     last_font    = NULL;
1090     last_font_id = -1;
1091     return NULL;
1092   }
1093 
1094   if ((font_id == last_font_id) && (last_font != NULL)
1095       && (last_font_id >= 0)){    /* 1st cache hits. */
1096     font = last_font;
1097   } else {                        /* use 2nd cache. */
1098     if ((font = (font_id_table->get_obj_by_id)(font_id_table, font_id))
1099         == NULL){
1100       vf_error = VF_ERR_ILL_FONTID;
1101       goto Error;
1102     }
1103     /* reload 1st cache. */
1104     last_font    = font;
1105     last_font_id = font_id;
1106   }
1107   return font;
1108 
1109 Error:
1110   /* discard 1st cache. */
1111   last_font    = NULL;
1112   last_font_id = -1;
1113   return NULL;
1114 }
1115 
1116 
1117 /* For Debugging Purpose Only */
1118 Public void
1119 VF_DumpFontTable(void)
     /* [<][>][^][v][top][bottom][index][help] */
1120 {
1121   VF_FONT    font;
1122   FONT_CLASS fc; 
1123   int        nfonts, r, i;
1124 
1125   nfonts = (font_id_table->get_nelements)(font_id_table);
1126 
1127   for (i = 0, r = nfonts; r > 0; i++){
1128     font = (font_id_table->get_obj_by_id)(font_id_table, i);
1129     if (font == NULL)
1130       continue;
1131     --r;
1132 
1133     fc = (FONT_CLASS)(font_class_table->get_obj_by_id)(font_class_table, 
1134                                                        font->font_class);
1135     printf("#% 3d: \"%s\"\n", i, font->font_name);
1136     printf("       font_class: %s, mode: %d\n", fc->class_name, font->mode);
1137     if (font->mode == 1)
1138       printf("       point size: %.3f, dpi_x: %.3f, dpi_y: %.3f\n",
1139              font->point_size, font->dpi_x, font->dpi_y);
1140     else
1141       printf("       point size: %.3f\n", font->point_size);
1142     printf("       max_x: %.3f, max_y: %.3f \n", font->mag_x, font->mag_y);
1143   }
1144 }
1145 
1146 /*EOF*/

/* [<][>][^][v][top][bottom][index][help] */