src/zeit.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- ZEIT_Init
- ZEIT_Open
- ZEIT_Close
- zeit_release
- zeit_make_header
- zeit_read_header
- zeit_correct_size
- ZEIT_ReadOutline
- zeit_code2c
- zeit_read_1byte
- zeit_read_4bytes
- zeit_init_bit_stream
- zeit_read_10bits
- zeit_seek
- zeit_current_pos
1 /*
2 * zeit.c - 'Syotai Kurabu' 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 "zeit.h"
32
33 static VF_TABLE zeit_table = NULL;
34
35
36
37 Private int
38 ZEIT_Init(void)
/* [<][>][^][v][top][bottom][index][help] */
39 {
40 ZEIT_GetZEIT(-1);
41
42 if ((zeit_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 zeit_release(ZEIT zeit);
52 Private int zeit_make_header(char*,int,char**,long**,long**,int);
53
54
55 Private int
56 ZEIT_Open(char *font_name)
/* [<][>][^][v][top][bottom][index][help] */
57 {
58 ZEIT zeit;
59 int zeit_id;
60
61 if ((zeit_id = (zeit_table->get_id_by_key)(zeit_table, font_name,
62 strlen(font_name)+1)) >= 0){
63 (zeit_table->link_by_id)(zeit_table, zeit_id);
64 return zeit_id;
65 }
66
67 ALLOC_IF_ERR(zeit, struct s_zeit){
68 vf_error = VF_ERR_NO_MEMORY;
69 return -1;
70 }
71 zeit->path_name1 = NULL;
72 zeit->ol_size1 = NULL;
73 zeit->ol_offset1 = NULL;
74 zeit->path_name2 = NULL;
75 zeit->ol_size2 = NULL;
76 zeit->ol_offset2 = NULL;
77
78 if (zeit_make_header(font_name, 1, &zeit->path_name1,
79 &zeit->ol_size1, &zeit->ol_offset1, 1) < 0)
80 goto Error;
81 if (zeit_make_header(font_name, 2, &zeit->path_name2,
82 &zeit->ol_size2, &zeit->ol_offset2, 2) < 0)
83 goto Error;
84
85 if ((zeit_id = (zeit_table->put)(zeit_table, zeit,
86 font_name, strlen(font_name)+1)) < 0){
87 vf_error = VF_ERR_NO_MEMORY;
88 goto Error;
89 }
90
91 ZEIT_SetZEIT(zeit_id, zeit);
92
93 return zeit_id;
94
95 Error:
96 zeit_release(zeit);
97 return -1;
98 }
99
100
101 Private void
102 ZEIT_Close(int zeit_id)
/* [<][>][^][v][top][bottom][index][help] */
103 {
104 ZEIT zeit;
105
106 if ((zeit = ZEIT_GetZEIT(zeit_id)) == NULL){
107 fprintf(stderr, "VFlib internal error: ZEIT_Close()\n");
108 vf_error = VF_ERR_INTERNAL;
109 return;
110 }
111 if ((zeit_table->unlink_by_id)(zeit_table, zeit_id) > 0)
112 return;
113 zeit_release(zeit);
114 }
115
116
117 Private void
118 zeit_release(ZEIT zeit)
/* [<][>][^][v][top][bottom][index][help] */
119 {
120 if (zeit != NULL){
121 vf_free(zeit->path_name1);
122 vf_free(zeit->path_name2);
123 vf_free(zeit->ol_offset1);
124 vf_free(zeit->ol_offset2);
125 vf_free(zeit->ol_size1);
126 vf_free(zeit->ol_size2);
127 vf_free(zeit);
128 }
129 }
130
131
132 Private int zeit_read_header(long**,long**,char*);
133
134 Private int zeit_correct_size(long*,long*,FILE*,int);
135 Private int zeit_code2c(int);
136 Private int zeit_read_1byte(FILE*);
137 Private unsigned long zeit_read_4bytes(FILE*);
138 Private void zeit_init_bit_stream(FILE*);
139 Private int zeit_read_10bits(void);
140 Private void zeit_seek(FILE*,long);
141 Private long zeit_current_pos(FILE*);
142
143
144 Private int
145 zeit_make_header(char *font_name, int ext, char **path_namep,
/* [<][>][^][v][top][bottom][index][help] */
146 long **ol_sizep, long **ol_offsetp, int type)
147 {
148 char *e;
149 char fname[MAXPATHLEN];
150 int i;
151 SEXP s;
152
153 *path_namep = NULL;
154 *ol_offsetp = NULL;
155 *ol_sizep = NULL;
156
157 for (s = default_extensions; vf_sexp_consp(s); s = vf_sexp_cdr(s)){
158 e = vf_sexp_get_cstring(vf_sexp_car(s));
159 sprintf(fname, "%s%s%d", font_name, e, ext);
160 if ((*path_namep
161 = vf_search_file(fname, -1, NULL, FALSE, -1,
162 default_fontdirs, NULL, NULL)) != NULL)
163 break;
164 }
165
166 if (*path_namep == NULL){
167 if (type == 1){
168 vf_error = VF_ERR_NO_FONT_FILE;
169 return -1;
170 }
171 return 0;
172 }
173
174 if (debug_on('f'))
175 printf("VFlib ZEIT: font path: %s\n", *path_namep);
176
177 ALLOCN_IF_ERR(*ol_offsetp, long, ZEIT_NCHARS){
178 vf_error = VF_ERR_NO_MEMORY;
179 goto Error;
180 }
181 ALLOCN_IF_ERR(*ol_sizep, long, ZEIT_NCHARS){
182 vf_error = VF_ERR_NO_MEMORY;
183 goto Error;
184 }
185
186 for (i = 0; i < ZEIT_NCHARS; i++){
187 (*ol_offsetp)[i] = -1;
188 (*ol_sizep)[i] = 0;
189 }
190
191 if (zeit_read_header(ol_sizep, ol_offsetp, *path_namep) < 0){
192 goto Error;
193 }
194
195 return 0;
196
197 Error:
198 vf_free(*path_namep); *path_namep = NULL;
199 vf_free(*ol_offsetp); *ol_offsetp = NULL;
200 vf_free(*ol_sizep); *ol_sizep = NULL;
201 return -1;
202 }
203
204
205 Private int
206 zeit_read_header(long **ol_sizep, long **ol_offsetp, char *font_path)
/* [<][>][^][v][top][bottom][index][help] */
207 {
208 int i, j;
209 FILE *fp;
210
211 if ((fp = vf_fm_OpenBinaryFileStream(font_path)) == NULL){
212 fprintf(stderr, "VFlib Error. File not found: %s\n", font_path);
213 return -1;
214 }
215
216 (void) zeit_read_1byte(fp);
217 (void) zeit_read_1byte(fp);
218
219 for (i = 0; i < ZEIT_NCHARS; i++){
220 (*ol_offsetp)[i] = zeit_read_4bytes(fp);
221 if (debug_on('i'))
222 printf("VFlib ZEIT: Header %04d: %08lx\n", i, (*ol_offsetp)[i]);
223 }
224
225 for (i = 0; i < ZEIT_NCHARS-1; i++){
226 if ((*ol_offsetp)[i] == 0xffffffff){
227 (*ol_sizep)[i] = 0;
228 continue;
229 }
230 for (j = i+1; ; j++){
231 if (j >= ZEIT_NCHARS){
232 (*ol_sizep)[i] = -(THRESHOLD_SIZE+1);
233 break;
234 }
235 if ((*ol_offsetp)[j] != 0xffffffff){
236 (*ol_sizep)[i] = -((*ol_offsetp)[j] - (*ol_offsetp)[i]); /* A MAGIC */
237 break;
238 }
239 }
240 if (-((*ol_sizep)[i]) > THRESHOLD_SIZE) /* Large... check size. */
241 zeit_correct_size(&((*ol_sizep)[i]), &((*ol_offsetp)[i]), fp, i);
242 }
243 if ((*ol_offsetp)[ZEIT_NCHARS-1] == 0xffffffff){
244 (*ol_sizep)[ZEIT_NCHARS-1] = 0;
245 } else {
246 (*ol_sizep)[ZEIT_NCHARS-1] = -(THRESHOLD_SIZE+1); /* A MAGIC */
247 zeit_correct_size(&((*ol_sizep)[i]), &((*ol_offsetp)[i]),
248 fp, ZEIT_NCHARS-1);
249 }
250
251 return 0;
252 }
253
254 Private int
255 zeit_correct_size(long *sizep, long *offsetp, FILE *fp, int i)
/* [<][>][^][v][top][bottom][index][help] */
256 {
257 int x, y;
258
259 if (debug_on('i'))
260 printf("VFlib ZEIT: Correct Size %04x: size %d, offs %ld\n",
261 i, (int)-(*sizep), *offsetp);
262
263 zeit_seek(fp, *offsetp);
264 zeit_init_bit_stream(fp);
265 for (;;){
266 x = zeit_read_10bits();
267 y = zeit_read_10bits();
268 if ((x == 1023) && (y == 1023))
269 break;
270 for (;;){
271 x = zeit_read_10bits();
272 y = zeit_read_10bits();
273 if ((x == 1023) && (y == 1023))
274 break;
275 }
276 }
277 *sizep = -(zeit_current_pos(fp) - *offsetp);
278
279 if (debug_on('i'))
280 printf("VFlib ZEIT: ==> %04x\n", (int)-(*sizep));
281
282 return *sizep;
283 }
284
285 Private VF_OUTLINE
286 ZEIT_ReadOutline(int zeit_id, int code_point,
/* [<][>][^][v][top][bottom][index][help] */
287 double mag_x, double mag_y)
288 {
289 FILE *fp;
290 ZEIT zeit;
291 int idx, x, y, xx, yy, max_code, space2121;
292 char *font_file;
293 VF_OUTLINE outline;
294 VF_OUTLINE_ELEM *sizep;
295 long size, offs;
296 unsigned int scode;
297 double mx, my;
298
299 mx = mag_x;
300 my = mag_y;
301 if (mx > 1){
302 mx = 1.0;
303 my = 1.0 / mx;
304 }
305
306 if ((zeit = ZEIT_GetZEIT(zeit_id)) == NULL){
307 fprintf(stderr, "VFlib internal error: ZEIT_ReadOutline()\n");
308 vf_error = VF_ERR_INTERNAL;
309 return NULL;
310 }
311
312 /* Assume JISX0208-1990 & KUTEN encoding */
313 max_code = 0x7426;
314 space2121 = 1;
315
316 if ((code_point < 0x2121) || (max_code < code_point)
317 || (code_point%256 < 0x21) || (0x7e < code_point%256)){
318 vf_error = VF_ERR_ILL_CODE_POINT;
319 return NULL;
320 }
321
322 if ((space2121 == 1) && (code_point == 0x2121)){
323 size = VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + 1;
324 ALLOCN_IF_ERR(outline, VF_OUTLINE_ELEM, size)
325 return NULL;
326 outline[VF_OL_HEADER_INDEX_DATA_SIZE] = size;
327 return outline;
328 }
329
330 scode = zeit_code2c(code_point);
331 if (code_point < 0x5000){
332 font_file = zeit->path_name1;
333 offs = zeit->ol_offset1[scode];
334 sizep = &zeit->ol_size1[scode];
335 } else {
336 font_file = zeit->path_name2;
337 offs = zeit->ol_offset2[scode];
338 sizep = &zeit->ol_size2[scode];
339 }
340 if (*sizep == 0)
341 return NULL;
342 if (*sizep < 0) /* A MAGIC */
343 size = 2*(-*sizep) + 1;
344 else
345 size = *sizep + 1;
346
347 ALLOCN_IF_ERR(outline, VF_OUTLINE_ELEM,
348 VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + size)
349 return NULL;
350
351 if ((fp = vf_fm_OpenBinaryFileStream(font_file)) == NULL){
352 fprintf(stderr, "VFlib Error. File not found: %s\n", font_file);
353 return NULL;
354 }
355
356 zeit_seek(fp, offs);
357 zeit_init_bit_stream(fp);
358 for (idx = 0; ; ){
359 x = zeit_read_10bits();
360 y = zeit_read_10bits();
361 if ((x == 1023) && (y == 1023))
362 break;
363 xx = VF_OL_COORD_OFFSET + mx * (x*VF_OL_COORD_RANGE)/ZEIT_MAX_VALUE;
364 yy = VF_OL_COORD_OFFSET + my * (y*VF_OL_COORD_RANGE)/ZEIT_MAX_VALUE;
365 outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + idx++]
366 = VF_OL_INSTR_TOKEN | VF_OL_INSTR_CWCURV | VF_OL_INSTR_LINE;
367 outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + idx++]
368 = VF_OL_MAKE_XY(xx, yy);
369 for (;;){
370 x = zeit_read_10bits();
371 y = zeit_read_10bits();
372 if ((x == 1023) && (y == 1023))
373 break;
374 xx = VF_OL_COORD_OFFSET + mx * (x*VF_OL_COORD_RANGE)/ZEIT_MAX_VALUE;
375 yy = VF_OL_COORD_OFFSET + my * (y*VF_OL_COORD_RANGE)/ZEIT_MAX_VALUE;
376 outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + idx++] = VF_OL_MAKE_XY(xx, yy);
377 }
378 }
379 outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0 + idx++] = 0;
380
381 if (outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0] != 0)
382 outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0] |= VF_OL_INSTR_CHAR;
383
384 if (*sizep < 0)
385 *sizep = (long)idx;
386
387 if (debug_on('i'))
388 printf("VFlib ZEIT: SIZE %5ld\n", *sizep);
389
390 outline[VF_OL_HEADER_INDEX_DATA_SIZE]
391 = *sizep + VF_OL_OUTLINE_HEADER_SIZE_TYPE0;
392
393 return outline;
394 }
395
396
397 Private int
398 zeit_code2c(int code)
/* [<][>][^][v][top][bottom][index][help] */
399 {
400 if (code < 0x5000)
401 return ((code/0x100) - 0x21)*0x5e + (code%0x100) - 0x21;
402
403 return ((code/0x100) - 0x50)*0x5e + (code%0x100) - 0x21;
404 }
405
406
407
408 Private int
409 zeit_read_1byte(FILE *fp)
/* [<][>][^][v][top][bottom][index][help] */
410 {
411 return getc(fp);
412 }
413
414 Private unsigned long
415 zeit_read_4bytes(FILE *fp)
/* [<][>][^][v][top][bottom][index][help] */
416 {
417 unsigned long i1, i2, i3, i4;
418
419 i1 = (unsigned long)zeit_read_1byte(fp);
420 i2 = (unsigned long)zeit_read_1byte(fp);
421 i3 = (unsigned long)zeit_read_1byte(fp);
422 i4 = (unsigned long)zeit_read_1byte(fp);
423
424 return i1 + i2*0x100 + i3*0x10000 + i4*0x1000000;
425 }
426
427
428 Private FILE *zeit_bitstream_fp = NULL;
429 Private unsigned int zeit_left_bits = 0;
430 Private unsigned long zeit_bit_stream = 0;
431 Private unsigned long zeit_power2tbl[] = {
432 0x000001,0x000002,0x000004,0x000008,0x000010,0x000020,0x000040,0x000080,
433 0x000100,0x000200,0x000400,0x000800,0x001000,0x002000,0x004000,0x008000,
434 0x010000,0x020000,0x040000,0x080000,0x100000,0x200000,0x400000,0x800000
435 };
436
437 Private void
438 zeit_init_bit_stream(FILE *fp)
/* [<][>][^][v][top][bottom][index][help] */
439 {
440 zeit_bitstream_fp = fp;
441 zeit_bit_stream = 0;
442 zeit_left_bits = 0;
443 }
444
445 Private int
446 zeit_read_10bits(void)
/* [<][>][^][v][top][bottom][index][help] */
447 {
448 if (zeit_left_bits < 10){
449 zeit_bit_stream *= 0x10000;
450 zeit_bit_stream += (unsigned int)zeit_read_1byte(zeit_bitstream_fp);
451 zeit_bit_stream += (unsigned int)zeit_read_1byte(zeit_bitstream_fp)*0x100;
452 zeit_left_bits += 16;
453 }
454 zeit_left_bits -= 10;
455
456 return (zeit_bit_stream/zeit_power2tbl[zeit_left_bits]) % ZEIT_MAX_VALUE;
457 }
458
459 Private void
460 zeit_seek(FILE *fp, long pos)
/* [<][>][^][v][top][bottom][index][help] */
461 {
462 fseek(fp, pos + ZEIT_HEADER_SIZE, SEEK_SET);
463 }
464
465 Private long
466 zeit_current_pos(FILE *fp)
/* [<][>][^][v][top][bottom][index][help] */
467 {
468 return ftell(fp) - ZEIT_HEADER_SIZE;
469 }
470
471
472 /*EOF*/