src/VFlib.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- STRPARAM
- VF_Init
- VF_GetVersion
- VF_ClearError
- VF_InstallFontDriver
- VF_FontDriverList
- VF_OpenFont1
- vf_openfont1
- VF_OpenFont2
- vf_openfont2
- open_font
- do_open_font
- VF_CloseFont
- VF_GetMetric1
- VF_GetMetric2
- VF_GetFontBoundingBox1
- VF_GetFontBoundingBox2
- VF_GetBitmap1
- VF_GetBitmap2
- VF_GetOutline
- VF_GetFontProp
- VF_QueryFontType
- id2font
- VF_DumpFontTable
1 /*
2 * VFlib.c - a main file for VFlib
3 *
4 * Programmed by Hirotsugu Kakugawa
5 *
6 * 5 Mar 1997 VFlib 3.1.4
7 * 20 Mar 1997 VFlib 3.1.5
8 * 22 Mar 1997 VFlib 3.2
9 * 1 Oct 1997 VFlib 3.2.6 Changed encoding & charset conversion module.
10 * 4 Aug 1997 VFlib 3.3 Changed API.
11 * 9 Jan 1998 VFlib 3.4 Changed vflibcap syntax.
12 * 17 Sep 1999 VFlib 3.6
13 * 18 Oct 2001 Fixed memory leak.
14 */
15
16 /*
17 * Copyright (C) 1996-2001 Hirotsugu Kakugawa.
18 * All rights reserved.
19 *
20 * This file is part of the VFlib Library. This library is free
21 * software; you can redistribute it and/or modify it under the terms of
22 * the GNU Library General Public License as published by the Free
23 * Software Foundation; either version 2 of the License, or (at your
24 * option) any later version. This library is distributed in the hope
25 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
26 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
27 * PURPOSE. See the GNU Library General Public License for more details.
28 * You should have received a copy of the GNU Library General Public
29 * License along with this library; if not, write to the Free Software
30 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 */
32
33 #include "config.h"
34 #include <stdio.h>
35 #include <stdlib.h>
36 #ifdef HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
39 #include <ctype.h>
40 #include "VFlib-3_6.h"
41 #include "VFsys.h"
42 #include "consts.h"
43 #include "vflpaths.h"
44 #include "params.h"
45 #include "vflibcap.h"
46 #include "str.h"
47 #include "sexp.h"
48 #include "metric.h"
49 #include "bitmap.h"
50 #include "cache.h"
51 #include "ccv.h"
52
53
54 Public int vf_error;
55
56
57 Private int vf_initialized = 0;
58 Private int open_nesting = 0;
59
60 Private VF_TABLE font_class_table = NULL;
61 Private VF_TABLE font_id_table = NULL;
62
63 struct s_font_class {
64 char* class_name;
65 int (*driver_entry)(VF_FONT,char*,char*,int,void*);
66 };
67 typedef struct s_font_class *FONT_CLASS;
68
69 Glocal int vf_dbg_font_open = 0;
70 Glocal int vf_dbg_font_search = 0;
71 Glocal int vf_dbg_kpathsea = 0;
72 Glocal int vf_dbg_vfcap = 0;
73 Glocal int vf_dbg_parameters = 0;
74 Glocal int vf_dbg_ccv = 0;
75 Glocal int vf_dbg_ccv_map = 0;
76 Glocal int vf_dbg_log = 0;
77 Glocal FILE*vf_dbg_log_fp = NULL;
78 #define DEBUG_LOG_FILE "__dbg.tmp"
79
80 struct s_open_arg_pack1 {
81 double dpi_x, dpi_y;
82 double point_size;
83 double mag_x, mag_y;
84 };
85 struct s_open_arg_pack2 {
86 int pixel_size;
87 double mag_x, mag_y;
88 };
89
90 Private int open_font(char *font_name, char *requested_font_class,
91 struct s_open_arg_pack1 *arg_mode1,
92 struct s_open_arg_pack2 *arg_mode2);
93
94 Private int do_open_font(char *font_class_spec,
95 char* font_name, int implicit, int mode,
96 char *cache_key,
97 VF_FONT font);
98
99 Private VF_FONT id2font(int);
100
101 extern int vf_drv_init(void);
102
103 #define STRPARAM(s) if ((s) != NULL){ fprintf(vf_dbg_log_fp, "\"%s\"", s); \
/* [<][>][^][v][top][bottom][index][help] */
104 } else { fprintf(vf_dbg_log_fp, "NULL"); }
105
106
107
108
109 /**
110 ** VF_Init
111 **/
112 Public int
113 VF_Init(char *vflibcap_path, char *parameters)
/* [<][>][^][v][top][bottom][index][help] */
114 {
115 if (vf_initialized != 0)
116 return 0;
117
118 vf_initialized = 1;
119 vf_error = 0;
120 open_nesting = 0;
121
122 /* Check Environment Variables for Debugging */
123 if (getenv(VF_ENV_DEBUG_FONT_OPEN) != NULL)
124 vf_dbg_font_open = 1;
125 if (getenv(VF_ENV_DEBUG_FONT_SEARCH) != NULL)
126 vf_dbg_font_search = 1;
127 if (getenv(VF_ENV_DEBUG_KPATHSEA) != NULL)
128 vf_dbg_kpathsea = 1;
129 if (getenv(VF_ENV_DEBUG_VFLIBCAP) != NULL)
130 vf_dbg_vfcap = 1;
131 if (getenv(VF_ENV_DEBUG_PARAMETERS) != NULL)
132 vf_dbg_parameters = 1;
133 if (getenv(VF_ENV_DEBUG_CCV) != NULL)
134 vf_dbg_ccv = 1;
135 if (getenv(VF_ENV_DEBUG_CCV_MAPPING) != NULL)
136 vf_dbg_ccv_map = 1;
137
138 if (getenv(VF_ENV_DEBUG_LOG) != NULL){
139 if ((vf_dbg_log = atoi(getenv(VF_ENV_DEBUG_LOG))) <= 0)
140 vf_dbg_log = 1;
141 if (vf_dbg_log > 1)
142 vf_dbg_log_fp = fopen(DEBUG_LOG_FILE, "w");
143 else
144 vf_dbg_log_fp = stdout;
145 }
146
147 if (vf_dbg_log > 0){
148 fprintf(vf_dbg_log_fp, "VF_Init(");
149 STRPARAM(vflibcap_path);
150 fprintf(vf_dbg_log_fp, ", ");
151 STRPARAM(parameters);
152 fprintf(vf_dbg_log_fp, ");\n");
153 }
154
155
156 /* Initialize File Stream Manager */
157 if (vf_fm_init() < 0)
158 return -1;
159
160 /* Initialize 'vflibcap' Database System */
161 if (vf_cap_init(vflibcap_path) < 0)
162 return -1;
163
164 /* set parameters (variable values for vflibcap) */
165 if (vf_params_init(parameters) < 0)
166 return -1;
167
168 /* Initialize Code Conversion Module */
169 vf_ccv_init();
170
171 /* Create a Table for Opened Font Table */
172 if (vf_defaults_init() < 0)
173 return -1;
174
175 /* Create a Table for Opened Font Table */
176 if ((font_id_table = vf_table_create()) == NULL){
177 vf_error = VF_ERR_NO_MEMORY;
178 return -1;
179 }
180
181 /* Create a Table for Font Drivers */
182 if ((font_class_table = vf_table_create()) == NULL){
183 vf_error = VF_ERR_NO_MEMORY;
184 return -1;
185 }
186
187 /* Call Initializer of Each Font Module (Install of Font Drivers) */
188 vf_drv_init();
189
190 return 0;
191 }
192
193
194 /**
195 ** VF_Version
196 **/
197 Public char*
198 VF_GetVersion(void)
/* [<][>][^][v][top][bottom][index][help] */
199 {
200 return VFLIB_VERSION;
201 }
202
203
204 /**
205 ** VF_ClearError
206 **/
207 Public void
208 VF_ClearError(void)
/* [<][>][^][v][top][bottom][index][help] */
209 {
210 vf_error = 0;
211 }
212
213
214 /**
215 ** VF_InstallFontDriver
216 **/
217 Public int
218 VF_InstallFontDriver(char *class_name,
/* [<][>][^][v][top][bottom][index][help] */
219 int(*driver_entry)(VF_FONT,char*,char*,int,void*))
220 {
221 int id;
222 FONT_CLASS fclass;
223
224 vf_error = 0;
225
226 #if 0
227 printf("** New font class: %s\n", class_name);
228 #endif
229
230 /* Check if a driver of the same name is installed or not. */
231 if ((font_class_table->get_obj_by_key)(font_class_table, class_name,
232 strlen(class_name)+1) != NULL){
233 vf_error = VF_ERR_USED_CLASS_NAME;
234 return -1;
235 }
236
237 /* Create font class object. */
238 ALLOC_IF_ERR(fclass, struct s_font_class){
239 vf_error = VF_ERR_NO_MEMORY;
240 return -1;
241 }
242 if ((fclass->class_name = vf_strdup(class_name)) == NULL){
243 vf_error = VF_ERR_NO_MEMORY;
244 vf_free(fclass);
245 return -1;
246 }
247 fclass->driver_entry = driver_entry;
248
249 /* Install font class object to font driver table. */
250 if ((id = (font_class_table->put)(font_class_table, fclass,
251 class_name, strlen(class_name)+1)) < 0){
252 vf_error = VF_ERR_NO_MEMORY;
253 vf_free(fclass->class_name);
254 vf_free(fclass);
255 return -1;
256 }
257
258 return id;
259 }
260
261
262 /**
263 ** VF_FontDriverList
264 **/
265 Public char**
266 VF_FontDriverList(void)
/* [<][>][^][v][top][bottom][index][help] */
267 {
268 int n, i, j;
269 char **drv_list;
270 FONT_CLASS fclass;
271
272 vf_error = 0;
273
274 /* Obtain the number of installed font drivers. */
275 n = (font_class_table->get_nelements)(font_class_table);
276
277 ALLOCN_IF_ERR(drv_list, char*, n+1){
278 vf_error = VF_ERR_NO_MEMORY;
279 return NULL;
280 }
281
282 j = 0;
283 for (i = 0; j < n; i++){
284 fclass
285 = (FONT_CLASS)(font_class_table->get_obj_by_id)(font_class_table, i);
286 if (fclass == NULL)
287 continue;
288 if ((drv_list[j] = vf_strdup(fclass->class_name)) == NULL){
289 vf_error = VF_ERR_NO_MEMORY;
290 for (j--; j >= 0; j--)
291 vf_free(drv_list[j]);
292 vf_free(drv_list);
293 return NULL;
294 }
295 j++;
296 }
297 drv_list[j] = NULL;
298
299 return drv_list;
300 }
301
302
303 /**
304 ** VF_OpenFont1
305 **/
306 Public int
307 VF_OpenFont1(char *font_name,
/* [<][>][^][v][top][bottom][index][help] */
308 double dpi_x, double dpi_y, double point_size,
309 double mag_x, double mag_y)
310 {
311 if (vf_dbg_font_open == 1){
312 printf(">>Font Open: VF_OpenFont1(%s, %.2f, %.2f, %.2f, %.3f, %.3f);\n",
313 font_name, dpi_x, dpi_y, point_size, mag_x, mag_y);
314 }
315
316 if (vf_dbg_log > 0){
317 if (vf_dbg_log > 1)
318 fprintf(vf_dbg_log_fp, "VF_OpenFont1(\"%s\", %f, %f, %f, %f, %f);\n",
319 font_name, dpi_x, dpi_y, point_size, mag_x, mag_y);
320 else
321 fprintf(vf_dbg_log_fp, "VF_OpenFont1(\"%s\", %f, %f, %f, %f, %f);\n",
322 font_name, dpi_x, dpi_y, point_size, mag_x, mag_y);
323 }
324
325 return vf_openfont1(font_name, NULL,
326 dpi_x, dpi_y, point_size, mag_x, mag_y);
327 }
328
329 Glocal int
330 vf_openfont1(char *font_name,
/* [<][>][^][v][top][bottom][index][help] */
331 char *requested_font_class,
332 double dpi_x, double dpi_y, double point_size,
333 double mag_x, double mag_y)
334 {
335 struct s_open_arg_pack1 arg1;
336
337 vf_error = 0;
338
339 /* Pack argments */
340 arg1.dpi_x = dpi_x;
341 arg1.dpi_y = dpi_y;
342 arg1.point_size = point_size;
343 arg1.mag_x = mag_x;
344 arg1.mag_y = mag_y;
345
346 return open_font(font_name, requested_font_class, &arg1, NULL);
347 }
348
349
350 /**
351 ** VF_OpenFont2
352 **/
353 Public int
354 VF_OpenFont2(char *font_name,
/* [<][>][^][v][top][bottom][index][help] */
355 int pixel_size,
356 double mag_x, double mag_y)
357 {
358 if (vf_dbg_font_open == 1){
359 printf(">>Font Open: VF_OpenFont2(\"%s\", %d, %.3f, %.3f);\n",
360 font_name, pixel_size, mag_x, mag_y);
361 }
362
363 if (vf_dbg_log > 0){
364 fprintf(vf_dbg_log_fp, "VF_OpenFont2(\"%s\", %d, %f, %f);\n",
365 font_name, pixel_size, mag_x, mag_y);
366 }
367
368 return vf_openfont2(font_name, NULL,
369 pixel_size, mag_x, mag_y);
370 }
371
372 Glocal int
373 vf_openfont2(char *font_name,
/* [<][>][^][v][top][bottom][index][help] */
374 char *requested_font_class,
375 int pixel_size,
376 double mag_x, double mag_y)
377 {
378 struct s_open_arg_pack2 arg2;
379
380 vf_error = 0;
381
382 /* Pack argments */
383 arg2.pixel_size = pixel_size;
384 arg2.mag_x = mag_x;
385 arg2.mag_y = mag_y;
386
387 return open_font(font_name, requested_font_class, NULL, &arg2);
388 }
389
390
391
392 Private int
393 open_font(char *font_name,
/* [<][>][^][v][top][bottom][index][help] */
394 char *requested_font_class,
395 struct s_open_arg_pack1 *arg_mode1,
396 struct s_open_arg_pack2 *arg_mode2)
397 {
398 VF_FONT font = NULL;
399 int font_id, mode;
400 char *class, *ext, key[1024];
401 SEXP_ALIST exh;
402 SEXP_LIST ife, pair;
403
404 font = NULL;
405
406 /* Check nesting of font opens. */
407 open_nesting++;
408 if (open_nesting > VF_MAX_OPEN_NESTING){
409 fprintf(stderr, "VFlib: too many nesting levels for font open.\n");
410 vf_error = VF_ERR_OPEN_NESTING;
411 goto Error;
412 }
413
414 /* Check if the same font is opened. */
415 if (arg_mode1 != NULL){ /* mode 1: high-resolution oriented mode */
416 mode = 1;
417 sprintf(key, "<%s,%d,%s,%d,%d,%d,%d,%d>",
418 (requested_font_class != NULL) ? requested_font_class : "_",
419 mode, font_name,
420 toint(arg_mode1->dpi_x*100), toint(arg_mode1->dpi_y*100),
421 toint(arg_mode1->point_size*100),
422 toint(arg_mode1->mag_x*100), toint(arg_mode1->mag_y*100));
423 } else if (arg_mode2 != NULL){ /* mode 2: low-resolution oriented mode */
424 mode = 2;
425 sprintf(key, "<%s,%d,%s,%d,%d,%d>",
426 (requested_font_class != NULL) ? requested_font_class : "_",
427 mode, font_name,
428 arg_mode2->pixel_size,
429 toint(arg_mode2->mag_x*100), toint(arg_mode2->mag_y*100));
430 } else {
431 fprintf(stderr, "VFlib internal error: Cannot happen in %s\n",
432 "open_font()");
433 abort();
434 }
435 font_id = (font_id_table->get_id_by_key)(font_id_table,
436 key, strlen(key)+1);
437 if (font_id >= 0){
438 /* Share the same font object. */
439 (font_id_table->link_by_id)(font_id_table, font_id);
440 goto Found;
441 }
442
443 /* Make a skeleton font object. */
444 ALLOC_IF_ERR(font, struct vf_s_font){
445 vf_error = VF_ERR_NO_MEMORY;
446 goto Error;
447 }
448 if (mode == 1){
449 font->font_name = NULL;
450 font->mode = 1;
451 font->point_size = arg_mode1->point_size;
452 font->pixel_size = -1;
453 font->mag_x = arg_mode1->mag_x;
454 font->mag_y = arg_mode1->mag_y;
455 font->dpi_x = arg_mode1->dpi_x;
456 font->dpi_y = arg_mode1->dpi_y;
457 } else if (mode == 2){
458 font->mode = 2;
459 font->point_size = -1;
460 font->pixel_size = arg_mode2->pixel_size;
461 font->mag_x = arg_mode2->mag_x;
462 font->mag_y = arg_mode2->mag_y;
463 font->dpi_x = -1;
464 font->dpi_y = -1;
465 } else {
466 fprintf(stderr, "VFlib internal error: Cannot happen in %s\n",
467 "open_font()");
468 abort();
469 }
470
471 font->font_type = 0;
472 font->get_metric1 = NULL;
473 font->get_metric2 = NULL;
474 font->get_fontbbx1 = NULL;
475 font->get_fontbbx2 = NULL;
476 font->get_bitmap1 = NULL;
477 font->get_bitmap2 = NULL;
478 font->get_outline = NULL;
479 font->get_font_prop = NULL;
480 font->query_font_type = NULL;
481 font->close = NULL;
482
483 /* If 'requested_font_class' is given, we open a font by calling the
484 corresponding font driver directly. */
485 if (requested_font_class != NULL){
486 /* try to open as an explicit font */
487 if ((font_id = do_open_font(requested_font_class,
488 font_name, 0, mode, key, font)) >= 0)
489 goto Found;
490 if (vf_error != VF_ERR_NO_FONT_ENTRY)
491 goto Error;
492 /* try to open as an implicit font */
493 vf_error = 0;
494 if ((font_id = do_open_font(requested_font_class,
495 font_name, 1, mode, key, font)) >= 0)
496 goto Found;
497 goto Error;
498 }
499
500 /* Try to open as an explicit font. */
501 if (vf_dbg_font_open == 1)
502 printf(">>Font Open: Try to open an explicit font %s.\n", font_name);
503 font_id = do_open_font(NULL, font_name, 0, mode, key, font);
504 if (font_id >= 0) /* Opened as an explicit font. */
505 goto Found;
506
507 /* If it is not an explicit font, clear error code and try to
508 open as an implicit font. */
509 if (vf_error != VF_ERR_NO_FONT_ENTRY)
510 goto Error;
511
512 /* Search an implicit font. */
513 if (vf_dbg_font_open == 1)
514 printf(">>Font Open: Try to open an implicit font %s.\n", font_name);
515
516 /* First, try to make use of extension hint. */
517 for (exh = vf_extension_hints; vf_sexp_consp(exh); exh = vf_sexp_cdr(exh)){
518 pair = vf_sexp_car(exh);
519 if (!vf_sexp_consp(pair)
520 || ((ext = vf_sexp_get_cstring(vf_sexp_car(pair))) == NULL)
521 || ((class = vf_sexp_get_cstring(vf_sexp_cadr(pair))) == NULL))
522 continue;
523 if (strlen(font_name) > strlen(ext)){
524 if (strcmp(ext, &font_name[strlen(font_name)-strlen(ext)]) == 0){
525 if (vf_dbg_font_open == 1)
526 printf(">>Font Open: Try font class '%s' by hint '%s'\n",
527 class, ext);
528 vf_error = 0;
529 font_id = do_open_font(class, font_name, 1, mode, key, font);
530 if (font_id >= 0) /* Font is found. */
531 goto Found;
532 }
533 }
534 }
535 if (vf_dbg_font_open == 1)
536 printf(">>Extension hint does not work. Try other classes.\n");
537
538 /* Next, try other implict classes not in extension hints. */
539 ife = NULL;
540 for (ife = vf_implicit_font_classes;
541 vf_sexp_consp(ife);
542 ife = vf_sexp_cdr(ife)){
543 for (exh = vf_extension_hints;
544 vf_sexp_consp(exh);
545 exh = vf_sexp_cdr(exh)){
546 ext = vf_sexp_get_cstring(vf_sexp_caar(exh));
547 if (strcmp(ext, vf_sexp_get_cstring(vf_sexp_car(ife))) == 0)
548 break; /* Skip this font class since it is checked already. */
549 }
550 if (vf_sexp_consp(exh))
551 continue;
552
553 if (vf_dbg_font_open == 1)
554 printf(">> ==> Trying %s\n",
555 vf_sexp_get_cstring(vf_sexp_car(ife)));
556 vf_error = 0;
557 font_id = do_open_font(vf_sexp_get_cstring(vf_sexp_car(ife)),
558 font_name, 1, mode, key, font);
559 if (font_id >= 0) /* Font is found. */
560 goto Found;
561 }
562
563 /* The font is not opened as an implicit font. Open error. */
564 vf_error = VF_ERR_NO_FONT_IMP;
565 Error:
566 if (font != NULL)
567 vf_free(font);
568 if (vf_dbg_font_open == 1)
569 printf(">>Font Open Failure: %s\n", font_name);
570 open_nesting--;
571 return -1;
572
573
574 /* The font is opened. */
575 Found:
576 vf_error = 0;
577 if (vf_dbg_font_open == 1)
578 printf(">>Font Open Success: %s fid=%d\n", font_name, font_id);
579 if ((font != NULL) && (font->font_name == NULL)){
580 font->font_name = vf_strdup(font_name);
581 }
582 open_nesting--;
583 return font_id;
584 }
585
586 Private int
587 do_open_font(char *font_class_spec,
/* [<][>][^][v][top][bottom][index][help] */
588 char *font_name, int implicit, int mode,
589 char *cache_key,
590 VF_FONT font)
591 {
592 int font_id, font_class_id;
593 char *class_name;
594 SEXP entry, s;
595 FONT_CLASS fclass;
596
597 /* Obtain font class name. */
598 if (implicit == 1){ /* open for implicit font. */
599 entry = NULL;
600 if ((class_name = font_class_spec) == NULL){
601 vf_error = VF_ERR_CLASS_UNKNOWN;
602 goto Error;
603 }
604 } else { /* open for explicit font. */
605 if ((entry = vf_cap_GetFontEntry(font_name)) == 0){
606 vf_error = VF_ERR_NO_FONT_ENTRY;
607 goto Error;
608 }
609 class_name = NULL;
610 for (s = vf_sexp_cddr(entry); vf_sexp_consp(s); s = vf_sexp_cdr(s)){
611 if (strcmp(vf_sexp_get_cstring(vf_sexp_caar(s)),
612 VF_CAPE_FONT_CLASS) == 0){
613 if (vf_sexp_stringp(vf_sexp_car(vf_sexp_cdar(s))))
614 class_name = vf_sexp_get_cstring(vf_sexp_car(vf_sexp_cdar(s)));
615 break;
616 }
617 }
618 if (class_name == NULL){
619 vf_error = VF_ERR_CLASS_UNKNOWN;
620 goto Error;
621 }
622 if ((font_class_spec != NULL)
623 && (strcmp(font_class_spec, class_name) != 0)){
624 /* class name mismatch. */
625 if (vf_dbg_font_open == 1)
626 printf(">>%s: fontname: %s requested class is %s but %s\n",
627 "Font Open: Font class name mismatch",
628 font_name, font_class_spec, class_name);
629 vf_error = VF_ERR_NO_FONT_ENTRY;
630 goto Error;
631 }
632 }
633
634 /* Get font class object for the font class. */
635 if ((fclass
636 = (font_class_table->get_obj_by_key)(font_class_table, class_name,
637 strlen(class_name)+1)) == NULL){
638 if (vf_dbg_font_open == 1)
639 printf(">>Font Open: Unknown font class '%s'\n", class_name);
640 vf_error = VF_ERR_NO_FONT_CLASS;
641 goto Error;
642 }
643 if (vf_dbg_font_open == 1)
644 printf(">>Font Open: entry=%s class=%s\n", font_name, class_name);
645
646 /* Get font class object id. */
647 if ((font_class_id
648 = (font_class_table->get_id_by_key)(font_class_table, class_name,
649 strlen(class_name)+1)) < 0){
650 vf_error = VF_ERR_NO_FONT_CLASS;
651 goto Error;
652 }
653 font->font_class = font_class_id;
654
655 /* Call font open procedure in a font driver.
656 For an implicit font, the driver searches a font. */
657 if ((fclass->driver_entry)(font, class_name,
658 font_name, implicit, entry) < 0){
659 goto Error;
660 }
661
662 /* If a font is opened, install the font object. */
663 if ((font_id = (font_id_table->put)(font_id_table, font,
664 cache_key, strlen(cache_key)+1)) < 0){
665 vf_error = VF_ERR_NO_MEMORY;
666 goto Error;
667 }
668
669 /* Font is Opened. */
670 if (entry != NULL)
671 vf_sexp_free(&entry);
672 return font_id;
673
674
675 Error:
676 if (entry != NULL)
677 vf_sexp_free(&entry);
678 return -1;
679 }
680
681
682 /**
683 ** VF_CloseFont
684 **/
685 Public int
686 VF_CloseFont(int font_id)
/* [<][>][^][v][top][bottom][index][help] */
687 {
688 VF_FONT font;
689 int v;
690
691 vf_error = 0;
692
693 if (vf_dbg_log > 0){
694 fprintf(vf_dbg_log_fp, "VF_CloseFont(%d);\n", font_id);
695 }
696
697 /* Obtain a font object for given font id. */
698 if ((font = id2font(font_id)) == NULL)
699 return -1;
700
701 /* Discard cache */
702 (void)id2font(-1);
703
704 /* Unlink the font object. If link count is not zero, close is deferred. */
705 if ((font_id_table->unlink_by_id)(font_id_table, font_id) >= 1)
706 return 0;
707
708 /* No one use the font object. Do close it. */
709 v = (font->close)(font);
710
711 vf_free(font->font_name);
712 vf_free(font);
713
714 return v;
715 }
716
717
718 /**
719 ** VF_GetMetric1
720 **/
721 Public VF_METRIC1
722 VF_GetMetric1(int font_id, long code_point, VF_METRIC1 metric1,
/* [<][>][^][v][top][bottom][index][help] */
723 double mag_x, double mag_y)
724 {
725 VF_FONT font;
726 VF_METRIC1 met1;
727 int val;
728
729 vf_error = 0;
730
731
732 /* Obtain a font object for given font id. */
733 if ((font = id2font(font_id)) == NULL)
734 return NULL;
735
736 /* Check if this font is opened as mode 1. */
737 if (font->mode != 1){
738 vf_error = VF_ERR_ILL_MODE;
739 return NULL;
740 }
741
742 /* Check if this operation is supported by a font driver. */
743 if (font->get_metric1 == NULL){
744 vf_error = VF_ERR_NOT_SUPPORTED_OP;
745 return NULL;
746 }
747
748 /* Allocate metric object if not given. */
749 if ((met1 = metric1) == NULL){
750 if ((met1 = vf_alloc_metric1()) == NULL){
751 vf_error = VF_ERR_NO_MEMORY;
752 return NULL;
753 }
754 }
755
756 /* Call a font driver's procedure. */
757 val = (font->get_metric1)(font, code_point, met1, mag_x, mag_y);
758 if (val < 0){
759 if (metric1 == NULL)
760 vf_free(met1);
761 return NULL;
762 }
763
764 return met1;
765 }
766
767 /**
768 ** VF_GetMetric2
769 **/
770 Public VF_METRIC2
771 VF_GetMetric2(int font_id, long code_point, VF_METRIC2 metric2,
/* [<][>][^][v][top][bottom][index][help] */
772 double mag_x, double mag_y)
773 {
774 VF_FONT font;
775 VF_METRIC2 met2;
776 int val;
777
778 vf_error = 0;
779
780 /* Obtain a font object for given font id. */
781 if ((font = id2font(font_id)) == NULL)
782 return NULL;
783
784 /* Check if this font is opened as mode 2. */
785 if (font->mode != 2){
786 vf_error = VF_ERR_ILL_MODE;
787 return NULL;
788 }
789
790 /* Check if this operation is supported by a font driver. */
791 if (font->get_metric1 == NULL){
792 vf_error = VF_ERR_NOT_SUPPORTED_OP;
793 return NULL;
794 }
795
796 /* Allocate metric object if not given. */
797 if ((met2 = metric2) == NULL){
798 if ((met2 = vf_alloc_metric2()) == NULL){
799 vf_error = VF_ERR_NO_MEMORY;
800 return NULL;
801 }
802 }
803
804 /* Call a font driver's procedure. */
805 val = (font->get_metric2)(font, code_point, met2, mag_x, mag_y);
806 if (val < 0){
807 if (metric2 == NULL)
808 vf_free(met2);
809 return NULL;
810 }
811
812 return met2;
813 }
814
815 /**
816 ** VF_GetFontBoundingBox1
817 **/
818 Public int
819 VF_GetFontBoundingBox1(int font_id, double mag_x, double mag_y,
/* [<][>][^][v][top][bottom][index][help] */
820 double *width_p, double *height_p,
821 double *xoff_p, double *yoff_p)
822 {
823 VF_FONT font;
824 double d1, d2, d3, d4;
825
826 vf_error = 0;
827
828 /* Obtain a font object for given font id. */
829 if ((font = id2font(font_id)) == NULL)
830 return -1;
831
832 /* Check if this font is opened as mode 1. */
833 if (font->mode != 1){
834 vf_error = VF_ERR_ILL_MODE;
835 return -1;
836 }
837
838 /* Check if this operation is supported by a font driver. */
839 if (font->get_fontbbx1 == NULL){
840 vf_error = VF_ERR_NOT_SUPPORTED_OP;
841 return -1;
842 }
843
844 if (width_p == NULL)
845 width_p = &d1;
846 if (height_p == NULL)
847 height_p = &d2;
848 if (xoff_p == NULL)
849 xoff_p = &d3;
850 if (yoff_p == NULL)
851 yoff_p = &d4;
852 *width_p = *height_p = *xoff_p = *yoff_p = 0;
853
854 /* Call a font driver's procedure. */
855 return (font->get_fontbbx1)(font, mag_x, mag_y,
856 width_p, height_p, xoff_p, yoff_p);
857 }
858
859 /**
860 ** VF_GetFontBoundingBox2
861 **/
862 Public int
863 VF_GetFontBoundingBox2(int font_id, double mag_x, double mag_y,
/* [<][>][^][v][top][bottom][index][help] */
864 int *width_p, int *height_p,
865 int *xoff_p, int *yoff_p)
866 {
867 VF_FONT font;
868 int d1, d2, d3, d4;
869
870 vf_error = 0;
871
872 /* Obtain a font object for given font id. */
873 if ((font = id2font(font_id)) == NULL)
874 return -1;
875
876 /* Check if this font is opened as mode 2. */
877 if (font->mode != 2){
878 vf_error = VF_ERR_ILL_MODE;
879 return -1;
880 }
881
882 /* Check if this operation is supported by a font driver. */
883 if (font->get_fontbbx2 == NULL){
884 vf_error = VF_ERR_NOT_SUPPORTED_OP;
885 return -1;
886 }
887
888 if (width_p == NULL)
889 width_p = &d1;
890 if (height_p == NULL)
891 height_p = &d2;
892 if (xoff_p == NULL)
893 xoff_p = &d3;
894 if (yoff_p == NULL)
895 yoff_p = &d4;
896 *width_p = *height_p = *xoff_p = *yoff_p = 0;
897
898 /* Call a font driver's procedure. */
899 return (font->get_fontbbx2)(font, mag_x, mag_y,
900 width_p, height_p, xoff_p, yoff_p);
901 }
902
903
904 /**
905 ** VF_GetBitmap1
906 **/
907 Public VF_BITMAP
908 VF_GetBitmap1(int font_id, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
909 double mag_x, double mag_y)
910 {
911 VF_FONT font;
912
913 vf_error = 0;
914
915 if (vf_dbg_log > 0){
916 if (vf_dbg_log > 1)
917 fprintf(vf_dbg_log_fp,
918 "VF_DumpBitmap(VF_GetBitmap1(%d, 0x%lx, %f, %f));\n",
919 font_id, code_point, mag_x, mag_y);
920 else
921 fprintf(vf_dbg_log_fp, "VF_GetBitmap1(%d, 0x%lx, %f, %f);\n",
922 font_id, code_point, mag_x, mag_y);
923 }
924
925 /* Obtain a font object for given font id. */
926 if ((font = id2font(font_id)) == NULL)
927 return NULL;
928
929 /* Check if this font is opened as mode 1. */
930 if (font->mode != 1){
931 vf_error = VF_ERR_ILL_MODE;
932 return NULL;
933 }
934
935 /* Check if this operation is supported by a font driver. */
936 if (font->get_bitmap1 == NULL){
937 vf_error = VF_ERR_NOT_SUPPORTED_OP;
938 return NULL;
939 }
940
941 /* Call a font driver's procedure. */
942 return (font->get_bitmap1)(font, code_point, mag_x, mag_y);
943 }
944
945
946 /**
947 ** VF_GetBitmap2
948 **/
949 Public VF_BITMAP
950 VF_GetBitmap2(int font_id, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
951 double mag_x, double mag_y)
952 {
953 VF_FONT font;
954
955 vf_error = 0;
956
957 if (vf_dbg_log > 0){
958 if (vf_dbg_log > 1)
959 fprintf(vf_dbg_log_fp,
960 "VF_DumpBitmap(VF_GetBitmap2(%d, 0x%lx, %f, %f));\n",
961 font_id, code_point, mag_x, mag_y);
962 else
963 fprintf(vf_dbg_log_fp, "VF_GetBitmap2(%d, 0x%lx, %f, %f);\n",
964 font_id, code_point, mag_x, mag_y);
965 }
966
967 /* Obtain a font object for given font id. */
968 if ((font = id2font(font_id)) == NULL)
969 return NULL;
970
971 /* Check if this font is opened as mode 2. */
972 if (font->mode != 2){
973 vf_error = VF_ERR_ILL_MODE;
974 return NULL;
975 }
976
977 /* Check if this operation is supported by a font driver. */
978 if (font->get_bitmap2 == NULL){
979 vf_error = VF_ERR_NOT_SUPPORTED_OP;
980 return NULL;
981 }
982
983 /* Call a font driver's procedure. */
984 return (font->get_bitmap2)(font, code_point, mag_x, mag_y);
985 }
986
987
988 /**
989 ** VF_GetOutline
990 **/
991 Public VF_OUTLINE
992 VF_GetOutline(int font_id, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
993 double mag_x, double mag_y)
994 {
995 VF_FONT font;
996
997 vf_error = 0;
998
999 /* Obtain a font object for given font id. */
1000 if ((font = id2font(font_id)) == NULL)
1001 return NULL;
1002
1003 /* Check if this font is opened as mode 1. */
1004 if (font->mode != 1){
1005 vf_error = VF_ERR_ILL_MODE;
1006 return NULL;
1007 }
1008
1009 /* Check if this operation is supported by a font driver. */
1010 if (font->get_outline == NULL){
1011 vf_error = VF_ERR_NOT_SUPPORTED_OP;
1012 return NULL;
1013 }
1014
1015 /* Call a font driver's procedure. */
1016 return (font->get_outline)(font, code_point, mag_x, mag_y);
1017 }
1018
1019
1020 /**
1021 ** VF_GetFontProp
1022 **/
1023 Public char*
1024 VF_GetFontProp(int font_id, char *prop_name)
/* [<][>][^][v][top][bottom][index][help] */
1025 {
1026 VF_FONT font;
1027
1028 vf_error = 0;
1029
1030 /* Obtain a font object for given font id. */
1031 if ((font = id2font(font_id)) == NULL)
1032 return NULL;
1033
1034 /* Check if this operation is supported by a font driver. */
1035 if (font->get_font_prop == NULL){
1036 vf_error = VF_ERR_NOT_SUPPORTED_OP;
1037 return NULL;
1038 }
1039
1040 /* Call a font driver's procedure. */
1041 return (font->get_font_prop)(font, prop_name);
1042 }
1043
1044
1045 /**
1046 ** VF_QueryFontType
1047 **/
1048 Public int
1049 VF_QueryFontType(int font_id, long code_point)
/* [<][>][^][v][top][bottom][index][help] */
1050 {
1051 VF_FONT font;
1052
1053 vf_error = 0;
1054
1055 /* Obtain a font object for given font id. */
1056 if ((font = id2font(font_id)) == NULL)
1057 return -1;
1058
1059 switch (font->font_type){
1060 case VF_FONT_TYPE_BITMAP:
1061 case VF_FONT_TYPE_OUTLINE:
1062 return font->font_type;
1063 default:
1064 case VF_FONT_TYPE_UNDEF:
1065 /* Check if this operation is supported by a font driver. */
1066 if (font->query_font_type == NULL){
1067 vf_error = VF_ERR_NOT_SUPPORTED_OP;
1068 return -1;
1069 }
1070 /* Call a font driver's procedure. */
1071 return (font->query_font_type)(font, code_point);
1072 }
1073
1074 return -1;
1075 }
1076
1077
1078
1079 /* font ID ==> font obj */
1080
1081 Private VF_FONT
1082 id2font(int font_id)
/* [<][>][^][v][top][bottom][index][help] */
1083 {
1084 VF_FONT font;
1085 static VF_FONT last_font = NULL; /* 1st cache */
1086 static int last_font_id = -1;
1087
1088 if (font_id < 0){
1089 last_font = NULL;
1090 last_font_id = -1;
1091 return NULL;
1092 }
1093
1094 if ((font_id == last_font_id) && (last_font != NULL)
1095 && (last_font_id >= 0)){ /* 1st cache hits. */
1096 font = last_font;
1097 } else { /* use 2nd cache. */
1098 if ((font = (font_id_table->get_obj_by_id)(font_id_table, font_id))
1099 == NULL){
1100 vf_error = VF_ERR_ILL_FONTID;
1101 goto Error;
1102 }
1103 /* reload 1st cache. */
1104 last_font = font;
1105 last_font_id = font_id;
1106 }
1107 return font;
1108
1109 Error:
1110 /* discard 1st cache. */
1111 last_font = NULL;
1112 last_font_id = -1;
1113 return NULL;
1114 }
1115
1116
1117 /* For Debugging Purpose Only */
1118 Public void
1119 VF_DumpFontTable(void)
/* [<][>][^][v][top][bottom][index][help] */
1120 {
1121 VF_FONT font;
1122 FONT_CLASS fc;
1123 int nfonts, r, i;
1124
1125 nfonts = (font_id_table->get_nelements)(font_id_table);
1126
1127 for (i = 0, r = nfonts; r > 0; i++){
1128 font = (font_id_table->get_obj_by_id)(font_id_table, i);
1129 if (font == NULL)
1130 continue;
1131 --r;
1132
1133 fc = (FONT_CLASS)(font_class_table->get_obj_by_id)(font_class_table,
1134 font->font_class);
1135 printf("#% 3d: \"%s\"\n", i, font->font_name);
1136 printf(" font_class: %s, mode: %d\n", fc->class_name, font->mode);
1137 if (font->mode == 1)
1138 printf(" point size: %.3f, dpi_x: %.3f, dpi_y: %.3f\n",
1139 font->point_size, font->dpi_x, font->dpi_y);
1140 else
1141 printf(" point size: %.3f\n", font->point_size);
1142 printf(" max_x: %.3f, max_y: %.3f \n", font->mag_x, font->mag_y);
1143 }
1144 }
1145
1146 /*EOF*/