src/vf.c

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

FUNCTIONS

This source file includes following functions.
  1. STACK
  2. vf_vf_init
  3. vf_vf_open
  4. vf_read_info
  5. vf_vf_close
  6. vf_vf_get_design_size
  7. vf_vf_get_vf
  8. vf_cache_loader
  9. vf_cache_disposer
  10. vf_vf_get_metric
  11. vf_vf_get_bitmap
  12. vf_do_glyph_style
  13. vf_run_dvi_program
  14. vf_dvi_interp
  15. vf_dvi_interp_put_char
  16. vf_dvi_interp_put_rule
  17. vf_dvi_interp_font_select
  18. vf_dvi_stack_init
  19. vf_dvi_stack_deinit
  20. vf_dvi_stack_push
  21. vf_dvi_stack_pop

   1 /* this is included by drv_vf.c */
   2 /*
   3  * vf.c - A vf (virtual font) interface
   4  * by Hirotsugu Kakugawa
   5  *
   6  * 30 Jan 1997  First implementation.
   7  *  7 Aug 1997  VFlib 3.3  Changed API.
   8  *  2 Feb 1998  VFlib 3.4
   9  *
  10  */
  11 /*
  12  * Copyright (C) 1997-1998  Hirotsugu Kakugawa. 
  13  * All rights reserved.
  14  *
  15  * This file is part of the VFlib Library.  This library is free
  16  * software; you can redistribute it and/or modify it under the terms of
  17  * the GNU Library General Public License as published by the Free
  18  * Software Foundation; either version 2 of the License, or (at your
  19  * option) any later version.  This library is distributed in the hope
  20  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  21  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  22  * PURPOSE.  See the GNU Library General Public License for more details.
  23  * You should have received a copy of the GNU Library General Public
  24  * License along with this library; if not, write to the Free Software
  25  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26  */
  27 
  28 
  29 
  30 Private VF_TABLE vf_font_table = NULL;
  31 Private VF_CACHE vf_font_cache = NULL;
  32 
  33 
  34 struct s_vf_dvi_stack {
  35   long    h, v, w, x, y, z;
  36   int     f;
  37   int                    font_id;
  38   struct s_vf_dvi_stack  *next;
  39 };
  40 typedef struct s_vf_dvi_stack  *VF_DVI_STACK;
  41 
  42 #define   STACK(X)     dvi_stack->next->X
     /* [<][>][^][v][top][bottom][index][help] */
  43 
  44 
  45 Private int        vf_read_info(VF,FILE*,int,VF_FONT);
  46 Private void       vf_do_glyph_style(VF_BITMAP,int);
  47 Private VF_BITMAP  vf_run_dvi_program(VF,VF_CHAR_PACKET,int,double,double);
  48 Private VF_CHAR_PACKET_TBL vf_cache_loader(VF_CACHE,VF_CACHE_KEY,int);
  49 Private void               vf_cache_disposer(VF_CHAR_PACKET_TBL);
  50 
  51 Private int   vf_dvi_interp(VF_BITMAPLIST,VF,
  52                             int,double,double,unsigned char*,int);
  53 Private void  vf_dvi_interp_font_select(VF,VF_DVI_STACK,long,double*);
  54 Private void  vf_dvi_interp_put_char(VF_BITMAPLIST,VF,VF_DVI_STACK,long,
  55                                      int,double,double);
  56 Private void  vf_dvi_interp_put_rule(VF_BITMAPLIST,VF,VF_DVI_STACK,long,long,
  57                                      double,double);
  58 Private int   vf_dvi_stack_init(VF,VF_DVI_STACK);
  59 Private int   vf_dvi_stack_deinit(VF,VF_DVI_STACK);
  60 Private int   vf_dvi_stack_push(VF,VF_DVI_STACK);
  61 Private int   vf_dvi_stack_pop(VF,VF_DVI_STACK);
  62 
  63 
  64 
  65 Private int
  66 vf_vf_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  67 {
  68   static int init_flag = 0;
  69 
  70   if (init_flag == 1)
  71     return 0;
  72 
  73   init_flag = 1;
  74   vf_font_cache
  75     = vf_cache_create(VF_CACHE_SIZE, VF_HASH_SIZE,
  76                       (void*(*)(VF_CACHE,void*,int))vf_cache_loader, 
  77                       (void(*)(void*))vf_cache_disposer);
  78   vf_font_table = vf_table_create();
  79   vf_vf_get_vf(-1);
  80 
  81   return 0;
  82 }
  83 
  84 
  85 Private int
  86 vf_vf_open(VF_FONT font, FONT_VF font_vf, int implicit)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88   int     vf_id;
  89   char    *vf_path, *tfm_path;
  90   double  dpi_x, dpi_y = 0.0;
  91   VF      vf;
  92   FILE    *fp;
  93   char    key[2*1024];
  94 
  95   vf_path = NULL;
  96   tfm_path = NULL;
  97 
  98   sprintf(key, "%s %.6f %.6f %.6f %.6f %.6f %.6f %.6f", 
  99           font_vf->font_file, 
 100           font->dpi_x, font->dpi_y, font->mag_x, font->mag_y,
 101           font_vf->dpi_x, font_vf->dpi_y, font_vf->mag);
 102 
 103   vf_id = (vf_font_table->get_id_by_key)(vf_font_table, key, strlen(key)+1);
 104   if (vf_id >= 0){
 105     (vf_font_table->link_by_id)(vf_font_table, vf_id);
 106     return vf_id;
 107   }
 108 
 109   vf_path = vf_tex_search_file_misc(font_vf->font_file, implicit,
 110                                     FSEARCH_FORMAT_TYPE_VF,
 111                                     default_fontdirs, default_extensions);
 112   if (vf_path == NULL)
 113     return -1;
 114 
 115 
 116   if (vf_debug('f'))
 117     printf("VFlib Virtual Font: font file %s\n   ==> %s\n", 
 118            font_vf->font_file, vf_path);
 119 
 120 
 121   tfm_path = vf_tex_search_file_tfm(font_vf->font_file, 
 122                                     default_tfm_dirs, default_tfm_extensions);
 123   if (tfm_path == NULL){
 124     vf_free(vf_path);
 125     return -1;
 126   }
 127 
 128   if (vf_debug('f'))
 129     printf("VFlib Virtual Font: TFM font file %s\n   ==> %s\n", 
 130            font_vf->font_file, tfm_path);
 131 
 132   if ((vf_path == NULL) || (tfm_path == NULL)){
 133     vf_free(vf_path);
 134     vf_free(tfm_path);
 135     return -1;
 136   }
 137 
 138   if (((dpi_x = font->dpi_x) < 0) || ((dpi_y = font->dpi_y) < 0)){
 139     if (((dpi_x = font_vf->dpi_x) < 0) || (dpi_x = font_vf->dpi_x)){
 140       dpi_x = dpi_y = vf_tex_default_dpi();
 141     }
 142   }
 143 
 144   ALLOC_IF_ERR(vf, struct s_vf){
 145     vf_error = VF_ERR_NO_MEMORY;
 146     return -1; 
 147   }
 148   vf->vf_path          = vf_path;
 149   vf->cs               = 0;
 150   vf->ds               = 0;
 151   vf->design_size      = 0;
 152   vf->dpi_x            = dpi_x;
 153   vf->dpi_y            = dpi_y;
 154   vf->mag_x            = font->mag_x * font_vf->mag;
 155   vf->mag_y            = font->mag_y * font_vf->mag;
 156   vf->tfm_path         = tfm_path;
 157   vf->tfm              = NULL;
 158   vf->subfonts         = NULL;
 159   vf->subfonts_opened  = 1;
 160   vf->offs_char_packet = 0;
 161 
 162   if ((vf->tfm = vf_tfm_open(vf->tfm_path)) == NULL)
 163     goto Error;
 164 
 165   if ((fp = vf_fm_OpenBinaryFileStream(vf->vf_path)) == NULL){
 166     if (vf_error != VF_ERR_NO_MEMORY)
 167       vf_error = VF_ERR_NO_FONT_FILE;
 168     goto Error;
 169   }
 170 
 171   if (vf_read_info(vf, fp, font_vf->open_style, font) < 0){
 172     vf_error = VF_ERR_ILL_FONT_FILE;
 173     goto Error;
 174   }
 175 
 176   if ((vf_id = (vf_font_table->put)(vf_font_table, vf,
 177                                     key, strlen(key)+1)) < 0){
 178     vf_error = VF_ERR_NO_MEMORY;
 179     goto Error;
 180   }
 181 
 182   return vf_id;
 183 
 184 
 185 Error:
 186   if (vf != NULL){
 187     vf_free(vf->vf_path);
 188     vf_free(vf->tfm_path);
 189     vf_tfm_free(vf->tfm);
 190     vf_free(vf);
 191   }
 192   return -1;
 193 }
 194 
 195 
 196 Private int
 197 vf_read_info(VF vf, FILE *fp, int open_style, VF_FONT font)
     /* [<][>][^][v][top][bottom][index][help] */
 198 {
 199   UINT1                id, a, l;
 200   UINT4                k, c, s, d;
 201   VF_SUBFONT           sf, sf0, sf_next;
 202   struct s_vf_subfont  subfont;
 203   double               scale;
 204   int                  fid, name_len, i;
 205   char                 subfont_name[1024];
 206 
 207   if (READ_UINT1(fp) != VFINST_PRE)
 208     return -1;
 209   id = READ_UINT1(fp);
 210   switch (id){
 211   case VFINST_ID_BYTE:
 212     break;
 213   default:
 214     return -1;
 215   }
 216 
 217   k = READ_UINT1(fp);  
 218   SKIP_N(fp,k);
 219 
 220   vf->cs = READ_UINT4(fp);
 221   vf->ds = READ_UINT4(fp);
 222   if ((vf->cs != vf->tfm->cs) || (vf->ds != vf->tfm->ds)){
 223     vf_error = VF_ERR_ILL_FONT_FILE;
 224     return -1;
 225   }
 226 
 227   vf->design_size     = (double)(vf->ds)/(double)(1<<20);
 228   vf->subfonts_opened = 1;
 229   vf->default_subfont = -1;
 230 
 231   subfont.next = NULL;
 232   for (sf0 = &subfont; ; sf0 = sf){
 233     ALLOC_IF_ERR(sf, struct s_vf_subfont){
 234       vf_error = VF_ERR_NO_MEMORY;
 235       goto error_exit;
 236     }
 237     sf0->next = sf;
 238     switch (READ_UINT1(fp)){
 239     default:
 240       vf->offs_char_packet = ftell(fp)-1;
 241       sf0->next = NULL;
 242       vf_free(sf);
 243       goto end_fontdef;
 244     case VFINST_FNTDEF1:
 245       k = (UINT4)READ_UINT1(fp);
 246       c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
 247       a = READ_UINT1(fp); l = READ_UINT1(fp);
 248       break;
 249     case VFINST_FNTDEF2:
 250       k = (UINT4)READ_UINT2(fp);
 251       c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
 252       a = READ_UINT1(fp); l = READ_UINT1(fp);
 253       break;
 254     case VFINST_FNTDEF3:
 255       k = (UINT4)READ_UINT3(fp);
 256       c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
 257       a = READ_UINT1(fp); l = READ_UINT1(fp);
 258       break;
 259     case VFINST_FNTDEF4:
 260       k = (UINT4)READ_UINT4(fp);
 261       c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
 262       a = READ_UINT1(fp); l = READ_UINT1(fp);
 263       break;
 264     }
 265 
 266     name_len = a + l;
 267     sf->k       = k;
 268     sf->s       = s;
 269     sf->d       = d;
 270     sf->a       = a;
 271     sf->l       = l;
 272     sf->next    = NULL;
 273 
 274     scale = (double)sf->s/(double)(1<<20);
 275 
 276     if ((sf->n = (char*)malloc(name_len + 1)) == NULL){
 277       vf_error = VF_ERR_NO_MEMORY;
 278       goto error_exit;
 279     }
 280     for (i = 0; i < name_len; i++)
 281       sf->n[i] = (char)READ_UINT1(fp);
 282     sf->n[i] = '\0';
 283 
 284 
 285     sprintf(subfont_name, "%s", &sf->n[sf->a]);
 286 
 287     if (vf_debug('s')){
 288       printf("VFlib Virtual Font: subfont %d: %s, scaled %f\n", 
 289              (int)sf->k, subfont_name, scale);
 290     }
 291     
 292     if (open_style != TEX_OPEN_STYLE_NONE){
 293       fid = vf_tex_try_map_and_open_font(font, subfont_name, 
 294                                          default_font_mapping,
 295                                          vf->tfm->design_size, NULL, NULL, 
 296                                          scale);
 297       if (fid >= 0){
 298         sf->font_id = fid;
 299         if (vf->default_subfont < 0)
 300           vf->default_subfont = sf->k;
 301         if (vf_debug('s'))
 302           printf("VFlib Virtual Font: subfont is opened: font id %d\n", fid);
 303       } else {
 304         sf->font_id = -1;
 305         vf->subfonts_opened = 0;
 306         if (vf_debug('s'))
 307           printf("VFlib Virtual Font: subfont %d is not opened\n", (int)sf->k);
 308       }
 309     } else {
 310       if (vf_debug('s'))
 311         printf("VFlib Virtual Font: subfont %d is not requested to open\n", 
 312                (int)sf->k);
 313     }
 314   }
 315 
 316 end_fontdef:
 317   if (vf->subfonts_opened == 0){
 318     if (open_style == TEX_OPEN_STYLE_REQUIRE){
 319       if (vf_debug('s'))
 320         printf("VFlib Virtual Font: all subfonts are required but failed\n");
 321       goto error_exit;
 322     } else {
 323       if (vf_debug('s'))
 324         printf("VFlib Virtual Font: not all fonts are opened; continue.\n");
 325     }
 326   }
 327 
 328   vf->subfonts = subfont.next;
 329   return 0;  
 330 
 331 
 332 error_exit:
 333   for (sf = subfont.next; sf != NULL; sf = sf_next){
 334     sf_next = sf->next;
 335     vf_free(sf->n);
 336     vf_free(sf);
 337   }
 338   vf->subfonts = NULL;
 339   return -1;
 340 }
 341 
 342 
 343 Private void
 344 vf_vf_close(int vf_id)
     /* [<][>][^][v][top][bottom][index][help] */
 345 {
 346   VF          vf;
 347   VF_SUBFONT  sf, sf_next;
 348 
 349   vf = vf_vf_get_vf(vf_id);
 350 
 351   if ((vf_font_table->unlink_by_id)(vf_font_table, vf_id) > 0)
 352     return;
 353   
 354   if (vf != NULL){
 355     vf_free(vf->vf_path);
 356     vf_free(vf->tfm_path);
 357     vf_tfm_free(vf->tfm);
 358     for (sf = vf->subfonts; sf != NULL; sf = sf_next){
 359       sf_next = sf->next;
 360       vf_free(sf->n);
 361       vf_free(sf);
 362     }
 363   }
 364 
 365   vf_vf_get_vf(-1);
 366   vf_free(vf);
 367 }
 368 
 369 
 370 Private double
 371 vf_vf_get_design_size(int vf_id)
     /* [<][>][^][v][top][bottom][index][help] */
 372 {
 373   VF   vf;
 374 
 375   vf = vf_vf_get_vf(vf_id);
 376   if ((vf == NULL) || (vf->tfm == NULL)){
 377     fprintf(stderr, "VFlib internal error in vf_vf_get_design_size()\n");
 378     abort();
 379   }
 380   return vf->tfm->design_size;
 381 }
 382 
 383 
 384 #if 0
 385 static VF         last_vf      = NULL;  
 386 static int        last_vf_id   = -1;  
 387 #endif
 388 
 389 Private VF
 390 vf_vf_get_vf(int vf_id)
     /* [<][>][^][v][top][bottom][index][help] */
 391 {
 392   VF   vf;
 393 
 394 #if 1
 395   vf = NULL;
 396   if (vf_id >= 0)
 397     vf = (vf_font_table->get_obj_by_id)(vf_font_table, vf_id);
 398 #else
 399   if (vf_id < 0){
 400     last_vf = NULL;
 401     last_vf_id = -1;
 402     return NULL;
 403   }
 404 
 405   if (vf_id == last_vf_id){
 406     vf = last_vf;
 407   } else {
 408     vf = (vf_font_table->get_obj_by_id)(vf_font_table, vf_id);
 409     if (vf != NULL){
 410       last_vf = vf;
 411       last_vf_id = vf_id;
 412     } else {
 413       last_vf = NULL;
 414       last_vf_id = -1;
 415     }
 416   }
 417 #endif
 418 
 419   return vf;
 420 }
 421 
 422 
 423 
 424 
 425 Private VF_CHAR_PACKET_TBL
 426 vf_cache_loader(VF_CACHE c, VF_CACHE_KEY ck, int l)
     /* [<][>][^][v][top][bottom][index][help] */
 427 {
 428   VF_CHAR_PACKET_TBL  vf_char_packets;
 429   VF_CHAR_PACKET      packets;
 430   int            npackets, ch;
 431   FILE           *fp;
 432   int            b;
 433   long           n;
 434   unsigned char  *cp;
 435 
 436 #if 0
 437   printf("* VF cache_load %s\n", ck->font_path);
 438 #endif
 439   npackets = ck->tfm->end_char - ck->tfm->begin_char + 1;
 440 
 441   if (ck->font_path == NULL)
 442     return NULL;
 443   if ((fp = vf_fm_OpenBinaryFileStream(ck->font_path)) == NULL)
 444     return NULL;
 445   
 446   ALLOC_IF_ERR(vf_char_packets, struct s_vf_char_packet_tbl){
 447     vf_error = VF_ERR_NO_MEMORY;
 448     return NULL; 
 449   }
 450   ALLOCN_IF_ERR(packets, struct s_vf_char_packet, 
 451                 npackets+1){  /* one more element for sentinel. 
 452                                  See vf_get_bitmap(). */
 453     vf_free(vf_char_packets);
 454     vf_error = VF_ERR_NO_MEMORY;
 455     return NULL; 
 456   }
 457   vf_char_packets->npackets = npackets;
 458   vf_char_packets->packets  = packets;
 459   for (ch = 0; ch < npackets; ch++){
 460     vf_char_packets->packets[ch].pl  = 0;
 461     vf_char_packets->packets[ch].cc  = 0;
 462     vf_char_packets->packets[ch].tfm = 0;
 463     vf_char_packets->packets[ch].dvi = NULL;
 464   }
 465 
 466   fseek(fp, ck->offs_char_packet, SEEK_SET);
 467   for (ch = 0; ch < npackets; ch++){
 468     b = (int)READ_UINT1(fp);
 469     if (((int)VFINST_CP_SHORT_CHAR0 <= b)
 470         && (b <= (int)VFINST_CP_SHORT_CHAR241)){
 471       vf_char_packets->packets[ch].pl  = (UINT4)b;
 472       vf_char_packets->packets[ch].cc  = (UINT4)READ_UINT1(fp);
 473       vf_char_packets->packets[ch].tfm = (UINT4)READ_UINT3(fp);
 474     } else if (b == (int)VFINST_CP_LONG_CHAR){
 475       vf_char_packets->packets[ch].pl  = READ_UINT4(fp);
 476       vf_char_packets->packets[ch].cc  = READ_UINT4(fp);
 477       vf_char_packets->packets[ch].tfm = READ_UINT4(fp);
 478     } else if (b == VFINST_POST){
 479       break;
 480     } else {
 481       fprintf(stderr, "VFlib warning: Broken VF file: %s\n", ck->font_path);
 482       break;
 483     }
 484 #if 0
 485     printf("  0x%02x: pl 0x%04lx: cc 0x%04lx\n", b,
 486            vf_char_packets->packets[ch].pl, 
 487            vf_char_packets->packets[ch].cc);
 488 #endif
 489 
 490     if (vf_char_packets->packets[ch].pl > 0){
 491       vf_char_packets->packets[ch].dvi 
 492         = (unsigned char*)malloc(vf_char_packets->packets[ch].pl);
 493       if (vf_char_packets->packets[ch].dvi == NULL){
 494         vf_free(vf_char_packets->packets);
 495         vf_free(vf_char_packets);
 496         vf_error = VF_ERR_NO_MEMORY;
 497         return NULL; 
 498       }
 499       n = vf_char_packets->packets[ch].pl;
 500       for (cp = vf_char_packets->packets[ch].dvi; n > 0; cp++, n--)
 501         *cp = READ_UINT1(fp);
 502     }
 503   }
 504 
 505   return vf_char_packets;
 506 }
 507 
 508 
 509 Private void
 510 vf_cache_disposer(VF_CHAR_PACKET_TBL vf_char_packets)
     /* [<][>][^][v][top][bottom][index][help] */
 511 {
 512   int   ch;
 513 
 514 #if 0
 515   printf("* VF cache_disposer\n");
 516 #endif
 517   if (vf_char_packets != NULL){
 518     if (vf_char_packets->packets != NULL){
 519       for (ch = vf_char_packets->npackets-1; ch >= 0; ch--)
 520         vf_free(vf_char_packets->packets[ch].dvi);
 521     }
 522     vf_free(vf_char_packets->packets);
 523   }
 524   vf_free(vf_char_packets);
 525 }
 526 
 527 
 528 Private int
 529 vf_vf_get_metric(int vf_id, long code_point, VF_METRIC1 met,
     /* [<][>][^][v][top][bottom][index][help] */
 530                  double *ret_design_size)
 531 {
 532   VF    vf;
 533   struct vf_s_metric1 metric1;
 534 
 535   if (   ((vf = vf_vf_get_vf(vf_id)) == NULL) 
 536       || (vf->tfm == NULL) ){
 537     fprintf(stderr, "VFlib internal error in vf_vf_get_metric()\n");
 538     abort();
 539   }
 540 
 541   if (ret_design_size != NULL)
 542     *ret_design_size = vf->tfm->design_size;
 543 
 544   if (met == NULL)
 545     met = &metric1;
 546 
 547   if (vf_tfm_metric(vf->tfm, code_point, met) == NULL)
 548     return -1;
 549 
 550   return 0;
 551 }
 552 
 553 Private VF_BITMAP
 554 vf_vf_get_bitmap(int vf_id, int mode, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 555                  double mag_x, double mag_y,
 556                  int open_style, int glyph_style)
 557 {
 558   VF                     vf;
 559   VF_BITMAP              bm;
 560   VF_CHAR_PACKET_TBL     cptbl;
 561   struct vf_s_metric1    met1;
 562   struct vf_s_metric2    met2;
 563   struct s_vf_cache_key  ck;
 564   int                    idx;
 565 
 566   if (   ((vf = vf_vf_get_vf(vf_id)) == NULL) 
 567       || (vf->tfm == NULL)  ){
 568     fprintf(stderr, "VFlib internal error in vf_vf_get_bitmap()\n");
 569     abort();
 570   }
 571 
 572   switch (open_style){
 573   default:
 574   case TEX_OPEN_STYLE_NONE:
 575     if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL)
 576       return NULL;
 577 #if 0 /*XXX*/
 578     bm = vf_alloc_bitmap_with_metric1(&met1, 
 579                                       vf->dpi_x * vf->mag_x * mag_x, 
 580                                       vf->dpi_y * vf->mag_y * mag_y);
 581 #else
 582     bm = vf_alloc_bitmap_with_metric1(&met1, 
 583                                       vf->dpi_x * mag_x, 
 584                                       vf->dpi_y * mag_y);
 585 #endif
 586     vf_do_glyph_style(bm, glyph_style);
 587     return bm;
 588   case TEX_OPEN_STYLE_TRY:
 589     if (vf->subfonts_opened == 0){
 590       if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL)
 591         return NULL;
 592 #if 0 /*XXX*/
 593       bm = vf_alloc_bitmap_with_metric1(&met1, 
 594                                         vf->dpi_x * vf->mag_x * mag_x, 
 595                                         vf->dpi_y * vf->mag_y * mag_y);
 596 #else
 597       bm = vf_alloc_bitmap_with_metric1(&met1, 
 598                                         vf->dpi_x * mag_x, 
 599                                         vf->dpi_y * mag_y);
 600 #endif
 601       vf_do_glyph_style(bm, glyph_style);
 602       return bm;
 603     }
 604     break;
 605   case TEX_OPEN_STYLE_REQUIRE:
 606     if (vf->subfonts_opened == 0)
 607       return NULL;
 608     break;
 609   }
 610 
 611   ck.font_path        = vf->vf_path;
 612   ck.tfm              = vf->tfm;
 613   ck.offs_char_packet = vf->offs_char_packet;
 614   if ((cptbl = (vf_font_cache->get)(vf_font_cache, &ck, sizeof(ck))) == NULL)
 615     return NULL;
 616 
 617   idx = 0; 
 618   cptbl->packets[cptbl->npackets].cc = code_point;   /* sentinel */
 619   while ((long)cptbl->packets[idx].cc != code_point)
 620     idx++;
 621 
 622   if (idx == cptbl->npackets){
 623     vf_error = VF_ERR_ILL_CODE_POINT;
 624     return NULL;
 625   }
 626 
 627   bm = vf_run_dvi_program(vf, &cptbl->packets[idx], mode, mag_x, mag_y);
 628   if (bm != NULL){
 629     if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL){
 630       VF_FreeBitmap(bm);
 631       return NULL;
 632     }
 633 #if 0 /*XXX*/
 634     vf_metric1_to_metric2(&met1, (double)vf->dpi_y * vf->mag_y * mag_y, &met2);
 635 #else
 636     vf_metric1_to_metric2(&met1, (double)vf->dpi_y * mag_y, &met2);
 637 #endif
 638     bm->mv_x = met2.mv_x;
 639     bm->mv_y = met2.mv_y;
 640   } else {
 641     if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL)
 642       return NULL;
 643 #if 0 /*XXX*/
 644     bm = vf_alloc_bitmap_with_metric1(&met1, 
 645                                       vf->dpi_x * vf->mag_x * mag_x, 
 646                                       vf->dpi_y * vf->mag_y * mag_y);
 647 #else
 648     bm = vf_alloc_bitmap_with_metric1(&met1, 
 649                                       vf->dpi_x * mag_x, 
 650                                       vf->dpi_y * mag_y);
 651 #endif
 652     vf_do_glyph_style(bm, glyph_style);
 653   }
 654 
 655   return bm;
 656 }
 657 
 658 Private void
 659 vf_do_glyph_style(VF_BITMAP bm, int glyph_style)
     /* [<][>][^][v][top][bottom][index][help] */
 660 {
 661   switch (glyph_style){
 662   default:
 663   case TEX_GLYPH_STYLE_EMPTY:
 664     break;
 665   case TEX_GLYPH_STYLE_FILL:
 666     VF_FillBitmap(bm);
 667     break;
 668   }
 669 }
 670 
 671 
 672 Private VF_BITMAP
 673 vf_run_dvi_program(VF vf, VF_CHAR_PACKET packet, 
     /* [<][>][^][v][top][bottom][index][help] */
 674                    int mode, double mag_x, double mag_y)
 675 {
 676   struct vf_s_bitmaplist  the_bmlist;
 677   VF_BITMAP               bm;
 678 
 679   vf_bitmaplist_init(&the_bmlist);
 680   vf_dvi_interp(&the_bmlist, vf, mode, mag_x, mag_y, packet->dvi, packet->pl);
 681   bm = vf_bitmaplist_compose(&the_bmlist);
 682   vf_bitmaplist_finish(&the_bmlist);
 683 
 684   return bm;
 685 }
 686 
 687 Private int
 688 vf_dvi_interp(VF_BITMAPLIST bmlist, VF vf,
     /* [<][>][^][v][top][bottom][index][help] */
 689               int mode, double mag_x, double mag_y, 
 690               unsigned char *dvi_prog, int prog_len)
 691 {
 692   int                    pc, instr, n, ret;
 693   long                   code_point, h, w, f, length;
 694   double                 fmag;
 695   double                 r_mv_x, r_mv_y;
 696   struct vf_s_metric1    met, *m;
 697   struct s_vf_dvi_stack  the_dvi_stack, *dvi_stack;
 698   
 699   fmag = 1.0;
 700   dvi_stack = &the_dvi_stack;
 701   vf_dvi_stack_init(vf, dvi_stack);
 702 
 703   pc = 0;
 704   ret = 0;
 705   while (pc < prog_len){
 706     if (vf_debug('d')){
 707       printf("VFlib Virtual Font\n   ");
 708       printf("DVI CODE  PC=0x%04x: INSTR=0x%02x (%d)  H=0x%08x V=0x%08x\n", 
 709              pc, (int)dvi_prog[pc], (int)dvi_prog[pc],
 710              (int)STACK(h), (int)STACK(v));
 711     }
 712     instr = (int)dvi_prog[pc++];
 713     if (instr <= VFINST_SET4){ /* SETCHAR0 ... SETCHAR127, SET1, ... ,SET4 */
 714       if ((code_point = instr) > VFINST_SETCHAR127){
 715         n = instr - VFINST_SET1 + 1;
 716         code_point = GET_UINTN(&dvi_prog[pc], n);
 717         pc += n;
 718       }
 719       vf_dvi_interp_put_char(bmlist, vf, dvi_stack, code_point,
 720                              mode, fmag * mag_x, fmag * mag_y);
 721       m = VF_GetMetric1(STACK(font_id), code_point, &met, 
 722                         fmag * mag_x, fmag * mag_y);
 723       if (m == NULL)
 724         continue;
 725       r_mv_x = (met.mv_x / vf->design_size) * (double)(1<<20);
 726       r_mv_y = (met.mv_y / vf->design_size) * (double)(1<<20);
 727       STACK(h) = STACK(h) + toint(r_mv_x);
 728       STACK(v) = STACK(v) + toint(r_mv_y);
 729     } else if ((VFINST_FNTNUM0 <= instr) && (instr <= (VFINST_FNTNUM63))){
 730       f = instr - VFINST_FNTNUM0;
 731       vf_dvi_interp_font_select(vf, dvi_stack, f, &fmag);
 732     } else {
 733       switch (instr){
 734       case VFINST_PUT1: case VFINST_PUT2: case VFINST_PUT3: case VFINST_PUT4:
 735         n = instr - VFINST_SET1 + 1;
 736         code_point = (UINT4)GET_UINTN(&dvi_prog[pc], n); pc += n;
 737         vf_dvi_interp_put_char(bmlist, vf, dvi_stack, code_point,
 738                                mode, fmag * mag_x, fmag * mag_y);
 739         break;  
 740       case VFINST_SETRULE:
 741         h = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
 742         w = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
 743         vf_dvi_interp_put_rule(bmlist, vf, dvi_stack, w, h, mag_x, mag_y);
 744         STACK(h) += w;
 745         break;
 746       case VFINST_PUTRULE:
 747         h = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
 748         w = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
 749         vf_dvi_interp_put_rule(bmlist, vf, dvi_stack, w, h, mag_x, mag_y);
 750         break;
 751       case VFINST_RIGHT1: case VFINST_RIGHT2: 
 752       case VFINST_RIGHT3: case VFINST_RIGHT4:
 753         n = instr - VFINST_RIGHT1 + 1;
 754         STACK(h) += (long)GET_INTN(&dvi_prog[pc], n); pc += n;
 755         break;
 756       case VFINST_X1: case VFINST_X2: case VFINST_X3: case VFINST_X4:
 757         n = instr - VFINST_X0;
 758         STACK(x) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
 759       case VFINST_X0:
 760         STACK(h) += STACK(x);
 761         break;
 762       case VFINST_W1: case VFINST_W2: case VFINST_W3: case VFINST_W4:
 763         n = instr - VFINST_W0;
 764         STACK(w) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
 765       case VFINST_W0: 
 766         STACK(h) += STACK(w);
 767         break;
 768       case VFINST_Y1: case VFINST_Y2: case VFINST_Y3: case VFINST_Y4:
 769         n = instr - VFINST_Y0;
 770         STACK(y) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
 771       case VFINST_Y0: 
 772         STACK(v) += STACK(y);
 773         break;
 774       case VFINST_Z1: case VFINST_Z2: case VFINST_Z3: case VFINST_Z4:
 775         n = instr - VFINST_Z0;
 776         STACK(z) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
 777       case VFINST_Z0: 
 778         STACK(v) += STACK(z);
 779         break;
 780       case VFINST_DOWN1: case VFINST_DOWN2: 
 781       case VFINST_DOWN3: case VFINST_DOWN4:
 782         n = instr - VFINST_DOWN1 + 1;
 783         STACK(v) += (long)GET_INTN(&dvi_prog[pc], n);
 784         break;
 785       case VFINST_XXX1: case VFINST_XXX2: case VFINST_XXX3: case VFINST_XXX4:
 786         n = instr - VFINST_XXX1 + 1;
 787         length = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
 788         pc += length;
 789         break;
 790       case VFINST_FNT1: case VFINST_FNT2: case VFINST_FNT3: case VFINST_FNT4:
 791         n = instr - VFINST_FNT1 + 1;
 792         f = GET_UINTN(&dvi_prog[pc], n); pc += n;
 793         vf_dvi_interp_font_select(vf, dvi_stack, f, &fmag);
 794         break;
 795       case VFINST_PUSH:
 796         vf_dvi_stack_push(vf, dvi_stack);
 797         break;
 798       case VFINST_POP:
 799         vf_dvi_stack_pop(vf, dvi_stack);
 800         break;
 801       case VFINST_NOP:
 802         break;
 803       default:
 804         vf_error = VF_ERR_ILL_FONT_FILE;
 805         ret = -1;
 806         goto ExitInterp;
 807       }
 808     }
 809   }
 810 
 811 ExitInterp:
 812   vf_dvi_stack_deinit(vf, dvi_stack);
 813   return ret;
 814 }
 815 
 816 Private void
 817 vf_dvi_interp_put_char(VF_BITMAPLIST bmlist, VF vf, VF_DVI_STACK dvi_stack,
     /* [<][>][^][v][top][bottom][index][help] */
 818                        long code_point, int mode, double mag_x, double mag_y)
 819 {
 820   VF_BITMAP  bm;
 821   double     rx, ry, ds;
 822   long       off_x, off_y;
 823 
 824   if (STACK(font_id) < 0)
 825     return;
 826   if (mode == 1){
 827     bm = VF_GetBitmap1(STACK(font_id), code_point, mag_x, mag_y);
 828   } else {
 829     bm = VF_GetBitmap2(STACK(font_id), code_point, mag_x, mag_y);
 830   }
 831 #if 0
 832   printf("** VF_GetBitmap(%d, 0x%lx, %.2f %.2f) = %p\n",
 833          STACK(font_id), code_point, mag_x, mag_y, bm);
 834   VF_DumpBitmap(bm);
 835 #endif
 836   if (bm == NULL)
 837     return;
 838 
 839   ds = vf->design_size / (double)(1<<20);
 840 #if 0 /*XXX*/
 841   rx = vf->mag_x * mag_x * (vf->dpi_x/72.27) * ds;
 842   ry = vf->mag_y * mag_y * (vf->dpi_y/72.27) * ds;
 843 #else
 844   rx = (vf->dpi_x/72.27) * ds;
 845   ry = (vf->dpi_y/72.27) * ds;
 846 #endif
 847   off_x =  rx * (double)STACK(h);
 848   off_y = -ry * (double)STACK(v);
 849 
 850   vf_bitmaplist_put(bmlist, bm, off_x, off_y);
 851 }
 852 
 853 Private void
 854 vf_dvi_interp_put_rule(VF_BITMAPLIST bmlist, VF vf, VF_DVI_STACK dvi_stack,
     /* [<][>][^][v][top][bottom][index][help] */
 855                        long w, long h, double mag_x, double mag_y)
 856 {
 857   VF_BITMAP      bm;
 858   double         rx, ry, ds;
 859   int            bm_w, bm_h;
 860   long           off_x, off_y;
 861 
 862   ds = vf->design_size / (double)(1<<20);
 863   rx = vf->mag_x * mag_x * vf->dpi_x/72.27 * ds;
 864   ry = vf->mag_y * mag_y * vf->dpi_y/72.27 * ds;
 865 
 866   bm_w = rx * w;
 867   bm_h = ry * h;
 868   if (bm_w <= 0)
 869     bm_w = 1;
 870   if (bm_h <= 0)
 871     bm_h = 1;
 872   
 873   bm = vf_alloc_bitmap(bm_w, bm_h);
 874   if (bm == NULL)
 875     return;
 876   VF_FillBitmap(bm);
 877 
 878   bm->off_x = 0;
 879   bm->off_y = bm_h - 1;
 880   off_x =  rx * (double)STACK(h);
 881   off_y = -ry * (double)STACK(v);
 882 
 883   vf_bitmaplist_put(bmlist, bm, off_x, off_y);
 884 }
 885 
 886 Private void
 887 vf_dvi_interp_font_select(VF vf, VF_DVI_STACK dvi_stack, long f,
     /* [<][>][^][v][top][bottom][index][help] */
 888                           double *fmag_p)
 889 {
 890   VF_SUBFONT  sf;
 891   
 892   STACK(f) = f;
 893   STACK(font_id) = -1;
 894   for (sf = vf->subfonts; sf != NULL; sf = sf->next){
 895     if (sf->k == f){
 896       STACK(font_id) = sf->font_id;
 897       if (fmag_p != NULL)
 898         *fmag_p = 1;
 899       break;
 900     }
 901   }
 902 }
 903 
 904 
 905 Private int
 906 vf_dvi_stack_init(VF vf, VF_DVI_STACK stack)
     /* [<][>][^][v][top][bottom][index][help] */
 907 {
 908   VF_DVI_STACK  top;
 909 
 910   ALLOC_IF_ERR(top, struct s_vf_dvi_stack){
 911     vf_error = VF_ERR_NO_MEMORY;
 912     return -1;
 913   }
 914   top->h = top->v = top->w = top->x = top->y = top->z = 0;
 915   top->f = vf->default_subfont;
 916   top->font_id = vf->subfonts->font_id;
 917   top->next    = NULL;
 918   stack->next = top;
 919   return 0;
 920 }
 921 
 922 Private int
 923 vf_dvi_stack_deinit(VF vf, VF_DVI_STACK stack)
     /* [<][>][^][v][top][bottom][index][help] */
 924 {
 925   VF_DVI_STACK  elem, elem_next;
 926 
 927   elem = stack->next; 
 928   while (elem != NULL){
 929     elem_next = elem->next;
 930     vf_free(elem);
 931     elem = elem_next;
 932   }
 933   return 0;  
 934 }
 935 
 936 Private int
 937 vf_dvi_stack_push(VF vf, VF_DVI_STACK stack)
     /* [<][>][^][v][top][bottom][index][help] */
 938 {
 939   VF_DVI_STACK  new_elem, top;
 940 
 941   ALLOC_IF_ERR(new_elem, struct s_vf_dvi_stack){
 942     vf_error = VF_ERR_NO_MEMORY;
 943     return -1;
 944   }
 945 
 946   top = stack->next;
 947   new_elem->h = top->h;
 948   new_elem->v = top->v;
 949   new_elem->w = top->w;
 950   new_elem->x = top->x;
 951   new_elem->y = top->y;
 952   new_elem->z = top->z;
 953   new_elem->f = top->f;
 954   new_elem->font_id = top->font_id;
 955   new_elem->next = top;
 956   stack->next = new_elem;
 957 
 958   return 0;
 959 }
 960 
 961 Private int
 962 vf_dvi_stack_pop(VF vf, VF_DVI_STACK stack)
     /* [<][>][^][v][top][bottom][index][help] */
 963 {
 964   VF_DVI_STACK  top;
 965 
 966   top = stack->next;
 967   if (top == NULL){
 968     fprintf(stderr, "VFlib warning: VF DVI stack under flow: %s\n",
 969             vf->vf_path);
 970     return -1;
 971   }
 972 
 973   stack->next = top->next;
 974   vf_free(top);
 975 
 976   return 0;
 977 }
 978 
 979 
 980 /*EOF*/

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