src/drv_gf.c

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

FUNCTIONS

This source file includes following functions.
  1. VF_Init_Driver_GF
  2. gf_create
  3. gf_close
  4. gf_get_metric1
  5. gf_get_fontbbx1
  6. gf_get_bitmap1
  7. gf_get_outline
  8. gf_get_metric2
  9. gf_get_fontbbx2
  10. gf_get_bitmap2
  11. gf_get_font_prop
  12. GF_Init
  13. GF_Open
  14. GF_Close
  15. GF_GetBitmap
  16. GF_GetMetric
  17. GF_GetFontBBX
  18. GF_GetGF
  19. GF_SetGFGlyph
  20. GF_GetGFGlyph
  21. debug_on

   1 /*
   2  * drv_gf.c - A font driver for TeX GF format fonts.
   3  *
   4  * 28 Sep 1996  First version.
   5  * 14 Dec 1996  for VFlib 3.1
   6  * 26 Feb 1997  Added 'query_font_type'.
   7  *  4 Aug 1997  VFlib 3.3  Changed API.
   8  * 30 Jan 1998  VFlib 3.4  Changed API.
   9  * 21 Apr 1998  Debugged get_font_prop().
  10  * 24 Nov 1998  Added get_fontbbx1() and get_fontbbx2().
  11  *  9 Dec 1998  Fixed bugs in get_fontbbx1() and get_fontbbx2().  (^o^;)
  12  * 16 Sep 1999  Changed not to use TFM files.
  13  * 18 Oct 2001  Fixed memory leak.
  14  */
  15 /*
  16  * Copyright (C) 1996-2001  Hirotsugu Kakugawa. 
  17  * All rights reserved.
  18  *
  19  * This file is part of the VFlib Library.  This library is free
  20  * software; you can redistribute it and/or modify it under the terms of
  21  * the GNU Library General Public License as published by the Free
  22  * Software Foundation; either version 2 of the License, or (at your
  23  * option) any later version.  This library is distributed in the hope
  24  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  25  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  26  * PURPOSE.  See the GNU Library General Public License for more details.
  27  * You should have received a copy of the GNU Library General Public
  28  * License along with this library; if not, write to the Free Software
  29  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  30  */
  31 
  32 /*
  33 
  34    (Suppose that default resolution is 300 dpi)
  35 
  36            ARGS FOR FONT OPEN                 BEHAVIOR of the DRIVER
  37  Case#  font_name device_dpi  mag       font_dpi dev_dpi bitmap_mag TFM_mag 
  38  ----------------------------------------------------------------------------
  39   1.    cmr10         -1      1            300    300        1        1 
  40   2.    cmr10         -1      1.2          360    300        1        1.2
  41   3.    cmr10        400      1            400    400        1        1
  42   4.    cmr10        400      1.2          480    400        1        1.2
  43   5.    cmr10.gf      -1      1            300    300        1        1
  44   6.    cmr10.gf      -1      1.2          360    300        1        1.2
  45   7.    cmr10.gf     400      1            400    400        1        1
  46   8.    cmr10.gf     400      1.2          480    400        1        1.2
  47   9.    cmr10.400gf   -1      1            400    400        1        1
  48  10.    cmr10.400gf   -1      1.2          480    400        1        1.2
  49  11.    cmr10.400gf  400      1            400    400        1        1
  50  12.    cmr10.400gf  400      1.2          400    400        1.2      1.2
  51  13.    cmr10.300gf  360      1            300    360        1.2      1
  52  14.    cmr10.300gf  360      1.2          300    360        1.44     1.2
  53 
  54  Font file is selected from the rules of the table shown above.
  55    a. A font file of 'font_dpi' dpi font and opened.
  56    b. Bitmaps of a font is scaled by 'bitmap_mag'.
  57    c. Font metrics are multiplied by 'TFM_mag'.
  58 
  59  Memo: 
  60   * Case 5:  We want a GF font file "cmr10" default device resolution.
  61         Thus, the bitmaps and metrics need not be scaled.
  62 
  63   * Case 6:  We want a GF font file "cmr10" default device resolution
  64         with maginication factor 1.2. Since default device resolution
  65         is 300 and magnification factor is 1.2, the font file we want
  66         is "cmr10.360gf". Since device resolution is 300, metrics
  67         must be scaled by 1.2.
  68 
  69   * Case 9:  This case requires a font "cmr10.400gf" and target device 
  70        is not considered. Thus bitmaps and metrics are not scaled.
  71 
  72   * Case 10: This case requires a font cmr10 for 400 dpi scaled by 1.2.
  73         Thus, "cmr10.480gf" is used for this request. 
  74         Since it is scaled by 1.2, font metrics are scaled by 1.2 but
  75         bitmaps in a font is not magnified.
  76 
  77   * Case 13: We want to use a GF font file "cmr10.300gf" for 360 dpi device. 
  78         Thus, the bitmaps of the font must be scaled by (360/300) = 1.2.
  79         Since the metrics in a TFM file are independent from device 
  80         resolution, metrics need not be scaled.
  81 
  82   * Case 14: We want to use a GF font file "cmr10.300gf" for 360 dpi device 
  83         and magnify it by 1.2. Thus, the bitmaps of the font must be scaled 
  84         by (1.2 x (360/300)) = 1.44.
  85         Since the metrics in a TFM file are independent from device 
  86         resolution, TFM metrics must be scaled by 1.2, which is a 
  87         magnification factor.
  88 */
  89 
  90 
  91 #include  "config.h"
  92 #include  "with.h"
  93 #include  <stdio.h>
  94 #include  <stdlib.h>
  95 #ifdef HAVE_UNISTD_H
  96 #  include <unistd.h>
  97 #endif
  98 #include  <ctype.h>
  99 
 100 #include  "VFlib-3_6.h"
 101 #include  "VFsys.h"
 102 #include  "vflibcap.h"
 103 #include  "cache.h"
 104 #include  "str.h"
 105 #include  "path.h"
 106 #include  "fsearch.h"
 107 #include  "sexp.h"
 108 #include  "texfonts.h"
 109 #include  "gf.h"
 110 
 111 
 112 struct s_font_gf {
 113   int      gf_id;
 114   char     *font_name;
 115   char     *font_file;
 116   double   point_size;
 117   double   pixel_size;
 118   double   mag;
 119   double   dpi_x, dpi_y;
 120   SEXP     props;
 121   double   extra_mag;
 122 };
 123 typedef struct s_font_gf  *FONT_GF;
 124 
 125 
 126 Private SEXP_LIST    default_fontdirs;
 127 Private SEXP_LIST    default_extensions;
 128 Private SEXP_STRING  default_point_size;
 129 Private double       v_default_point_size;
 130 Private SEXP_STRING  default_pixel_size;
 131 Private double       v_default_pixel_size;
 132 Private SEXP_STRING  default_dpi;
 133 Private double       v_default_dpi_x, v_default_dpi_y;
 134 Private SEXP_STRING  default_make_glyph;
 135 Private int          v_default_make_glyph = 0;
 136 Private SEXP_ALIST   default_properties;
 137 Private SEXP_ALIST   default_variables;
 138 Private SEXP_STRING  default_debug_mode;
 139 
 140 
 141 Private int         gf_create(VF_FONT,char*,char*,int,SEXP);
 142 Private int         gf_close(VF_FONT);
 143 Private int         gf_get_metric1(VF_FONT,long,VF_METRIC1,double,double);
 144 Private int         gf_get_metric2(VF_FONT,long,VF_METRIC2,double,double);
 145 Private int         gf_get_fontbbx1(VF_FONT,double,double,
 146                                     double*,double*,double*,double*);
 147 Private int         gf_get_fontbbx2(VF_FONT,double,double, 
 148                                     int*,int*,int*,int*);
 149 Private VF_BITMAP   gf_get_bitmap1(VF_FONT,long,double,double);
 150 Private VF_BITMAP   gf_get_bitmap2(VF_FONT,long,double,double);
 151 Private VF_OUTLINE  gf_get_outline(VF_FONT,long,double,double);
 152 Private char*       gf_get_font_prop(VF_FONT,char*);
 153 
 154 
 155 Private int         GF_Init(void);
 156 Private int         GF_Open(FONT_GF font_gf, VF_FONT font, int implicit);
 157 Private void        GF_Close(int gf_id);
 158 Private VF_BITMAP   GF_GetBitmap(int gf_id, long code_point);
 159 Private int         GF_GetMetric(int gf_id, long code_point, VF_METRIC1 me, 
 160                                  double *ret_dpi_x, double *ret_dpi_y, 
 161                                  double *ret_design_size);
 162 Private void        GF_GetFontBBX(int gf_id, int *bbx_w_p, int *bbx_h_p,
 163                                   int *bbx_xoff_p, int *bbx_yoff_p);
 164 Private int         debug_on(char type);
 165 
 166 
 167 
 168 
 169 Public int
 170 VF_Init_Driver_GF(void)
     /* [<][>][^][v][top][bottom][index][help] */
 171 {
 172   int  z;
 173   struct s_capability_table  ct[20];
 174 
 175   z = 0;
 176   /* VF_CAPE_FONT_DIRECTORIES */
 177   ct[z].cap = VF_CAPE_FONT_DIRECTORIES;     ct[z].type = CAPABILITY_LIST;
 178   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_fontdirs;
 179   /* VF_CAPE_EXTENSIONS */
 180   ct[z].cap = VF_CAPE_EXTENSIONS;           ct[z].type = CAPABILITY_LIST;
 181   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_extensions;
 182   /* VF_CAPE_POINT_SIZE */
 183   ct[z].cap = VF_CAPE_POINT_SIZE;           ct[z].type = CAPABILITY_STRING;
 184   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_point_size;
 185   /* VF_CAPE_PIXEL_SIZE */
 186   ct[z].cap = VF_CAPE_PIXEL_SIZE;           ct[z].type = CAPABILITY_STRING;
 187   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_pixel_size;
 188   /* VF_CAPE_DPI */
 189   ct[z].cap = VF_CAPE_DPI;                  ct[z].type = CAPABILITY_STRING;
 190   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_dpi;
 191   /* VF_CAPE_MAKE_MISSING_GLYPH */
 192   ct[z].cap = VF_CAPE_MAKE_MISSING_GLYPH;   ct[z].type = CAPABILITY_STRING;
 193   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_make_glyph;
 194   /* VF_CAPE_PROPERTIES */
 195   ct[z].cap = VF_CAPE_PROPERTIES;           ct[z].type = CAPABILITY_ALIST;
 196   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_properties;
 197   /* VF_CAPE_VARIABLE_VALUES */
 198   ct[z].cap = VF_CAPE_VARIABLE_VALUES;      ct[z].type = CAPABILITY_ALIST;
 199   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_variables;
 200   /* VF_CAPE_DEBUG */
 201   ct[z].cap = VF_CAPE_DEBUG;                ct[z].type = CAPABILITY_STRING;
 202   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_debug_mode;
 203   /* end */
 204   ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
 205 
 206   if (vf_tex_init() < 0)
 207     return -1;
 208 
 209   if (vf_cap_GetParsedClassDefault(FONTCLASS_NAME_GF, ct, 
 210                                    vf_tex_default_variables, NULL) 
 211       == VFLIBCAP_PARSED_ERROR)
 212     return -1;
 213 
 214   if (default_extensions == NULL)
 215     default_extensions = vf_sexp_cstring2list(DEFAULT_EXTENSIONS_GF);
 216 
 217   v_default_point_size = -1;
 218   if (default_point_size != NULL)
 219     v_default_point_size = atof(vf_sexp_get_cstring(default_point_size));
 220 
 221   v_default_pixel_size = -1;
 222   if (default_pixel_size != NULL)
 223     v_default_pixel_size = atof(vf_sexp_get_cstring(default_pixel_size));
 224 
 225   v_default_dpi_x  = -1;
 226   v_default_dpi_y  = -1;
 227   if (default_dpi != NULL)
 228     v_default_dpi_x = v_default_dpi_y = atof(vf_sexp_get_cstring(default_dpi));
 229 
 230   v_default_make_glyph = 0;
 231   if (default_make_glyph != NULL){
 232     v_default_make_glyph
 233       = vf_parse_bool(vf_sexp_get_cstring(default_make_glyph));
 234   }
 235 
 236   if (GF_Init() < 0)
 237     return -1;
 238 
 239   if ((v_default_dpi_x < 0) || (v_default_dpi_x < 0)){
 240     v_default_dpi_x = vf_tex_default_dpi();
 241     v_default_dpi_y = vf_tex_default_dpi();
 242   }
 243   
 244   VF_InstallFontDriver(FONTCLASS_NAME_GF, (DRIVER_FUNC_TYPE)gf_create);
 245 
 246   return 0;
 247 }
 248 
 249 
 250 Private int
 251 gf_create(VF_FONT font, char *font_class, 
     /* [<][>][^][v][top][bottom][index][help] */
 252           char *font_name, int implicit, SEXP entry)
 253 {
 254   FONT_GF   font_gf;
 255   SEXP      cap_ffile, cap_point, cap_pixel;
 256   SEXP      cap_dpi, cap_mag, cap_props;
 257   char      *font_file;
 258   int       val, gf_id;
 259   struct s_capability_table  ct[10];
 260   int z;
 261 
 262   z = 0;
 263   /* VF_CAPE_FONT_CLASS */
 264   ct[z].cap = VF_CAPE_FONT_CLASS;    ct[z].type = CAPABILITY_STRING;
 265   ct[z].ess = CAPABILITY_ESSENTIAL;  ct[z++].val = NULL;
 266   /* VF_CAPE_FONT_FILE */
 267   ct[z].cap = VF_CAPE_FONT_FILE;     ct[z].type = CAPABILITY_STRING;
 268   ct[z].ess = CAPABILITY_OPTIONAL;   ct[z++].val = &cap_ffile;
 269   /* VF_CAPE_POINT_SIZE */
 270   ct[z].cap = VF_CAPE_POINT_SIZE;    ct[z].type = CAPABILITY_STRING;
 271   ct[z].ess = CAPABILITY_OPTIONAL;   ct[z++].val = &cap_point;
 272   /* VF_CAPE_PIXEL_SIZE */
 273   ct[z].cap = VF_CAPE_PIXEL_SIZE;    ct[z].type = CAPABILITY_STRING;
 274   ct[z].ess = CAPABILITY_OPTIONAL;   ct[z++].val = &cap_pixel;
 275   /* VF_CAPE_DPI */
 276   ct[z].cap = VF_CAPE_DPI;           ct[z].type = CAPABILITY_STRING;
 277   ct[z].ess = CAPABILITY_OPTIONAL;   ct[z++].val = &cap_dpi;
 278   /* VF_CAPE_MAG */
 279   ct[z].cap = VF_CAPE_MAG;           ct[z].type = CAPABILITY_STRING;
 280   ct[z].ess = CAPABILITY_OPTIONAL;   ct[z++].val = &cap_mag;
 281   /* VF_CAPE_PROPERTIES */
 282   ct[z].cap = VF_CAPE_PROPERTIES;    ct[z].type = CAPABILITY_ALIST;
 283   ct[z].ess = CAPABILITY_OPTIONAL;   ct[z++].val = &cap_props;
 284   /* end */
 285   ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
 286 
 287   if (implicit == 1){   /* implicit font */
 288     font_file = font_name;
 289   } else {              /* explicit font */
 290     if (vf_cap_GetParsedFontEntry(entry, font_name, ct,
 291                                   default_variables, vf_tex_default_variables) 
 292         == VFLIBCAP_PARSED_ERROR)
 293       return -1;
 294     if (cap_ffile == NULL){
 295       /* Use font name as font file name if font file name is not given. */
 296       font_file = font_name;
 297     } else {
 298       font_file = vf_sexp_get_cstring(cap_ffile);
 299     }
 300   }
 301 
 302   font->font_type       = VF_FONT_TYPE_BITMAP;
 303   font->get_metric1     = gf_get_metric1;
 304   font->get_metric2     = gf_get_metric2;
 305   font->get_fontbbx1    = gf_get_fontbbx1;
 306   font->get_fontbbx2    = gf_get_fontbbx2;
 307   font->get_bitmap1     = gf_get_bitmap1;
 308   font->get_bitmap2     = gf_get_bitmap2;
 309   font->get_outline     = gf_get_outline;
 310   font->get_font_prop   = gf_get_font_prop;
 311   font->query_font_type = NULL;
 312   font->close           = gf_close;
 313 
 314   val = -1;
 315   font_gf = NULL;
 316 
 317   ALLOC_IF_ERR(font_gf, struct s_font_gf)
 318     goto NoMemoryError;
 319 
 320   font_gf->gf_id      = -1;
 321   font_gf->font_name  = NULL; 
 322   font_gf->font_file  = NULL; 
 323   font_gf->point_size = v_default_point_size;
 324   font_gf->pixel_size = v_default_pixel_size;
 325   font_gf->dpi_x      = v_default_dpi_x;
 326   font_gf->dpi_y      = v_default_dpi_y;
 327   font_gf->mag        = 1.0;
 328   font_gf->props      = NULL;
 329   font_gf->extra_mag  = 1.0;
 330 
 331   if (implicit == 0){
 332     if (cap_point != NULL)
 333       font_gf->point_size = atof(vf_sexp_get_cstring(cap_point));
 334     if (cap_pixel != NULL)
 335       font_gf->pixel_size = atof(vf_sexp_get_cstring(cap_pixel));
 336     if (cap_dpi != NULL)
 337       font_gf->dpi_x = font_gf->dpi_y = atof(vf_sexp_get_cstring(cap_dpi));
 338     if (cap_mag != NULL)
 339       font_gf->mag = atof(vf_sexp_get_cstring(cap_mag));
 340     if (cap_props != NULL)
 341       font_gf->props = cap_props;
 342   }
 343 
 344   if ((font_gf->font_file = vf_strdup(font_file)) == NULL)
 345     goto NoMemoryError;
 346   if ((font_gf->font_name = vf_strdup(font_name)) == NULL)
 347     goto NoMemoryError;
 348 
 349   if ((gf_id = GF_Open(font_gf, font, implicit)) < 0)
 350     goto Error;
 351 
 352   font_gf->gf_id = gf_id;
 353   font->private = font_gf;
 354 
 355   val = 0;
 356   goto End;
 357 
 358 
 359 NoMemoryError:
 360   vf_error = VF_ERR_NO_MEMORY;
 361 Error:
 362   if (font_gf != NULL){
 363     vf_free(font_gf->font_name);
 364     vf_free(font_gf->font_file);
 365   }
 366   if (implicit == 0)
 367     vf_sexp_free1(&cap_props);
 368   vf_free(font_gf); 
 369 
 370 End:
 371   if (implicit == 0){
 372     vf_sexp_free3(&cap_ffile, &cap_point, &cap_pixel);
 373     vf_sexp_free2(&cap_dpi, &cap_mag);
 374   }
 375 
 376   return val;
 377 }
 378 
 379 
 380 Private int
 381 gf_close(VF_FONT font)
     /* [<][>][^][v][top][bottom][index][help] */
 382 {
 383   FONT_GF  font_gf;
 384 
 385   font_gf = (FONT_GF)font->private;
 386   if (font_gf != NULL){
 387     GF_Close(font_gf->gf_id);
 388     vf_sexp_free1(&font_gf->props);
 389     vf_free(font_gf->font_name);
 390     vf_free(font_gf->font_file);
 391   }
 392   vf_free(font_gf);
 393 
 394   return 0; 
 395 }
 396 
 397 
 398 Private int
 399 gf_get_metric1(VF_FONT font, long code_point, VF_METRIC1 metric,
     /* [<][>][^][v][top][bottom][index][help] */
 400                double mag_x, double mag_y)
 401 {
 402   FONT_GF   font_gf;
 403   double    mx, my, ps, design_size;
 404 
 405   if (metric == NULL){
 406     fprintf(stderr, "VFlib internal error: in gf_get_metric1()\n");
 407     abort();
 408   }
 409   if ((font_gf = (FONT_GF)font->private) == NULL){
 410     fprintf(stderr, "VFlib internal error: in gf_get_metric1()\n");
 411     abort();
 412   }
 413 
 414   if (GF_GetMetric(font_gf->gf_id, code_point, metric, 
 415                    NULL, NULL, &design_size) < 0)
 416     return -1;
 417 
 418   if ((ps = font->point_size) < 0)
 419     if ((ps = font_gf->point_size) < 0)
 420       ps = -1;
 421 
 422   if ((ps < 0) || (design_size < 1.0e-3)){
 423     mx = mag_x * font->mag_x * font_gf->mag;
 424     my = mag_y * font->mag_y * font_gf->mag;
 425   } else {
 426     mx = mag_x * font->mag_x * font_gf->mag * (ps/design_size);
 427     my = mag_y * font->mag_y * font_gf->mag * (ps/design_size);
 428   }
 429 
 430   metric->bbx_width  *= mx;
 431   metric->bbx_height *= my;
 432   metric->off_x      *= mx;
 433   metric->off_y      *= my;
 434   metric->mv_x       *= mx;
 435   metric->mv_y       *= my;
 436 
 437   return 0;
 438 }
 439 
 440 Private int
 441 gf_get_fontbbx1(VF_FONT font, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 442                 double *w_p, double *h_p, double *xoff_p, double *yoff_p)
 443 {
 444   FONT_GF   font_gf;
 445   double    mx, my, ps, design_size, dpi_x, dpi_y;
 446   int       w, h, xoff, yoff;
 447 
 448   if ((font_gf = (FONT_GF)font->private) == NULL){
 449     fprintf(stderr, "VFlib internal error: in gf_get_fontbbx1()\n");
 450     abort();
 451   }
 452 
 453   if (GF_GetMetric(font_gf->gf_id, -1, NULL, 
 454                    &dpi_x, &dpi_y, &design_size) < 0)
 455     return -1;
 456 
 457   if ((ps = font->point_size) < 0)
 458     if ((ps = font_gf->point_size) < 0)
 459       ps = -1;
 460 
 461   if ((ps < 0) || (design_size < 1.0e-3)){
 462     mx = mag_x * font->mag_x * font_gf->mag;
 463     my = mag_y * font->mag_y * font_gf->mag;
 464   } else {
 465     mx = mag_x * font->mag_x * font_gf->mag * (ps/design_size);
 466     my = mag_y * font->mag_y * font_gf->mag * (ps/design_size);
 467   }
 468 
 469   GF_GetFontBBX(font_gf->gf_id, &w, &h, &xoff, &yoff);
 470 
 471 #if 0
 472   printf("*** %d %d %d %d   %.3f %.3f   %.3f %.3f\n",
 473          w, h, xoff, yoff, mx, my, dpi_x, dpi_y);
 474 #endif
 475 
 476   *w_p = mx * w * 72.27 / dpi_x;
 477   *h_p = my * h * 72.27 / dpi_y;
 478   *xoff_p = mx * xoff * 72.27 / dpi_x;
 479   *yoff_p = my * yoff * 72.27 / dpi_y;
 480 
 481   return 0;
 482 }
 483 
 484 Private VF_BITMAP
 485 gf_get_bitmap1(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 486                double mag_x, double mag_y)
 487 {
 488   VF_BITMAP  bm;
 489   FONT_GF    font_gf;
 490   double     mx, my, ps, design_size;
 491 
 492   if ((font_gf = (FONT_GF)font->private) == NULL){
 493     fprintf(stderr, "VFlib internal error in gf_get_bitmap1()\n");
 494     abort();
 495   }
 496 
 497   if ((bm = GF_GetBitmap(font_gf->gf_id, code_point)) == NULL)
 498     return NULL;
 499   /* 'bm' SHOULD NOT BE RELEASED. */
 500 
 501   if (GF_GetMetric(font_gf->gf_id, code_point, NULL, 
 502                    NULL, NULL, &design_size) < 0)
 503     return NULL;
 504 
 505   if ((ps = font->point_size) < 0)
 506     if ((ps = font_gf->point_size) < 0)
 507       ps = -1;
 508 
 509   if ((ps < 0) || (design_size < 1.0e-3)){
 510     /* Note: font->mag_x and font_gf->mag are already used to select 
 511        scaled glyph, e.g., cmr10.360gf for 300dpi with mag 1.2. */
 512     mx = font_gf->extra_mag * mag_x;
 513     my = font_gf->extra_mag * mag_y; 
 514   } else {
 515 #if 0
 516     m = font->mag_y * font_gf->mag;
 517     mx = font_gf->extra_mag * mag_x * m * (ps/design_size);
 518     my = font_gf->extra_mag * mag_y * m * (ps/design_size);
 519 #endif
 520     mx = font_gf->extra_mag * mag_x * (ps/design_size);
 521     my = font_gf->extra_mag * mag_y * (ps/design_size);
 522   }
 523 
 524   if (debug_on('m'))
 525     printf("VFlib GF: get_bitmap1: bitmap mag: %.4f %.4f\n", mx, my);
 526 
 527   return VF_MakeScaledBitmap(bm, mx, my);
 528 }
 529 
 530 Private VF_OUTLINE
 531 gf_get_outline(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 532                double mag_x, double mag_y)
 533 {
 534   VF_BITMAP   bm;
 535   VF_OUTLINE  ol;
 536   FONT_GF     font_gf;
 537   int         bbx_w, bbx_h;
 538   double      dpi_x, dpi_y, design_size;
 539 
 540   if ((font_gf = (FONT_GF)font->private) == NULL){
 541     fprintf(stderr, "VFlib internal error in gf_get_outline()\n");
 542     abort();
 543   }
 544 
 545   if ((bm = gf_get_bitmap1(font, code_point, mag_x, mag_y)) == NULL)
 546     return NULL;
 547   
 548   if (GF_GetMetric(font_gf->gf_id, code_point, NULL, 
 549                    &dpi_x, &dpi_y, &design_size) < 0){
 550     VF_FreeBitmap(bm);
 551     return NULL;
 552   }
 553 
 554   GF_GetFontBBX(font_gf->gf_id, &bbx_w, &bbx_h, NULL, NULL);
 555   ol = vf_bitmap_to_outline(bm, bbx_w, bbx_h,
 556                             dpi_x, dpi_y, design_size, 1.0, 1.0);
 557   VF_FreeBitmap(bm);
 558 
 559   return ol;
 560 }
 561 
 562 
 563 Private int
 564 gf_get_metric2(VF_FONT font, long code_point, VF_METRIC2 metric, 
     /* [<][>][^][v][top][bottom][index][help] */
 565                double mag_x, double mag_y)
 566 {
 567   VF_BITMAP  bm;
 568   FONT_GF    font_gf;
 569   double     mx, my, dpi_x, dpi_y, ps, design_size;
 570 
 571   if (   (metric == NULL)
 572       || ((font_gf = (FONT_GF)font->private) == NULL) ){
 573     fprintf(stderr, "VFlib internal error: in gf_get_metric2()\n");
 574     abort();
 575   }
 576 
 577   if ((bm = GF_GetBitmap(font_gf->gf_id, code_point)) == NULL)
 578     return -1;
 579   /* 'bm' SHOULD NOT BE RELEASED. */
 580 
 581   if (GF_GetMetric(font_gf->gf_id, code_point, NULL,
 582                    &dpi_x, &dpi_y, &design_size) < 0)
 583     return -1;
 584 
 585   if ((ps = font->pixel_size) < 0)
 586     if ((ps = font_gf->pixel_size) < 0)
 587       ps = -1;
 588 
 589   if ((ps < 0) || (design_size < 1.0e-3)){
 590     mx = font->mag_x * font_gf->mag * mag_x;
 591     my = font->mag_y * font_gf->mag * mag_y;
 592   } else {
 593     mx = font->mag_x * font_gf->mag * mag_x * (ps*72.27)/(design_size*dpi_x);
 594     my = font->mag_y * font_gf->mag * mag_y * (ps*72.27)/(design_size*dpi_y);
 595   }
 596 
 597   metric->bbx_width  = toint(mx * bm->bbx_width);
 598   metric->bbx_height = toint(my * bm->bbx_height);
 599   metric->off_x      = toint(mx * bm->off_x);
 600   metric->off_y      = toint(my * bm->off_y);
 601   metric->mv_x       = toint(mx * bm->mv_x);
 602   metric->mv_y       = toint(my * bm->mv_y);
 603 
 604   return 0;
 605 }
 606 
 607 Private int
 608 gf_get_fontbbx2(VF_FONT font, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 609                 int *w_p, int *h_p, int *xoff_p, int *yoff_p)
 610 {
 611   FONT_GF   font_gf;
 612   double    mx, my, dpi_x, dpi_y, ps, design_size;
 613 
 614   if ((font_gf = (FONT_GF)font->private) == NULL){
 615     fprintf(stderr, "VFlib internal error: in gf_get_fontbbx2()\n");
 616     abort();
 617   }
 618 
 619   if (GF_GetMetric(font_gf->gf_id, -1, NULL,
 620                    &dpi_x, &dpi_y, &design_size) < 0)
 621     return -1;
 622 
 623   if ((ps = font->pixel_size) < 0)
 624     if ((ps = font_gf->pixel_size) < 0)
 625       ps = -1;
 626 
 627   if ((ps < 0) || (design_size < 1.0e-3)){
 628     mx = font->mag_x * font_gf->mag * mag_x;
 629     my = font->mag_y * font_gf->mag * mag_y;
 630   } else {
 631     mx = font->mag_x * font_gf->mag * mag_x * (ps*72.27)/(design_size*dpi_x);
 632     my = font->mag_y * font_gf->mag * mag_y * (ps*72.27)/(design_size*dpi_y);
 633   }
 634 
 635   GF_GetFontBBX(font_gf->gf_id, w_p, h_p, xoff_p, yoff_p);
 636 
 637   *w_p = mx * (*w_p);
 638   *h_p = mx * (*h_p);
 639   *xoff_p = mx * (*xoff_p);
 640   *yoff_p = mx * (*yoff_p);
 641 
 642   return 0;
 643 }
 644 
 645 
 646 Private VF_BITMAP
 647 gf_get_bitmap2(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 648                double mag_x, double mag_y)
 649 {
 650   VF_BITMAP  bm;
 651   FONT_GF    font_gf;
 652   double     mx, my, dpi_x, dpi_y, ps, design_size;
 653 
 654   if ((font_gf = (FONT_GF)font->private) == NULL){
 655     fprintf(stderr, "VFlib internal error in gf_get_bitmap2()\n");
 656     abort();
 657   }
 658 
 659   if ((bm = GF_GetBitmap(font_gf->gf_id, code_point)) == NULL)
 660     return NULL;
 661   /* 'bm' SHOULD NOT BE RELEASED. */
 662 
 663   if (GF_GetMetric(font_gf->gf_id, code_point, NULL, 
 664                    &dpi_x, &dpi_y, &design_size) < 0)
 665     return NULL;
 666 
 667   if ((ps = font->pixel_size) < 0)
 668     if ((ps = font_gf->pixel_size) < 0)
 669       ps = -1;
 670 
 671 #if 0
 672   printf("** %.3f %.3f %.3f   %.3f   %.3f %.3f  %d %.3f\n", 
 673          mag_x, mag_y, ps, design_size, dpi_x, dpi_y,
 674          font->pixel_size, font_gf->pixel_size); 
 675 #endif
 676 
 677   if ((ps < 0) || (design_size < 1.0e-3)){
 678     /* Note: font_gf->mag_x and font_gf->mag are already used to select 
 679        scaled glyph, e.g., cmr10.360gf for 300dpi with mag 1.2. */
 680     mx = font_gf->extra_mag * mag_x;
 681     my = font_gf->extra_mag * mag_y;
 682   } else {
 683 #if 0
 684     m = font->mag_y * font_gf->mag;
 685     mx = font_gf->extra_mag * mag_x * m * (ps*72.27)/(design_size*dpi_x);
 686     my = font_gf->extra_mag * mag_y * m * (ps*72.27)/(design_size*dpi_y);
 687 #endif
 688     mx = font_gf->extra_mag * mag_x 
 689          * (font->mag_x * font_gf->mag) * (ps*72.27)/(design_size*dpi_x);
 690     my = font_gf->extra_mag * mag_y 
 691          * (font->mag_y * font_gf->mag) * (ps*72.27)/(design_size*dpi_y);
 692   }
 693 
 694   return VF_MakeScaledBitmap(bm, mx, my);
 695 }
 696 
 697 
 698 Private char*
 699 gf_get_font_prop(VF_FONT font, char *prop_name)
     /* [<][>][^][v][top][bottom][index][help] */
 700 {
 701   FONT_GF  font_gf;
 702   double   dpi_x, dpi_y, design_size, ps, m;
 703   char     str[256];
 704   SEXP     v;
 705 
 706   if ((font_gf = (FONT_GF)font->private) == NULL){
 707     fprintf(stderr, "VFlib internal error in gf_get_font_prop()\n");
 708     abort();
 709   }
 710 
 711   if ((v = vf_sexp_assoc(prop_name, font_gf->props)) != NULL){
 712     return vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)));
 713   } else if ((v = vf_sexp_assoc(prop_name, default_properties)) != NULL){
 714     return vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)));
 715   } else {
 716     if (GF_GetMetric(font_gf->gf_id, -1, NULL, 
 717                      &dpi_x, &dpi_y, &design_size) < 0){
 718       return NULL;
 719     }
 720     m = font->mag_y * font_gf->mag;
 721 #if 0
 722     printf("** %.3f %.3f %.3f   %.4f   %d %.3f   %.3f %.3f\n",
 723            dpi_x, dpi_y, design_size, m,
 724            font->pixel_size, font_gf->pixel_size,
 725            font->point_size, font_gf->point_size);
 726 #endif
 727     if (font->mode == 1){
 728       if ((ps = font->point_size) < 0)
 729         if ((ps = font_gf->point_size) < 0)
 730           ps = design_size;
 731       if (strcmp(prop_name, "POINT_SIZE") == 0){
 732         sprintf(str, "%d", toint(ps * m * 10.0));
 733         return vf_strdup(str);
 734       } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
 735         sprintf(str, "%d", toint(ps * dpi_y / 72.27));
 736         return vf_strdup(str);
 737       } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
 738         sprintf(str, "%d", toint(dpi_x));
 739         return vf_strdup(str);
 740       } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
 741         sprintf(str, "%d", toint(dpi_y));
 742         return vf_strdup(str);
 743       }
 744 
 745     } else if (font->mode == 2){
 746       if (strcmp(prop_name, "POINT_SIZE") == 0){
 747         if ((ps = font->pixel_size) < 0){
 748           if ((ps = font_gf->pixel_size) < 0){
 749             sprintf(str, "%d", toint(design_size * m));
 750             return vf_strdup(str);
 751           }
 752         }
 753         sprintf(str, "%d", toint(ps * 10.0 * (72.27 / dpi_y)));
 754         return vf_strdup(str);
 755       } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
 756         if ((ps = font->pixel_size) < 0)
 757           if ((ps = font_gf->pixel_size) < 0){
 758             ps = design_size * dpi_y / 72.27;
 759             sprintf(str, "%d", toint(ps));
 760             return vf_strdup(str);
 761           }
 762         sprintf(str, "%d", toint(ps * m));
 763         return vf_strdup(str);
 764       } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
 765         sprintf(str, "%d", toint(dpi_x));
 766         return vf_strdup(str);
 767       } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
 768         sprintf(str, "%d", toint(dpi_y));
 769         return vf_strdup(str);
 770       }
 771     }
 772   }
 773 
 774   return NULL;
 775 }
 776 
 777 
 778 
 779 #ifndef CACHE_SIZE
 780 #  define CACHE_SIZE  48
 781 #endif
 782 #ifndef HASH_SIZE
 783 #  define HASH_SIZE   11
 784 #endif
 785 
 786 
 787 struct s_gf {
 788   int      type;
 789   char    *font_path;
 790 };
 791 typedef struct s_gf  *GF;
 792 
 793 struct s_gf_glyph {
 794   int         code_min, code_max; 
 795   VF_BITMAP   bm_table;
 796   double      ds, hppp, vppp;
 797   int         font_bbx_w, font_bbx_h;
 798   int         font_bbx_xoff, font_bbx_yoff;
 799 };
 800 typedef struct s_gf_glyph  *GF_GLYPH;
 801 
 802 Private VF_TABLE gf_table       = NULL;
 803 Private VF_CACHE gf_glyph_cache = NULL;
 804 
 805 Private void        GF_CacheDisposer(GF_GLYPH go);
 806 Private GF_GLYPH    GF_CacheLoader(VF_CACHE c, char *path, int l);
 807 
 808 Private GF          GF_GetGF(int gf_id);
 809 Private void        GF_SetGFGlyph(char *path, GF_GLYPH go);
 810 Private GF_GLYPH    GF_GetGFGlyph(char *path);
 811 
 812 
 813 Private int
 814 GF_Init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 815 {
 816   static int init_flag = 0;
 817 
 818   if (init_flag == 0){
 819     init_flag = 1;
 820     if ((gf_table = vf_table_create()) == NULL){
 821       vf_error = VF_ERR_NO_MEMORY;
 822       return -1;
 823     }
 824     gf_glyph_cache
 825       = vf_cache_create(CACHE_SIZE, HASH_SIZE,
 826                         (void*(*)(VF_CACHE,void*,int))GF_CacheLoader, 
 827                         (void(*)(void*))GF_CacheDisposer);
 828   }
 829 
 830   return 0;
 831 }
 832 
 833 Private int
 834 GF_Open(FONT_GF font_gf, VF_FONT font, int implicit)
     /* [<][>][^][v][top][bottom][index][help] */
 835 {
 836   GF      gf;
 837   char    *gf_path, *p;
 838   int     gf_id, dev_dpi;
 839   double  font_mag;
 840 
 841   gf = NULL;
 842 
 843   if (vf_dbg_drv_texfonts == 1)
 844     printf(">> GF Open: %s\n", font_gf->font_file);
 845 
 846   /* Parse font name.  Formats of file names that this routine supports:
 847    *    "cmr10.300XX" - A "cmr10" font for 300 dpi.
 848    *    "cmr10.XX"    - A "cmr10" font. Dpi value is default value.
 849    *    "cmr10"       -   ditto.
 850    * ("XX" can be any string such as "pk", "gf", and "tfm".)
 851    */
 852   p = vf_index(font_gf->font_file, '.');
 853   if ((p != NULL) && (isdigit((int)*(p+1)))){   /* "cmr10.300gf" */
 854     dev_dpi = atoi(p+1);
 855     if (font->dpi_y > 0)
 856       font_gf->extra_mag = (double)font->dpi_y / (double)dev_dpi;
 857     else
 858       font_gf->extra_mag = 1.0;
 859   } else {                                 /* "cmr10" or "cmr10.gf" */
 860     if ((dev_dpi = font->dpi_y) < 0)
 861       dev_dpi = font_gf->dpi_y;
 862     font_gf->extra_mag = 1.0;
 863   }
 864 
 865   font_mag = font->mag_y * font_gf->mag;
 866   gf_path = vf_tex_search_file_glyph(font_gf->font_file, implicit,
 867                                      FSEARCH_FORMAT_TYPE_GF,
 868                                      default_fontdirs, dev_dpi, font_mag,
 869                                      default_extensions);
 870   if (gf_path == NULL){
 871     if (vf_dbg_drv_texfonts == 1)
 872       printf(">> GF Open: GF file not found\n");
 873     if (v_default_make_glyph == 0)
 874       return -1;
 875     if (vf_tex_make_glyph(FSEARCH_FORMAT_TYPE_GF, 
 876                           font_gf->font_file, dev_dpi, font_mag) < 0)
 877       return -1;
 878     gf_path = vf_tex_search_file_glyph(font_gf->font_file, implicit,
 879                                        FSEARCH_FORMAT_TYPE_GF,
 880                                        default_fontdirs, dev_dpi, font_mag,
 881                                        default_extensions);
 882     if (gf_path == NULL){
 883       if (vf_dbg_drv_texfonts == 1)
 884         printf(">> GF Open: GF file not found\n");
 885       return -1;
 886     }
 887   }
 888 
 889   if (debug_on('f'))
 890     printf("VFlib GF: font:%s, dpi:%d, mag:%f, extra_mag:%f\n   ==> %s\n",
 891            font_gf->font_file, dev_dpi, font_mag, font_gf->extra_mag, gf_path);
 892 
 893   ALLOC_IF_ERR(gf, struct s_gf){
 894     goto NoMemoryError;
 895   }
 896   gf->font_path = gf_path;
 897   if ((gf_id = (gf_table->put)(gf_table, gf, gf->font_path,
 898                                strlen(gf->font_path)+1)) < 0)
 899     goto NoMemoryError;
 900 
 901   return gf_id;
 902 
 903 
 904 NoMemoryError:
 905   vf_error = VF_ERR_NO_MEMORY;
 906   if (gf != NULL)
 907     vf_free(gf->font_path);
 908   vf_free(gf);
 909   return -1;
 910 }
 911 
 912 Private void
 913 GF_Close(int gf_id)
     /* [<][>][^][v][top][bottom][index][help] */
 914 {
 915   GF   gf;
 916 
 917   gf = GF_GetGF(gf_id);
 918 
 919   if ((gf_table->unlink_by_id)(gf_table, gf_id) > 0)
 920     return;
 921 
 922   if (gf != NULL)
 923     vf_free(gf->font_path);
 924   vf_free(gf);
 925   GF_SetGFGlyph(NULL, NULL);
 926 }
 927 
 928 
 929 Private VF_BITMAP
 930 GF_GetBitmap(int gf_id, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 931      /* MEMO: CALLER MUST *NOT* 'FREE' THE BITMAP RETURNED BY THIS FUNC. */
 932 {
 933   GF_GLYPH  go;
 934   GF        gf;
 935 
 936   gf = GF_GetGF(gf_id);
 937   if ((go = GF_GetGFGlyph(gf->font_path)) == NULL)
 938     return NULL;
 939 
 940   if ((go->code_min <= code_point) && (code_point <= go->code_max))
 941     return &go->bm_table[code_point - go->code_min];
 942 
 943   return NULL;
 944 }
 945 
 946 Private int
 947 GF_GetMetric(int gf_id, long code_point, VF_METRIC1 me, 
     /* [<][>][^][v][top][bottom][index][help] */
 948              double *ret_dpi_x, double *ret_dpi_y, double *ret_design_size)
 949 {
 950   VF_BITMAP  bm;
 951   GF_GLYPH   go;
 952   GF         gf;
 953 
 954   gf = GF_GetGF(gf_id);
 955   if ((go = GF_GetGFGlyph(gf->font_path)) == NULL)
 956     return -1;
 957 
 958   if (code_point < 0)
 959     code_point = go->code_min;
 960   if ((code_point < go->code_min) || (go->code_max < code_point)){
 961     vf_error = VF_ERR_ILL_CODE_POINT;
 962     return -1;
 963   }
 964 
 965   if ((bm = &go->bm_table[code_point - go->code_min]) == NULL){
 966     vf_error = VF_ERR_ILL_CODE_POINT;
 967     return -1;
 968   }
 969 
 970   if (me != NULL){
 971     me->bbx_width  = bm->bbx_width  / go->hppp;
 972     me->bbx_height = bm->bbx_height / go->vppp;
 973     me->off_x      = bm->off_x / go->hppp;
 974     me->off_y      = bm->off_y / go->vppp;
 975     me->mv_x       = bm->mv_x  / go->hppp;
 976     me->mv_y       = bm->mv_y  / go->vppp;
 977   }
 978 
 979   if (ret_dpi_x != NULL)
 980     *ret_dpi_x = go->hppp * 72.27;
 981   if (ret_dpi_y != NULL)
 982     *ret_dpi_y = go->vppp * 72.27;
 983   if (ret_design_size != NULL)
 984     *ret_design_size = go->ds;
 985 
 986   return 0;
 987 }
 988 
 989 Private void
 990 GF_GetFontBBX(int gf_id, int *bbx_w_p, int *bbx_h_p, 
     /* [<][>][^][v][top][bottom][index][help] */
 991               int *bbx_xoff_p, int *bbx_yoff_p)
 992 {
 993   GF_GLYPH  go;
 994   GF        gf;
 995 
 996   gf = GF_GetGF(gf_id);
 997   if ((go = GF_GetGFGlyph(gf->font_path)) == NULL)
 998     return;
 999 
1000   if (bbx_w_p != NULL)
1001     *bbx_w_p = go->font_bbx_w;
1002   if (bbx_h_p != NULL)
1003     *bbx_h_p = go->font_bbx_h;
1004   if (bbx_xoff_p != NULL)
1005     *bbx_xoff_p = go->font_bbx_xoff;
1006   if (bbx_yoff_p != NULL)
1007     *bbx_yoff_p = go->font_bbx_yoff;
1008 }
1009 
1010 
1011 /* 
1012  * GF file interface
1013  */
1014 
1015 #include  "gf.c"
1016 
1017 
1018 Private GF
1019 GF_GetGF(int gf_id)
     /* [<][>][^][v][top][bottom][index][help] */
1020 {
1021   if (gf_id < 0)
1022     abort();
1023   return (gf_table->get_obj_by_id)(gf_table, gf_id);
1024 }
1025 
1026 
1027 static char     *gf_last_go_path = NULL;
1028 static GF_GLYPH  gf_last_go    = NULL;
1029 
1030 Private void
1031 GF_SetGFGlyph(char *path, GF_GLYPH go)
     /* [<][>][^][v][top][bottom][index][help] */
1032 {
1033   gf_last_go_path = path;
1034   gf_last_go      = go;
1035 }
1036 
1037 Private GF_GLYPH
1038 GF_GetGFGlyph(char *path)
     /* [<][>][^][v][top][bottom][index][help] */
1039 {
1040   GF_GLYPH   go;
1041 
1042   if (path == NULL){
1043     gf_last_go_path = NULL;
1044     gf_last_go      = NULL;
1045     return NULL;
1046   }
1047   if ((gf_last_go_path != NULL)
1048       && (strcmp(gf_last_go_path, path) == 0)
1049       && (gf_last_go != NULL) ){
1050     return gf_last_go;
1051   }
1052   
1053   go = (gf_glyph_cache->get)(gf_glyph_cache, path, strlen(path)+1);
1054   gf_last_go_path = path;
1055   gf_last_go      = go;  
1056 
1057   return go;
1058 }
1059 
1060 
1061 Private int
1062 debug_on(char type)
     /* [<][>][^][v][top][bottom][index][help] */
1063 {
1064   char  *p;
1065 
1066   if (default_debug_mode == NULL)
1067     return FALSE;
1068   if ((p = vf_sexp_get_cstring(default_debug_mode)) == NULL)
1069     return FALSE;
1070   
1071   while (*p != '\0'){
1072     if (*p == type)
1073       return TRUE;
1074     p++;
1075   }
1076 
1077   while (*p != '\0'){
1078     if (*p == '*')
1079       return TRUE;
1080     p++;
1081   }
1082 
1083   return TRUE;
1084 }
1085 
1086 
1087 /*EOF*/

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