src/tfm.c

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

FUNCTIONS

This source file includes following functions.
  1. RDS2PT
  2. vf_tfm_init
  3. vf_tfm_open
  4. vf_tfm_jfm_chartype
  5. vf_tfm_metric
  6. read_tfm
  7. vf_tfm_free

   1 /*
   2  * tfm.c - TFM files interface
   3  *
   4  * 28 Sep 1996
   5  * 25 Mar 1997  Added setting a program name for kpathsea by variable.
   6  * 02 Apr 1997  Added support for .ofm files (Omega metrics file) (WL)
   7  *  3 Jul 1997  Added Virtual Font support.
   8  *  8 Aug 1997  for VFlib 3.3  
   9  *  1 Feb 1998  for VFlib 3.4
  10  */
  11 /*
  12  * Copyright (C) 1996-1998  by 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 #include  "config.h"
  29 #include  "with.h"
  30 
  31 #include  <stdio.h>
  32 #include  <stdlib.h>
  33 #include  <ctype.h>
  34 #ifdef HAVE_UNISTD_H
  35 #  include <unistd.h>
  36 #endif
  37 #include  "VFlib-3_6.h"
  38 #include  "VFsys.h"
  39 #include  "vflibcap.h"
  40 #include  "consts.h"
  41 #include  "metric.h"
  42 #include  "cache.h"
  43 #include  "sexp.h"
  44 #include  "texfonts.h"
  45 #include  "tfm.h"
  46 
  47 
  48 #define RDS2PT(rds)    (tfm->design_size * ((double)(rds)/(double)(1<<20)))
     /* [<][>][^][v][top][bottom][index][help] */
  49 
  50 
  51 Glocal SEXP_LIST     vf_tex_tfm_fontdirs;
  52 Glocal SEXP_LIST     vf_tex_tfm_extensions;
  53 
  54 Private VF_TABLE  tfm_table = NULL;
  55 
  56 
  57 
  58 Glocal int
  59 vf_tfm_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61   static int   inited = 0;
  62 
  63   if (inited == 0){
  64     inited = 1;
  65     if ((tfm_table = vf_table_create()) == NULL){
  66       vf_error = VF_ERR_NO_MEMORY;
  67       return -1;
  68     }
  69   }
  70 
  71   return 0;
  72 }
  73 
  74 
  75 Private TFM   read_tfm(FILE* fp);
  76 
  77 
  78 Glocal TFM
  79 vf_tfm_open(char *tfm_path)
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81   int    tfm_id;
  82   TFM    tfm;
  83   FILE   *fp;
  84 
  85   if ((tfm_id = (tfm_table->get_id_by_key)(tfm_table, tfm_path, 
  86                                            strlen(tfm_path)+1)) >= 0){
  87     (tfm_table->link_by_id)(tfm_table, tfm_id);
  88     return (tfm_table->get_obj_by_id)(tfm_table, tfm_id);
  89   }
  90 
  91 #if 0
  92   printf("* TFM Open: %s\n", tfm_path);
  93 #endif
  94 
  95   if ((fp = vf_fm_OpenBinaryFileStream(tfm_path)) == NULL)
  96     goto Error;
  97 
  98   if ((tfm = read_tfm(fp)) == NULL)
  99     goto Error;
 100 
 101   if ((tfm_table->put)(tfm_table, tfm, tfm_path, strlen(tfm_path)+1) < 0)
 102     return NULL;
 103 
 104   return tfm;
 105 
 106 
 107 Error:
 108   vf_error = VF_ERR_NO_METRIC_FILE;
 109   return NULL;
 110 }
 111 
 112 
 113 
 114 
 115 Glocal int
 116 vf_tfm_jfm_chartype(TFM tfm, UINT4 code)
     /* [<][>][^][v][top][bottom][index][help] */
 117 {
 118   int  i;
 119 
 120   tfm->ct_kcode[tfm->nt] = code; 
 121   i = 0;
 122   while (tfm->ct_kcode[i] != code)
 123     i++;
 124   if (i == tfm->nt)
 125     return 0;
 126   return tfm->ct_ctype[i];
 127 }
 128 
 129 
 130 Glocal VF_METRIC1
 131 vf_tfm_metric(TFM tfm, UINT4 code, VF_METRIC1 metric)
     /* [<][>][^][v][top][bottom][index][help] */
 132 {
 133   int      dir_h, index;
 134   double   w, h, d;
 135 
 136   if (metric == NULL)
 137     if ((metric = vf_alloc_metric1()) == NULL)
 138       return NULL;
 139 
 140   if ((tfm->type == METRIC_TYPE_TFM) || (tfm->type == METRIC_TYPE_OFM)){
 141     dir_h = 1;
 142     index = (int)code;
 143   } else {   /* == METRIC_TYPE_JFM */
 144     dir_h = (tfm->type_aux == METRIC_TYPE_JFM_AUX_H) ? 1 : 0;
 145     if (code == 0)
 146       index = 0;
 147     else
 148       index = vf_tfm_jfm_chartype(tfm, code);
 149   }
 150   if ((index < tfm->begin_char) || (tfm->end_char < index)){
 151     vf_error = VF_ERR_ILL_CODE_POINT;
 152     return NULL;
 153   }
 154 
 155   w = RDS2PT(tfm->width[index - tfm->begin_char]);
 156   h = RDS2PT(tfm->height[index - tfm->begin_char]);
 157   d = RDS2PT(tfm->depth[index - tfm->begin_char]);
 158 #if 0
 159   printf("* %d: W=%f H=%f D=%f\n", index, w, h, d);
 160 #endif
 161 
 162   if (dir_h == 1){
 163     metric->bbx_width  = w;
 164     metric->bbx_height = h + d;
 165     metric->off_x = 0;
 166     metric->off_y = h;
 167     metric->mv_x = w;
 168     metric->mv_y = 0;
 169   } else {
 170     metric->bbx_width  = h + d;
 171     metric->bbx_height = w;
 172     metric->off_x = -d;
 173     metric->off_y = 0;
 174     metric->mv_x = 0;
 175     metric->mv_y = -w;
 176   }
 177   return metric;
 178 }
 179 
 180 
 181 Private TFM
 182 read_tfm(FILE* fp)
     /* [<][>][^][v][top][bottom][index][help] */
 183 {
 184   TFM    tfm;
 185   UINT4  lf, lh, nc, nci, err;
 186   UINT4  offset_header, offset_char_info, offset_param;
 187   UINT4  nw,  nh,  nd,  ni, nl, nk, neng, np, dir;
 188   INT4   *w,  *h,  *d;
 189   UINT4  *ci, v;
 190   UINT4  i;
 191   INT4   bbxw, bbxh, xoff, yoff;
 192   
 193   ALLOC_IF_ERR(tfm, struct s_tfm){
 194     vf_error = VF_ERR_NO_MEMORY;
 195     return NULL;
 196   }
 197 
 198   tfm->width  = NULL;
 199   tfm->height = NULL;
 200   tfm->depth  = NULL;
 201   tfm->ct_kcode = NULL;
 202   tfm->ct_ctype = NULL;
 203 
 204   tfm->font_bbx_w = 0.0;
 205   tfm->font_bbx_h = 0.0;
 206   tfm->font_bbx_xoff = 0.0;
 207   tfm->font_bbx_yoff = 0.0;
 208   
 209   err = 0;
 210   rewind(fp);
 211   lf = (UINT4)READ_UINT2(fp);
 212   if ((lf == 11) || (lf == 9)){
 213     /* JFM file of Japanese TeX by ASCII Coop. */
 214     tfm->type        = METRIC_TYPE_JFM;
 215     tfm->type_aux    = (lf == 11)?METRIC_TYPE_JFM_AUX_H:METRIC_TYPE_JFM_AUX_V;
 216     tfm->nt          = (UINT4)READ_UINT2(fp);
 217     lf               = (UINT4)READ_UINT2(fp);
 218     lh               = (UINT4)READ_UINT2(fp);    
 219     offset_header    = 4*7;
 220     offset_char_info = 4*(7+tfm->nt+lh);
 221   } else if (lf == 0){
 222     /* Omega Metric File */
 223     tfm->type        = METRIC_TYPE_OFM;
 224     tfm->type_aux    = READ_INT2(fp);    /* ofm_level */
 225     if ((tfm->type_aux < 0) || (1 < tfm->type_aux))
 226       tfm->type_aux = 0;  /* broken, maybe */
 227     lf               = READ_UINT4(fp);
 228     lh               = READ_UINT4(fp);
 229     if (tfm->type_aux == 0){   /* level 0 OFM */
 230       offset_header    = 4*14;
 231       offset_char_info = 4*(14+lh);
 232     } else {                   /* level 1 OFM: *** NOT SUPPORTED YET *** */
 233       offset_header    = 4*29;
 234       offset_char_info = 4*(29+lh);
 235     }
 236   } else {
 237     /* Traditional TeX Metric File */
 238     tfm->type        = METRIC_TYPE_TFM;
 239     tfm->type_aux    = 0;
 240     lh               = (int)READ_UINT2(fp);    
 241     offset_header    = 4*6;
 242     offset_char_info = 4*(6+lh);
 243   }
 244 
 245   if (tfm->type == METRIC_TYPE_OFM){
 246     tfm->begin_char  = READ_UINT4(fp);
 247     tfm->end_char    = READ_UINT4(fp);
 248     nw   = READ_UINT4(fp);
 249     nh   = READ_UINT4(fp);
 250     nd   = READ_UINT4(fp);
 251 
 252     ni   = READ_UINT4(fp);
 253     nl   = READ_UINT4(fp);
 254     nk   = READ_UINT4(fp);
 255     neng = READ_UINT4(fp);
 256     np   = READ_UINT4(fp);
 257     dir  = READ_UINT4(fp); 
 258 
 259     if (((signed)(tfm->begin_char-1) > (signed)tfm->end_char) ||
 260         (tfm->end_char > 65535)){
 261       vf_error = VF_ERR_INVALID_METRIC;
 262       return NULL;
 263     }
 264   } else {
 265     tfm->begin_char  = (int)READ_UINT2(fp); 
 266     tfm->end_char    = (int)READ_UINT2(fp);
 267     nw   = (UINT4)READ_UINT2(fp);
 268     nh   = (UINT4)READ_UINT2(fp);
 269     nd   = (UINT4)READ_UINT2(fp);
 270 
 271     ni   = (UINT4)READ_UINT2(fp);
 272     nl   = (UINT4)READ_UINT2(fp);
 273     nk   = (UINT4)READ_UINT2(fp);
 274     neng = (UINT4)READ_UINT2(fp);
 275     np   = (UINT4)READ_UINT2(fp);
 276 
 277     if (tfm->type == METRIC_TYPE_TFM){
 278       if (((signed)(tfm->begin_char-1) > (signed)tfm->end_char) ||
 279           (tfm->end_char > 255)){
 280         vf_error = VF_ERR_INVALID_METRIC;
 281         return NULL;
 282       }
 283     }
 284   }
 285 
 286   fseek(fp, offset_header, SEEK_SET);
 287   tfm->cs          = READ_UINT4(fp); 
 288   tfm->ds          = READ_UINT4(fp); 
 289   tfm->design_size = (double)(tfm->ds)/(double)(1<<20);
 290   
 291   nc  = tfm->end_char - tfm->begin_char + 1;
 292   nci = nc;
 293   if (tfm->type == METRIC_TYPE_OFM)
 294     nci *= 2;
 295   ci = (UINT4*)calloc(nci, sizeof(UINT4));
 296   w  = (INT4*)calloc(nw,  sizeof(UINT4));
 297   h  = (INT4*)calloc(nh,  sizeof(UINT4));
 298   d  = (INT4*)calloc(nd,  sizeof(UINT4));
 299   if ((ci == NULL) || (w == NULL) || (h == NULL) || (d == NULL)){
 300     err = VF_ERR_NO_MEMORY;
 301     goto Exit;
 302   }
 303   fseek(fp, offset_char_info, SEEK_SET);
 304   for (i = 0; i < nci; i++)
 305     ci[i] = READ_UINT4(fp);
 306   offset_param = ftell(fp) + 4*(nw + nh + nd + ni + nl + nk + neng);
 307   for (i = 0; i < nw; i++)
 308     w[i] = READ_INT4(fp);
 309   for (i = 0; i < nh; i++)
 310     h[i] = READ_INT4(fp);
 311   for (i = 0; i < nd; i++)
 312     d[i] = READ_INT4(fp);
 313 
 314   tfm->width  = (INT4*)calloc(nc, sizeof(INT4));
 315   tfm->height = (INT4*)calloc(nc, sizeof(INT4));
 316   tfm->depth  = (INT4*)calloc(nc, sizeof(INT4));
 317   if ((tfm->width == NULL) || (tfm->height == NULL) || (tfm->depth == NULL)){
 318     err = VF_ERR_NO_MEMORY;
 319     goto Exit;
 320   }
 321   bbxw = 0;
 322   bbxh = 0;
 323   xoff = 0;
 324   yoff = 0;
 325   if (tfm->type == METRIC_TYPE_OFM){
 326     for (i = 0; i < nc; i++){
 327       v = ci[2*i];
 328       tfm->depth[i]  = d[v & 0xff]; v >>= 8;
 329       tfm->height[i] = h[v & 0xff]; v >>= 8;
 330       tfm->width[i]  = w[v & 0xffff];
 331       if (bbxw < tfm->width[i])
 332         bbxw = tfm->width[i];
 333       if (bbxh < (tfm->height[i] + tfm->depth[i]))
 334         bbxh = tfm->height[i] + tfm->depth[i];
 335       if (yoff > -tfm->depth[i])
 336         yoff = -tfm->depth[i];
 337 #if 0
 338       printf("** %.3f %.3f %.3f\n",
 339              (double)tfm->width[i]/(double)(1<<20), 
 340              (double)tfm->height[i]/(double)(1<<20), 
 341              (double)tfm->depth[i]/(double)(1<<20));
 342 #endif
 343     }
 344   } else {
 345     for (i = 0; i < nc; i++){
 346       v = ci[i] / 0x10000L;
 347       tfm->depth[i]  = d[v & 0xf];  v >>= 4;
 348       tfm->height[i] = h[v & 0xf];  v >>= 4;
 349       tfm->width[i]  = w[v & 0xff];
 350       if (bbxw < tfm->width[i])
 351         bbxw = tfm->width[i];
 352       if (bbxh < (tfm->height[i] + tfm->depth[i]))
 353         bbxh = tfm->height[i] + tfm->depth[i];
 354       if (yoff > -tfm->depth[i])
 355         yoff = -tfm->depth[i];
 356 #if 0
 357       printf("** %.3f %.3f\n",
 358              (double)tfm->height[i]/(double)(1<<20), 
 359              (double)tfm->depth[i]/(double)(1<<20));
 360 #endif
 361     }
 362   }
 363   tfm->font_bbx_w = tfm->design_size * ((double)bbxw / (double)(1<<20));
 364   tfm->font_bbx_h = tfm->design_size * ((double)bbxh / (double)(1<<20));
 365   tfm->font_bbx_xoff = tfm->design_size * ((double)xoff / (double)(1<<20));
 366   tfm->font_bbx_yoff = tfm->design_size * ((double)yoff / (double)(1<<20));
 367 
 368   if (tfm->type == METRIC_TYPE_JFM){
 369     fseek(fp, 4*(7+lh), SEEK_SET);
 370     tfm->ct_kcode = (unsigned int*)calloc(tfm->nt+1, sizeof(unsigned int));
 371     tfm->ct_ctype = (unsigned int*)calloc(tfm->nt+1, sizeof(unsigned int));
 372     if ((tfm->ct_kcode == NULL) || (tfm->ct_ctype == NULL)){
 373       err = VF_ERR_NO_MEMORY;
 374       goto Exit;
 375     }
 376     for (i = 0; i < tfm->nt; i++){
 377       v = READ_UINT4(fp);
 378       tfm->ct_kcode[i] = v/0x10000L;
 379       tfm->ct_ctype[i] = v%0x10000L;
 380     }
 381     tfm->ct_kcode[tfm->nt] = 0; /* sentinel */
 382     tfm->ct_ctype[tfm->nt] = 0;
 383   }
 384 
 385   fseek(fp, offset_param, SEEK_SET);
 386   tfm->slant = (double)READ_INT4(fp)/(double)(1<<20);
 387 
 388 Exit:
 389   vf_free(ci);
 390   vf_free(w);
 391   vf_free(h);
 392   vf_free(d);
 393 
 394   if (err != 0){
 395     vf_tfm_free(tfm);
 396     vf_error = err;
 397     return NULL;
 398   }
 399   return tfm;
 400 }
 401 
 402 
 403 Glocal void
 404 vf_tfm_free(TFM tfm)
     /* [<][>][^][v][top][bottom][index][help] */
 405 {
 406   int  tfm_id;
 407 
 408   if (tfm == NULL)
 409     return;
 410 
 411   tfm_id = (tfm_table->get_id_by_obj)(tfm_table, tfm);
 412   if (tfm_id < 0)
 413     return;
 414 
 415   if ((tfm_table->unlink_by_id)(tfm_table, tfm_id) <= 0){
 416     vf_free(tfm->width);    
 417     vf_free(tfm->height);
 418     vf_free(tfm->depth);    
 419     vf_free(tfm->ct_kcode);
 420     vf_free(tfm->ct_ctype);
 421     vf_free(tfm);
 422   }
 423 }
 424 
 425 
 426 /*EOF*/

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