src/jg.c

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

FUNCTIONS

This source file includes following functions.
  1. JG_Init
  2. JG_Open
  3. JG_Close
  4. jg_release
  5. jg_make_header
  6. jg_read_header
  7. jg_correct_size
  8. JG_ReadOutline
  9. CONV_COORD_X
  10. CONV_COORD_Y
  11. jg_charcode2c
  12. jg_read_1byte
  13. jg_read_4bytes
  14. jg_init_bit_stream
  15. jg_read_12bits
  16. jg_read_xy

   1 /*
   2  * jg.c - JG font interface
   3  * by Hirotsugu Kakugawa
   4  *
   5  *  3 Dec 1996  First version.
   6  * 10 Dec 1996  Changed for VFlib version 3.1
   7  * 12 Dec 1996  Eliminated "do" capability.
   8  * 26 Feb 1997  Added 'query_font_type'.
   9  *  7 Aug 1997  VFlib 3.3  Changed API.
  10  * 27 Jan 1998  VFlib 3.4  Changed API.
  11  * 18 Oct 2001    Fixed memory leaks.
  12  *
  13  */
  14 /*
  15  * Copyright (C) 1993-2001 Hirotsugu Kakugawa. 
  16  * All rights reserved.
  17  *
  18  * This file is part of the VFlib Library.  This library is free
  19  * software; you can redistribute it and/or modify it under the terms of
  20  * the GNU Library General Public License as published by the Free
  21  * Software Foundation; either version 2 of the License, or (at your
  22  * option) any later version.  This library is distributed in the hope
  23  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  24  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  25  * PURPOSE.  See the GNU Library General Public License for more details.
  26  * You should have received a copy of the GNU Library General Public
  27  * License along with this library; if not, write to the Free Software
  28  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  29  */
  30 
  31 #include  "jg.h"
  32 
  33 
  34 Private  VF_TABLE  jg_table    = NULL;
  35 
  36 
  37 Private int
  38 JG_Init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40   JG_GetJG(-1);
  41 
  42   if ((jg_table = vf_table_create()) == NULL){
  43     vf_error = VF_ERR_NO_MEMORY;
  44     return -1;
  45   }
  46 
  47   return 0;
  48 }
  49 
  50 
  51 Private void  jg_release(JG jg);
  52 Private int   jg_make_header(char*,JG,int);
  53 Private int   jg_correct_size(int seq, FILE *fp, JG_HEADER header);
  54 
  55 Private int
  56 JG_Open(char *font_name)
     /* [<][>][^][v][top][bottom][index][help] */
  57 {
  58   JG   jg;
  59   int  jg_id, i;
  60 
  61   if ((jg_id = (jg_table->get_id_by_key)(jg_table, font_name, 
  62                                          strlen(font_name)+1)) >= 0){
  63     (jg_table->link_by_id)(jg_table, jg_id);
  64     return jg_id;
  65   }
  66 
  67   ALLOC_IF_ERR(jg, struct s_jg){
  68     vf_error = VF_ERR_NO_MEMORY;
  69     return -1;
  70   }
  71 
  72   jg->nfiles = 3;
  73 
  74   ALLOCN_IF_ERR(jg->headers, JG_HEADER, jg->nfiles){
  75     vf_error = VF_ERR_NO_MEMORY;
  76     goto Error;
  77   }
  78   for (i = 0; i < jg->nfiles; i++)
  79     jg->headers[i] = NULL;
  80 
  81   for (i = 0; i < jg->nfiles; i++){
  82     ALLOC_IF_ERR(jg->headers[i], struct s_jg_header){
  83       vf_error = VF_ERR_NO_MEMORY;
  84       goto Error;
  85     }
  86   }
  87   jg->headers[0]->nchars = JG_CODE_SIZE0;
  88   jg->headers[1]->nchars = JG_CODE_SIZE1;
  89   jg->headers[2]->nchars = JG_CODE_SIZE2;
  90 
  91   for (i = 0; i < jg->nfiles; i++){
  92     if (jg_make_header(font_name, jg, i) < 0)
  93       goto Error;
  94   }    
  95 
  96   if ((jg_id = (jg_table->put)(jg_table, jg, 
  97                                font_name, strlen(font_name)+1)) < 0){
  98     vf_error = VF_ERR_NO_MEMORY;
  99     goto Error;
 100   }
 101 
 102   JG_SetJG(jg_id, jg);
 103 
 104   return jg_id;
 105 
 106 Error:
 107   jg_release(jg);
 108   return -1;
 109 }
 110 
 111 
 112 Private void
 113 JG_Close(int jg_id)
     /* [<][>][^][v][top][bottom][index][help] */
 114 {
 115   JG   jg;
 116 
 117   if ((jg = JG_GetJG(jg_id)) == NULL){
 118     fprintf(stderr, "VFlib internal error: JG_Close()\n");
 119     vf_error = VF_ERR_INTERNAL;
 120     return;
 121   }
 122   if ((jg_table->unlink_by_id)(jg_table, jg_id) > 0)
 123     return;
 124 
 125   jg_release(jg);
 126 }
 127 
 128 Private void
 129 jg_release(JG jg)
     /* [<][>][^][v][top][bottom][index][help] */
 130 {
 131   int  i;
 132 
 133   if (jg != NULL){ 
 134     for (i = 0; i < jg->nfiles; i++){
 135       if (jg->headers[i] != NULL){
 136         vf_free(jg->headers[i]->font_path);
 137         vf_free(jg->headers[i]->ol_offset);
 138         vf_free(jg->headers[i]->ol_size);
 139         vf_free(jg->headers[i]);
 140       }
 141     }
 142     vf_free(jg->headers);
 143     vf_free(jg);
 144   }
 145 }
 146 
 147 
 148 Private int   jg_read_header(char*,JG_HEADER);
 149 
 150 Private int            jg_read_1byte(FILE*);
 151 Private unsigned long  jg_read_4bytes(FILE*);
 152 Private void           jg_init_bit_stream(FILE*);
 153 Private unsigned int   jg_read_12bits(void);
 154 Private int            jg_read_xy(int*,int*);
 155 
 156 
 157 Private int
 158 jg_make_header(char *font_name, JG jg, int fseq)
     /* [<][>][^][v][top][bottom][index][help] */
 159 {
 160   char   *font_path, *e;
 161   char   fname[MAXPATHLEN];
 162   int    i;
 163   SEXP   s;
 164 
 165   font_path = NULL;
 166   for (s = default_extensions; vf_sexp_consp(s); s = vf_sexp_cdr(s)){
 167     e = vf_sexp_get_cstring(vf_sexp_car(s));
 168     sprintf(fname, "%s%s%d", font_name, e, fseq);
 169     if ((font_path
 170          = vf_search_file(fname, -1, NULL, FALSE, -1,
 171                           default_fontdirs, NULL, NULL)) != NULL)
 172       break;
 173   }
 174   
 175   if (font_path == NULL){
 176     if (fseq == 0){
 177       vf_error = VF_ERR_NO_FONT_FILE;
 178       return -1;
 179     } else {
 180       jg->headers[fseq]->font_path = NULL;
 181       jg->headers[fseq]->ol_offset = NULL;
 182       jg->headers[fseq]->ol_size   = NULL;
 183     }
 184     return 0;
 185   }
 186 
 187   if (debug_on('f'))
 188     printf("VFlib JG: font path: %s\n", font_path);
 189 
 190   jg->headers[fseq]->font_path = font_path;
 191   ALLOCN_IF_ERR(jg->headers[fseq]->ol_offset, long, jg->headers[fseq]->nchars)
 192     goto Error;
 193   ALLOCN_IF_ERR(jg->headers[fseq]->ol_size, long, jg->headers[fseq]->nchars)
 194     goto Error;
 195 
 196   for (i = 0; i < jg->headers[fseq]->nchars; i++){
 197     jg->headers[fseq]->ol_offset[i] = -1;
 198     jg->headers[fseq]->ol_size[i]   = 0;
 199   }
 200 
 201   if (jg_read_header(font_path, jg->headers[fseq]) < 0)
 202     goto Error;
 203 
 204   return 0;
 205 
 206 Error:
 207   vf_error = VF_ERR_NO_MEMORY;
 208   vf_free(jg->headers[fseq]->font_path); jg->headers[fseq]->font_path = NULL;
 209   vf_free(jg->headers[fseq]->ol_offset); jg->headers[fseq]->ol_offset = NULL;
 210   vf_free(jg->headers[fseq]->ol_size);   jg->headers[fseq]->ol_size   = NULL;
 211   return -1;
 212 }
 213 
 214 Private int 
 215 jg_read_header(char *font_path, JG_HEADER header)
     /* [<][>][^][v][top][bottom][index][help] */
 216 {
 217   int   prefix, i, j;
 218   FILE  *fp;
 219 
 220   if ((fp = vf_fm_OpenBinaryFileStream(font_path)) == NULL){
 221     fprintf(stderr, "VFlib Error. File not found: %s\n", font_path);
 222     return -1;
 223   }
 224 
 225   fseek(fp, 8L, SEEK_SET);
 226   prefix  = (unsigned int) jg_read_1byte(fp);
 227   prefix += (unsigned int) jg_read_1byte(fp) * 0x100;
 228   header->base = 10 + prefix + 4*header->nchars;
 229 
 230   if (debug_on('i'))
 231     printf("VFlib JG: PREFIX %04x \n", prefix); 
 232 
 233   fseek(fp, (long)(prefix+0x0a), SEEK_SET);
 234   for (i = 0; i < header->nchars; i++){
 235     header->ol_offset[i] = jg_read_4bytes(fp);
 236     if (debug_on('i'))
 237       printf("VFlib JG: Index: %04x,  offset: %04lx\n",
 238              i, header->ol_offset[i]);
 239     if (header->ol_offset[i] != EMPTY_PTR)
 240       header->ol_offset[i] += header->base;
 241   }
 242 
 243   for (i = 0; i < header->nchars-1; i++){
 244     if (header->ol_offset[i] == EMPTY_PTR){
 245       header->ol_size[i] = 0;
 246     } else {
 247       for (j = i+1; ; j++){
 248         if (j >= header->nchars){
 249           header->ol_size[i] = -(THRESHOLD_SIZE+1);
 250           break;
 251         }
 252         if (header->ol_offset[j] != EMPTY_PTR){
 253           header->ol_size[i] = -(header->ol_offset[j] - header->ol_offset[i]);
 254           break;
 255         }
 256       }
 257     }
 258     if (debug_on('i'))
 259       printf("VFlib JG:  index: %04x,  ol size: %04lx\n",
 260              i, -header->ol_size[i]);
 261     if (-(header->ol_size[i]) > THRESHOLD_SIZE)
 262       header->ol_size[i] = EMPTY_PTR;
 263   }
 264 
 265   /* when i == header->nchars-1: */
 266   if (header->ol_offset[header->nchars-1] == EMPTY_PTR){
 267     header->ol_size[header->nchars-1] = 0;
 268   } else {
 269     header->ol_size[header->nchars-1] = -(THRESHOLD_SIZE+1);
 270     jg_correct_size(header->nchars-1, fp, header);
 271   }
 272 
 273   return 0;
 274 }
 275 
 276 /* correct the size of font data */
 277 Private int
 278 jg_correct_size(int seq, FILE *fp, JG_HEADER header) 
     /* [<][>][^][v][top][bottom][index][help] */
 279 {
 280   int   x, y;
 281 
 282   if (debug_on('i'))
 283     printf("VFlib JG:  Too Large for %04x\n   Size:%04lx ",
 284            seq, -header->ol_size[seq]); 
 285 
 286   fseek(fp, header->ol_offset[seq], SEEK_SET);
 287   jg_init_bit_stream(fp);
 288   for (;;){
 289     if (jg_read_xy(&x, &y) == -1)
 290       break;
 291     while (jg_read_xy(&x, &y) != -1)
 292       ;
 293   }
 294   header->ol_size[seq] = -(ftell(fp) - header->ol_offset[seq]);
 295 
 296   if (debug_on('i'))
 297     printf("VFlib JG:  ==>  %04lx\n", -header->ol_size[seq]);
 298 
 299   return header->ol_size[seq];
 300 }
 301 
 302 
 303 Private int   jg_correct_size(int,FILE*,JG_HEADER);
 304 Private int   jg_charcode2c(int);
 305 
 306 Private VF_OUTLINE
 307 JG_ReadOutline(int jg_id, int code_point, 
     /* [<][>][^][v][top][bottom][index][help] */
 308                double mag_x, double mag_y)
 309 {
 310   FILE       *fp;
 311   JG         jg;
 312   int        fseq, max_code, space2121;
 313   int        token_idx, idx, cnt, cmd, x, y, cmdp, xp, yp, cmd0, x0, y0;
 314   long          size, offs;
 315   unsigned int  scode;
 316   VF_OUTLINE        outline;
 317   VF_OUTLINE_ELEM   *sizep, chd;
 318   double        mx, my;
 319 #define CONV_COORD_X(p)  \
     /* [<][>][^][v][top][bottom][index][help] */
 320    ((unsigned int)(VF_OL_COORD_OFFSET + ((p)*mx*VF_OL_COORD_RANGE)/JG_MAX_XY))
 321 #define CONV_COORD_Y(p)  \
     /* [<][>][^][v][top][bottom][index][help] */
 322    ((unsigned int)(VF_OL_COORD_OFFSET + ((p)*my*VF_OL_COORD_RANGE)/JG_MAX_XY))
 323 
 324   mx = mag_x;
 325   my = mag_y;
 326   if (mx > 1){
 327     my /= mx;
 328     mx = 1.0;
 329   }
 330   if (my > 1){
 331     mx /= my;
 332     my = 1.0;
 333   }
 334 
 335   if ((jg = JG_GetJG(jg_id)) == NULL){
 336     fprintf(stderr, "VFlib internal error: JG_ReadOutline()\n");
 337     vf_error = VF_ERR_INTERNAL;
 338     return NULL;
 339   }
 340   
 341   /* Assume JISX0208-1990 & JIS encoding */
 342   max_code = 0x7426;
 343   space2121 = 1;
 344 
 345   if ((code_point < 0x2121) || (max_code < code_point)
 346       || (code_point%256 < 0x21) || (0x7e < code_point%256) ){
 347     vf_error = VF_ERR_ILL_CODE_POINT;
 348     return NULL;
 349   }
 350 
 351   if ((space2121 == 1) && (code_point == 0x2121)){
 352     ALLOCN_IF_ERR(outline, VF_OUTLINE_ELEM, 
 353                   VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + 1)
 354       return NULL;
 355     outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0] = 0L;
 356     return outline;
 357   }
 358 
 359   if (code_point < 0x3000){
 360     fseq = 0;
 361   } else if (code_point < 0x5000){
 362     fseq = 1;
 363   } else {
 364     fseq = 2;
 365   }
 366   scode = jg_charcode2c((int)code_point);
 367 
 368   if ((fp = vf_fm_OpenBinaryFileStream(jg->headers[fseq]->font_path)) == NULL){
 369     fprintf(stderr, "VFlib Error. File not found: %s\n", 
 370             jg->headers[fseq]->font_path);
 371     return NULL;
 372   }
 373 
 374   offs  = jg->headers[fseq]->ol_offset[scode];
 375   sizep = &jg->headers[fseq]->ol_size[scode];
 376   if (*sizep == EMPTY_PTR)
 377     jg_correct_size(scode, fp, jg->headers[fseq]);
 378   
 379   if (*sizep == 0)
 380     return NULL;
 381   if (*sizep < 0)
 382     size = -3*(*sizep) + 1;
 383   else
 384     size = *sizep;
 385 
 386   ALLOCN_IF_ERR(outline, VF_OUTLINE_ELEM, 
 387                 VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + size)
 388     return NULL;
 389   
 390   fseek(fp, offs, SEEK_SET);
 391   jg_init_bit_stream(fp);
 392 
 393   cnt = 0;
 394   idx = VF_OL_OUTLINE_HEADER_SIZE_TYPE0;
 395   chd = VF_OL_INSTR_CHAR;
 396   for (;;){
 397 NEXT_CIRCLE:
 398     if ((cmd = jg_read_xy(&x, &y)) == -1)
 399       break;
 400     cmd0 = cmd; x0 = x; y0 = y;
 401     cmdp = cmd; xp = x; yp = y; 
 402     if (debug_on('o'))
 403       printf("VFlib JG:  CMD0=%d, X0=%d, Y0=%d\n", cmd0, x0, y0);
 404     token_idx = idx;
 405     outline[idx++] = (chd | VF_OL_INSTR_CWCURV | VF_OL_INSTR_TOKEN);
 406     cnt++;
 407     chd = 0L;
 408 
 409     for (;;){ 
 410       cmd = jg_read_xy(&x, &y);
 411       switch (cmd){
 412       case -1:
 413       END_OF_CCURV:
 414         if (cmdp != cmd0){
 415           outline[idx++] 
 416             = ((cmd0==0) ? VF_OL_INSTR_LINE : VF_OL_INSTR_BEZ) 
 417               | VF_OL_INSTR_TOKEN;
 418           cnt++;
 419         }
 420         outline[idx++] = VF_OL_MAKE_XY(CONV_COORD_X(xp), CONV_COORD_Y(yp));
 421         cnt++;
 422         goto NEXT_CIRCLE;
 423       case 0:
 424       LINE:
 425         outline[token_idx] |= (VF_OL_INSTR_LINE | VF_OL_INSTR_TOKEN);
 426         outline[idx++] = VF_OL_MAKE_XY(CONV_COORD_X(xp), CONV_COORD_Y(yp));
 427         cnt++;
 428         cmdp = cmd;  xp = x; yp = y;
 429         cmd = jg_read_xy(&x, &y);
 430         while (cmd == 0){
 431           outline[idx++] = VF_OL_MAKE_XY(CONV_COORD_X(xp), CONV_COORD_Y(yp));
 432           cnt++;
 433           cmdp = cmd;  xp = x; yp = y; 
 434           cmd = jg_read_xy(&x, &y);
 435         }
 436         if (cmd == -1)
 437           goto END_OF_CCURV; 
 438         token_idx = idx;
 439         outline[idx++] = 0L;
 440         cnt++;
 441         goto BEZ;
 442       case 1:
 443       BEZ: 
 444         outline[token_idx] |= (VF_OL_INSTR_BEZ | VF_OL_INSTR_TOKEN);
 445         outline[idx++] = VF_OL_MAKE_XY(CONV_COORD_X(xp), CONV_COORD_Y(yp));
 446         cnt++;
 447         cmdp = cmd;  xp = x; yp = y; 
 448         cmd = jg_read_xy(&x, &y);
 449         while (cmd == 1){
 450           outline[idx++] = VF_OL_MAKE_XY(CONV_COORD_X(xp), CONV_COORD_Y(yp));
 451           cnt++;
 452           cmdp = cmd;  xp = x; yp = y; 
 453           cmd = jg_read_xy(&x, &y);
 454         }
 455         if (cmd == -1)
 456           goto END_OF_CCURV; 
 457         token_idx = idx;
 458         outline[idx++] = 0L;
 459         cnt++;
 460         goto LINE;
 461       }
 462     }
 463   }
 464   outline[idx++] = 0L;
 465   cnt++;
 466 
 467   if (*sizep < 0)
 468     *sizep = (long) cnt;
 469 
 470   if (debug_on('o'))
 471     printf("VFlib JG:  SIZE %5ld\n", *sizep);
 472 
 473   return outline;
 474 }
 475 
 476 
 477 Private int
 478 jg_charcode2c(int code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 479 {
 480   int  jgcode;
 481   
 482   if (code_point < 0x3000)
 483     jgcode = (code_point/256 - 0x21)*0x5e + (code_point%256) - 0x21;
 484   else if (code_point < 0x5000)
 485     jgcode = (code_point/256 - 0x30)*0x5e + (code_point%256) - 0x21;
 486   else 
 487     jgcode = (code_point/256 - 0x50)*0x5e + (code_point%256) - 0x21;
 488 
 489   return jgcode;
 490 }
 491 
 492 
 493 
 494 Private int
 495 jg_read_1byte(FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 496 {
 497   return fgetc(fp);
 498 }
 499 
 500 Private unsigned long
 501 jg_read_4bytes(FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 502 {
 503   unsigned long i1, i2, i3, i4;
 504   
 505   i1 = (unsigned long)jg_read_1byte(fp);
 506   i2 = (unsigned long)jg_read_1byte(fp);
 507   i3 = (unsigned long)jg_read_1byte(fp);
 508   i4 = (unsigned long)jg_read_1byte(fp);
 509 
 510   return i1 + i2*0x100 + i3*0x10000 + i4*0x1000000;
 511 }
 512 
 513 
 514 Private FILE           *jg_bitstream_fp = NULL;
 515 Private unsigned int    jg_left_bits  = 0;
 516 Private unsigned long   jg_bit_stream = 0;
 517 
 518 Private void
 519 jg_init_bit_stream(FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 520 {
 521   jg_bitstream_fp = fp;
 522   jg_bit_stream   = 0;
 523   jg_left_bits    = 0;
 524 }
 525 
 526 Private unsigned int 
 527 jg_read_12bits(void)
     /* [<][>][^][v][top][bottom][index][help] */
 528 {
 529   if (jg_left_bits < 12){
 530     jg_bit_stream  = jg_bit_stream * 0x10000L;
 531     jg_bit_stream  += (unsigned int) jg_read_1byte(jg_bitstream_fp);
 532     jg_bit_stream  += (unsigned int) jg_read_1byte(jg_bitstream_fp) * 0x0100L;
 533     jg_left_bits   += 16;
 534   }
 535   jg_left_bits -= 12;
 536 
 537   return (jg_bit_stream >> jg_left_bits) & JG_MAX_VALUE;
 538 }
 539 
 540 Private int
 541 jg_read_xy(int *xp, int *yp)
     /* [<][>][^][v][top][bottom][index][help] */
 542 {
 543   int   x, y, fx, fy;
 544 
 545   x = jg_read_12bits();
 546   y = jg_read_12bits();
 547   if ((x == JG_MAX_VALUE) && (y == JG_MAX_VALUE))
 548     return -1;
 549 
 550   *xp  = x & JG_XY_MASK;
 551   *yp  = y & JG_XY_MASK;
 552   fx   = x & JG_CMD_MASK;
 553   fy   = y & JG_CMD_MASK;
 554 
 555   if (*xp > (JG_MAX_XY+1)/2)
 556     *xp = (JG_MAX_XY+1) - *xp;
 557   else 
 558     *xp += (JG_MAX_XY+1)/2;
 559   if (*yp < (JG_MAX_XY+1)/2)
 560     *yp  = (JG_MAX_XY+1)/2 - *yp;
 561 
 562   *xp -= (JG_MAX_XY+1)/4;
 563   *xp = (*xp < 0) ? 0: *xp * 2;
 564   *yp -= (JG_MAX_XY+1)*5/16;
 565   *yp = (*yp < 0) ? 0: *yp * 2;
 566   if (fx != 0)
 567     return 1;
 568 
 569   return 0;
 570 }
 571 
 572 
 573 
 574 /*EOF*/

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