src/drv_ttf.c

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

FUNCTIONS

This source file includes following functions.
  1. VF_Init_Driver_TrueType
  2. ttf_create
  3. ttf_close
  4. ttf_open_method
  5. ttf_close_method
  6. ttf_get_metric1
  7. ttf_get_fontbbx1
  8. ttf_get_bitmap1
  9. ttf_get_outline1
  10. ttf_get_metric2
  11. ttf_get_fontbbx2
  12. ttf_get_bitmap2
  13. ttf_get_xxx
  14. fix_jisx0212_row47_empty_sjis
  15. get_outline_ttf_to_vflib
  16. ConvX
  17. ConvY
  18. ttf_get_font_prop
  19. find_encoding_mapping
  20. get_id_from_platform_name
  21. get_id_from_encoding_name
  22. name2id
  23. conv_encoding_ttf_to_vflib
  24. platform_id2name
  25. encoding_id2name
  26. ttf_debug
  27. ttf_debug2

   1 /*
   2  * drv_ttf.c - A font driver for TrueType fonts with FreeType library.  
   3  * by Hirotsugu Kakugawa
   4  *
   5  *  6 Jan 1998  First implementation by FreeType 1.0.
   6  *  5 Feb 1998  VFlib 3.4  Changed API.
   7  * 20 Mar 1998  Added outline data extract routine.
   8  *  2 Jun 1998  Added 'hinting' capablity
   9  * 18 Jun 1998  Adopted FreeType 1.1
  10  * 21 Sep 1998  Fixed a bug that dumps core when a font is closed.
  11  *  9 Dec 1998  Adopted FreeType 1.2
  12  *  9 Dec 1998  Added debug flag control by environment variable.
  13  *              Added get_fontbbx1() and get_fontbbx2().
  14  * 20 Dec 1998  Added a feature to open/close font files dynamically on demand.
  15  * 28 Dec 1998  Fixed a bug in code for dynamic open/close font files.
  16  *  4 Mar 1999  Added ad-hoc solution to handle buggy JIS X 0212 fonts
  17  *              with empty Row 47 (e.g., Ricoh TrueTypeWorld ValueFont DX).
  18  *              Add "jisx0212-row47-empty-sjis" capability with "yes" value
  19  *              in vflibcap to use such fonts.
  20  * 29 Jul 1999  Fixed a bug in makeing outline data (refrence point).
  21  */
  22 /*
  23  * Copyright (C) 1996-1999 Hirotsugu Kakugawa. 
  24  * All rights reserved.
  25  *
  26  * This file is part of the VFlib Library.  This library is free
  27  * software; you can redistribute it and/or modify it under the terms of
  28  * the GNU Library General Public License as published by the Free
  29  * Software Foundation; either version 2 of the License, or (at your
  30  * option) any later version.  This library is distributed in the hope
  31  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  32  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  33  * PURPOSE.  See the GNU Library General Public License for more details.
  34  * You should have received a copy of the GNU Library General Public
  35  * License along with this library; if not, write to the Free Software
  36  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  37  */
  38 
  39 /* debug flag in vflibcap (debug capability):
  40  *    f - print font file path
  41  *    n - the number of fonts in a font file
  42  *    c - code mapping table information (ccv info)
  43  *    p - code mapping table information (non-ccv info)
  44  *    i - print char index
  45  *    m - print metrics
  46  *    * - everything
  47  */
  48 
  49 #include  "config.h"
  50 #include  <stdio.h>
  51 #include  <stdlib.h>
  52 #ifdef HAVE_UNISTD_H
  53 #  include <unistd.h>
  54 #endif
  55 #include  <ctype.h>
  56 #include  <math.h>
  57 #include  <sys/param.h>
  58 #include  "VFlib-3_6.h"
  59 #include  "VFsys.h"
  60 #include  "vflibcap.h"
  61 #include  "bitmap.h"
  62 #include  "cache.h"
  63 #include  "fsearch.h"
  64 #include  "str.h"
  65 #include  "sexp.h"
  66 #include  "ccv.h"
  67 
  68 
  69 #include  "freetype.h"
  70 #include  "ttf.h"
  71 
  72 #define DIRECTION_HORIZONTAL  0
  73 #define DIRECTION_VERTICAL    1
  74 
  75 
  76 Private SEXP_LIST    default_fontdirs;
  77 Private SEXP_STRING  default_point_size;
  78 Private double       v_default_point_size;
  79 Private SEXP_STRING  default_pixel_size;
  80 Private double       v_default_pixel_size;
  81 Private SEXP_STRING  default_dpi, default_dpi_x, default_dpi_y;
  82 Private double       v_default_dpi_x, v_default_dpi_y;
  83 Private SEXP_STRING  default_aspect;
  84 Private double       v_default_aspect;
  85 Private SEXP_STRING  default_direction;
  86 Private char         v_default_direction;
  87 Private SEXP_STRING  default_platform_id;
  88 Private int          v_default_platform_id;
  89 Private SEXP_STRING  default_encoding_id;
  90 Private int          v_default_encoding_id;
  91 Private SEXP_STRING  default_hinting;
  92 Private int          v_default_hinting;
  93 Private SEXP_ALIST   default_properties;
  94 Private SEXP_ALIST   default_variables;
  95 Private SEXP_STRING  default_debug_mode;
  96 Private char        *env_debug_mode = NULL;
  97 #define DEBUG_ENV_NAME   "VFLIB_TTF_DEBUG"
  98 
  99 
 100 struct s_font_ttf {
 101   int       release_on_close;
 102   int       ttf_opened;
 103   TT_Face             tt_face;
 104   TT_Instance         tt_instance;
 105   TT_CharMap          tt_charmap;
 106   TT_Glyph            tt_glyph;
 107   TT_Face_Properties  tt_fprops;
 108   TT_UShort           tt_upem;
 109   char     *font_name;
 110   char     *file_path;
 111   double    point_size;
 112   double    pixel_size;
 113   double    dpi_x, dpi_y; 
 114   double    aspect;
 115   double    mag;
 116   char      direction;
 117   int       font_number;
 118   int       platform_id;
 119   int       encoding_id;
 120   int       mapping_id;
 121   int       encoding_force;
 122   int       hinting;
 123   int       jisx0212_r47e_sjis;
 124   char     *charset_name;
 125   char     *encoding_name;
 126   SEXP      props;
 127   int       ccv_id;
 128 };
 129 typedef struct s_font_ttf  *FONT_TTF;
 130 
 131 
 132 struct s_id_name_tbl {
 133   int   id;
 134   char  *name;
 135 };
 136 typedef struct s_id_name_tbl  *ID_NAME_TBL;
 137 
 138  
 139 struct s_fontbbx1 {
 140   double  w, h;
 141   double  xoff, yoff;
 142 };
 143 typedef struct s_fontbbx1  *FONTBBX1; 
 144 struct s_fontbbx2 {
 145   int     w, h;
 146   int     xoff, yoff;
 147 };
 148 typedef struct s_fontbbx2  *FONTBBX2;
 149 
 150 #define MODE_METRIC1  1  
 151 #define MODE_BITMAP1  2  
 152 #define MODE_FONTBBX1 3  
 153 #define MODE_OUTLINE  4
 154 #define MODE_METRIC2  5
 155 #define MODE_FONTBBX2 6  
 156 #define MODE_BITMAP2  7
 157 
 158 Private TT_Face *ttf_open_method(char*,long,long,VF_FONT,FONT_TTF);
 159 Private void     ttf_close_method(TT_Face*,long,long,VF_FONT,FONT_TTF);
 160 
 161 Private void* ttf_get_xxx(int mode, 
 162                           VF_FONT font, long code_point, 
 163                           double mag_x, double mag_y, 
 164                           VF_METRIC1 metric1, VF_METRIC2 metric2,
 165                           FONTBBX1 bbx1, FONTBBX2 bbx2);
 166 
 167 Private int         ttf_create(VF_FONT,char*,char*,int,SEXP);
 168 Private int         ttf_close(VF_FONT);
 169 Private int         ttf_get_metric1(VF_FONT,long,VF_METRIC1,double,double);
 170 Private int         ttf_get_metric2(VF_FONT,long,VF_METRIC2,double,double);
 171 Private int         ttf_get_fontbbx1(VF_FONT font,double,double,
 172                                      double*,double*,double*,double*);
 173 Private int         ttf_get_fontbbx2(VF_FONT font, double,double,
 174                                      int*,int*,int*,int*);
 175 Private VF_BITMAP   ttf_get_bitmap1(VF_FONT,long,double,double);
 176 Private VF_BITMAP   ttf_get_bitmap2(VF_FONT,long,double,double);
 177 Private VF_OUTLINE  ttf_get_outline1(VF_FONT,long,double,double);
 178 Private char       *ttf_get_font_prop(VF_FONT,char*);
 179 
 180 Private VF_OUTLINE
 181   get_outline_ttf_to_vflib(FONT_TTF,TT_Outline*,
 182                            TT_Glyph_Metrics*, TT_Instance_Metrics*,
 183                            double ps, double mag_x, double mag_y, 
 184                            double dpix, double dpiy, double asp);
 185 Private long   fix_jisx0212_row47_empty_sjis(long code_point);
 186 Private int    find_encoding_mapping(FONT_TTF);
 187 Private int      get_id_from_platform_name(char*);
 188 Private int      get_id_from_encoding_name(char*,int);
 189 Private int         name2id(char*,ID_NAME_TBL,int,char*);
 190 Private char*  conv_encoding_ttf_to_vflib(int ttf_enc, int plat);
 191 Private char*  platform_id2name(int plat_id);
 192 Private char*  encoding_id2name(int,int);
 193 Private int    ttf_debug(char);
 194 
 195 
 196 
 197 
 198 static TT_Engine   FreeType_Engine;
 199 static int         Initialized_FreeType = 0;
 200 
 201 
 202 
 203 Public int
 204 VF_Init_Driver_TrueType(void)
     /* [<][>][^][v][top][bottom][index][help] */
 205 {
 206   TT_Error  error;
 207   char      *p;
 208   struct s_capability_table  ct[20];
 209   int  z;
 210 
 211   z = 0;
 212   /* VF_CAPE_FONT_DIRECTORIES */
 213   ct[z].cap = VF_CAPE_FONT_DIRECTORIES;  ct[z].type = CAPABILITY_LIST;
 214   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_fontdirs;
 215   /* VF_CAPE_POINT_SIZE */
 216   ct[z].cap = VF_CAPE_POINT_SIZE;        ct[z].type = CAPABILITY_STRING;
 217   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_point_size;
 218   /* VF_CAPE_PIXEL_SIZE */
 219   ct[z].cap = VF_CAPE_PIXEL_SIZE;        ct[z].type = CAPABILITY_STRING;
 220   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_pixel_size;
 221   /* VF_CAPE_DPI */
 222   ct[z].cap = VF_CAPE_DPI;               ct[z].type = CAPABILITY_STRING;
 223   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_dpi;
 224   /* VF_CAPE_DPI_X */
 225   ct[z].cap = VF_CAPE_DPI_X;             ct[z].type = CAPABILITY_STRING;
 226   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_dpi_x;
 227   /* VF_CAPE_DPI_Y */
 228   ct[z].cap = VF_CAPE_DPI_Y;             ct[z].type = CAPABILITY_STRING;
 229   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_dpi_y;
 230   /* VF_CAPE_ASPECT_RATIO */
 231   ct[z].cap = VF_CAPE_ASPECT_RATIO;      ct[z].type = CAPABILITY_STRING;
 232   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_aspect;
 233   /* VF_CAPE_DIRECTION */
 234   ct[z].cap = VF_CAPE_DIRECTION;         ct[z].type = CAPABILITY_STRING;
 235   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_direction;
 236   /* VF_CAPE_TTF_PLATFORM_ID */
 237   ct[z].cap = VF_CAPE_TTF_PLATFORM_ID;   ct[z].type = CAPABILITY_STRING;
 238   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_platform_id;
 239   /* VF_CAPE_TTF_ENCODING_ID */
 240   ct[z].cap = VF_CAPE_TTF_ENCODING_ID;   ct[z].type = CAPABILITY_STRING;
 241   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_encoding_id;
 242   /* VF_CAPE_TTF_HINTING */
 243   ct[z].cap = VF_CAPE_TTF_HINTING;       ct[z].type = CAPABILITY_STRING;
 244   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_hinting;
 245   /* VF_CAPE_PROPERTIES */
 246   ct[z].cap = VF_CAPE_PROPERTIES;        ct[z].type = CAPABILITY_ALIST;
 247   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_properties;
 248   /* VF_CAPE_VARIABLE_VALUES */
 249   ct[z].cap = VF_CAPE_VARIABLE_VALUES;   ct[z].type = CAPABILITY_ALIST;
 250   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_variables;
 251   /* VF_CAPE_DEBUG */
 252   ct[z].cap = VF_CAPE_DEBUG;             ct[z].type = CAPABILITY_STRING;
 253   ct[z].ess = CAPABILITY_OPTIONAL;       ct[z++].val = &default_debug_mode;
 254   /* end */
 255   ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
 256 
 257   if (vf_cap_GetParsedClassDefault(FONTCLASS_NAME, ct, NULL, NULL) 
 258       == VFLIBCAP_PARSED_ERROR)
 259     return -1;
 260 
 261   if (Initialized_FreeType == 0){
 262     error = TT_Init_FreeType(&FreeType_Engine);
 263     if (error){
 264       vf_error = VF_ERR_FREETYPE_INIT;
 265       return -1;
 266     }
 267     Initialized_FreeType = 1;
 268   }
 269 
 270   v_default_point_size = DEFAULT_POINT_SIZE;
 271   if (default_point_size != NULL)
 272     v_default_point_size = atof(vf_sexp_get_cstring(default_point_size));
 273   if (v_default_point_size < 0)
 274     v_default_point_size = DEFAULT_POINT_SIZE;
 275 
 276   v_default_pixel_size = DEFAULT_PIXEL_SIZE;
 277   if (default_pixel_size != NULL)
 278     v_default_pixel_size = atof(vf_sexp_get_cstring(default_pixel_size));
 279   if (v_default_pixel_size < 0)
 280     v_default_pixel_size  = DEFAULT_PIXEL_SIZE;
 281 
 282   v_default_dpi_x  = VF_DEFAULT_DPI;
 283   v_default_dpi_y  = VF_DEFAULT_DPI;
 284   if (default_dpi != NULL)
 285     v_default_dpi_x = v_default_dpi_y = atof(vf_sexp_get_cstring(default_dpi));
 286   if (default_dpi_x != NULL)
 287     v_default_dpi_x = atof(vf_sexp_get_cstring(default_dpi_x));
 288   if (default_dpi_y != NULL)
 289     v_default_dpi_y = atof(vf_sexp_get_cstring(default_dpi_y));
 290   if (v_default_dpi_x < 0)
 291     v_default_dpi_x = VF_DEFAULT_DPI;
 292   if (v_default_dpi_y < 0)
 293     v_default_dpi_y = VF_DEFAULT_DPI;
 294 
 295   v_default_aspect = 1.0;
 296   if (default_aspect != NULL)
 297     v_default_aspect = atof(vf_sexp_get_cstring(default_aspect));
 298   if (v_default_aspect < 0)
 299     v_default_aspect = 1.0;
 300 
 301   v_default_direction = DEFAULT_DIRECTION;
 302   if (default_direction != NULL){
 303     p = vf_sexp_get_cstring(default_direction);
 304     switch (*p){
 305     case 'h': case 'H':
 306       v_default_direction = DIRECTION_HORIZONTAL;
 307       break;
 308     case 'v': case 'V':
 309       v_default_direction = DIRECTION_VERTICAL;
 310       break;
 311     default:
 312       fprintf(stderr, "VFlib Warning: Unknown writing direction: %s\n", p);
 313       break;
 314     }
 315   }
 316 
 317   v_default_platform_id = TT_PLAT_ID_MICROSOFT;
 318   if (default_platform_id != NULL)
 319     v_default_platform_id
 320       = get_id_from_platform_name(vf_sexp_get_cstring(default_platform_id));
 321 
 322   v_default_encoding_id = TT_ENC_ID_ANY;
 323   if (default_encoding_id != NULL)
 324     v_default_encoding_id
 325       = get_id_from_encoding_name(vf_sexp_get_cstring(default_encoding_id),
 326                                   v_default_platform_id);
 327 
 328   v_default_hinting = TRUE;
 329   if (default_hinting != NULL){
 330     v_default_hinting = vf_parse_bool(vf_sexp_get_cstring(default_hinting));
 331   }
 332 
 333   env_debug_mode = getenv(DEBUG_ENV_NAME);
 334 
 335   VF_InstallFontDriver(FONTCLASS_NAME, (DRIVER_FUNC_TYPE)ttf_create);
 336 
 337   return 0;
 338 }
 339   
 340 
 341 Private int
 342 ttf_create(VF_FONT font, char *font_class, char *font_name, 
     /* [<][>][^][v][top][bottom][index][help] */
 343            int implicit, SEXP entry)
 344 {
 345   FONT_TTF   font_ttf;
 346   char       *font_file, *font_path, *p;
 347   int        val;
 348   SEXP       cap_fontdirs, cap_font, cap_point, cap_pixel;
 349   SEXP       cap_dpi, cap_dpi_x, cap_dpi_y, cap_mag, cap_aspect;
 350   SEXP       cap_font_number, cap_direction, cap_platform_id, cap_encoding_id;
 351   SEXP       cap_hinting, cap_mapping_id, cap_encoding_force;
 352   SEXP       cap_jisx0212_r47e_sjis;
 353   SEXP       cap_charset, cap_encoding, cap_props;
 354   struct s_capability_table  ct[30];
 355   int  z;
 356 
 357   z = 0;
 358   /* VF_CAPE_FONT_CLASS */
 359   ct[z].cap = VF_CAPE_FONT_CLASS;         ct[z].type = CAPABILITY_STRING;
 360   ct[z].ess = CAPABILITY_ESSENTIAL;       ct[z++].val = NULL;
 361   /* VF_CAPE_FONT_DIRECTORIES */
 362   ct[z].cap = VF_CAPE_FONT_DIRECTORIES;   ct[z].type = CAPABILITY_STRING_LIST1;
 363   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_fontdirs;
 364   /* VF_CAPE_FONT_FILE */
 365   ct[z].cap = VF_CAPE_FONT_FILE;          ct[z].type = CAPABILITY_STRING;
 366   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_font;
 367   /* VF_CAPE_POINT_SIZE */
 368   ct[z].cap = VF_CAPE_POINT_SIZE;         ct[z].type = CAPABILITY_STRING;
 369   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_point;
 370   /* VF_CAPE_PIXEL_SIZE */
 371   ct[z].cap = VF_CAPE_PIXEL_SIZE;         ct[z].type = CAPABILITY_STRING;
 372   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_pixel;
 373   /* VF_CAPE_DPI */
 374   ct[z].cap = VF_CAPE_DPI;                ct[z].type = CAPABILITY_STRING;
 375   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_dpi;
 376   /* VF_CAPE_DPI_X */
 377   ct[z].cap = VF_CAPE_DPI_X;              ct[z].type = CAPABILITY_STRING;
 378   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_dpi_x;
 379   /* VF_CAPE_DPI_Y */
 380   ct[z].cap = VF_CAPE_DPI_Y;              ct[z].type = CAPABILITY_STRING;
 381   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_dpi_y;
 382   /* VF_CAPE_MAG */
 383   ct[z].cap = VF_CAPE_MAG;                ct[z].type = CAPABILITY_STRING;
 384   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_mag;
 385   /* VF_CAPE_ASPECT_RATIO */
 386   ct[z].cap = VF_CAPE_ASPECT_RATIO;       ct[z].type = CAPABILITY_STRING;
 387   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_aspect;
 388   /* VF_CAPE_DIRECTION */
 389   ct[z].cap = VF_CAPE_DIRECTION;          ct[z].type = CAPABILITY_STRING;
 390   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_direction;
 391   /* VF_CAPE_TTF_FONT_NUMBER */
 392   ct[z].cap = VF_CAPE_TTF_FONT_NUMBER;    ct[z].type = CAPABILITY_STRING;
 393   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_font_number;
 394   /* VF_CAPE_TTF_PLATFORM_ID */
 395   ct[z].cap = VF_CAPE_TTF_PLATFORM_ID;    ct[z].type = CAPABILITY_STRING;
 396   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_platform_id;
 397   /* VF_CAPE_TTF_ENCODING_ID */
 398   ct[z].cap = VF_CAPE_TTF_ENCODING_ID;    ct[z].type = CAPABILITY_STRING;
 399   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_encoding_id;
 400   /* VF_CAPE_TTF_MAPPING_ID */
 401   ct[z].cap = VF_CAPE_TTF_MAPPING_ID;     ct[z].type = CAPABILITY_STRING;
 402   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_mapping_id;
 403   /* VF_CAPE_TTF_HINTING */
 404   ct[z].cap = VF_CAPE_TTF_HINTING;        ct[z].type = CAPABILITY_STRING;
 405   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_hinting;
 406   /* VF_CAPE_TTF_ENCODING_FORCE */
 407   ct[z].cap = VF_CAPE_TTF_ENCODING_FORCE; ct[z].type = CAPABILITY_STRING;
 408   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_encoding_force;
 409   /* VF_CAPE_CHARSET */
 410   ct[z].cap = VF_CAPE_CHARSET;            ct[z].type = CAPABILITY_STRING;
 411   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_charset;
 412   /* VF_CAPE_ENCODING */
 413   ct[z].cap = VF_CAPE_ENCODING;           ct[z].type = CAPABILITY_STRING;
 414   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_encoding;
 415   /* VF_CAPE_TTF_JISX0212_R47E_SJIS */
 416   ct[z].cap = VF_CAPE_TTF_JISX0212_R47ES; ct[z].type = CAPABILITY_STRING;
 417   ct[z].ess = CAPABILITY_OPTIONAL;     ct[z++].val = &cap_jisx0212_r47e_sjis;
 418   /* VF_CAPE_PROPERTIES */
 419   ct[z].cap = VF_CAPE_PROPERTIES;         ct[z].type = CAPABILITY_ALIST;
 420   ct[z].ess = CAPABILITY_OPTIONAL;        ct[z++].val = &cap_props;
 421   /* end */
 422   ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
 423 
 424 
 425   if (implicit == 1){   /* implicit font */
 426     font_file = font_name;
 427   } else {              /* explicit font */
 428     if (vf_cap_GetParsedFontEntry(entry, font_name, ct,
 429                                   default_variables, NULL) < 0)
 430       return -1;
 431     if (cap_font == NULL){
 432       /* Use font name as font file name if font file name is not given. */
 433       font_file = font_name;
 434     } else {
 435       font_file = vf_sexp_get_cstring(cap_font);
 436     }
 437   }
 438 
 439   val = -1;
 440 
 441   font_path = NULL;
 442   if ((implicit == 0) && (cap_fontdirs != NULL)){
 443     font_path = vf_search_file(font_file, -1, NULL, 
 444                                TRUE, FSEARCH_FORMAT_TYPE_TTF, 
 445                                cap_fontdirs, NULL, NULL);
 446   }
 447   if (font_path == NULL){
 448     font_path = vf_search_file(font_file, -1, NULL, 
 449                                TRUE, FSEARCH_FORMAT_TYPE_TTF, 
 450                                default_fontdirs, NULL, NULL);
 451   }
 452   if (font_path == NULL){
 453     vf_error = VF_ERR_NO_FONT_FILE;
 454     return -1;
 455   }
 456 
 457   if (ttf_debug('f')) 
 458     printf("VFlib TrueType: font file %s\n   ==> %s\n", font_file, font_path);
 459 
 460   font->font_type       = VF_FONT_TYPE_OUTLINE;
 461   font->get_metric1     = ttf_get_metric1;
 462   font->get_metric2     = ttf_get_metric2;
 463   font->get_fontbbx1    = ttf_get_fontbbx1;
 464   font->get_fontbbx2    = ttf_get_fontbbx2;
 465   font->get_bitmap1     = ttf_get_bitmap1;
 466   font->get_bitmap2     = ttf_get_bitmap2;
 467   font->get_outline     = ttf_get_outline1;
 468   font->get_font_prop   = ttf_get_font_prop;
 469   font->query_font_type = NULL;  /* Use font->font_type value. */
 470   font->close           = ttf_close;
 471 
 472   ALLOC_IF_ERR(font_ttf, struct s_font_ttf){
 473     vf_error = VF_ERR_NO_MEMORY;
 474     return -1;
 475   }
 476   font->private = font_ttf;
 477 
 478   font_ttf->release_on_close = 0;
 479   font_ttf->ttf_opened       = 0;
 480   font_ttf->font_name      = NULL;
 481   font_ttf->file_path      = font_path;
 482   font_ttf->point_size     = v_default_point_size;
 483   font_ttf->pixel_size     = v_default_pixel_size;
 484   font_ttf->mag            = 1.0;
 485   font_ttf->dpi_x          = v_default_dpi_x;
 486   font_ttf->dpi_y          = v_default_dpi_y;
 487   font_ttf->aspect         = v_default_aspect;
 488   font_ttf->direction      = v_default_direction;
 489   font_ttf->font_number    = -1;
 490   font_ttf->platform_id    = v_default_platform_id;
 491   font_ttf->encoding_id    = v_default_encoding_id;
 492   font_ttf->mapping_id     = TT_MAP_ID_SEARCH;
 493   font_ttf->encoding_force = -1;
 494   font_ttf->hinting        = v_default_hinting;
 495   font_ttf->charset_name   = NULL;
 496   font_ttf->encoding_name  = NULL;
 497 
 498   if (implicit == 0){
 499     if (cap_point != NULL)
 500       font_ttf->point_size = atof(vf_sexp_get_cstring(cap_point));
 501     if (cap_pixel != NULL)
 502       font_ttf->pixel_size = atof(vf_sexp_get_cstring(cap_pixel));
 503     if (cap_dpi != NULL)
 504       font_ttf->dpi_x = font_ttf->dpi_y = atof(vf_sexp_get_cstring(cap_dpi));
 505     if (cap_dpi_x != NULL)
 506       font_ttf->dpi_x = atof(vf_sexp_get_cstring(cap_dpi_x));
 507     if (cap_dpi_y != NULL)
 508       font_ttf->dpi_y = atof(vf_sexp_get_cstring(cap_dpi_y));
 509     if (cap_mag != NULL)
 510       font_ttf->mag = atof(vf_sexp_get_cstring(cap_mag));
 511     if (cap_aspect != NULL)
 512       font_ttf->aspect = atof(vf_sexp_get_cstring(cap_aspect));
 513     if (cap_direction != NULL){
 514       p = vf_sexp_get_cstring(cap_direction);
 515       switch (*p){
 516       case 'h': case 'H':
 517         font_ttf->direction = DIRECTION_HORIZONTAL;  break;
 518       case 'v': case 'V':
 519         font_ttf->direction = DIRECTION_VERTICAL;    break;
 520       default:
 521         fprintf(stderr, "VFlib Warning: Unknown writing direction: %s\n", p);
 522         break;
 523       }
 524     }
 525     if (cap_font_number != NULL)
 526       font_ttf->font_number = atoi(vf_sexp_get_cstring(cap_font_number));
 527     if (cap_platform_id != NULL)
 528       font_ttf->platform_id 
 529         = get_id_from_platform_name(vf_sexp_get_cstring(cap_platform_id));
 530     if (cap_encoding_id != NULL)
 531       font_ttf->encoding_id
 532         = get_id_from_encoding_name(vf_sexp_get_cstring(cap_encoding_id),
 533                                     font_ttf->platform_id);
 534     if (cap_mapping_id != NULL)
 535       font_ttf->mapping_id = atoi(vf_sexp_get_cstring(cap_mapping_id));
 536     if (cap_encoding_force != NULL)
 537       font_ttf->encoding_force
 538         = get_id_from_encoding_name(vf_sexp_get_cstring(cap_encoding_force),
 539                                     font_ttf->platform_id);
 540     if (cap_charset != NULL)
 541       font_ttf->charset_name = vf_strdup(vf_sexp_get_cstring(cap_charset));
 542     if (cap_encoding != NULL)
 543       font_ttf->encoding_name = vf_strdup(vf_sexp_get_cstring(cap_encoding));
 544     if (cap_props != NULL)
 545       font_ttf->props = cap_props;
 546     if (cap_hinting != NULL){
 547       font_ttf->hinting = vf_parse_bool(vf_sexp_get_cstring(cap_hinting));
 548     }
 549     if (cap_jisx0212_r47e_sjis != NULL){
 550       font_ttf->jisx0212_r47e_sjis 
 551         = vf_parse_bool(vf_sexp_get_cstring(cap_jisx0212_r47e_sjis));
 552     }
 553   }
 554 
 555   if ((font_ttf->font_name = vf_strdup(font_name)) == NULL){
 556     vf_error = VF_ERR_NO_MEMORY;
 557     goto Error;
 558   }
 559 
 560   if (vf_fm_OpenFileStreamApp(font_ttf->file_path,
 561                               font_ttf->font_number, -1, font, font_ttf,
 562                               (FM_OPEN_METHOD)ttf_open_method, 
 563                               (FM_CLOSE_METHOD)ttf_close_method, 
 564                               "FreeType") == NULL)
 565     goto Error;
 566 
 567   font_ttf->ccv_id = find_encoding_mapping(font_ttf);
 568 
 569   val = 0;
 570 
 571 Error:
 572   if (implicit == 0){   /* explicit font */
 573     vf_sexp_free4(&cap_fontdirs, &cap_font, &cap_point, &cap_pixel);
 574     vf_sexp_free3(&cap_dpi, &cap_dpi_x, &cap_dpi_y);
 575     vf_sexp_free3(&cap_mag, &cap_aspect, &cap_direction);
 576     vf_sexp_free3(&cap_platform_id, &cap_encoding_id, &cap_hinting);
 577     vf_sexp_free3(&cap_mapping_id, &cap_encoding_force, &cap_charset);
 578     vf_sexp_free1(&cap_encoding);
 579     vf_sexp_free1(&cap_jisx0212_r47e_sjis);
 580   }
 581 
 582   if ((val != 0) && (font_ttf != NULL)){
 583     vf_sexp_free1(&cap_props); 
 584     vf_free(font_ttf->font_name);
 585     vf_free(font_ttf->file_path);
 586     vf_free(font_ttf->charset_name);
 587     vf_free(font_ttf->encoding_name);
 588     vf_free(font_ttf); 
 589   }
 590 
 591   return val;
 592 }
 593 
 594 
 595 Private int
 596 ttf_close(VF_FONT font)
     /* [<][>][^][v][top][bottom][index][help] */
 597 {
 598   FONT_TTF  font_ttf;
 599 
 600   if ((font_ttf = (FONT_TTF)font->private) != NULL){
 601     vf_free(font_ttf->charset_name);
 602     vf_free(font_ttf->encoding_name);
 603     font_ttf->release_on_close = 1;
 604     /* `font_ttf' and `font_ttf->font_name' are
 605        released in ttf_close_method() */
 606   }
 607   return 0; 
 608 }
 609 
 610 Private TT_Face*
 611 ttf_open_method(char *font_path, long fontnum, long iarg2,
     /* [<][>][^][v][top][bottom][index][help] */
 612                 VF_FONT font, FONT_TTF font_ttf)
 613 {
 614   TT_Error  error;
 615 
 616   if (font_ttf == NULL)
 617     return NULL;
 618   
 619   if (font_ttf->ttf_opened == 0){
 620     if (fontnum < 0){
 621       if (ttf_debug('f')) 
 622         printf("VFlib TrueType: TT_Open_Face %s\n", font_ttf->font_name);
 623       error = TT_Open_Face(FreeType_Engine, font_path,
 624                            &font_ttf->tt_face);
 625     } else {
 626       if (ttf_debug('f')) 
 627         printf("VFlib TrueType: TT_Open_Collection %s, %ld\n", 
 628                font_ttf->font_name, fontnum);
 629       error = TT_Open_Collection(FreeType_Engine, font_path, 
 630                                  fontnum, &font_ttf->tt_face);
 631     }
 632     if (error)
 633       return NULL;
 634 
 635     font_ttf->ttf_opened = 1;
 636 
 637     (void) TT_Get_Face_Properties(font_ttf->tt_face, &font_ttf->tt_fprops);
 638     font_ttf->tt_upem = font_ttf->tt_fprops.header->Units_Per_EM;
 639     
 640     if (ttf_debug('n')) 
 641       printf("VFlib TrueType: the number of embedded faces: %ld\n",
 642              (long)font_ttf->tt_fprops.num_Faces);
 643     
 644     error = TT_New_Glyph(font_ttf->tt_face, &font_ttf->tt_glyph);
 645     if (error)
 646       return NULL;
 647     error = TT_New_Instance(font_ttf->tt_face, &font_ttf->tt_instance);
 648     if (error)
 649       return NULL;
 650   }
 651 
 652   return  &font_ttf->tt_face;
 653 }
 654 
 655 Private void
 656 ttf_close_method(TT_Face *ttface, long iarg1, long iarg2, 
     /* [<][>][^][v][top][bottom][index][help] */
 657                  VF_FONT font, FONT_TTF font_ttf)
 658 {
 659   if (font_ttf->release_on_close == 0){
 660     /* close temporality by the limitation of
 661        the number of simultaneously opened files */
 662     if (ttf_debug('f')) 
 663       printf("VFlib TrueType: TT_Flush_Face %s\n", font_ttf->font_name);
 664     TT_Flush_Face(font_ttf->tt_face);
 665   } else {
 666     /* after a font is closed */
 667     if (ttf_debug('f')) 
 668       printf("VFlib TrueType: TT_Close_Face %s\n", font_ttf->font_name);
 669     TT_Done_Glyph(font_ttf->tt_glyph);
 670     TT_Done_Instance(font_ttf->tt_instance);
 671     TT_Close_Face(font_ttf->tt_face);
 672     vf_free(font_ttf->font_name); 
 673     vf_free(font_ttf->file_path);
 674     vf_free(font_ttf);
 675   }
 676 } 
 677 
 678 
 679 Private int
 680 ttf_get_metric1(VF_FONT font, long code_point, VF_METRIC1 metric, 
     /* [<][>][^][v][top][bottom][index][help] */
 681                 double mag_x, double mag_y)
 682 {
 683   if (ttf_get_xxx(MODE_METRIC1, font, code_point, mag_x, mag_y, 
 684                   metric, NULL, NULL, NULL) == NULL)
 685     return -1;
 686   return 0;
 687 }
 688 
 689 Private int
 690 ttf_get_fontbbx1(VF_FONT font, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 691                  double *w_p, double *h_p, double *xoff_p, double *yoff_p)
 692 {
 693   struct s_fontbbx1  bbx1;
 694 
 695   if (ttf_get_xxx(MODE_FONTBBX1, font, -1, mag_x, mag_y, 
 696                   NULL, NULL, &bbx1, NULL) == NULL)
 697     return -1;
 698 
 699   *w_p    = bbx1.w;
 700   *h_p    = bbx1.h; 
 701   *xoff_p = bbx1.xoff;
 702   *yoff_p = bbx1.yoff;
 703   return 0;
 704 }
 705 
 706 Private VF_BITMAP
 707 ttf_get_bitmap1(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 708                 double mag_x, double mag_y)
 709 {
 710   return (VF_BITMAP)ttf_get_xxx(MODE_BITMAP1, font, code_point, mag_x, mag_y, 
 711                                 NULL, NULL, NULL, NULL);
 712 }
 713 
 714 
 715 Private VF_OUTLINE
 716 ttf_get_outline1(VF_FONT font, long code_point,
     /* [<][>][^][v][top][bottom][index][help] */
 717                  double mag_x, double mag_y)
 718 {
 719   return (VF_OUTLINE)ttf_get_xxx(MODE_OUTLINE, font, code_point, mag_x, mag_y, 
 720                                  NULL, NULL, NULL, NULL);
 721 }
 722 
 723 
 724 Private int
 725 ttf_get_metric2(VF_FONT font, long code_point, VF_METRIC2 metric,
     /* [<][>][^][v][top][bottom][index][help] */
 726                 double mag_x, double mag_y)
 727 {
 728   if (ttf_get_xxx(MODE_METRIC2, font, code_point, mag_x, mag_y,
 729                   NULL, metric, NULL, NULL) == NULL)
 730     return -1;
 731   return 0;
 732 }
 733 
 734 Private int
 735 ttf_get_fontbbx2(VF_FONT font, double mag_x, double mag_y,
     /* [<][>][^][v][top][bottom][index][help] */
 736                  int *w_p, int *h_p, int *xoff_p, int *yoff_p)
 737 {
 738   struct s_fontbbx2  bbx2;
 739 
 740   if (ttf_get_xxx(MODE_FONTBBX2, font, -1, mag_x, mag_y, 
 741                   NULL, NULL, NULL, &bbx2) == NULL)
 742     return -1;
 743 
 744   *w_p    = bbx2.w;
 745   *h_p    = bbx2.h; 
 746   *xoff_p = bbx2.xoff;
 747   *yoff_p = bbx2.yoff;
 748   return 0;
 749 }
 750 
 751 Private VF_BITMAP
 752 ttf_get_bitmap2(VF_FONT font, long code_point, 
     /* [<][>][^][v][top][bottom][index][help] */
 753                 double mag_x, double mag_y)
 754 {
 755   return (VF_BITMAP)ttf_get_xxx(MODE_BITMAP2,
 756                                 font, code_point, mag_x, mag_y, 
 757                                 NULL, NULL, NULL, NULL);
 758 }
 759 
 760 
 761 Private void*
 762 ttf_get_xxx(int mode, 
     /* [<][>][^][v][top][bottom][index][help] */
 763             VF_FONT font, long code_point, 
 764             double mag_x, double mag_y,
 765             VF_METRIC1 metric1, VF_METRIC2 metric2,
 766             FONTBBX1 fontbbx1, FONTBBX2 fontbbx2)
 767 {
 768   FONT_TTF   font_ttf;
 769   VF_BITMAP  bm;
 770   VF_OUTLINE ol;
 771   void      *val;
 772   double     ps = 0.0, mx, my, asp, aspd; 
 773   double dpix = 0.0, dpiy = 0.0; 
 774   long       cp;
 775   int        chindex;
 776   int        load_flag;
 777   TT_Raster_Map       tt_bitmap;
 778   TT_Glyph_Metrics    tt_metrics;
 779   TT_Instance_Metrics tt_imetrics;
 780   TT_Outline        tt_outline;
 781   TT_Short          xoff, yoff;
 782   TT_Error          error;
 783 
 784   error = 0;
 785 
 786   if ((font_ttf = (FONT_TTF)font->private) == NULL){
 787     fprintf(stderr, "VFlib: Internal error in ttf_get_xxx()\n");
 788     abort();
 789   }
 790 
 791   mx = mag_x * font_ttf->mag * font->mag_x;
 792   my = mag_y * font_ttf->mag * font->mag_y;
 793   asp = v_default_aspect * font_ttf->aspect * (mx / my);
 794 
 795   if (   (mode == MODE_METRIC1) 
 796       || (mode == MODE_FONTBBX1) 
 797       || (mode == MODE_BITMAP1) 
 798       || (mode == MODE_OUTLINE) ){
 799     if (((dpix = font->dpi_x) <= 0) || ((dpiy = font->dpi_y) <= 0)){
 800       dpix = font_ttf->dpi_x;
 801       dpiy = font_ttf->dpi_y;
 802     }
 803     if ((ps = font->point_size) < 0)
 804       ps = font_ttf->point_size;
 805     ps = ps * my;
 806   } else if (   (mode == MODE_METRIC2) 
 807              || (mode == MODE_FONTBBX2) 
 808              || (mode == MODE_BITMAP2) ){
 809     if ((ps = font->pixel_size) < 0)
 810       ps = font_ttf->pixel_size;
 811     ps = ps * my;
 812     dpix = POINTS_PER_INCH;
 813     dpiy = POINTS_PER_INCH;
 814   }
 815 
 816   vf_fm_OpenFileStreamApp(font_ttf->file_path,
 817                           font_ttf->font_number, -1, font, font_ttf,
 818                           (FM_OPEN_METHOD)ttf_open_method, 
 819                           (FM_CLOSE_METHOD)ttf_close_method, "FreeType");
 820 
 821   if (mode != MODE_OUTLINE){
 822     TT_Set_Instance_Resolutions(font_ttf->tt_instance, dpix, dpiy);
 823     error = TT_Set_Instance_PointSize(font_ttf->tt_instance, ps);
 824   } else {
 825     TT_Set_Instance_Resolutions(font_ttf->tt_instance, 
 826                                 96*4, 96*4); /*XXX THESE ARE AD-HOC VALUES!!*/
 827     error = TT_Set_Instance_PointSize(font_ttf->tt_instance, 12);
 828   } 
 829   if (error){
 830     vf_error = VF_ERR_NO_GLYPH;
 831     return NULL;
 832   }
 833 
 834 
 835   if ((mode == MODE_FONTBBX1) || (mode == MODE_FONTBBX2)){
 836     chindex = -1;
 837   } else {
 838     cp = code_point;
 839     if (font_ttf->ccv_id >= 0)
 840       cp = vf_ccv_conv(font_ttf->ccv_id, code_point);
 841     
 842     if (ttf_debug('c')) 
 843       printf("VFlib TrueType: CCV  0x%lx => 0x%lx\n", code_point, cp);
 844     
 845     if (font_ttf->jisx0212_r47e_sjis == TRUE){
 846       cp = fix_jisx0212_row47_empty_sjis(cp);
 847     }
 848 
 849     chindex = TT_Char_Index(font_ttf->tt_charmap, (int)cp);
 850     if (chindex <= 0){
 851       vf_error = VF_ERR_ILL_CODE_POINT;
 852       return NULL;
 853     }
 854     if (ttf_debug('i')) 
 855       printf("VFlib TrueType: charindex 0x%x  (code point 0x%lx)\n", 
 856              chindex, code_point);
 857 
 858     if (font_ttf->hinting == TRUE)
 859       load_flag = TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH;
 860     else 
 861       load_flag = TTLOAD_SCALE_GLYPH;
 862     error = TT_Load_Glyph(font_ttf->tt_instance, font_ttf->tt_glyph, 
 863                           chindex, load_flag);
 864     if (error){
 865       vf_error = VF_ERR_NO_GLYPH;
 866       return NULL;
 867     }
 868     (void) TT_Get_Glyph_Metrics(font_ttf->tt_glyph, &tt_metrics);
 869   }
 870 
 871   (void) TT_Get_Instance_Metrics(font_ttf->tt_instance, &tt_imetrics);
 872 
 873   if (ttf_debug('m')){
 874     printf("VFlib TrueType: Metrics\n");
 875     printf("  in Header   upem: %d, xMin: %d, yMin:%d, xMax:%d, yMax:%d\n",
 876            font_ttf->tt_fprops.header->Units_Per_EM,
 877            font_ttf->tt_fprops.header->xMin, 
 878            font_ttf->tt_fprops.header->yMin, 
 879            font_ttf->tt_fprops.header->xMax, 
 880            font_ttf->tt_fprops.header->yMax);
 881     printf("  tt_metrics.bbx  xMin:%ld, yMin:%ld, xMax:%ld, yMax:%ld\n",
 882            tt_metrics.bbox.xMin, tt_metrics.bbox.yMin, 
 883            tt_metrics.bbox.xMax, tt_metrics.bbox.yMax);
 884     printf("  tt_imetrics  x_ppem:%d, y_ppem:%d, pointSize:%.4f, upem:%d\n",
 885            tt_imetrics.x_ppem, tt_imetrics.y_ppem, 
 886            (double)tt_imetrics.pointSize/64.0, font_ttf->tt_upem);
 887   }
 888 
 889   val = NULL;
 890   if ((mode == MODE_BITMAP1) || (mode == MODE_BITMAP2)){
 891     tt_bitmap.width = (tt_metrics.bbox.xMax-tt_metrics.bbox.xMin)*asp/64 + 1;
 892     tt_bitmap.rows  = (tt_metrics.bbox.yMax-tt_metrics.bbox.yMin)/64 + 1;
 893     tt_bitmap.cols  = (tt_bitmap.width + 7) >> 3;
 894     tt_bitmap.size  = tt_bitmap.cols * tt_bitmap.rows;
 895     tt_bitmap.bitmap = (void *) malloc(tt_bitmap.size);
 896     tt_bitmap.flow  = TT_Flow_Down;
 897     (void)memclr((char*) tt_bitmap.bitmap, tt_bitmap.size);
 898     xoff = -tt_metrics.bbox.xMin;
 899     yoff = -tt_metrics.bbox.yMin;
 900     aspd = 1.0 - asp;
 901     if (aspd < 0)
 902       aspd = 0.0 - aspd;
 903     if (aspd < 1.0e-6){
 904       error = TT_Get_Glyph_Bitmap(font_ttf->tt_glyph, &tt_bitmap, xoff, yoff);
 905       if (error)
 906         return NULL;
 907     } else {
 908       TT_Matrix  mat;
 909       mat.xx = asp * (1<<16);  mat.xy = 0;
 910       mat.yx = 0;              mat.yy = 1 * (1<<16);
 911       TT_Get_Glyph_Outline(font_ttf->tt_glyph, &tt_outline);
 912       TT_Transform_Outline(&tt_outline, &mat);
 913       TT_Translate_Outline(&tt_outline, 
 914                            -asp*tt_metrics.bbox.xMin, -tt_metrics.bbox.yMin);
 915       error = TT_Get_Outline_Bitmap(FreeType_Engine, &tt_outline, &tt_bitmap);
 916       TT_Done_Outline(&tt_outline);
 917     }
 918     ALLOC_IF_ERR(bm, struct vf_s_bitmap){
 919       vf_error = VF_ERR_NO_MEMORY;
 920       return NULL;
 921     }
 922     bm->bbx_width  = tt_bitmap.width;
 923     bm->bbx_height = tt_bitmap.rows;
 924     bm->raster     = tt_bitmap.cols;
 925     bm->bitmap     = (unsigned char*)tt_bitmap.bitmap;
 926     bm->off_x      = tt_metrics.bearingX * asp / 64;
 927     bm->off_y      = tt_metrics.bbox.yMax / 64;
 928     bm->mv_x       = tt_metrics.advance * asp / 64;
 929     bm->mv_y       = 0;
 930     val = (void*) bm;
 931     
 932   } else if (mode == MODE_METRIC1){
 933     double  xppem = 64.0 * (double)tt_imetrics.x_ppem;
 934     double  yppem = 64.0 * (double)tt_imetrics.y_ppem;
 935     double  pt  = (double)tt_imetrics.pointSize / 64.0;
 936     double  ptx = (double)tt_imetrics.pointSize * asp / 64.0;
 937     if (metric1 != NULL){
 938       metric1->bbx_width 
 939         = (double)((tt_metrics.bbox.xMax - tt_metrics.bbox.xMin) / xppem)*ptx;
 940       metric1->bbx_height 
 941         = (double)((tt_metrics.bbox.yMax - tt_metrics.bbox.yMin) / yppem)*pt;
 942       metric1->off_x = (double)(tt_metrics.bearingX  / xppem) * ptx;
 943       metric1->off_y = (double)(tt_metrics.bbox.yMax / yppem) * pt;
 944       metric1->mv_x = (double)(tt_metrics.advance / xppem) * ptx; /*XXX*/
 945       metric1->mv_y = 0.0 * pt;                                   /*XXX*/
 946     }
 947     val = (void*) metric1;
 948 
 949   } else if (mode == MODE_METRIC2){
 950     if (metric2 != NULL){
 951       metric2->bbx_width 
 952         = toint((double)(tt_metrics.bbox.xMax-tt_metrics.bbox.xMin)*asp /64.0);
 953       metric2->bbx_height 
 954         = toint((double)(tt_metrics.bbox.yMax-tt_metrics.bbox.yMin) /64.0);
 955       metric2->off_x = toint((double)tt_metrics.bearingX * asp / 64.0);
 956       metric2->off_y = toint((double)tt_metrics.bbox.yMax / 64.0);
 957       metric2->mv_x  = toint((double)tt_metrics.advance * asp / 64.0);
 958       metric2->mv_y  = 0.0;
 959     }
 960     val = (void*) metric2;
 961 
 962   } else if (mode == MODE_OUTLINE){
 963     error = TT_Get_Glyph_Outline(font_ttf->tt_glyph, &tt_outline);
 964     if (error)
 965       return NULL;
 966     ol = get_outline_ttf_to_vflib(font_ttf, 
 967                                   &tt_outline, &tt_metrics, &tt_imetrics,
 968                                   ps, mag_x, mag_y, dpix, dpiy, asp);
 969     TT_Done_Outline(&tt_outline);
 970     val = (void*) ol;
 971 
 972   } else if (mode == MODE_FONTBBX1){
 973     long  xmax = font_ttf->tt_fprops.header->xMax;
 974     long  xmin = font_ttf->tt_fprops.header->xMin;
 975     long  ymax = font_ttf->tt_fprops.header->yMax;
 976     long  ymin = font_ttf->tt_fprops.header->yMin;
 977     if (fontbbx1 != NULL){
 978       fontbbx1->w = (double)(xmax - xmin) * ps * asp / font_ttf->tt_upem;
 979       fontbbx1->h = (double)(ymax - ymin) * ps       / font_ttf->tt_upem;
 980       fontbbx1->xoff = (double) xmin * ps  * asp / font_ttf->tt_upem;
 981       fontbbx1->yoff = (double) ymin * ps        / font_ttf->tt_upem;
 982     }
 983     val = (void*) fontbbx1;
 984 
 985   } else if (mode == MODE_FONTBBX2){
 986     long  xmax = font_ttf->tt_fprops.header->xMax;
 987     long  xmin = font_ttf->tt_fprops.header->xMin;
 988     long  ymax = font_ttf->tt_fprops.header->yMax;
 989     long  ymin = font_ttf->tt_fprops.header->yMin;
 990     if (fontbbx2 != NULL){
 991       fontbbx2->w = (double)(xmax - xmin) * ps * asp / font_ttf->tt_upem;
 992       fontbbx2->h = (double)(ymax - ymin) * ps       / font_ttf->tt_upem;
 993       fontbbx2->xoff = (double) xmin * ps * asp / font_ttf->tt_upem;
 994       fontbbx2->yoff = (double) ymin * ps       / font_ttf->tt_upem;
 995     }
 996     val = (void*) fontbbx2;
 997 
 998   } else {
 999     fprintf(stderr, "VFlib: Internal error in ttf_get_xxx1()\n");
1000     fprintf(stderr, "Unknown mode: %d\n", mode);
1001     abort();
1002   }
1003 
1004   return val;
1005 }
1006 
1007 Private long
1008 fix_jisx0212_row47_empty_sjis(long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
1009 {
1010   unsigned int   c1, c2;
1011   int            row_offset, cell_offset, adjust;
1012 
1013   if (code_point < 256)
1014     return code_point;
1015 
1016   c1 = code_point / 0x100;
1017   c2 = code_point % 0x100;
1018 
1019   /* SJIS->JIS */
1020   if (c2 < 159)
1021     adjust = 1;
1022   else
1023     adjust = 0;
1024   row_offset  = (c1 < 160) ? 112 : 176;
1025   cell_offset = (adjust == 1) ? ((c2 > 127) ? 32 : 31) : 126;
1026   c1 = ((c1 - row_offset) << 1) - adjust;
1027   c2 -= cell_offset;
1028 
1029   /* Fix */
1030   if (c1 >= (47 + 0x20))
1031     c1++;
1032 
1033   /* JIS -> SJIS */
1034   row_offset  = (c1 < 95) ? 112 : 176;
1035   cell_offset = (c1 % 2) ? ((c2 > 95) ? 32 : 31) : 126;
1036   c1 = ((c1 + 1) >> 1) + row_offset;
1037   c2 += cell_offset;
1038 
1039   return c1*0x100 + c2;
1040 }
1041 
1042 
1043 /*
1044  * The following routine is snarfed from VF_Ftype.c
1045  * in VFlib 2.23 by Mr Matsuda.    
1046  *                                           --- H.Kakugawa
1047  */
1048 Private VF_OUTLINE
1049 get_outline_ttf_to_vflib(FONT_TTF font_ttf, 
     /* [<][>][^][v][top][bottom][index][help] */
1050                          TT_Outline *tt_outline, 
1051                          TT_Glyph_Metrics *tt_metrics,
1052                          TT_Instance_Metrics *tt_imetrics,
1053                          double ps, double mag_x, double mag_y, 
1054                          double dpix, double dpiy, double asp)
1055 {
1056   int              vfsize, ct, pt, sp, ep, p1, p2, p3;
1057   int              maxw, maxh, bbx;
1058   double           x1, y1, x2, y2, x3, y3, f, fupem,  mmm;
1059   VF_OUTLINE_ELEM  token, *vfdata, *vfp;
1060 
1061   mmm = 4*4;   /*ad-hoc*/
1062 
1063   maxw = (tt_metrics->bbox.xMax - tt_metrics->bbox.xMin + 1);
1064   maxh = (tt_metrics->bbox.yMax - tt_metrics->bbox.yMin + 1); 
1065   if ((bbx = maxw) < maxh)
1066     bbx = maxh;
1067 
1068 #if 0
1069   printf("*** %d %d %d   %d   %d %d %d %d\n",
1070          maxw, maxh, bbx, font_ttf->tt_upem,
1071          font_ttf->tt_fprops.header->xMin, font_ttf->tt_fprops.header->yMin, 
1072          font_ttf->tt_fprops.header->xMax, font_ttf->tt_fprops.header->yMax);
1073 #endif
1074 #if 0
1075   printf("*** %.3f  %.3f %.3f  %ld %ld %ld %ld\n",
1076          tt_metrics->advance/64.0, 
1077          tt_metrics->bearingX/64.0, tt_metrics->bearingY/64.0,
1078          tt_metrics->bbox.xMax/64, tt_metrics->bbox.xMin/64,
1079          tt_metrics->bbox.yMax/64, tt_metrics->bbox.yMin/64);
1080   printf("  %.3f %.3f\n",
1081          (double)tt_imetrics->x_ppem / font_ttf->tt_upem,
1082          (double)tt_imetrics->y_ppem / font_ttf->tt_upem);
1083 #endif
1084 
1085   vfsize = VF_OL_OUTLINE_HEADER_SIZE_TYPE0;
1086   for (ct = pt = 0; ct < tt_outline->n_contours; ct++){ 
1087     token = 0L;
1088     sp = pt;
1089     ep = tt_outline->contours[ct];  
1090     for (; pt <= ep; pt++) {
1091       p1 = pt;
1092       p2 = (p1 < ep)? (p1 + 1) : sp;
1093 #if 0
1094       printf(" (%ld %ld)\n", 
1095              tt_outline->points.x[p1], tt_outline->points.y[p1]);
1096 #endif
1097       /*XXX 1.0    [] => 1.1        XXX*/
1098       /*XXX conEnds[] => contors[]  XXX*/
1099       /*XXX contours  => n_contours XXX*/
1100       /*XXX xCoord    => points.x   XXX*/
1101       /*XXX yCoord    => points.y   XXX*/
1102       /*XXX flag[]    => flags      XXX*/
1103       if (tt_outline->flags[p1] & tt_outline->flags[p2] & TTF_OL_ONCURVE){
1104         /* Line */
1105         if (token != VF_OL_INSTR_LINE){
1106           token = VF_OL_INSTR_LINE;
1107           vfsize++;
1108         }
1109         vfsize += 1;
1110       } else {
1111         if (tt_outline->flags[p2] & TTF_OL_ONCURVE) 
1112           continue;
1113         /* spline */
1114         if (token != VF_OL_INSTR_BEZ){
1115           token = VF_OL_INSTR_BEZ;
1116           vfsize++;
1117         }
1118         vfsize += 3;
1119       }
1120     }
1121   }
1122   vfsize++;
1123 
1124   if ((vfdata = (VF_OUTLINE)malloc(vfsize*sizeof(long))) == (VF_OUTLINE)NULL)
1125     return NULL;
1126 
1127   f     = (double)VF_OL_COORD_RANGE / (double)(bbx * mmm);
1128   fupem = (double)VF_OL_COORD_RANGE / (double)bbx;
1129   vfdata[VF_OL_HEADER_INDEX_HEADER_TYPE] = VF_OL_OUTLINE_HEADER_TYPE0; 
1130   vfdata[VF_OL_HEADER_INDEX_DATA_SIZE]   = vfsize; 
1131   vfdata[VF_OL_HEADER_INDEX_DPI_X]       = VF_OL_HEADER_ENCODE(dpix); 
1132   vfdata[VF_OL_HEADER_INDEX_DPI_Y]       = VF_OL_HEADER_ENCODE(dpiy); 
1133   vfdata[VF_OL_HEADER_INDEX_POINT_SIZE]  = VF_OL_HEADER_ENCODE(ps); 
1134   vfdata[VF_OL_HEADER_INDEX_EM]          = ceil(fupem * font_ttf->tt_upem);
1135   vfdata[VF_OL_HEADER_INDEX_MAX_X] 
1136     = toint(f * (tt_metrics->bbox.xMax - tt_metrics->bbox.xMin)) + 1;
1137   vfdata[VF_OL_HEADER_INDEX_MAX_Y] 
1138     = toint(f * (tt_metrics->bbox.yMax - tt_metrics->bbox.yMin)) + 1;
1139   /* ... horizintal direction only. B-( */
1140   vfdata[VF_OL_HEADER_INDEX_REF_X] = toint(f * (tt_metrics->bearingX));
1141   vfdata[VF_OL_HEADER_INDEX_REF_Y] = toint(f * tt_metrics->bbox.yMax);
1142   vfdata[VF_OL_HEADER_INDEX_MV_X]  = toint(f * (tt_metrics->advance));
1143   vfdata[VF_OL_HEADER_INDEX_MV_Y]  = toint(f * 0);
1144 
1145 #define ConvX(x) (long)(VF_OL_COORD_OFFSET + f * ((x)-tt_metrics->bbox.xMin))
     /* [<][>][^][v][top][bottom][index][help] */
1146 #define ConvY(y) (long)(VF_OL_COORD_OFFSET + f * (tt_metrics->bbox.yMax-(y)))
     /* [<][>][^][v][top][bottom][index][help] */
1147 
1148   vfp = &vfdata[VF_OL_OUTLINE_HEADER_SIZE_TYPE0];
1149   for (ct = pt = 0; ct < tt_outline->n_contours; ct++){
1150     token = (VF_OL_INSTR_TOKEN | VF_OL_INSTR_CWCURV);
1151     sp = pt;
1152     ep = tt_outline->contours[ct];
1153     for (; pt <= ep; pt++){
1154       p1 = pt;
1155       p2 = (p1 < ep) ? (p1 + 1) : sp;
1156       p3 = (p2 < ep) ? (p2 + 1) : sp;
1157       if (tt_outline->flags[p1] & tt_outline->flags[p2] & TTF_OL_ONCURVE){
1158         /* Line */
1159         if (token != (VF_OL_INSTR_TOKEN | VF_OL_INSTR_LINE)) {
1160           if (token == (VF_OL_INSTR_TOKEN | VF_OL_INSTR_CWCURV)){
1161             *(vfp++) = token | VF_OL_INSTR_LINE;
1162           } else {
1163             *(vfp++) = VF_OL_INSTR_TOKEN | VF_OL_INSTR_LINE;
1164           }
1165           token = VF_OL_INSTR_TOKEN | VF_OL_INSTR_LINE;
1166         }
1167         x1 = tt_outline->points[p1].x;
1168         y1 = tt_outline->points[p1].y;
1169         *(vfp++) = VF_OL_MAKE_XY(ConvX(x1), ConvY(y1));
1170       } else {
1171         if (tt_outline->flags[p2] & TTF_OL_ONCURVE)
1172           continue;
1173         /* spline */
1174         if (token != (VF_OL_INSTR_TOKEN | VF_OL_INSTR_BEZ)){
1175           if (token == (VF_OL_INSTR_TOKEN | VF_OL_INSTR_CWCURV)){
1176             *(vfp++) = token | VF_OL_INSTR_BEZ;
1177           } else {
1178             *(vfp++) = VF_OL_INSTR_TOKEN | VF_OL_INSTR_BEZ;
1179           }
1180           token = VF_OL_INSTR_TOKEN | VF_OL_INSTR_BEZ;
1181         }
1182         if (tt_outline->flags[p1] & TTF_OL_ONCURVE){
1183           x1 = tt_outline->points[p1].x;
1184           y1 = tt_outline->points[p1].y;
1185         } else {
1186           x1 = (tt_outline->points[p1].x + tt_outline->points[p2].x) / 2.0;
1187           y1 = (tt_outline->points[p1].y + tt_outline->points[p2].y) / 2.0;
1188         }
1189         x2 = tt_outline->points[p2].x;
1190         y2 = tt_outline->points[p2].y;
1191         if (tt_outline->flags[p3] & TTF_OL_ONCURVE){
1192           x3 = tt_outline->points[p3].x;
1193           y3 = tt_outline->points[p3].y;
1194         } else {
1195           x3 = (tt_outline->points[p2].x + tt_outline->points[p3].x) / 2.0;
1196           y3 = (tt_outline->points[p2].y + tt_outline->points[p3].y) / 2.0;
1197         }
1198         *(vfp++) = VF_OL_MAKE_XY(ConvX(x1), ConvY(y1));
1199         *(vfp++) = VF_OL_MAKE_XY(ConvX((x1 + 2.0 * x2) / 3.0),
1200                                  ConvY((y1 + 2.0 * y2) / 3.0));
1201         *(vfp++) = VF_OL_MAKE_XY(ConvX((2.0 * x2 + x3) / 3.0),
1202                                  ConvY((2.0 * y2 + y3) / 3.0));
1203       }
1204     }
1205   }
1206   *(vfp++) = 0L;
1207 
1208   if (vfdata[VF_OL_OUTLINE_HEADER_SIZE_TYPE0] != 0L)
1209     vfdata[VF_OL_OUTLINE_HEADER_SIZE_TYPE0] |= VF_OL_INSTR_CHAR;
1210 
1211   return (VF_OUTLINE)vfdata;
1212 }
1213 
1214 
1215 
1216 Private char*
1217 ttf_get_font_prop(VF_FONT font, char *prop_name)
     /* [<][>][^][v][top][bottom][index][help] */
1218 { /* CALLER MUST RELEASE RETURNED STRING LATER */
1219   SEXP       v;
1220   FONT_TTF   font_ttf;
1221   char       str[512];
1222   double     dpix, dpiy, p;
1223 
1224   if ((font_ttf = (FONT_TTF)font->private) == NULL){
1225     fprintf(stderr, "VFlib: internal error in ttf_get_font_prop()\n");
1226     abort();
1227   }
1228 
1229   if ((v = vf_sexp_assoc(prop_name, font_ttf->props)) != NULL){
1230     return vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)));
1231   } else if ((v = vf_sexp_assoc(prop_name, default_properties)) != NULL){
1232     return vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)));
1233   }
1234 
1235   if (font->mode == 1){
1236     if ((dpix = font->dpi_x) < 0)
1237       if ((dpix = font_ttf->dpi_x) < 0)
1238         dpix = v_default_dpi_x; 
1239     if ((dpiy = font->dpi_y) < 0)
1240       if ((dpiy = font_ttf->dpi_y) < 0)
1241         dpiy = v_default_dpi_y; 
1242     if ((p = font->point_size) < 0)
1243       if ((p = font_ttf->point_size) < 0)
1244         p = v_default_point_size;
1245     p = p * font->mag_y * font_ttf->mag;
1246     if (strcmp(prop_name, "POINT_SIZE") == 0){  
1247       sprintf(str, "%d", toint(p * 10.0)); 
1248       return vf_strdup(str);
1249     } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
1250       sprintf(str, "%d", toint(p * dpiy / POINTS_PER_INCH));
1251       return vf_strdup(str);
1252     } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
1253       sprintf(str, "%d", toint(dpix)); 
1254       return vf_strdup(str);
1255     } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
1256       sprintf(str, "%d", toint(dpiy)); 
1257       return vf_strdup(str);
1258     }
1259 
1260   } else if (font->mode == 2){
1261     if ((p = font->pixel_size) < 0)
1262       if ((p = font_ttf->pixel_size) < 0)
1263         p = v_default_pixel_size;
1264     p = p * font->mag_y * font_ttf->mag;
1265     if (strcmp(prop_name, "POINT_SIZE") == 0){  
1266       sprintf(str, "%d", toint(p * 10.0 * POINTS_PER_INCH / VF_DEFAULT_DPI)); 
1267     } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
1268       sprintf(str, "%d", toint(p));
1269       return vf_strdup(str);
1270     } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
1271       sprintf(str, "%d", toint(VF_DEFAULT_DPI)); 
1272       return vf_strdup(str);
1273     } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
1274       sprintf(str, "%d", toint(VF_DEFAULT_DPI)); 
1275       return vf_strdup(str);
1276     }
1277   }
1278     
1279 #if 0
1280   if (strcmp(prop_name, "FONT_ASCENT") == 0){
1281     ;
1282   } else if (strcmp(prop_name, "FONT_DESCENT") == 0){
1283     ;
1284   }
1285 #endif
1286 
1287   return NULL;
1288 }
1289 
1290 
1291 
1292 Private int
1293 find_encoding_mapping(FONT_TTF font_ttf)
     /* [<][>][^][v][top][bottom][index][help] */
1294 {
1295   int               ccv_id, map, ntables;
1296   char              *internal_enc, *cs;
1297   unsigned short    platform_id, encoding_id;
1298   TT_Error          error;
1299 
1300   if (ttf_debug('p')){
1301     printf("VFlib TrueType: Searching platform:%d (%s), encoding:%d (%s))\n", 
1302            font_ttf->platform_id,
1303            platform_id2name(font_ttf->platform_id), 
1304            font_ttf->encoding_id,
1305            encoding_id2name(font_ttf->platform_id,font_ttf->encoding_id));
1306   }
1307 
1308   /* Find mapping table number to be used in TrueType font file. */
1309   map = font_ttf->mapping_id;
1310   ntables = TT_Get_CharMap_Count(font_ttf->tt_face);
1311   if (map != TT_MAP_ID_SEARCH){
1312     if (ntables == 0){
1313       fprintf(stderr, "VFlib TrueType warning: No mapping tables: %s\n",
1314               font_ttf->font_name);
1315       return -1;
1316     } else if (ntables < 0){
1317       fprintf(stderr, "VFlib TrueType Internal error: CharMap_Count()%s\n",
1318               font_ttf->font_name);
1319       return -1;
1320     } else if ((map < 0) || (ntables <= map)){
1321       map = 0;
1322       fprintf(stderr, "VFlib TrueType warning: Illegal mapping table ID.");
1323       fprintf(stderr, "Use mapping table #0.\n");
1324     }
1325     error = TT_Get_CharMap_ID(font_ttf->tt_face, map, 
1326                               &platform_id, &encoding_id);
1327     if (error)
1328       return -1;
1329     if (ttf_debug('p')) 
1330       printf("VFlib TrueType:  Platform,Encoding=(%s,%s)\n", 
1331              platform_id2name(platform_id), 
1332              encoding_id2name(platform_id, encoding_id));
1333   } else {
1334     for (map = 0; map < ntables; map++){
1335       error = TT_Get_CharMap_ID(font_ttf->tt_face, map, 
1336                                 &platform_id, &encoding_id);
1337       if (ttf_debug('p'))
1338         printf("VFlib TrueType:   mapping #%d: Platform: %s, Encoding:%s\n", 
1339                map, 
1340                platform_id2name(platform_id), 
1341                encoding_id2name(platform_id, encoding_id));
1342       if (   ((font_ttf->platform_id == TT_PLAT_ID_ANY)
1343               || (platform_id == font_ttf->platform_id))
1344           && ((font_ttf->encoding_id == TT_ENC_ID_ANY) 
1345               || (encoding_id == font_ttf->encoding_id)) ){
1346         break;
1347       }
1348       font_ttf->mapping_id = 0;
1349     }
1350     if (map == ntables){
1351       fprintf(stderr, "VFlib TrueType: Mapping table not found.\n");
1352       return -1;
1353     }
1354   }
1355 
1356   font_ttf->mapping_id = map;
1357 
1358   if (ttf_debug('p'))
1359     printf("VFlib TrueType: Use mapping table #%d (encoding#%d)\n", 
1360            font_ttf->mapping_id, encoding_id);
1361   
1362   error = TT_Get_CharMap(font_ttf->tt_face, font_ttf->mapping_id, 
1363                          &font_ttf->tt_charmap);
1364   if (error)
1365     return -1;
1366 
1367   if (font_ttf->encoding_force < 0){
1368     internal_enc = conv_encoding_ttf_to_vflib(encoding_id, platform_id);
1369   } else {
1370     internal_enc = conv_encoding_ttf_to_vflib(font_ttf->encoding_force,
1371                                               platform_id);
1372     if (ttf_debug('p')){
1373       printf("VFlib TrueType: Encoding force: %s ==> %s\n", 
1374              encoding_id2name(platform_id, encoding_id),
1375              encoding_id2name(platform_id, font_ttf->encoding_force));
1376     }
1377   }
1378 
1379   /* ad-hoc */
1380   cs = font_ttf->charset_name; 
1381   if ((internal_enc != NULL) && (strcmp(internal_enc, "UNICODE") == 0))
1382     cs = "UNICODE";
1383 
1384   ccv_id = vf_ccv_require(font_ttf->charset_name, font_ttf->encoding_name,
1385                           cs, internal_enc);
1386 
1387   if (ttf_debug('p') || ttf_debug('c'))
1388     printf("VFlib TrueType: CCV ID = %d\n", ccv_id);
1389 
1390   return ccv_id;
1391 }
1392 
1393 
1394 Private struct s_id_name_tbl  PlatformNameTable[] = {
1395   {TT_PLAT_ID_ANY,       "any"},       {TT_PLAT_ID_ANY,       "?"},
1396   {TT_PLAT_ID_ANY,       "*"},         {TT_PLAT_ID_APPLE,     "apple"},
1397   {TT_PLAT_ID_MACINTOSH, "macintosh"}, {TT_PLAT_ID_MACINTOSH, "mac"},
1398   {TT_PLAT_ID_ISO,       "iso"},       {TT_PLAT_ID_ISO,       "ascii"},
1399   {TT_PLAT_ID_MICROSOFT, "windows"},   {TT_PLAT_ID_MICROSOFT, "microsoft"},
1400   {TT_PLAT_ID_MICROSOFT, "ms"},        {-1, NULL}}; 
1401 
1402 Private struct s_id_name_tbl  EncodingNameTableISO[] = {
1403   {TT_ENC_ID_ANY,        "any"},
1404   {TT_ENC_ID_ANY,        "?"},
1405   {TT_ENC_ID_ANY,        "*"},          
1406   {TT_ENC_ID_ISO_ASCII,             "ascii"},   
1407   {TT_ENC_ID_ISO_10646,             "iso10464"},
1408   {TT_ENC_ID_ISO_8859_1,            "iso8859-1"},
1409   {-1, NULL}}; 
1410 Private struct s_id_name_tbl  EncodingNameTableMS[] = {
1411   {TT_ENC_ID_ANY,        "any"},        
1412   {TT_ENC_ID_ANY,        "?"},
1413   {TT_ENC_ID_ANY,        "*"},
1414   {TT_ENC_ID_MS_SYMBOL,     "symbol"},
1415   {TT_ENC_ID_MS_UNICODE,    "unicode"},
1416   {TT_ENC_ID_MS_SHIFT_JIS,  "shift-jis"},
1417   {TT_ENC_ID_MS_SHIFT_JIS,  "sjis"},    
1418   {TT_ENC_ID_MS_SHIFT_JIS,  "ms-kanji"},
1419   {TT_ENC_ID_MS_BIG5,       "big5"},   
1420   {TT_ENC_ID_MS_RPC,        "rpc"},
1421   {TT_ENC_ID_MS_WANSUNG,    "wansung"},
1422   {TT_ENC_ID_MS_JOHAB,      "johab"},
1423   {-1, NULL}}; 
1424 Private struct s_id_name_tbl  EncodingNameTableApple[] = {
1425   {TT_ENC_ID_ANY,        "any"},
1426   {TT_ENC_ID_ANY,        "?"},
1427   {TT_ENC_ID_ANY,        "*"},          
1428   {TT_ENC_ID_APPLE_DEFAULT,       "default"},   
1429   {TT_ENC_ID_APPLE_UNICODE_1_1,   "unicode1.1"},
1430   {TT_ENC_ID_APPLE_UNICODE_2_0,   "unicode2.0"},
1431   {TT_ENC_ID_APPLE_ISO_10646,     "iso10464"},
1432   {-1, NULL}}; 
1433 Private struct s_id_name_tbl  EncodingNameTableMac[] = {
1434   {TT_ENC_ID_ANY,        "any"},
1435   {TT_ENC_ID_ANY,        "?"},
1436   {TT_ENC_ID_ANY,        "*"},          
1437   {TT_ENC_ID_MAC_ROMAN,               "roman"},   
1438   {TT_ENC_ID_MAC_JAPANESE,            "japanese"},
1439   {TT_ENC_ID_MAC_TRADITIONAL_CHINESE, "traditional-chinese"},
1440   {TT_ENC_ID_MAC_KOREAN,              "korean"},
1441   {TT_ENC_ID_MAC_ARABIC,              "arabic"},
1442   {TT_ENC_ID_MAC_HEBREW,              "hebrew"},
1443   {TT_ENC_ID_MAC_GREEK,               "greek"},
1444   {TT_ENC_ID_MAC_RUSSIAN,             "russian"},
1445   {-1, NULL}}; 
1446 Private struct s_id_name_tbl  *EncodingNameTableTable[] = {
1447   EncodingNameTableApple,
1448   EncodingNameTableMac,
1449   EncodingNameTableISO,
1450   EncodingNameTableMS,
1451   NULL
1452 };
1453 
1454 Private int 
1455 get_id_from_platform_name(char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1456 {
1457   return name2id(name, PlatformNameTable, TT_PLAT_ID_ANY, "platform name");
1458 }
1459 
1460 Private int 
1461 get_id_from_encoding_name(char *name, int platform)
     /* [<][>][^][v][top][bottom][index][help] */
1462 {
1463   struct s_id_name_tbl *tbl;
1464 
1465   tbl = EncodingNameTableTable[platform];
1466   return name2id(name, tbl, TT_ENC_ID_ANY, "encoding name");
1467 }
1468 
1469 Private int 
1470 name2id(char *name, ID_NAME_TBL tbl, int value_default, char *desc)
     /* [<][>][^][v][top][bottom][index][help] */
1471 {
1472   int         id, t;
1473   char        *p;
1474 
1475   for (p = name; *p != '\0'; p++){
1476     if (!isspace((int)*p))
1477       break;
1478   }
1479   if (*p == '\0'){
1480     id = value_default;
1481   } else if (isdigit((int)*p)){
1482     id = atoi(p);
1483   } else {
1484     id = value_default;
1485     for (t = 0; tbl[t].name != NULL; t++){
1486       if (vf_strncmp_ci(name, tbl[t].name, strlen(tbl[t].name)) == 0)
1487         return tbl[t].id;
1488     }
1489     fprintf(stderr, "VFlib warning: in vflibcap - No such %s: %s\n", 
1490             desc, name);
1491   }
1492   return id;
1493 }
1494 
1495 
1496 struct s_ttf_encoding_tbl {
1497   int  ttf_enc;
1498   char *str_name;
1499 };
1500 Private struct s_ttf_encoding_tbl  ttf_encoding_tbl_apple[] = {
1501   {-10000,                   NULL}
1502 };
1503 Private struct s_ttf_encoding_tbl  ttf_encoding_tbl_mac[] = {
1504   {-10000,                   NULL}
1505 };
1506 Private struct s_ttf_encoding_tbl  ttf_encoding_tbl_iso[] = {
1507   {-10000,                   NULL}
1508 };
1509 Private struct s_ttf_encoding_tbl  ttf_encoding_tbl_ms[] = {
1510   {TT_ENC_ID_MS_SYMBOL,      "Symbol"}, 
1511   {TT_ENC_ID_MS_UNICODE,     "UNICODE"},
1512   {TT_ENC_ID_MS_SHIFT_JIS,   "SJIS"}, 
1513   {TT_ENC_ID_MS_BIG5,        "BIG5"},   
1514   {TT_ENC_ID_MS_RPC,         "RPC"}, 
1515   {TT_ENC_ID_MS_WANSUNG,     "WANSUNG"}, 
1516   {TT_ENC_ID_MS_JOHAB,       "JOHAB"}, 
1517   {TT_ENC_ID_ANY,            NULL},       
1518   {-10000,                   NULL}
1519 };
1520 
1521 Private struct s_ttf_encoding_tbl  *ttf_encoding_tbltbl[] = {
1522   ttf_encoding_tbl_apple,
1523   ttf_encoding_tbl_mac,
1524   ttf_encoding_tbl_iso,
1525   ttf_encoding_tbl_ms,
1526   NULL
1527 };
1528 
1529 Private char*
1530 conv_encoding_ttf_to_vflib(int ttf_enc, int platform)
     /* [<][>][^][v][top][bottom][index][help] */
1531 {
1532   int   i;
1533   struct s_ttf_encoding_tbl  *tbl;
1534 
1535   tbl = ttf_encoding_tbltbl[platform];
1536   for (i = 0; tbl[i].ttf_enc >= -10; i++){
1537     if (tbl[i].ttf_enc == ttf_enc)
1538       return tbl[i].str_name;
1539   }
1540   return NULL;
1541 }
1542 
1543 
1544 
1545 Private char*  platform_id2name(int);
1546 Private char *ttf_platform_name[] = {
1547   "Apple", "Macintosh", "ISO", "Microsoft",  NULL };
1548 
1549 Private char *ttf_encoding_name_apple[] = {
1550   "Apple" "Unicode 1.1", "IS10646", "Unicode 2.0", NULL };
1551 Private char *ttf_encoding_name_mac[] = {
1552   "Roman",      "Japanese",  "Chinese",   "Koran",    "Arabic", 
1553   "Hebrew",     "Greek",     "Russian",   "RSymbol",  "Devanagari",
1554   "Gurmukhi",   "Gujarati",  "Oriya",     "Bengali",   "Tamil",
1555   "Telugu",     "Kannada",   "Malayalam", "Singalese", "Burmese",
1556   "Khmer",      "Thai",      "Laotian",   "Georgian",  "Armenian",
1557   "Maldivian",  "Tibetan",   "Mongolian", "Geez",      "Slavic", 
1558   "Vietnamese", "Sindhi",    "Uninterp",  NULL };
1559 Private char *ttf_encoding_name_iso[] = {
1560   "7-bit ASCII", "ISO 10646", "ISO 8859-1", NULL};
1561 Private char *ttf_encoding_name_ms[] = {
1562   "Symbol", "Unicode", "Shift JIS", "Big 5", 
1563   "RPC",    "WanSung", "Johab",     NULL };
1564 Private char **ttf_encoding_table[] = {
1565   ttf_encoding_name_apple,
1566   ttf_encoding_name_mac, 
1567   ttf_encoding_name_iso, 
1568   ttf_encoding_name_ms, 
1569 };
1570 
1571 Private char*
1572 platform_id2name(int plat_id)
     /* [<][>][^][v][top][bottom][index][help] */
1573 {
1574   int  j;
1575   char *s;
1576 
1577   for (j = 0; ttf_platform_name[j] != NULL; j++){
1578     if (j == plat_id)
1579       break;
1580   }
1581   if ((s = ttf_platform_name[j]) == NULL)
1582     return "?";
1583   return s;
1584 }
1585 
1586 Private char*
1587 encoding_id2name(int plat_id, int enc_id)
     /* [<][>][^][v][top][bottom][index][help] */
1588 {
1589   int  j;
1590   char *s;
1591 
1592   for (j = 0; ttf_encoding_table[plat_id][j] != NULL; j++){
1593     if (j == enc_id)
1594       break;
1595   }
1596   if ((s = ttf_encoding_table[plat_id][j]) == NULL)
1597     return "?";
1598   return s;
1599 }
1600 
1601 
1602 
1603 Private int  ttf_debug2(char type, char *str);
1604 
1605 Private int
1606 ttf_debug(char type)
     /* [<][>][^][v][top][bottom][index][help] */
1607 {
1608   int    v;
1609   char  *p0;
1610 
1611   v = FALSE;
1612   if (env_debug_mode != NULL){
1613     if ((v = ttf_debug2(type, env_debug_mode)) == TRUE)
1614       return TRUE;
1615   }
1616 
1617   if (default_debug_mode == NULL)
1618     return FALSE;
1619   if ((p0 = vf_sexp_get_cstring(default_debug_mode)) == NULL)
1620     return FALSE;
1621   return ttf_debug2(type, p0);
1622 }
1623 
1624 Private int
1625 ttf_debug2(char type, char *p0)
     /* [<][>][^][v][top][bottom][index][help] */
1626 {
1627   char  *p;
1628 
1629   for (p = p0; *p != '\0'; p++){
1630     if (*p == type)
1631       return TRUE;
1632   }
1633   for (p = p0; *p != '\0'; p++){
1634     if (*p == '*')
1635       return TRUE;
1636   }
1637   return FALSE;
1638 }
1639 
1640 /*EOF*/

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