src/jg.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- JG_Init
- JG_Open
- JG_Close
- jg_release
- jg_make_header
- jg_read_header
- jg_correct_size
- JG_ReadOutline
- CONV_COORD_X
- CONV_COORD_Y
- jg_charcode2c
- jg_read_1byte
- jg_read_4bytes
- jg_init_bit_stream
- jg_read_12bits
- 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*/