src/drv_jtex.c

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

FUNCTIONS

This source file includes following functions.
  1. VF_Init_Driver_JTEX
  2. jtex_create
  3. release_font_jtex
  4. jtex_close
  5. jtex_get_metric1
  6. jtex_get_fontbbx1
  7. jtex_get_bitmap1
  8. jtex_get_outline
  9. jtex_get_metric2
  10. jtex_get_fontbbx2
  11. jtex_get_bitmap2
  12. jtex_get_font_prop
  13. jtex_query_font_type
  14. jtex_rotate_bitmap
  15. jtex_met_adjustment
  16. jtex_met_cc_adjustment
  17. jtex_read_met_adjustment_file
  18. jtex_free_adj
  19. realloc_cc_corr
  20. find_adj

   1 /*
   2  * drv_jtex.c - A font driver for ASCII Japanese TeX Kanji fonts.
   3  *
   4  *  4 Oct 1996  First version.
   5  * 17 Jan 1997  for VFlib 3.1
   6  * 26 Feb 1997  Added 'query_font_type'.
   7  *  4 Aug 1997  VFlib 3.3  Changed API.
   8  * 15 Feb 1998  VFlib 3.4  Changed API.
   9  * 21 Apr 1998  Added 'implicit-font-mapping-suffix' capability
  10  * 27 Jul 1998  Added a code to return some font properties by itself.
  11  * 07 Sep 1998  Added 'char-all' directive in adj file.
  12  * 24 Nov 1998  Added get_fontbbx1() and get_fontbbx2().
  13  * 20 Jan 1999  Changed to adj file searching.
  14  * 29 Jul 1999  Fixed bugs in jtex_met_adjustment().
  15  */
  16 /*
  17  * Copyright (C) 1996-1999  Hirotsugu Kakugawa. 
  18  * All rights reserved.
  19  *
  20  * This file is part of the VFlib Library.  This library is free
  21  * software; you can redistribute it and/or modify it under the terms of
  22  * the GNU Library General Public License as published by the Free
  23  * Software Foundation; either version 2 of the License, or (at your
  24  * option) any later version.  This library is distributed in the hope
  25  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  26  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  27  * PURPOSE.  See the GNU Library General Public License for more details.
  28  * You should have received a copy of the GNU Library General Public
  29  * License along with this library; if not, write to the Free Software
  30  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  31  */
  32 
  33 #include  "config.h"
  34 #include  <stdio.h>
  35 #include  <stdlib.h>
  36 #ifdef HAVE_UNISTD_H
  37 #  include <unistd.h>
  38 #endif
  39 #include  <ctype.h>
  40 #include  <sys/param.h>
  41 #include  <math.h>
  42 #include  "VFlib-3_6.h"
  43 #include  "VFsys.h"
  44 #include  "vflibcap.h"
  45 #include  "bitmap.h"
  46 #include  "sexp.h"
  47 #include  "str.h"
  48 #include  "path.h"
  49 #include  "vflpaths.h"
  50 #include  "metric.h"
  51 #include  "fsearch.h"
  52 #include  "tfm.h"
  53 #include  "jtex.h"
  54 
  55 Private int vf_dbg_drv_ascii_jtex      = 0;
  56 Private int vf_dbg_drv_ascii_jtex_dump = 0;
  57 Private int vf_dbg_drv_ascii_jtex_adj  = 0;
  58 
  59 
  60 #define KW_CHAR_TYPE             "char-type"
  61 #define KW_CHAR_CODE             "char-code"
  62 #define KW_CHAR_ALL              "char-all"
  63 
  64 #define KW_SEMANTICS             "semantics"
  65 #define KW_SEM_BITMAP               "bitmap-size"
  66 #define KW_SEM_DESIGN               "design-size"
  67 #define SEMANTICS_AUX_BITMAP        0
  68 #define SEMANTICS_DESIGN_SIZE       1
  69 
  70 #define KW_DIR                   "direction"
  71 #define KW_DIR_HORIZONTAL           "horizontal"
  72 #define KW_DIR_VERTICAL             "vertical"
  73 #define DIR_HORIZONTAL              0
  74 #define DIR_VERTICAL                1
  75 
  76 #define KW_ROTATION              "rotation-semantics"
  77 #define KW_ROT_PTEX                 "ptex"
  78 #define KW_ROT_JISX0208             "jisx0208"
  79 #define ROT_JISX0208                (1<<0)
  80 #define ROT_PTEX                   ((1<<1) | ROT_JISX0208)
  81 
  82 
  83 
  84 #define N_CC_CORR   64
  85 
  86 struct s_met_adj_ct_corr {
  87   int     need_cc_corr;
  88   int     may_need_rotate;
  89   double  dx, dy;
  90 };
  91 struct s_met_adj_cc_corr {
  92   long    code_point;
  93   double  dx, dy;
  94 };
  95 typedef struct s_met_adj_cc_corr  *ADJ_CC_CORR;
  96 
  97 struct s_met_adj_table {
  98   int   semantics;
  99   int   dir;
 100   int   rot_semantics;
 101   struct s_met_adj_ct_corr  ct_corr[JTEX_MAX_CHARTYPE];
 102   struct s_met_adj_ct_corr  ct_corr_all;
 103   int   n_cc_corr;
 104   struct s_met_adj_cc_corr *cc_corr;
 105 };
 106 typedef struct s_met_adj_table  *ADJ;
 107 
 108 
 109 struct s_vert_rotation {
 110   int   code_point;
 111   int   angle;
 112   int   mirror;
 113   int   rot_semantics;
 114 };
 115 static struct s_vert_rotation VertCharInfo[] = {
 116   /* Code,  Rotation Angle, Mirror, Rotation in JISX0208 */
 117   { 0x213c, VF_BM_ROTATE_270, 1, ROT_JISX0208 }, /* Chou-On */
 118   { 0x213d, VF_BM_ROTATE_270, 0, ROT_PTEX },     /* Zenkaku-dash */
 119   { 0x213e, VF_BM_ROTATE_270, 0, ROT_PTEX },     /* Hyphen-dash */
 120   { 0x2141, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Nami-dash */
 121   { 0x2144, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Santen leader */
 122   { 0x2142, VF_BM_ROTATE_270, 0, ROT_PTEX },     /* Heikou */
 123   { 0x2143, VF_BM_ROTATE_270, 0, ROT_PTEX },     /* Tatesen */
 124   { 0x2145, VF_BM_ROTATE_270, 0, ROT_PTEX },     /* Niten leader */
 125   { 0x214a, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Syou-Kakko */
 126   { 0x214b, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Syou-Kakko */
 127   { 0x214c, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Kikkou-Kakko */
 128   { 0x214d, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Kikkou-Kakko */
 129   { 0x214e, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Kaku-Kakko */
 130   { 0x214f, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Kaku-Kakko */
 131   { 0x2150, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Chuu-Kakko */
 132   { 0x2151, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Chuu-Kakko */
 133   { 0x2152, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Yama-Kakko */
 134   { 0x2153, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Yama-Kakko */
 135   { 0x2154, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* NijuuYama-Kakko */
 136   { 0x2155, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* NijuuYama-Kakko */
 137   { 0x2156, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Kagi-Kakko */
 138   { 0x2157, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Kagi-Kakko */
 139   { 0x2158, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* NijuuKagi-Kakko */
 140   { 0x2159, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* NijuuKagi-Kakko */
 141   { 0x215a, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Sumitsuki-Kakko */
 142   { 0x215b, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* Sumitsuki-Kakko */
 143   { 0x2161, VF_BM_ROTATE_270, 0, ROT_JISX0208 }, /* '=' sign */
 144   { -1, -1, -1, -1 }
 145 };
 146 
 147 
 148 struct s_font_jtex {
 149   char     *font_name;
 150   char     *kanji_font;
 151   int      kanji_font_id;
 152   double   kf_point_size;
 153   int      kf_pixel_size;
 154   double   kf_mag;
 155   char     *tfm_file;
 156   TFM      tfm;
 157   char     *adj_file;
 158   ADJ      adj;
 159   double   mode2_factor_x, mode2_factor_y;
 160   SEXP     props;
 161 };
 162 typedef struct s_font_jtex  *FONT_JTEX;
 163 
 164 
 165 Private SEXP_STRING  default_map_suffix     = NULL;
 166 Private SEXP_LIST    default_tfm_dirs       = NULL;
 167 Private SEXP_LIST    default_tfm_extensions = NULL;
 168 Private SEXP_ALIST   default_properties     = NULL;
 169 Private SEXP_ALIST   default_variables      = NULL;
 170 Private SEXP_STRING  default_debug_mode     = NULL;
 171 
 172 
 173 Private int        jtex_create(VF_FONT,char*,char*,int,SEXP);
 174 Private int        jtex_close(VF_FONT);
 175 Private int        jtex_get_metric1(VF_FONT,long,VF_METRIC1,double,double);
 176 Private int        jtex_get_metric2(VF_FONT,long,VF_METRIC2,double,double);
 177 Private int        jtex_get_fontbbx1(VF_FONT,double,double,
 178                                      double*,double*,double*,double*);
 179 Private int        jtex_get_fontbbx2(VF_FONT,double,double, 
 180                                      int*,int*,int*,int*);
 181 Private VF_BITMAP  jtex_get_bitmap1(VF_FONT,long,double,double);
 182 Private VF_BITMAP  jtex_get_bitmap2(VF_FONT,long,double,double);
 183 Private VF_OUTLINE jtex_get_outline(VF_FONT,long,double,double);
 184 Private int        jtex_query_font_type(VF_FONT,long);
 185 Private char      *jtex_get_font_prop(VF_FONT,char*);
 186 Private VF_BITMAP  jtex_rotate_bitmap(VF_BITMAP bm0, long code_point, 
 187                                       FONT_JTEX font_jtex, int *need_free_p);
 188 Private int        jtex_met_adjustment(VF_BITMAP,VF_METRIC2,long,
 189                                        VF_FONT,FONT_JTEX,double,double);
 190 Private ADJ        jtex_read_met_adjustment_file(FONT_JTEX,char*);
 191 Private void       jtex_free_adj(ADJ adj);
 192 Private void       jtex_met_cc_adjustment(ADJ adj, long code_point,
 193                                           int char_type, 
 194                                           double *fxp, double *fyp);
 195 Private ADJ        realloc_cc_corr(ADJ adj);
 196 Private char      *find_adj(char *fname);
 197 Private void       release_font_jtex(FONT_JTEX);
 198 
 199 
 200 
 201 
 202 Public int
 203 VF_Init_Driver_JTEX(void)
     /* [<][>][^][v][top][bottom][index][help] */
 204 {
 205   struct s_capability_table  ct[10];
 206   int  z;
 207   
 208   z = 0;
 209   /* VF_CAPE_JTEX_MAP_SUFIX */
 210   ct[z].cap = VF_CAPE_JTEX_MAP_SUFIX;      ct[z].type = CAPABILITY_STRING;
 211   ct[z].ess = CAPABILITY_OPTIONAL;         ct[z++].val = &default_map_suffix;
 212   /* VF_CAPE_TEX_TFM_DIRECTORIES */
 213   ct[z].cap = VF_CAPE_TEX_TFM_DIRECTORIES; ct[z].type = CAPABILITY_LIST;
 214   ct[z].ess = CAPABILITY_OPTIONAL;         ct[z++].val = &default_tfm_dirs;
 215   /* VF_CAPE_TEX_TFM_EXTENSIONS */
 216   ct[z].cap = VF_CAPE_TEX_TFM_EXTENSIONS;  ct[z].type = CAPABILITY_LIST;
 217   ct[z].ess = CAPABILITY_OPTIONAL;      ct[z++].val = &default_tfm_extensions;
 218   /* VF_CAPE_PROPERTIES */
 219   ct[z].cap = VF_CAPE_PROPERTIES;          ct[z].type = CAPABILITY_ALIST;
 220   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_properties;
 221   /* VF_CAPE_VARIABLE_VALUES */
 222   ct[z].cap = VF_CAPE_VARIABLE_VALUES;      ct[z].type = CAPABILITY_ALIST;
 223   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_variables;
 224   /* VF_CAPE_DEBUG */
 225   ct[z].cap = VF_CAPE_DEBUG;                ct[z].type = CAPABILITY_STRING;
 226   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &default_debug_mode;
 227   /* end */
 228   ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
 229 
 230 
 231   if (vf_cap_GetParsedClassDefault(FONTCLASS_NAME_JTEX, ct, NULL, NULL) 
 232       == VFLIBCAP_PARSED_ERROR)
 233     return -1;
 234 
 235   if (vf_tex_init() < 0)
 236     return -1;
 237 
 238   if (getenv("VFLIB_DEBUG_ASCII_JTEX") != NULL)
 239     vf_dbg_drv_ascii_jtex = 1;
 240 
 241   if (getenv("VFLIB_DEBUG_ASCII_JTEX_DUMP") != NULL)
 242     vf_dbg_drv_ascii_jtex_dump = 1;
 243 
 244   if (getenv("VFLIB_DEBUG_ASCII_JTEX_ADJ") != NULL)
 245     vf_dbg_drv_ascii_jtex_adj = 1;
 246 
 247   VF_InstallFontDriver(FONTCLASS_NAME_JTEX, (DRIVER_FUNC_TYPE)jtex_create);
 248 
 249   return 0;
 250 }
 251 
 252 
 253 Private int
 254 jtex_create(VF_FONT font, char *font_class, 
     /* [<][>][^][v][top][bottom][index][help] */
 255             char *font_name, int implicit, SEXP entry)
 256 {
 257   FONT_JTEX   font_jtex;
 258   double      point_size, dpi, dpix = 0.0, dpiy = 0.0;
 259   int         pixel_size;
 260   char        *mapped_font, *name_core, *suffix, *tfm_path, *p;
 261   SEXP        entry2, cap_kanji, cap_kf_point, cap_kf_pixel, cap_kf_mag;
 262   SEXP        cap_tfm, cap_adj, cap_props;
 263   SEXP        tfm_ext;
 264   struct s_capability_table  ct[10];
 265   int  z;
 266 
 267   z = 0;
 268   /* VF_CAPE_FONT_CLASS */
 269   ct[z].cap = VF_CAPE_FONT_CLASS;           ct[z].type = CAPABILITY_STRING;
 270   ct[z].ess = CAPABILITY_ESSENTIAL;         ct[z++].val = NULL;
 271   /* VF_CAPE_JTEX_KANJI_FONT */
 272   ct[z].cap = VF_CAPE_JTEX_KANJI_FONT;      ct[z].type = CAPABILITY_STRING;
 273   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_kanji;
 274   /* VF_CAPE_JTEX_KF_POINT_SIZE */
 275   ct[z].cap = VF_CAPE_JTEX_KF_POINT_SIZE;   ct[z].type = CAPABILITY_STRING;
 276   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_kf_point;
 277   /* VF_CAPE_JTEX_KF_PIXEL_SIZE */
 278   ct[z].cap = VF_CAPE_JTEX_KF_PIXEL_SIZE;   ct[z].type = CAPABILITY_STRING;
 279   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_kf_pixel;
 280   /* VF_CAPE_JTEX_KF_MAG */
 281   ct[z].cap = VF_CAPE_JTEX_KF_MAG;          ct[z].type = CAPABILITY_STRING;
 282   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_kf_mag;
 283   /* VF_CAPE_JTEX_TFM_FILE */
 284   ct[z].cap = VF_CAPE_JTEX_TFM_FILE;        ct[z].type = CAPABILITY_STRING;
 285   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_tfm;
 286   /* VF_CAPE_JTEX_ADJUSTMENT_FILE */
 287   ct[z].cap = VF_CAPE_JTEX_ADJUSTMENT_FILE; ct[z].type = CAPABILITY_STRING;
 288   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_adj;
 289   /* VF_CAPE_PROPERTIES */
 290   ct[z].cap = VF_CAPE_PROPERTIES;           ct[z].type = CAPABILITY_ALIST;
 291   ct[z].ess = CAPABILITY_OPTIONAL;          ct[z++].val = &cap_props;
 292   /* end */
 293   ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
 294 
 295 
 296   font_jtex = NULL;
 297   mapped_font = NULL;
 298   name_core = NULL;
 299   tfm_path = NULL;
 300   entry2 = NULL;
 301 
 302   if (vf_dbg_drv_ascii_jtex == 1){
 303     printf(">>VFlib ascii jtex: open request %s\n", font_name);
 304   }
 305 
 306   if (implicit == 1){
 307     /* font name mapping: 
 308      *   requested font: "min10.400pk" or "min10.pk"
 309      *    ==>  "min10XXX", where XXX is a suffix (e.g., ".pk")
 310      */
 311     suffix = "";
 312     if ((default_map_suffix != NULL) 
 313         && (vf_sexp_get_cstring(default_map_suffix) != NULL)){
 314       suffix = vf_sexp_get_cstring(default_map_suffix);
 315     }
 316     if ((name_core = vf_path_base_core(font_name)) == NULL)
 317       return -1;
 318     ALLOCN_IF_ERR(mapped_font, char, strlen(name_core)+strlen(suffix)+1){
 319       vf_free(name_core);
 320       return -1;
 321     }
 322     sprintf(mapped_font, "%s%s", name_core, suffix);
 323     if (vf_dbg_drv_ascii_jtex == 1){
 324       printf(">>VFlib ascii jtex font mapping:  %s ==> %s\n", 
 325              font_name, mapped_font);
 326     }
 327     if (strcmp(mapped_font, font_name) == 0){        /* a loop */
 328       vf_free(name_core);
 329       vf_free(mapped_font);
 330       return -1;
 331     }
 332 
 333     /* Parse font name.  Formats of file names that this routine supports:
 334      *   "cmr10.300XX" - A "cmr10" font for 300 dpi.
 335      *   "cmr10.XX"    - A "cmr10" font. Dpi value is default value.
 336      *   "cmr10"       -   ditto.
 337      * ("XX" can be any string such as "pk", "gf", and "tfm".)
 338      */
 339     if (font->mode == 1){
 340       p = vf_index(font_name, '.');
 341       dpi = font->dpi_y;
 342       if ((p != NULL) && (isdigit((int)*(p+1)))){ /* "cmr10.300gf" */
 343         if (dpi < 0)
 344           dpi = (double)atoi(p+1);
 345       } else {                  /* "cmr10" or "cmr10.gf" */
 346         if (dpi < 0)
 347           dpi = (double)vf_tex_default_dpi();
 348       }
 349       dpix = dpi * (double)font->dpi_x / (double)font->dpi_y;
 350       dpiy = dpi;
 351     }
 352 
 353     if ((entry2 = vf_cap_GetFontEntry(mapped_font)) == NULL){
 354       vf_error = VF_ERR_NO_FONT_ENTRY;
 355       vf_free(name_core);
 356       vf_free(mapped_font);
 357       return -1;
 358     }
 359     if (vf_cap_GetParsedFontEntry(entry2, mapped_font, ct, 
 360                                   default_variables, NULL)
 361         == VFLIBCAP_PARSED_ERROR){
 362       vf_sexp_free(&entry2);
 363       vf_free(name_core);
 364       vf_free(mapped_font);
 365       return -1;
 366     }
 367   } else {
 368     if (vf_cap_GetParsedFontEntry(entry, font_name, ct, 
 369                                   default_variables, NULL)
 370         == VFLIBCAP_PARSED_ERROR){
 371       return -1;
 372     }
 373     dpi = font->dpi_y;
 374     if (dpi < 0)
 375       dpi = (double)vf_tex_default_dpi();
 376     dpix = dpi * (double)font->dpi_x / (double)font->dpi_y;
 377     dpiy = dpi;
 378   }
 379 
 380   font->font_type       = VF_FONT_TYPE_UNDEF; /* call jtex_query_font_type() */
 381   font->get_metric1     = jtex_get_metric1;
 382   font->get_metric2     = jtex_get_metric2;
 383   font->get_fontbbx1    = jtex_get_fontbbx1;
 384   font->get_fontbbx2    = jtex_get_fontbbx2;
 385   font->get_bitmap1     = jtex_get_bitmap1;
 386   font->get_bitmap2     = jtex_get_bitmap2;
 387   font->get_outline     = jtex_get_outline;
 388   font->get_font_prop   = jtex_get_font_prop;
 389   font->query_font_type = jtex_query_font_type;
 390   font->close           = jtex_close;
 391 
 392   ALLOC_IF_ERR(font_jtex, struct s_font_jtex){
 393     vf_error = VF_ERR_NO_MEMORY;
 394     vf_sexp_free(&entry2);
 395     vf_free(name_core);
 396     vf_free(mapped_font);
 397     return -1;
 398   }
 399 
 400   font_jtex->font_name      = vf_strdup(font_name);
 401   font_jtex->kanji_font     = NULL;
 402   font_jtex->kanji_font_id  = -1;
 403   font_jtex->kf_point_size  = -1;
 404   font_jtex->kf_pixel_size  = -1;
 405   font_jtex->kf_mag         = 1.0;
 406   font_jtex->tfm_file       = NULL;
 407   font_jtex->tfm            = NULL;
 408   font_jtex->adj_file       = NULL;
 409   font_jtex->adj            = NULL;
 410   font_jtex->mode2_factor_x = -1;
 411   font_jtex->mode2_factor_y = -1;
 412   font_jtex->props          = NULL;
 413 
 414   if (default_tfm_extensions == NULL)
 415     default_tfm_extensions = vf_sexp_cstring2list(DEFAULT_EXTENSIONS_TFM);
 416   if (cap_kanji != NULL)
 417     font_jtex->kanji_font = vf_strdup(vf_sexp_get_cstring(cap_kanji));
 418   else 
 419     font_jtex->kanji_font = vf_path_base_core(font_name);
 420   if (font_jtex->kanji_font == NULL){
 421     vf_error = VF_ERR_NO_AUX_FONT_NAME;
 422     vf_sexp_free(&entry2);
 423     vf_free(name_core);
 424     vf_free(mapped_font);
 425     vf_free(font_jtex);
 426     return -1;
 427   }
 428   if (cap_kf_point != NULL)
 429     font_jtex->kf_point_size = atof(vf_sexp_get_cstring(cap_kf_point));
 430   if (cap_kf_pixel != NULL)
 431     font_jtex->kf_pixel_size = atoi(vf_sexp_get_cstring(cap_kf_pixel));
 432   if (cap_kf_mag != NULL)
 433     font_jtex->kf_mag = atof(vf_sexp_get_cstring(cap_kf_mag));
 434   if (cap_tfm != NULL)
 435     font_jtex->tfm_file = vf_strdup(vf_sexp_get_cstring(cap_tfm));
 436   else
 437     font_jtex->tfm_file = vf_path_base_core(font_name);
 438   if (cap_adj != NULL)
 439     font_jtex->adj_file = vf_strdup(vf_sexp_get_cstring(cap_adj));
 440   font_jtex->props = cap_props;
 441 
 442   if (vf_dbg_drv_ascii_jtex == 1){
 443     printf(">>VFlib ascii jtex font name:  %s\n",   font_jtex->font_name);
 444     printf(">>VFlib ascii jtex kanji font: %s\n",   font_jtex->kanji_font);
 445     printf(">>VFlib ascii jtex tfm file:   %s\n",   font_jtex->tfm_file);
 446     printf(">>VFlib ascii jtex adj file:   %s\n",   font_jtex->adj_file);
 447     printf(">>VFlib ascii jtex kf point:   %.3f\n", font_jtex->kf_point_size);
 448     printf(">>VFlib ascii jtex kf pixel:   %d\n",   font_jtex->kf_pixel_size);
 449     printf(">>VFlib ascii jtex kf mag:     %.3f\n", font_jtex->kf_mag);
 450   }
 451 
 452   /* Open aux kanji font */
 453   if (font->mode == 1){
 454     if ((point_size = font->point_size) < 0)
 455       point_size = font_jtex->kf_point_size;
 456     font_jtex->kanji_font_id
 457       = VF_OpenFont1(font_jtex->kanji_font, dpix, dpiy, point_size, 
 458                      font->mag_x * font_jtex->kf_mag, 
 459                      font->mag_y * font_jtex->kf_mag);
 460   } else if (font->mode == 2){
 461     if ((pixel_size = font->pixel_size) < 0)
 462       pixel_size = font_jtex->kf_pixel_size;
 463     font_jtex->kanji_font_id 
 464       = VF_OpenFont2(font_jtex->kanji_font, pixel_size,
 465                      font->mag_x * font_jtex->kf_mag,
 466                      font->mag_y * font_jtex->kf_mag);
 467   }
 468   if (vf_dbg_drv_ascii_jtex == 1)
 469     printf(">>VFlib ascii jtex:  Aux Kanji font ID: %d\n",
 470            font_jtex->kanji_font_id);
 471 
 472   if (font_jtex->kanji_font_id < 0){
 473     vf_error = VF_ERR_NO_FONT_ENTRY;
 474     goto Error;
 475   }
 476 
 477   /* Search TFM */
 478   tfm_ext = (cap_tfm != NULL) ? NULL : default_tfm_extensions;
 479   tfm_path = vf_tex_search_file_tfm(font_jtex->tfm_file,
 480                                     default_tfm_dirs, tfm_ext);
 481   if (vf_dbg_drv_ascii_jtex == 1)
 482     printf(">>VFlib ascii jtex:  TFM path: %s ==> %s\n",
 483            font_jtex->tfm_file, (tfm_path==NULL)?"(not found)":tfm_path);
 484   if (tfm_path == NULL)
 485     goto Error;
 486   if ((font_jtex->tfm = vf_tfm_open(tfm_path)) == NULL)
 487     goto Error;
 488 
 489   /* Check if it is a JFM (Japanese Font Metric) format */
 490   if (font_jtex->tfm->type != METRIC_TYPE_JFM){
 491     vf_error = VF_ERR_NOT_JFM;
 492     goto Error;
 493   }
 494 
 495   /* Read ADJ file */
 496   if (cap_adj != NULL){
 497     font_jtex->adj_file = vf_strdup(vf_sexp_get_cstring(cap_adj));
 498     if (font_jtex->adj_file != NULL)
 499       font_jtex->adj 
 500         = jtex_read_met_adjustment_file(font_jtex, font_jtex->adj_file);
 501     if (font_jtex->adj == NULL){
 502       fprintf(stderr, "VFlib warning: Can't read: %s\n", font_jtex->adj_file);
 503     }
 504   } else {
 505     fprintf(stderr, "VFlib warning: no ADJ file.\n");
 506   }
 507 
 508   if (font->mode == 2){
 509     p = VF_GetFontProp(font_jtex->kanji_font_id, "PIXEL_SIZE");
 510     if (p != NULL){
 511       font_jtex->mode2_factor_x
 512         = font->mag_x * atof(p) / font_jtex->tfm->design_size;
 513       font_jtex->mode2_factor_y
 514         = font->mag_y * atof(p) / font_jtex->tfm->design_size;
 515 #if 0
 516       printf("*** pixel_size:%.3f  design_size: %.3f\n", 
 517              atof(p), font_jtex->tfm->design_size);
 518       printf("*** factor_x:%.3f  factor_y: %.3f\n", 
 519              font_jtex->mode2_factor_x, font_jtex->mode2_factor_y);
 520 #endif
 521     }
 522   }    
 523 
 524   font->private = font_jtex;
 525 
 526   vf_free(mapped_font);
 527   vf_free(name_core);
 528   vf_free(tfm_path);
 529   if (implicit == 0){
 530     vf_sexp_free4(&cap_kanji, &cap_kf_point, &cap_kf_pixel, &cap_kf_mag);
 531     vf_sexp_free2(&cap_tfm, &cap_adj);
 532   }
 533   vf_sexp_free(&entry2);
 534   return 0;
 535 
 536 
 537 Error:
 538   release_font_jtex(font_jtex);
 539   vf_free(mapped_font);
 540   vf_free(name_core);
 541   vf_free(tfm_path);
 542   if (implicit == 0){
 543     vf_sexp_free4(&cap_kanji, &cap_kf_point, &cap_kf_pixel, &cap_kf_mag);
 544     vf_sexp_free2(&cap_tfm, &cap_adj);
 545     vf_sexp_free(&cap_props);
 546   }
 547   vf_sexp_free(&entry2);
 548   return -1;
 549 }
 550 
 551 
 552 Private void
 553 release_font_jtex(FONT_JTEX font_jtex)
     /* [<][>][^][v][top][bottom][index][help] */
 554 {
 555   if (font_jtex != NULL){
 556     vf_free(font_jtex->font_name);
 557     vf_free(font_jtex->kanji_font);
 558     if (font_jtex->kanji_font_id >= 0)
 559       VF_CloseFont(font_jtex->kanji_font_id);
 560     vf_free(font_jtex->tfm_file);
 561     vf_tfm_free(font_jtex->tfm);
 562     vf_free(font_jtex->adj_file); 
 563     jtex_free_adj(font_jtex->adj);
 564     vf_sexp_free1(&font_jtex->props);
 565     vf_free(font_jtex); 
 566   }
 567 }
 568 
 569 
 570 Private int
 571 jtex_close(VF_FONT font)
     /* [<][>][^][v][top][bottom][index][help] */
 572 {
 573   FONT_JTEX    font_jtex;
 574 
 575   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 576     fprintf(stderr, "VFlib: internal error in jtex_close()\n");
 577     abort();
 578   }
 579 
 580   release_font_jtex(font_jtex);
 581   return 0; 
 582 }
 583 
 584 
 585 Private int
 586 jtex_get_metric1(VF_FONT font, long code_point, VF_METRIC1 metric, 
     /* [<][>][^][v][top][bottom][index][help] */
 587                  double mag_x, double mag_y)
 588 {
 589   FONT_JTEX    font_jtex;
 590   double       ds, dr;
 591 
 592   if (  (metric == NULL)
 593       || ((font_jtex = (FONT_JTEX)font->private) == NULL) ){
 594     fprintf(stderr, "VFlib internal error in jtex_get_metric1()\n");
 595     abort();
 596   }
 597 
 598   if (vf_tfm_metric(font_jtex->tfm, code_point, metric) == NULL)
 599     return -1;
 600 
 601   ds = font_jtex->tfm->design_size;
 602   dr = 1.0;
 603   if (font->point_size > 0)
 604     dr = font->point_size / ds;
 605 
 606   metric->bbx_width  *= mag_x * font->mag_x;
 607   metric->bbx_height *= mag_y * font->mag_y;
 608   metric->off_x      *= mag_x * font->mag_x;
 609   metric->off_y      *= mag_y * font->mag_y;
 610   metric->mv_x       *= mag_x * font->mag_x * dr;
 611   metric->mv_y       *= mag_y * font->mag_y * dr;
 612 
 613   return 0;
 614 }
 615 
 616 Private int
 617 jtex_get_fontbbx1(VF_FONT font, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 618                  double *w_p, double *h_p, double *xoff_p, double *yoff_p)
 619 {
 620   FONT_JTEX    font_jtex;
 621 
 622   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 623     fprintf(stderr, "VFlib internal error in jtex_get_fontbbx1()\n");
 624     abort();
 625   }
 626 
 627   *w_p    = font_jtex->tfm->font_bbx_w * mag_x * font->mag_x;
 628   *h_p    = font_jtex->tfm->font_bbx_h * mag_y * font->mag_y;
 629   *xoff_p = font_jtex->tfm->font_bbx_xoff * mag_x * font->mag_x;
 630   *yoff_p = font_jtex->tfm->font_bbx_yoff * mag_y * font->mag_y;
 631 
 632   return 0;
 633 }
 634 
 635 Private VF_BITMAP
 636 jtex_get_bitmap1(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 637                  double mag_x, double mag_y)
 638 {
 639   FONT_JTEX     font_jtex;
 640   VF_BITMAP     bm_kanji, bm;
 641   int           need_free;
 642   double        dpi_x, dpi_y, mx, my;
 643   struct vf_s_metric1  met1; 
 644   struct vf_s_metric2  met2; 
 645 
 646   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 647     fprintf(stderr, "VFlib: Internal error in jtex_get_bitmap1().\n");
 648     abort();
 649   }
 650 
 651   if (font_jtex->kanji_font_id < 0){
 652     vf_error = VF_ERR_ILL_CODE_POINT;
 653     return NULL;
 654   }
 655 
 656   bm_kanji = VF_GetBitmap1(font_jtex->kanji_font_id, code_point, mag_x, mag_y);
 657   if (bm_kanji == NULL){
 658 #if 1
 659     bm_kanji = vf_alloc_bitmap(1, 1);
 660 #else
 661     return NULL;
 662 #endif
 663   }
 664 
 665   bm = jtex_rotate_bitmap(bm_kanji, code_point, font_jtex, &need_free);
 666   if (bm == NULL){
 667     VF_FreeBitmap(bm_kanji);
 668     return NULL;
 669   }
 670 
 671   if (jtex_get_metric1(font, code_point, &met1, mag_x, mag_y) < 0){
 672     VF_FreeBitmap(bm_kanji);
 673     if (need_free == 1)
 674       VF_FreeBitmap(bm);
 675     return NULL;
 676   }
 677 
 678   if (((dpi_x = font->dpi_x) < 0) || ((dpi_y = font->dpi_y) < 0)){
 679     dpi_x = vf_tex_default_dpi();
 680     dpi_y = vf_tex_default_dpi();
 681   }
 682   mx = dpi_x/72.27;
 683   my = dpi_y/72.27;
 684 
 685   met2.bbx_width  = bm->bbx_width;
 686   met2.bbx_height = bm->bbx_height;
 687   met2.off_x      = bm->off_x;
 688   met2.off_y      = bm->off_y;
 689   met2.mv_x       = toint(met1.mv_x * mx);
 690   met2.mv_y       = toint(met1.mv_y * my);
 691 
 692   if (vf_dbg_drv_ascii_jtex_dump == 1){
 693     printf(">>* ascii_jtex: get bitmap 1\n");
 694     printf("  CharCode: 0x%04lx  (char-type: %d)\n", 
 695            code_point, vf_tfm_jfm_chartype(font_jtex->tfm, (UINT4)code_point));
 696     printf(">>  metric 1\n");
 697     vf_dump_metric1(&met1);
 698     printf(">>  metric 2\n");
 699     vf_dump_metric2(&met2);
 700     printf(">>  bitmap (orig)\n");
 701     VF_DumpBitmap(bm);
 702   }
 703 
 704   jtex_met_adjustment(bm, &met2, code_point, font, font_jtex, mag_x, mag_y);
 705 
 706   if (vf_dbg_drv_ascii_jtex_dump == 1){
 707     printf(">>  bitmap (adj)\n");
 708     VF_DumpBitmap(bm);
 709   }
 710 
 711   if (need_free == 1){
 712     VF_FreeBitmap(bm_kanji);  /* bm is a new object, we don't need bm_kanji */
 713   } else {
 714     ; /*empty*/               /* bm and bm_kanji points to the same object.*/
 715   }
 716 
 717   return bm;
 718 }
 719 
 720 
 721 Private VF_OUTLINE
 722 jtex_get_outline(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 723                  double mag_x, double mag_y)
 724 {
 725   FONT_JTEX     font_jtex;
 726 
 727   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 728     fprintf(stderr, "VFlib: Internal error in jtex_get_outline().\n");
 729     abort();
 730   }
 731 
 732   if (font_jtex->kanji_font_id < 0){
 733     vf_error = VF_ERR_ILL_CODE_POINT;
 734     return NULL;
 735   }
 736 
 737   /**
 738   ** Metric correction is not supported. Sorry.
 739   **/
 740 
 741   return  VF_GetOutline(font_jtex->kanji_font_id, code_point, mag_x, mag_y);
 742 }
 743 
 744 
 745 Private int
 746 jtex_get_metric2(VF_FONT font, long code_point, VF_METRIC2 metric,
     /* [<][>][^][v][top][bottom][index][help] */
 747                  double mag_x, double mag_y)
 748 {
 749   FONT_JTEX   font_jtex;
 750   TFM         tfm;
 751   struct vf_s_metric1  met1;
 752 
 753   if (   (metric == NULL)
 754       || ((font_jtex = (FONT_JTEX)font->private) == NULL)
 755       || ((tfm = font_jtex->tfm) == NULL) ){
 756     fprintf(stderr, "VFlib internal error in htex_get_metric2()\n");
 757     abort();
 758   }
 759 
 760   if (vf_tfm_metric(tfm, code_point, &met1) == NULL)
 761     return -1;
 762 
 763   metric->bbx_width  = toint(met1.bbx_width  * mag_x * font->mag_x);
 764   metric->bbx_height = toint(met1.bbx_height * mag_y * font->mag_y);
 765   metric->off_x      = toint(met1.off_x * mag_x * font->mag_x);
 766   metric->off_y      = toint(met1.off_y * mag_y * font->mag_y);
 767   metric->mv_x       = toint(met1.mv_x  * mag_x * font->mag_x);
 768   metric->mv_y       = toint(met1.mv_y  * mag_y * font->mag_y);
 769 
 770   return 0;
 771 }
 772 
 773 
 774 Private int
 775 jtex_get_fontbbx2(VF_FONT font, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 776                   int *w_p, int *h_p, int *xoff_p, int *yoff_p)
 777 {
 778   FONT_JTEX    font_jtex;
 779 
 780   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 781     fprintf(stderr, "VFlib internal error in jtex_get_fontbbx2()\n");
 782     abort();
 783   }
 784 
 785   *w_p    = toint(font_jtex->tfm->font_bbx_w * mag_x * font->mag_x);
 786   *h_p    = toint(font_jtex->tfm->font_bbx_h * mag_y * font->mag_y);
 787   *xoff_p = toint(font_jtex->tfm->font_bbx_xoff * mag_x * font->mag_x);
 788   *yoff_p = toint(font_jtex->tfm->font_bbx_yoff * mag_y * font->mag_y);
 789 
 790   return 0;
 791 }
 792 
 793 Private VF_BITMAP
 794 jtex_get_bitmap2(VF_FONT font, long code_point, 
     /* [<][>][^][v][top][bottom][index][help] */
 795                  double mag_x, double mag_y)
 796 {
 797   FONT_JTEX     font_jtex;
 798   VF_BITMAP     bm_kanji, bm;
 799   int           need_free;
 800   struct vf_s_metric1  met1; 
 801   struct vf_s_metric2  met2; 
 802 
 803   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 804     fprintf(stderr, "VFlib: Internal error in jtex_get_bitmap2().\n");
 805     abort();
 806   }
 807 
 808   if (font_jtex->kanji_font_id < 0){
 809     vf_error = VF_ERR_ILL_CODE_POINT;
 810     return NULL;
 811   }
 812 
 813   bm_kanji = VF_GetBitmap2(font_jtex->kanji_font_id, code_point, mag_x, mag_y);
 814   if (bm_kanji == NULL){
 815 #if 1
 816     bm_kanji = vf_alloc_bitmap(1, 1);
 817 #else
 818     return NULL;
 819 #endif
 820   }
 821 
 822   bm = jtex_rotate_bitmap(bm_kanji, code_point, font_jtex, &need_free);
 823   if (bm == NULL){
 824     VF_FreeBitmap(bm_kanji);
 825     return NULL;
 826   }
 827 
 828   if (vf_tfm_metric(font_jtex->tfm, code_point, &met1) == NULL){
 829     VF_FreeBitmap(bm_kanji);
 830     if (need_free == 1)
 831       VF_FreeBitmap(bm);
 832     return NULL;
 833   }
 834 
 835   met2.bbx_width  = bm->bbx_width;
 836   met2.bbx_height = bm->bbx_height;
 837   met2.off_x      = bm->off_x;
 838   met2.off_y      = bm->off_y;
 839   if ((font_jtex->mode2_factor_x > 0) && (font_jtex->mode2_factor_x > 0)){
 840     met2.mv_x     = met1.mv_x * font_jtex->mode2_factor_x;
 841     met2.mv_y     = met1.mv_y * font_jtex->mode2_factor_y;
 842   } else {
 843     met2.mv_x     = bm->mv_x;
 844     met2.mv_y     = bm->mv_y;
 845   }
 846 
 847   if (vf_dbg_drv_ascii_jtex_dump == 1){
 848     printf(">>* ascii_jtex: get bitmap 2\n");
 849     printf(">>  metric\n");
 850     vf_dump_metric2(&met2);
 851     printf(">>  bitmap (orig)\n");
 852     VF_DumpBitmap(bm);
 853   }
 854 
 855   jtex_met_adjustment(bm, &met2, code_point, font, font_jtex, mag_x, mag_y);
 856 
 857   if (vf_dbg_drv_ascii_jtex_dump == 1){
 858     printf(">>  bitmap (adj)\n");
 859     VF_DumpBitmap(bm);
 860   }
 861 
 862   if (need_free == 1){
 863     VF_FreeBitmap(bm_kanji);  /* bm is a new object, we don't need bm_kanji */
 864   } else {
 865     ; /*empty*/               /* bm and bm_kanji points to the same object.*/
 866   }
 867 
 868   return bm;
 869 }
 870 
 871 
 872 Private char*
 873 jtex_get_font_prop(VF_FONT font, char *prop_name)
     /* [<][>][^][v][top][bottom][index][help] */
 874 {
 875   FONT_JTEX  font_jtex;
 876   double     dpi_x, dpi_y;
 877   SEXP       v;
 878   char       *r;
 879 
 880   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 881     fprintf(stderr, "VFlib: Internal error in jtex_get_font_prop().\n");
 882     abort();
 883   }
 884   if (font_jtex->kanji_font_id < 0){
 885     return NULL;
 886   }
 887 
 888   if ((v = vf_sexp_assoc(prop_name, font_jtex->props)) != NULL){
 889     if ((r = vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)))) == NULL){
 890       vf_error = VF_ERR_NO_MEMORY;
 891       return NULL;
 892     }
 893     return r;
 894   } else if ((v = vf_sexp_assoc(prop_name, default_properties)) != NULL){
 895     if ((r = vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)))) == NULL){
 896       vf_error = VF_ERR_NO_MEMORY;
 897       return NULL;
 898     }
 899     return r;
 900   }
 901 
 902   if (((dpi_x = font->dpi_x)<=0) || ((dpi_y = font->dpi_y)<=0)){
 903     dpi_x = vf_tex_default_dpi();
 904     dpi_y = vf_tex_default_dpi();
 905   }
 906 
 907 #if 0
 908   if (font->mode == 1){
 909     if ((ps = font->point_size) < 0)
 910       ps = font_jtex->tfm->design_size;
 911     ps = ps * font->mag_y;
 912     if (strcmp(prop_name, "POINT_SIZE") == 0){
 913       sprintf(str, "%d", toint(ps * 10.0));
 914       return vf_strdup(str);
 915     } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
 916       sprintf(str, "%d", toint(ps * dpi_y / 72.27));
 917       return vf_strdup(str);
 918     } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
 919       sprintf(str, "%d", toint(dpi_x));
 920       return vf_strdup(str);
 921     } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
 922       sprintf(str, "%d", toint(dpi_y));
 923       return vf_strdup(str);
 924     }
 925 
 926   } else if (font->mode == 2){
 927     if (strcmp(prop_name, "POINT_SIZE") == 0){
 928       if ((ps = font->pixel_size) < 0){
 929         sprintf(str, "%d", toint(font_jtex->tfm->design_size 
 930                                  * 10.0 * font->mag_y));
 931         return vf_strdup(str);
 932       }
 933       ps = ps * font->mag_y; 
 934       sprintf(str, "%d", toint(ps * 10.0 * 72.27 / dpi_y));
 935       return vf_strdup(str);
 936     } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
 937       if ((ps = font->pixel_size) < 0)
 938         ps = font_jtex->tfm->design_size * dpi_y / 72.27;
 939       ps = ps * font->mag_y;
 940       sprintf(str, "%d", toint(ps));
 941       return vf_strdup(str);
 942     } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
 943       sprintf(str, "%d", toint(dpi_x));
 944       return vf_strdup(str);
 945     } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
 946       sprintf(str, "%d", toint(dpi_y));
 947       return vf_strdup(str);
 948     }
 949   }
 950 #endif
 951 
 952   return VF_GetFontProp(font_jtex->kanji_font_id, prop_name);
 953 }
 954 
 955 
 956 Private int
 957 jtex_query_font_type(VF_FONT font, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 958 {
 959   FONT_JTEX  font_jtex;
 960 
 961   if ((font_jtex = (FONT_JTEX)font->private) == NULL){
 962     fprintf(stderr, "VFlib: Internal error in jtex_get_font_prop().\n");
 963     abort();
 964   }
 965 
 966   return VF_QueryFontType(font_jtex->kanji_font_id, code_point);
 967 }
 968 
 969 
 970 
 971 Private VF_BITMAP
 972 jtex_rotate_bitmap(VF_BITMAP bm0, long code_point, 
     /* [<][>][^][v][top][bottom][index][help] */
 973                    FONT_JTEX font_jtex, int *need_free_p)
 974 {
 975   VF_BITMAP  bm, bm_mirror;
 976   ADJ        adj;
 977   int        ctype, i;
 978 
 979   *need_free_p = 0;
 980   if (((adj = font_jtex->adj) == NULL)
 981       || (font_jtex->tfm->type_aux != METRIC_TYPE_JFM_AUX_V))
 982     return bm0;
 983 
 984   ctype = vf_tfm_jfm_chartype(font_jtex->tfm, (UINT4)code_point);
 985   if (adj->ct_corr[ctype].may_need_rotate == FALSE)
 986     return bm0;
 987 
 988   for (i = 0; VertCharInfo[i].code_point > 0; i++){
 989     if ((VertCharInfo[i].code_point == code_point)
 990         && ((VertCharInfo[i].rot_semantics & adj->rot_semantics) != 0)){
 991       if ((bm = VF_RotatedBitmap(bm0, VertCharInfo[i].angle)) == NULL)
 992         return NULL;
 993       if (VertCharInfo[i].mirror == 0){
 994         *need_free_p = 1;
 995         return bm;
 996       }
 997       if ((bm_mirror = VF_ReflectedBitmap(bm, 1, 0)) == NULL){
 998         VF_FreeBitmap(bm);
 999         return NULL;
1000       }
1001       VF_FreeBitmap(bm);
1002       *need_free_p = 1;
1003       return bm_mirror;
1004     }
1005   }
1006 
1007   *need_free_p = 0;
1008   return bm0;
1009 }
1010 
1011 
1012 
1013 Private int
1014 jtex_met_adjustment(VF_BITMAP bm, VF_METRIC2 met2, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
1015                     VF_FONT font, FONT_JTEX font_jtex, 
1016                     double mag_x, double mag_y)
1017 {
1018   ADJ        adj;
1019   int        ctype, dx, dy;
1020   double     dpix, dpiy, fdx, fdy, ds, dr; 
1021 
1022   bm->mv_x = met2->mv_x; 
1023   bm->mv_y = met2->mv_y; 
1024 
1025   if ((adj = font_jtex->adj) == NULL){
1026     if (vf_dbg_drv_ascii_jtex_adj == 1)
1027       printf(">>VFlib ascii jtex ADJ: none\n");
1028     return 0;
1029   }
1030 
1031   ctype = vf_tfm_jfm_chartype(font_jtex->tfm, (UINT4)code_point);
1032   fdx = adj->ct_corr[ctype].dx + adj->ct_corr_all.dx;
1033   fdy = adj->ct_corr[ctype].dy + adj->ct_corr_all.dy;
1034   if (adj->ct_corr[ctype].need_cc_corr)
1035     jtex_met_cc_adjustment(adj, code_point, ctype, &fdx, &fdy);
1036 
1037   ds = font_jtex->tfm->design_size;
1038   dr = 1.0;
1039   if (font->point_size > 0)
1040     dr = font->point_size / ds;
1041   
1042   dx = 0; 
1043   dy = 0; 
1044 
1045   switch (font->mode){
1046   case 1:
1047     if (adj->semantics == SEMANTICS_AUX_BITMAP){
1048       dx = met2->bbx_width  * fdx * mag_x * font->mag_x;
1049       dy = met2->bbx_height * fdy * mag_y * font->mag_y;
1050     } else if (adj->semantics == SEMANTICS_DESIGN_SIZE){
1051       if (((dpix = font->dpi_x) < 0) || ((dpiy = font->dpi_y) < 0)){
1052         dpix = vf_tex_default_dpi();
1053         dpiy = vf_tex_default_dpi();
1054       }
1055       dx = (dpix/72.27) * ds * dr * fdx * mag_x * font->mag_x;
1056       dy = (dpiy/72.27) * ds * dr * fdy * mag_y * font->mag_y;
1057     }
1058     break;
1059   case 2:
1060   default:
1061     if (adj->semantics == SEMANTICS_AUX_BITMAP){
1062       dx = met2->bbx_width  * fdx * mag_x * font->mag_x;
1063       dy = met2->bbx_height * fdy * mag_y * font->mag_y;
1064     } else if (adj->semantics == SEMANTICS_DESIGN_SIZE){
1065       dx = font_jtex->mode2_factor_x * ds * dr * fdx * mag_x * font->mag_x;
1066       dy = font_jtex->mode2_factor_y * ds * dr * fdy * mag_y * font->mag_y;
1067     }
1068     break;
1069   }
1070   bm->off_x += dx;
1071   bm->off_y += dy;
1072 
1073   if (vf_dbg_drv_ascii_jtex_adj == 1){
1074     printf(">>VFlib ascii jtex ADJ 0x%x CharType %d %.3f,%.3f BBX[%d,%d]\n",
1075            (int)code_point, ctype, 
1076            adj->ct_corr[ctype].dx, adj->ct_corr[ctype].dy, 
1077            met2->bbx_width, met2->bbx_height);
1078   }
1079 
1080   return 0;
1081 }
1082 
1083 Private void
1084 jtex_met_cc_adjustment(ADJ adj, long code_point, int char_type, 
     /* [<][>][^][v][top][bottom][index][help] */
1085                        double *fxp, double *fyp)
1086 {
1087   int  i, last;
1088 
1089   last = adj->n_cc_corr - 1;
1090   adj->cc_corr[last].code_point = code_point;
1091   adj->cc_corr[last].dx = 0.0;
1092   adj->cc_corr[last].dy = 0.0;
1093 
1094   for (i = 0; adj->cc_corr[i].code_point != code_point; i++)
1095     ;
1096   
1097   if (i != last){
1098     if (vf_dbg_drv_ascii_jtex_adj == 1)
1099       printf(">>VFlib: ascii jtex:   cc adj: 0x%04lx  %.3f %.3f\n",
1100              code_point, adj->cc_corr[i].dx, adj->cc_corr[i].dy);
1101     /* Override! */
1102     *fxp = adj->cc_corr[i].dx;
1103     *fyp = adj->cc_corr[i].dy;
1104   }
1105 }
1106 
1107 
1108 Private ADJ
1109 jtex_read_met_adjustment_file(FONT_JTEX font_jtex, char* file_name)
     /* [<][>][^][v][top][bottom][index][help] */
1110 {
1111   FILE    *fp;
1112   ADJ     adj;
1113   SEXP    s, s0, s1, s2, s3;
1114   int     ct, i_cc, i;
1115   long    cc;
1116   char    *path, *key;
1117 
1118   if (file_name == NULL){
1119     vf_error = VF_ERR_CANT_OPEN;
1120     return NULL;
1121   }
1122 
1123   path = find_adj(file_name);
1124   if (path == NULL){
1125     vf_error = VF_ERR_CANT_OPEN;
1126     return NULL;
1127   }
1128 
1129   if ((fp = vf_fm_OpenTextFileStream(path)) == NULL){
1130     vf_free(path);
1131     vf_error = VF_ERR_CANT_OPEN;
1132     return NULL;
1133   }
1134 
1135   ALLOC_IF_ERR(adj, struct s_met_adj_table){
1136     vf_error = VF_ERR_NO_MEMORY;
1137     vf_free(path);
1138     return NULL;
1139   }
1140 
1141   adj->semantics = -1;
1142   adj->dir = -1;
1143   adj->rot_semantics = -1;
1144   for (ct = 0; ct < JTEX_MAX_CHARTYPE; ct++){
1145     adj->ct_corr[ct].need_cc_corr = FALSE;
1146     adj->ct_corr[ct].may_need_rotate = FALSE;
1147     adj->ct_corr[ct].dx = 0.0;
1148     adj->ct_corr[ct].dy = 0.0;
1149   }
1150   adj->ct_corr_all.dx = 0.0;
1151   adj->ct_corr_all.dy = 0.0;
1152 
1153   for (i = 0; VertCharInfo[i].code_point > 0; i++){
1154     ct = vf_tfm_jfm_chartype(font_jtex->tfm, 
1155                              (UINT4)VertCharInfo[i].code_point);
1156     adj->ct_corr[ct].may_need_rotate = TRUE;
1157   }
1158 
1159   adj->n_cc_corr = 0;
1160   if (realloc_cc_corr(adj) == NULL){
1161     vf_free(adj);
1162     vf_free(path);
1163     return NULL;
1164   }
1165 
1166   i_cc = 0;
1167   s = NULL;
1168 
1169   for (;;){
1170     vf_sexp_free(&s);
1171     if ((s = vf_sexp_read(fp)) == NULL)
1172       break;
1173 
1174     if (vf_dbg_drv_ascii_jtex_adj == 1){
1175       printf(">>VFlib ascii jtex ADJ: ");
1176       vf_sexp_pp(s);
1177     }
1178 
1179     if (!vf_sexp_listp(s)){
1180       fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ", path);
1181       vf_sexp_pp(s);
1182       continue;
1183     }
1184     s0 = vf_sexp_car(s);
1185     if (!vf_sexp_stringp(s0)){
1186       fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ", path);
1187       vf_sexp_pp(s);
1188       continue;
1189     }
1190 
1191     key = vf_sexp_get_cstring(s0);
1192 
1193     if (vf_strcmp_ci(key, KW_CHAR_ALL) == 0){
1194       if (vf_sexp_length(s) != 3){
1195         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1196                 path);
1197         vf_sexp_pp(s);
1198         continue;
1199       }
1200       s1 = vf_sexp_cadr(s);
1201       s2 = vf_sexp_caddr(s);
1202       if (!vf_sexp_stringp(s1)||!vf_sexp_stringp(s2)){
1203         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1204                 path);
1205         vf_sexp_pp(s);
1206         continue;
1207       }
1208       adj->ct_corr_all.dx = atof(vf_sexp_get_cstring(s1));
1209       adj->ct_corr_all.dy = atof(vf_sexp_get_cstring(s2));
1210       if (vf_dbg_drv_ascii_jtex_adj == 1){
1211         printf(">>  %s: Correction: %.3f,%.3f\n",
1212                KW_CHAR_ALL, adj->ct_corr_all.dx, adj->ct_corr_all.dy);
1213       }
1214 
1215     } else if (vf_strcmp_ci(key, KW_CHAR_TYPE) == 0){
1216       if (vf_sexp_length(s) != 4){
1217         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1218                 path);
1219         vf_sexp_pp(s);
1220         continue;
1221       }
1222       s1 = vf_sexp_cadr(s);
1223       s2 = vf_sexp_caddr(s);
1224       s3 = vf_sexp_caddr(vf_sexp_cdr(s));
1225       if (!vf_sexp_stringp(s1)||!vf_sexp_stringp(s2)||!vf_sexp_stringp(s2)){
1226         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1227                 path);
1228         vf_sexp_pp(s);
1229         continue;
1230       }
1231       ct = atoi(vf_sexp_get_cstring(s1));
1232       if ((ct < 0) || (JTEX_MAX_CHARTYPE <= ct)){
1233         fprintf(stderr, "VFlib warning: %s %d out of range in %s.\n", 
1234                 KW_CHAR_TYPE, ct, path);
1235         continue;
1236       }
1237       adj->ct_corr[ct].dx = atof(vf_sexp_get_cstring(s2));
1238       adj->ct_corr[ct].dy = atof(vf_sexp_get_cstring(s3));
1239       if (vf_dbg_drv_ascii_jtex_adj == 1){
1240         printf(">>  %s CharType: %02d, Correction: %.3f,%.3f\n",
1241                KW_CHAR_TYPE, ct, adj->ct_corr[ct].dx, adj->ct_corr[ct].dy);
1242       }
1243 
1244     } else if (vf_strcmp_ci(key, KW_CHAR_CODE) == 0){
1245       if (vf_sexp_length(s) != 4){
1246         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1247                 path);
1248         vf_sexp_pp(s);
1249         continue;
1250       }
1251       s1 = vf_sexp_cadr(s);
1252       s2 = vf_sexp_caddr(s);
1253       s3 = vf_sexp_caddr(vf_sexp_cdr(s));
1254       if (!vf_sexp_stringp(s1)||!vf_sexp_stringp(s2)||!vf_sexp_stringp(s2)){
1255         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1256                 path);
1257         vf_sexp_pp(s);
1258         continue;
1259       }
1260       cc = atoi(vf_sexp_get_cstring(s1));
1261       if (cc < 0){
1262         fprintf(stderr, "VFlib warning: %s %d out of range in %s.\n", 
1263                 KW_CHAR_CODE, ct, path);
1264         continue;
1265       }
1266       if (i_cc >= (adj->n_cc_corr-1))
1267         realloc_cc_corr(adj);
1268       sscanf(vf_sexp_get_cstring(s1), "%li", &cc);
1269       adj->cc_corr[i_cc].code_point = cc;
1270       adj->cc_corr[i_cc].dx         = atof(vf_sexp_get_cstring(s2));
1271       adj->cc_corr[i_cc].dy         = atof(vf_sexp_get_cstring(s3));
1272       if (vf_dbg_drv_ascii_jtex_adj == 1){
1273         printf(">>  %s  Code: 0x%lx, Correection: %.3f,%.3f\n", 
1274                KW_CHAR_CODE, cc,
1275                adj->cc_corr[i_cc].dx, adj->cc_corr[i_cc].dy);
1276       }
1277       i_cc++;
1278       ct = vf_tfm_jfm_chartype(font_jtex->tfm, (UINT4)cc);
1279       adj->ct_corr[ct].need_cc_corr = TRUE;
1280 
1281     } else if (vf_strcmp_ci(key, KW_SEMANTICS) == 0){
1282       if (vf_sexp_length(s) != 2){
1283         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ", 
1284                 path);
1285         vf_sexp_pp(s);
1286         continue;
1287       }
1288       s1 = vf_sexp_cadr(s);
1289       if (!vf_sexp_stringp(s1)){
1290         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1291                 path);
1292         vf_sexp_pp(s);
1293         continue;
1294       }
1295       if (vf_strcmp_ci(vf_sexp_get_cstring(s1), KW_SEM_BITMAP) == 0){
1296         adj->semantics = SEMANTICS_AUX_BITMAP;
1297       } else if (vf_strcmp_ci(vf_sexp_get_cstring(s1), KW_SEM_DESIGN) == 0){
1298         adj->semantics = SEMANTICS_DESIGN_SIZE;
1299       } else {
1300         fprintf(stderr, "VFlib warning: Unknown semantics name %s in %s.\n", 
1301                 vf_sexp_get_cstring(s1), path);
1302       }
1303 
1304     } else if (vf_strcmp_ci(key, KW_DIR) == 0){
1305       if (vf_sexp_length(s) != 2){
1306         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ", 
1307                 path);
1308         vf_sexp_pp(s);
1309         continue;
1310       }
1311       s1 = vf_sexp_cadr(s);
1312       if (!vf_sexp_stringp(s1)){
1313         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1314                 path);
1315         vf_sexp_pp(s);
1316         continue;
1317       }
1318       if (vf_strcmp_ci(vf_sexp_get_cstring(s1), KW_DIR_HORIZONTAL) == 0){
1319         adj->dir = DIR_HORIZONTAL;
1320       } else if (vf_strcmp_ci(vf_sexp_get_cstring(s1), KW_DIR_VERTICAL) == 0){
1321         adj->dir = DIR_VERTICAL;
1322       } else {
1323         fprintf(stderr, "VFlib warning: Unknown direction name %s in %s.\n", 
1324                 vf_sexp_get_cstring(s1), path);
1325         fprintf(stderr, "Use \"%s\" or \"%s\"\n", 
1326                 KW_DIR_HORIZONTAL, KW_DIR_VERTICAL);
1327       }
1328 
1329     } else if (vf_strcmp_ci(key, KW_ROTATION) == 0){
1330       if (vf_sexp_length(s) != 2){
1331         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ", 
1332                 path);
1333         vf_sexp_pp(s);
1334         continue;
1335       }
1336       s1 = vf_sexp_cadr(s);
1337       if (!vf_sexp_stringp(s1)){
1338         fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ",
1339                 path);
1340         vf_sexp_pp(s);
1341         continue;
1342       }
1343       if (vf_strcmp_ci(vf_sexp_get_cstring(s1), KW_ROT_PTEX) == 0){
1344         adj->rot_semantics = ROT_PTEX;
1345       } else if (vf_strcmp_ci(vf_sexp_get_cstring(s1), KW_ROT_JISX0208) == 0){
1346         adj->rot_semantics = ROT_JISX0208;
1347       } else {
1348         fprintf(stderr, "VFlib warning: Unknown keyword %s in %s.\n", 
1349                 vf_sexp_get_cstring(s1), path);
1350         fprintf(stderr, "Use \"%s\" or \"%s\"\n", 
1351                 KW_ROT_PTEX, KW_ROT_JISX0208);
1352       }
1353 
1354     } else {
1355       fprintf(stderr, "VFlib warning: Illegal ADJ file format in %s: ", path);
1356       vf_sexp_pp(s);
1357       continue;
1358     }
1359   }
1360 
1361   /* default values */
1362   if (adj->semantics == -1)
1363     adj->semantics = SEMANTICS_AUX_BITMAP;
1364   if (adj->dir == -1)
1365     adj->dir = DIR_HORIZONTAL;
1366   if (adj->rot_semantics == -1)
1367     adj->rot_semantics = ROT_PTEX;
1368 
1369   vf_free(path);
1370 
1371   return adj;
1372 }
1373 
1374 Private void
1375 jtex_free_adj(ADJ adj)
     /* [<][>][^][v][top][bottom][index][help] */
1376 {
1377   if (adj != NULL){
1378     vf_free(adj->cc_corr);
1379     vf_free(adj);
1380   }
1381 }
1382 
1383 Private ADJ
1384 realloc_cc_corr(ADJ adj)
     /* [<][>][^][v][top][bottom][index][help] */
1385 {
1386   ADJ_CC_CORR  new_cc_corr;
1387   int          new_size, i;
1388 
1389   new_size = 2 * adj->n_cc_corr;
1390   if (new_size <= 0)
1391     new_size = N_CC_CORR;
1392 
1393   ALLOCN_IF_ERR(new_cc_corr, struct s_met_adj_cc_corr, new_size){
1394     vf_error = VF_ERR_NO_MEMORY;
1395     return NULL;
1396   }
1397 
1398   for (i = 0; i < adj->n_cc_corr; i++){
1399     new_cc_corr[i].code_point = adj->cc_corr[i].code_point;
1400     new_cc_corr[i].dx         = adj->cc_corr[i].dx;
1401     new_cc_corr[i].dy         = adj->cc_corr[i].dy;
1402   }
1403   for (i = adj->n_cc_corr; i < new_size; i++){
1404     new_cc_corr[i].code_point = -1L;
1405     new_cc_corr[i].dx         = 0.0;
1406     new_cc_corr[i].dy         = 0.0;
1407   }
1408 
1409   vf_free(adj->cc_corr);
1410   adj->n_cc_corr = new_size;
1411   adj->cc_corr   = new_cc_corr;
1412 
1413   return adj;
1414 }
1415 
1416 
1417 Private char*
1418 find_adj(char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
1419 {
1420   char  *path; 
1421 
1422   if (fname == NULL)
1423     return NULL;
1424 
1425   if (vf_dbg_drv_ascii_jtex_adj == 1)
1426     printf(">>VFlib ascii jtex:   Searching ADJ file: %s\n", fname);
1427 
1428   path = NULL;
1429   if (vf_path_absolute(fname)){
1430     if (vf_path_file_read_ok(fname)){
1431       if ((path = vf_strdup(fname)) == NULL)
1432         vf_error = VF_ERR_NO_MEMORY;
1433     }
1434   } else {
1435     path = vf_path_find_runtime_file("ascii-jtex", fname, 
1436                                      VFLIB_ENV_ASCII_JTEX_DIR);
1437   }
1438 
1439   if (vf_dbg_drv_ascii_jtex_adj == 1){
1440     if (path != NULL)
1441       printf(">>      --- found: %s\n", path);
1442     else 
1443       printf(">>      --- not found\n");
1444   }
1445 
1446   return path;
1447 }
1448 
1449 
1450 
1451 /*EOF*/

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