src/drv_pk.c

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

FUNCTIONS

This source file includes following functions.
  1. VF_Init_Driver_PK
  2. pk_create
  3. pk_close
  4. pk_get_metric1
  5. pk_get_fontbbx1
  6. pk_get_bitmap1
  7. pk_get_outline
  8. pk_get_metric2
  9. pk_get_fontbbx2
  10. pk_get_bitmap2
  11. pk_get_font_prop
  12. PK_Init
  13. PK_Open
  14. PK_Close
  15. PK_GetBitmap
  16. PK_GetMetric
  17. PK_GetFontBBX
  18. PK_GetPK
  19. PK_SetPKGlyph
  20. PK_GetPKGlyph
  21. debug_on

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

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