src/drv_gf.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- VF_Init_Driver_GF
- gf_create
- gf_close
- gf_get_metric1
- gf_get_fontbbx1
- gf_get_bitmap1
- gf_get_outline
- gf_get_metric2
- gf_get_fontbbx2
- gf_get_bitmap2
- gf_get_font_prop
- GF_Init
- GF_Open
- GF_Close
- GF_GetBitmap
- GF_GetMetric
- GF_GetFontBBX
- GF_GetGF
- GF_SetGFGlyph
- GF_GetGFGlyph
- debug_on
1 /*
2 * drv_gf.c - A font driver for TeX GF format fonts.
3 *
4 * 28 Sep 1996 First version.
5 * 14 Dec 1996 for VFlib 3.1
6 * 26 Feb 1997 Added 'query_font_type'.
7 * 4 Aug 1997 VFlib 3.3 Changed API.
8 * 30 Jan 1998 VFlib 3.4 Changed API.
9 * 21 Apr 1998 Debugged get_font_prop().
10 * 24 Nov 1998 Added get_fontbbx1() and get_fontbbx2().
11 * 9 Dec 1998 Fixed bugs in get_fontbbx1() and get_fontbbx2(). (^o^;)
12 * 16 Sep 1999 Changed not to use TFM files.
13 * 18 Oct 2001 Fixed memory leak.
14 */
15 /*
16 * Copyright (C) 1996-2001 Hirotsugu Kakugawa.
17 * All rights reserved.
18 *
19 * This file is part of the VFlib Library. This library is free
20 * software; you can redistribute it and/or modify it under the terms of
21 * the GNU Library General Public License as published by the Free
22 * Software Foundation; either version 2 of the License, or (at your
23 * option) any later version. This library is distributed in the hope
24 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
25 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
26 * PURPOSE. See the GNU Library General Public License for more details.
27 * You should have received a copy of the GNU Library General Public
28 * License along with this library; if not, write to the Free Software
29 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 */
31
32 /*
33
34 (Suppose that default resolution is 300 dpi)
35
36 ARGS FOR FONT OPEN BEHAVIOR of the DRIVER
37 Case# font_name device_dpi mag font_dpi dev_dpi bitmap_mag TFM_mag
38 ----------------------------------------------------------------------------
39 1. cmr10 -1 1 300 300 1 1
40 2. cmr10 -1 1.2 360 300 1 1.2
41 3. cmr10 400 1 400 400 1 1
42 4. cmr10 400 1.2 480 400 1 1.2
43 5. cmr10.gf -1 1 300 300 1 1
44 6. cmr10.gf -1 1.2 360 300 1 1.2
45 7. cmr10.gf 400 1 400 400 1 1
46 8. cmr10.gf 400 1.2 480 400 1 1.2
47 9. cmr10.400gf -1 1 400 400 1 1
48 10. cmr10.400gf -1 1.2 480 400 1 1.2
49 11. cmr10.400gf 400 1 400 400 1 1
50 12. cmr10.400gf 400 1.2 400 400 1.2 1.2
51 13. cmr10.300gf 360 1 300 360 1.2 1
52 14. cmr10.300gf 360 1.2 300 360 1.44 1.2
53
54 Font file is selected from the rules of the table shown above.
55 a. A font file of 'font_dpi' dpi font and opened.
56 b. Bitmaps of a font is scaled by 'bitmap_mag'.
57 c. Font metrics are multiplied by 'TFM_mag'.
58
59 Memo:
60 * Case 5: We want a GF font file "cmr10" default device resolution.
61 Thus, the bitmaps and metrics need not be scaled.
62
63 * Case 6: We want a GF font file "cmr10" default device resolution
64 with maginication factor 1.2. Since default device resolution
65 is 300 and magnification factor is 1.2, the font file we want
66 is "cmr10.360gf". Since device resolution is 300, metrics
67 must be scaled by 1.2.
68
69 * Case 9: This case requires a font "cmr10.400gf" and target device
70 is not considered. Thus bitmaps and metrics are not scaled.
71
72 * Case 10: This case requires a font cmr10 for 400 dpi scaled by 1.2.
73 Thus, "cmr10.480gf" is used for this request.
74 Since it is scaled by 1.2, font metrics are scaled by 1.2 but
75 bitmaps in a font is not magnified.
76
77 * Case 13: We want to use a GF font file "cmr10.300gf" for 360 dpi device.
78 Thus, the bitmaps of the font must be scaled by (360/300) = 1.2.
79 Since the metrics in a TFM file are independent from device
80 resolution, metrics need not be scaled.
81
82 * Case 14: We want to use a GF font file "cmr10.300gf" for 360 dpi device
83 and magnify it by 1.2. Thus, the bitmaps of the font must be scaled
84 by (1.2 x (360/300)) = 1.44.
85 Since the metrics in a TFM file are independent from device
86 resolution, TFM metrics must be scaled by 1.2, which is a
87 magnification factor.
88 */
89
90
91 #include "config.h"
92 #include "with.h"
93 #include <stdio.h>
94 #include <stdlib.h>
95 #ifdef HAVE_UNISTD_H
96 # include <unistd.h>
97 #endif
98 #include <ctype.h>
99
100 #include "VFlib-3_6.h"
101 #include "VFsys.h"
102 #include "vflibcap.h"
103 #include "cache.h"
104 #include "str.h"
105 #include "path.h"
106 #include "fsearch.h"
107 #include "sexp.h"
108 #include "texfonts.h"
109 #include "gf.h"
110
111
112 struct s_font_gf {
113 int gf_id;
114 char *font_name;
115 char *font_file;
116 double point_size;
117 double pixel_size;
118 double mag;
119 double dpi_x, dpi_y;
120 SEXP props;
121 double extra_mag;
122 };
123 typedef struct s_font_gf *FONT_GF;
124
125
126 Private SEXP_LIST default_fontdirs;
127 Private SEXP_LIST default_extensions;
128 Private SEXP_STRING default_point_size;
129 Private double v_default_point_size;
130 Private SEXP_STRING default_pixel_size;
131 Private double v_default_pixel_size;
132 Private SEXP_STRING default_dpi;
133 Private double v_default_dpi_x, v_default_dpi_y;
134 Private SEXP_STRING default_make_glyph;
135 Private int v_default_make_glyph = 0;
136 Private SEXP_ALIST default_properties;
137 Private SEXP_ALIST default_variables;
138 Private SEXP_STRING default_debug_mode;
139
140
141 Private int gf_create(VF_FONT,char*,char*,int,SEXP);
142 Private int gf_close(VF_FONT);
143 Private int gf_get_metric1(VF_FONT,long,VF_METRIC1,double,double);
144 Private int gf_get_metric2(VF_FONT,long,VF_METRIC2,double,double);
145 Private int gf_get_fontbbx1(VF_FONT,double,double,
146 double*,double*,double*,double*);
147 Private int gf_get_fontbbx2(VF_FONT,double,double,
148 int*,int*,int*,int*);
149 Private VF_BITMAP gf_get_bitmap1(VF_FONT,long,double,double);
150 Private VF_BITMAP gf_get_bitmap2(VF_FONT,long,double,double);
151 Private VF_OUTLINE gf_get_outline(VF_FONT,long,double,double);
152 Private char* gf_get_font_prop(VF_FONT,char*);
153
154
155 Private int GF_Init(void);
156 Private int GF_Open(FONT_GF font_gf, VF_FONT font, int implicit);
157 Private void GF_Close(int gf_id);
158 Private VF_BITMAP GF_GetBitmap(int gf_id, long code_point);
159 Private int GF_GetMetric(int gf_id, long code_point, VF_METRIC1 me,
160 double *ret_dpi_x, double *ret_dpi_y,
161 double *ret_design_size);
162 Private void GF_GetFontBBX(int gf_id, int *bbx_w_p, int *bbx_h_p,
163 int *bbx_xoff_p, int *bbx_yoff_p);
164 Private int debug_on(char type);
165
166
167
168
169 Public int
170 VF_Init_Driver_GF(void)
/* [<][>][^][v][top][bottom][index][help] */
171 {
172 int z;
173 struct s_capability_table ct[20];
174
175 z = 0;
176 /* VF_CAPE_FONT_DIRECTORIES */
177 ct[z].cap = VF_CAPE_FONT_DIRECTORIES; ct[z].type = CAPABILITY_LIST;
178 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_fontdirs;
179 /* VF_CAPE_EXTENSIONS */
180 ct[z].cap = VF_CAPE_EXTENSIONS; ct[z].type = CAPABILITY_LIST;
181 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_extensions;
182 /* VF_CAPE_POINT_SIZE */
183 ct[z].cap = VF_CAPE_POINT_SIZE; ct[z].type = CAPABILITY_STRING;
184 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_point_size;
185 /* VF_CAPE_PIXEL_SIZE */
186 ct[z].cap = VF_CAPE_PIXEL_SIZE; ct[z].type = CAPABILITY_STRING;
187 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_pixel_size;
188 /* VF_CAPE_DPI */
189 ct[z].cap = VF_CAPE_DPI; ct[z].type = CAPABILITY_STRING;
190 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_dpi;
191 /* VF_CAPE_MAKE_MISSING_GLYPH */
192 ct[z].cap = VF_CAPE_MAKE_MISSING_GLYPH; ct[z].type = CAPABILITY_STRING;
193 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_make_glyph;
194 /* VF_CAPE_PROPERTIES */
195 ct[z].cap = VF_CAPE_PROPERTIES; ct[z].type = CAPABILITY_ALIST;
196 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_properties;
197 /* VF_CAPE_VARIABLE_VALUES */
198 ct[z].cap = VF_CAPE_VARIABLE_VALUES; ct[z].type = CAPABILITY_ALIST;
199 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_variables;
200 /* VF_CAPE_DEBUG */
201 ct[z].cap = VF_CAPE_DEBUG; ct[z].type = CAPABILITY_STRING;
202 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &default_debug_mode;
203 /* end */
204 ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
205
206 if (vf_tex_init() < 0)
207 return -1;
208
209 if (vf_cap_GetParsedClassDefault(FONTCLASS_NAME_GF, ct,
210 vf_tex_default_variables, NULL)
211 == VFLIBCAP_PARSED_ERROR)
212 return -1;
213
214 if (default_extensions == NULL)
215 default_extensions = vf_sexp_cstring2list(DEFAULT_EXTENSIONS_GF);
216
217 v_default_point_size = -1;
218 if (default_point_size != NULL)
219 v_default_point_size = atof(vf_sexp_get_cstring(default_point_size));
220
221 v_default_pixel_size = -1;
222 if (default_pixel_size != NULL)
223 v_default_pixel_size = atof(vf_sexp_get_cstring(default_pixel_size));
224
225 v_default_dpi_x = -1;
226 v_default_dpi_y = -1;
227 if (default_dpi != NULL)
228 v_default_dpi_x = v_default_dpi_y = atof(vf_sexp_get_cstring(default_dpi));
229
230 v_default_make_glyph = 0;
231 if (default_make_glyph != NULL){
232 v_default_make_glyph
233 = vf_parse_bool(vf_sexp_get_cstring(default_make_glyph));
234 }
235
236 if (GF_Init() < 0)
237 return -1;
238
239 if ((v_default_dpi_x < 0) || (v_default_dpi_x < 0)){
240 v_default_dpi_x = vf_tex_default_dpi();
241 v_default_dpi_y = vf_tex_default_dpi();
242 }
243
244 VF_InstallFontDriver(FONTCLASS_NAME_GF, (DRIVER_FUNC_TYPE)gf_create);
245
246 return 0;
247 }
248
249
250 Private int
251 gf_create(VF_FONT font, char *font_class,
/* [<][>][^][v][top][bottom][index][help] */
252 char *font_name, int implicit, SEXP entry)
253 {
254 FONT_GF font_gf;
255 SEXP cap_ffile, cap_point, cap_pixel;
256 SEXP cap_dpi, cap_mag, cap_props;
257 char *font_file;
258 int val, gf_id;
259 struct s_capability_table ct[10];
260 int z;
261
262 z = 0;
263 /* VF_CAPE_FONT_CLASS */
264 ct[z].cap = VF_CAPE_FONT_CLASS; ct[z].type = CAPABILITY_STRING;
265 ct[z].ess = CAPABILITY_ESSENTIAL; ct[z++].val = NULL;
266 /* VF_CAPE_FONT_FILE */
267 ct[z].cap = VF_CAPE_FONT_FILE; ct[z].type = CAPABILITY_STRING;
268 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &cap_ffile;
269 /* VF_CAPE_POINT_SIZE */
270 ct[z].cap = VF_CAPE_POINT_SIZE; ct[z].type = CAPABILITY_STRING;
271 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &cap_point;
272 /* VF_CAPE_PIXEL_SIZE */
273 ct[z].cap = VF_CAPE_PIXEL_SIZE; ct[z].type = CAPABILITY_STRING;
274 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &cap_pixel;
275 /* VF_CAPE_DPI */
276 ct[z].cap = VF_CAPE_DPI; ct[z].type = CAPABILITY_STRING;
277 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &cap_dpi;
278 /* VF_CAPE_MAG */
279 ct[z].cap = VF_CAPE_MAG; ct[z].type = CAPABILITY_STRING;
280 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &cap_mag;
281 /* VF_CAPE_PROPERTIES */
282 ct[z].cap = VF_CAPE_PROPERTIES; ct[z].type = CAPABILITY_ALIST;
283 ct[z].ess = CAPABILITY_OPTIONAL; ct[z++].val = &cap_props;
284 /* end */
285 ct[z].cap = NULL; ct[z].type = 0; ct[z].ess = 0; ct[z++].val = NULL;
286
287 if (implicit == 1){ /* implicit font */
288 font_file = font_name;
289 } else { /* explicit font */
290 if (vf_cap_GetParsedFontEntry(entry, font_name, ct,
291 default_variables, vf_tex_default_variables)
292 == VFLIBCAP_PARSED_ERROR)
293 return -1;
294 if (cap_ffile == NULL){
295 /* Use font name as font file name if font file name is not given. */
296 font_file = font_name;
297 } else {
298 font_file = vf_sexp_get_cstring(cap_ffile);
299 }
300 }
301
302 font->font_type = VF_FONT_TYPE_BITMAP;
303 font->get_metric1 = gf_get_metric1;
304 font->get_metric2 = gf_get_metric2;
305 font->get_fontbbx1 = gf_get_fontbbx1;
306 font->get_fontbbx2 = gf_get_fontbbx2;
307 font->get_bitmap1 = gf_get_bitmap1;
308 font->get_bitmap2 = gf_get_bitmap2;
309 font->get_outline = gf_get_outline;
310 font->get_font_prop = gf_get_font_prop;
311 font->query_font_type = NULL;
312 font->close = gf_close;
313
314 val = -1;
315 font_gf = NULL;
316
317 ALLOC_IF_ERR(font_gf, struct s_font_gf)
318 goto NoMemoryError;
319
320 font_gf->gf_id = -1;
321 font_gf->font_name = NULL;
322 font_gf->font_file = NULL;
323 font_gf->point_size = v_default_point_size;
324 font_gf->pixel_size = v_default_pixel_size;
325 font_gf->dpi_x = v_default_dpi_x;
326 font_gf->dpi_y = v_default_dpi_y;
327 font_gf->mag = 1.0;
328 font_gf->props = NULL;
329 font_gf->extra_mag = 1.0;
330
331 if (implicit == 0){
332 if (cap_point != NULL)
333 font_gf->point_size = atof(vf_sexp_get_cstring(cap_point));
334 if (cap_pixel != NULL)
335 font_gf->pixel_size = atof(vf_sexp_get_cstring(cap_pixel));
336 if (cap_dpi != NULL)
337 font_gf->dpi_x = font_gf->dpi_y = atof(vf_sexp_get_cstring(cap_dpi));
338 if (cap_mag != NULL)
339 font_gf->mag = atof(vf_sexp_get_cstring(cap_mag));
340 if (cap_props != NULL)
341 font_gf->props = cap_props;
342 }
343
344 if ((font_gf->font_file = vf_strdup(font_file)) == NULL)
345 goto NoMemoryError;
346 if ((font_gf->font_name = vf_strdup(font_name)) == NULL)
347 goto NoMemoryError;
348
349 if ((gf_id = GF_Open(font_gf, font, implicit)) < 0)
350 goto Error;
351
352 font_gf->gf_id = gf_id;
353 font->private = font_gf;
354
355 val = 0;
356 goto End;
357
358
359 NoMemoryError:
360 vf_error = VF_ERR_NO_MEMORY;
361 Error:
362 if (font_gf != NULL){
363 vf_free(font_gf->font_name);
364 vf_free(font_gf->font_file);
365 }
366 if (implicit == 0)
367 vf_sexp_free1(&cap_props);
368 vf_free(font_gf);
369
370 End:
371 if (implicit == 0){
372 vf_sexp_free3(&cap_ffile, &cap_point, &cap_pixel);
373 vf_sexp_free2(&cap_dpi, &cap_mag);
374 }
375
376 return val;
377 }
378
379
380 Private int
381 gf_close(VF_FONT font)
/* [<][>][^][v][top][bottom][index][help] */
382 {
383 FONT_GF font_gf;
384
385 font_gf = (FONT_GF)font->private;
386 if (font_gf != NULL){
387 GF_Close(font_gf->gf_id);
388 vf_sexp_free1(&font_gf->props);
389 vf_free(font_gf->font_name);
390 vf_free(font_gf->font_file);
391 }
392 vf_free(font_gf);
393
394 return 0;
395 }
396
397
398 Private int
399 gf_get_metric1(VF_FONT font, long code_point, VF_METRIC1 metric,
/* [<][>][^][v][top][bottom][index][help] */
400 double mag_x, double mag_y)
401 {
402 FONT_GF font_gf;
403 double mx, my, ps, design_size;
404
405 if (metric == NULL){
406 fprintf(stderr, "VFlib internal error: in gf_get_metric1()\n");
407 abort();
408 }
409 if ((font_gf = (FONT_GF)font->private) == NULL){
410 fprintf(stderr, "VFlib internal error: in gf_get_metric1()\n");
411 abort();
412 }
413
414 if (GF_GetMetric(font_gf->gf_id, code_point, metric,
415 NULL, NULL, &design_size) < 0)
416 return -1;
417
418 if ((ps = font->point_size) < 0)
419 if ((ps = font_gf->point_size) < 0)
420 ps = -1;
421
422 if ((ps < 0) || (design_size < 1.0e-3)){
423 mx = mag_x * font->mag_x * font_gf->mag;
424 my = mag_y * font->mag_y * font_gf->mag;
425 } else {
426 mx = mag_x * font->mag_x * font_gf->mag * (ps/design_size);
427 my = mag_y * font->mag_y * font_gf->mag * (ps/design_size);
428 }
429
430 metric->bbx_width *= mx;
431 metric->bbx_height *= my;
432 metric->off_x *= mx;
433 metric->off_y *= my;
434 metric->mv_x *= mx;
435 metric->mv_y *= my;
436
437 return 0;
438 }
439
440 Private int
441 gf_get_fontbbx1(VF_FONT font, double mag_x, double mag_y,
/* [<][>][^][v][top][bottom][index][help] */
442 double *w_p, double *h_p, double *xoff_p, double *yoff_p)
443 {
444 FONT_GF font_gf;
445 double mx, my, ps, design_size, dpi_x, dpi_y;
446 int w, h, xoff, yoff;
447
448 if ((font_gf = (FONT_GF)font->private) == NULL){
449 fprintf(stderr, "VFlib internal error: in gf_get_fontbbx1()\n");
450 abort();
451 }
452
453 if (GF_GetMetric(font_gf->gf_id, -1, NULL,
454 &dpi_x, &dpi_y, &design_size) < 0)
455 return -1;
456
457 if ((ps = font->point_size) < 0)
458 if ((ps = font_gf->point_size) < 0)
459 ps = -1;
460
461 if ((ps < 0) || (design_size < 1.0e-3)){
462 mx = mag_x * font->mag_x * font_gf->mag;
463 my = mag_y * font->mag_y * font_gf->mag;
464 } else {
465 mx = mag_x * font->mag_x * font_gf->mag * (ps/design_size);
466 my = mag_y * font->mag_y * font_gf->mag * (ps/design_size);
467 }
468
469 GF_GetFontBBX(font_gf->gf_id, &w, &h, &xoff, &yoff);
470
471 #if 0
472 printf("*** %d %d %d %d %.3f %.3f %.3f %.3f\n",
473 w, h, xoff, yoff, mx, my, dpi_x, dpi_y);
474 #endif
475
476 *w_p = mx * w * 72.27 / dpi_x;
477 *h_p = my * h * 72.27 / dpi_y;
478 *xoff_p = mx * xoff * 72.27 / dpi_x;
479 *yoff_p = my * yoff * 72.27 / dpi_y;
480
481 return 0;
482 }
483
484 Private VF_BITMAP
485 gf_get_bitmap1(VF_FONT font, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
486 double mag_x, double mag_y)
487 {
488 VF_BITMAP bm;
489 FONT_GF font_gf;
490 double mx, my, ps, design_size;
491
492 if ((font_gf = (FONT_GF)font->private) == NULL){
493 fprintf(stderr, "VFlib internal error in gf_get_bitmap1()\n");
494 abort();
495 }
496
497 if ((bm = GF_GetBitmap(font_gf->gf_id, code_point)) == NULL)
498 return NULL;
499 /* 'bm' SHOULD NOT BE RELEASED. */
500
501 if (GF_GetMetric(font_gf->gf_id, code_point, NULL,
502 NULL, NULL, &design_size) < 0)
503 return NULL;
504
505 if ((ps = font->point_size) < 0)
506 if ((ps = font_gf->point_size) < 0)
507 ps = -1;
508
509 if ((ps < 0) || (design_size < 1.0e-3)){
510 /* Note: font->mag_x and font_gf->mag are already used to select
511 scaled glyph, e.g., cmr10.360gf for 300dpi with mag 1.2. */
512 mx = font_gf->extra_mag * mag_x;
513 my = font_gf->extra_mag * mag_y;
514 } else {
515 #if 0
516 m = font->mag_y * font_gf->mag;
517 mx = font_gf->extra_mag * mag_x * m * (ps/design_size);
518 my = font_gf->extra_mag * mag_y * m * (ps/design_size);
519 #endif
520 mx = font_gf->extra_mag * mag_x * (ps/design_size);
521 my = font_gf->extra_mag * mag_y * (ps/design_size);
522 }
523
524 if (debug_on('m'))
525 printf("VFlib GF: get_bitmap1: bitmap mag: %.4f %.4f\n", mx, my);
526
527 return VF_MakeScaledBitmap(bm, mx, my);
528 }
529
530 Private VF_OUTLINE
531 gf_get_outline(VF_FONT font, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
532 double mag_x, double mag_y)
533 {
534 VF_BITMAP bm;
535 VF_OUTLINE ol;
536 FONT_GF font_gf;
537 int bbx_w, bbx_h;
538 double dpi_x, dpi_y, design_size;
539
540 if ((font_gf = (FONT_GF)font->private) == NULL){
541 fprintf(stderr, "VFlib internal error in gf_get_outline()\n");
542 abort();
543 }
544
545 if ((bm = gf_get_bitmap1(font, code_point, mag_x, mag_y)) == NULL)
546 return NULL;
547
548 if (GF_GetMetric(font_gf->gf_id, code_point, NULL,
549 &dpi_x, &dpi_y, &design_size) < 0){
550 VF_FreeBitmap(bm);
551 return NULL;
552 }
553
554 GF_GetFontBBX(font_gf->gf_id, &bbx_w, &bbx_h, NULL, NULL);
555 ol = vf_bitmap_to_outline(bm, bbx_w, bbx_h,
556 dpi_x, dpi_y, design_size, 1.0, 1.0);
557 VF_FreeBitmap(bm);
558
559 return ol;
560 }
561
562
563 Private int
564 gf_get_metric2(VF_FONT font, long code_point, VF_METRIC2 metric,
/* [<][>][^][v][top][bottom][index][help] */
565 double mag_x, double mag_y)
566 {
567 VF_BITMAP bm;
568 FONT_GF font_gf;
569 double mx, my, dpi_x, dpi_y, ps, design_size;
570
571 if ( (metric == NULL)
572 || ((font_gf = (FONT_GF)font->private) == NULL) ){
573 fprintf(stderr, "VFlib internal error: in gf_get_metric2()\n");
574 abort();
575 }
576
577 if ((bm = GF_GetBitmap(font_gf->gf_id, code_point)) == NULL)
578 return -1;
579 /* 'bm' SHOULD NOT BE RELEASED. */
580
581 if (GF_GetMetric(font_gf->gf_id, code_point, NULL,
582 &dpi_x, &dpi_y, &design_size) < 0)
583 return -1;
584
585 if ((ps = font->pixel_size) < 0)
586 if ((ps = font_gf->pixel_size) < 0)
587 ps = -1;
588
589 if ((ps < 0) || (design_size < 1.0e-3)){
590 mx = font->mag_x * font_gf->mag * mag_x;
591 my = font->mag_y * font_gf->mag * mag_y;
592 } else {
593 mx = font->mag_x * font_gf->mag * mag_x * (ps*72.27)/(design_size*dpi_x);
594 my = font->mag_y * font_gf->mag * mag_y * (ps*72.27)/(design_size*dpi_y);
595 }
596
597 metric->bbx_width = toint(mx * bm->bbx_width);
598 metric->bbx_height = toint(my * bm->bbx_height);
599 metric->off_x = toint(mx * bm->off_x);
600 metric->off_y = toint(my * bm->off_y);
601 metric->mv_x = toint(mx * bm->mv_x);
602 metric->mv_y = toint(my * bm->mv_y);
603
604 return 0;
605 }
606
607 Private int
608 gf_get_fontbbx2(VF_FONT font, double mag_x, double mag_y,
/* [<][>][^][v][top][bottom][index][help] */
609 int *w_p, int *h_p, int *xoff_p, int *yoff_p)
610 {
611 FONT_GF font_gf;
612 double mx, my, dpi_x, dpi_y, ps, design_size;
613
614 if ((font_gf = (FONT_GF)font->private) == NULL){
615 fprintf(stderr, "VFlib internal error: in gf_get_fontbbx2()\n");
616 abort();
617 }
618
619 if (GF_GetMetric(font_gf->gf_id, -1, NULL,
620 &dpi_x, &dpi_y, &design_size) < 0)
621 return -1;
622
623 if ((ps = font->pixel_size) < 0)
624 if ((ps = font_gf->pixel_size) < 0)
625 ps = -1;
626
627 if ((ps < 0) || (design_size < 1.0e-3)){
628 mx = font->mag_x * font_gf->mag * mag_x;
629 my = font->mag_y * font_gf->mag * mag_y;
630 } else {
631 mx = font->mag_x * font_gf->mag * mag_x * (ps*72.27)/(design_size*dpi_x);
632 my = font->mag_y * font_gf->mag * mag_y * (ps*72.27)/(design_size*dpi_y);
633 }
634
635 GF_GetFontBBX(font_gf->gf_id, w_p, h_p, xoff_p, yoff_p);
636
637 *w_p = mx * (*w_p);
638 *h_p = mx * (*h_p);
639 *xoff_p = mx * (*xoff_p);
640 *yoff_p = mx * (*yoff_p);
641
642 return 0;
643 }
644
645
646 Private VF_BITMAP
647 gf_get_bitmap2(VF_FONT font, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
648 double mag_x, double mag_y)
649 {
650 VF_BITMAP bm;
651 FONT_GF font_gf;
652 double mx, my, dpi_x, dpi_y, ps, design_size;
653
654 if ((font_gf = (FONT_GF)font->private) == NULL){
655 fprintf(stderr, "VFlib internal error in gf_get_bitmap2()\n");
656 abort();
657 }
658
659 if ((bm = GF_GetBitmap(font_gf->gf_id, code_point)) == NULL)
660 return NULL;
661 /* 'bm' SHOULD NOT BE RELEASED. */
662
663 if (GF_GetMetric(font_gf->gf_id, code_point, NULL,
664 &dpi_x, &dpi_y, &design_size) < 0)
665 return NULL;
666
667 if ((ps = font->pixel_size) < 0)
668 if ((ps = font_gf->pixel_size) < 0)
669 ps = -1;
670
671 #if 0
672 printf("** %.3f %.3f %.3f %.3f %.3f %.3f %d %.3f\n",
673 mag_x, mag_y, ps, design_size, dpi_x, dpi_y,
674 font->pixel_size, font_gf->pixel_size);
675 #endif
676
677 if ((ps < 0) || (design_size < 1.0e-3)){
678 /* Note: font_gf->mag_x and font_gf->mag are already used to select
679 scaled glyph, e.g., cmr10.360gf for 300dpi with mag 1.2. */
680 mx = font_gf->extra_mag * mag_x;
681 my = font_gf->extra_mag * mag_y;
682 } else {
683 #if 0
684 m = font->mag_y * font_gf->mag;
685 mx = font_gf->extra_mag * mag_x * m * (ps*72.27)/(design_size*dpi_x);
686 my = font_gf->extra_mag * mag_y * m * (ps*72.27)/(design_size*dpi_y);
687 #endif
688 mx = font_gf->extra_mag * mag_x
689 * (font->mag_x * font_gf->mag) * (ps*72.27)/(design_size*dpi_x);
690 my = font_gf->extra_mag * mag_y
691 * (font->mag_y * font_gf->mag) * (ps*72.27)/(design_size*dpi_y);
692 }
693
694 return VF_MakeScaledBitmap(bm, mx, my);
695 }
696
697
698 Private char*
699 gf_get_font_prop(VF_FONT font, char *prop_name)
/* [<][>][^][v][top][bottom][index][help] */
700 {
701 FONT_GF font_gf;
702 double dpi_x, dpi_y, design_size, ps, m;
703 char str[256];
704 SEXP v;
705
706 if ((font_gf = (FONT_GF)font->private) == NULL){
707 fprintf(stderr, "VFlib internal error in gf_get_font_prop()\n");
708 abort();
709 }
710
711 if ((v = vf_sexp_assoc(prop_name, font_gf->props)) != NULL){
712 return vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)));
713 } else if ((v = vf_sexp_assoc(prop_name, default_properties)) != NULL){
714 return vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)));
715 } else {
716 if (GF_GetMetric(font_gf->gf_id, -1, NULL,
717 &dpi_x, &dpi_y, &design_size) < 0){
718 return NULL;
719 }
720 m = font->mag_y * font_gf->mag;
721 #if 0
722 printf("** %.3f %.3f %.3f %.4f %d %.3f %.3f %.3f\n",
723 dpi_x, dpi_y, design_size, m,
724 font->pixel_size, font_gf->pixel_size,
725 font->point_size, font_gf->point_size);
726 #endif
727 if (font->mode == 1){
728 if ((ps = font->point_size) < 0)
729 if ((ps = font_gf->point_size) < 0)
730 ps = design_size;
731 if (strcmp(prop_name, "POINT_SIZE") == 0){
732 sprintf(str, "%d", toint(ps * m * 10.0));
733 return vf_strdup(str);
734 } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
735 sprintf(str, "%d", toint(ps * dpi_y / 72.27));
736 return vf_strdup(str);
737 } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
738 sprintf(str, "%d", toint(dpi_x));
739 return vf_strdup(str);
740 } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
741 sprintf(str, "%d", toint(dpi_y));
742 return vf_strdup(str);
743 }
744
745 } else if (font->mode == 2){
746 if (strcmp(prop_name, "POINT_SIZE") == 0){
747 if ((ps = font->pixel_size) < 0){
748 if ((ps = font_gf->pixel_size) < 0){
749 sprintf(str, "%d", toint(design_size * m));
750 return vf_strdup(str);
751 }
752 }
753 sprintf(str, "%d", toint(ps * 10.0 * (72.27 / dpi_y)));
754 return vf_strdup(str);
755 } else if (strcmp(prop_name, "PIXEL_SIZE") == 0){
756 if ((ps = font->pixel_size) < 0)
757 if ((ps = font_gf->pixel_size) < 0){
758 ps = design_size * dpi_y / 72.27;
759 sprintf(str, "%d", toint(ps));
760 return vf_strdup(str);
761 }
762 sprintf(str, "%d", toint(ps * m));
763 return vf_strdup(str);
764 } else if (strcmp(prop_name, "RESOLUTION_X") == 0){
765 sprintf(str, "%d", toint(dpi_x));
766 return vf_strdup(str);
767 } else if (strcmp(prop_name, "RESOLUTION_Y") == 0){
768 sprintf(str, "%d", toint(dpi_y));
769 return vf_strdup(str);
770 }
771 }
772 }
773
774 return NULL;
775 }
776
777
778
779 #ifndef CACHE_SIZE
780 # define CACHE_SIZE 48
781 #endif
782 #ifndef HASH_SIZE
783 # define HASH_SIZE 11
784 #endif
785
786
787 struct s_gf {
788 int type;
789 char *font_path;
790 };
791 typedef struct s_gf *GF;
792
793 struct s_gf_glyph {
794 int code_min, code_max;
795 VF_BITMAP bm_table;
796 double ds, hppp, vppp;
797 int font_bbx_w, font_bbx_h;
798 int font_bbx_xoff, font_bbx_yoff;
799 };
800 typedef struct s_gf_glyph *GF_GLYPH;
801
802 Private VF_TABLE gf_table = NULL;
803 Private VF_CACHE gf_glyph_cache = NULL;
804
805 Private void GF_CacheDisposer(GF_GLYPH go);
806 Private GF_GLYPH GF_CacheLoader(VF_CACHE c, char *path, int l);
807
808 Private GF GF_GetGF(int gf_id);
809 Private void GF_SetGFGlyph(char *path, GF_GLYPH go);
810 Private GF_GLYPH GF_GetGFGlyph(char *path);
811
812
813 Private int
814 GF_Init(void)
/* [<][>][^][v][top][bottom][index][help] */
815 {
816 static int init_flag = 0;
817
818 if (init_flag == 0){
819 init_flag = 1;
820 if ((gf_table = vf_table_create()) == NULL){
821 vf_error = VF_ERR_NO_MEMORY;
822 return -1;
823 }
824 gf_glyph_cache
825 = vf_cache_create(CACHE_SIZE, HASH_SIZE,
826 (void*(*)(VF_CACHE,void*,int))GF_CacheLoader,
827 (void(*)(void*))GF_CacheDisposer);
828 }
829
830 return 0;
831 }
832
833 Private int
834 GF_Open(FONT_GF font_gf, VF_FONT font, int implicit)
/* [<][>][^][v][top][bottom][index][help] */
835 {
836 GF gf;
837 char *gf_path, *p;
838 int gf_id, dev_dpi;
839 double font_mag;
840
841 gf = NULL;
842
843 if (vf_dbg_drv_texfonts == 1)
844 printf(">> GF Open: %s\n", font_gf->font_file);
845
846 /* Parse font name. Formats of file names that this routine supports:
847 * "cmr10.300XX" - A "cmr10" font for 300 dpi.
848 * "cmr10.XX" - A "cmr10" font. Dpi value is default value.
849 * "cmr10" - ditto.
850 * ("XX" can be any string such as "pk", "gf", and "tfm".)
851 */
852 p = vf_index(font_gf->font_file, '.');
853 if ((p != NULL) && (isdigit((int)*(p+1)))){ /* "cmr10.300gf" */
854 dev_dpi = atoi(p+1);
855 if (font->dpi_y > 0)
856 font_gf->extra_mag = (double)font->dpi_y / (double)dev_dpi;
857 else
858 font_gf->extra_mag = 1.0;
859 } else { /* "cmr10" or "cmr10.gf" */
860 if ((dev_dpi = font->dpi_y) < 0)
861 dev_dpi = font_gf->dpi_y;
862 font_gf->extra_mag = 1.0;
863 }
864
865 font_mag = font->mag_y * font_gf->mag;
866 gf_path = vf_tex_search_file_glyph(font_gf->font_file, implicit,
867 FSEARCH_FORMAT_TYPE_GF,
868 default_fontdirs, dev_dpi, font_mag,
869 default_extensions);
870 if (gf_path == NULL){
871 if (vf_dbg_drv_texfonts == 1)
872 printf(">> GF Open: GF file not found\n");
873 if (v_default_make_glyph == 0)
874 return -1;
875 if (vf_tex_make_glyph(FSEARCH_FORMAT_TYPE_GF,
876 font_gf->font_file, dev_dpi, font_mag) < 0)
877 return -1;
878 gf_path = vf_tex_search_file_glyph(font_gf->font_file, implicit,
879 FSEARCH_FORMAT_TYPE_GF,
880 default_fontdirs, dev_dpi, font_mag,
881 default_extensions);
882 if (gf_path == NULL){
883 if (vf_dbg_drv_texfonts == 1)
884 printf(">> GF Open: GF file not found\n");
885 return -1;
886 }
887 }
888
889 if (debug_on('f'))
890 printf("VFlib GF: font:%s, dpi:%d, mag:%f, extra_mag:%f\n ==> %s\n",
891 font_gf->font_file, dev_dpi, font_mag, font_gf->extra_mag, gf_path);
892
893 ALLOC_IF_ERR(gf, struct s_gf){
894 goto NoMemoryError;
895 }
896 gf->font_path = gf_path;
897 if ((gf_id = (gf_table->put)(gf_table, gf, gf->font_path,
898 strlen(gf->font_path)+1)) < 0)
899 goto NoMemoryError;
900
901 return gf_id;
902
903
904 NoMemoryError:
905 vf_error = VF_ERR_NO_MEMORY;
906 if (gf != NULL)
907 vf_free(gf->font_path);
908 vf_free(gf);
909 return -1;
910 }
911
912 Private void
913 GF_Close(int gf_id)
/* [<][>][^][v][top][bottom][index][help] */
914 {
915 GF gf;
916
917 gf = GF_GetGF(gf_id);
918
919 if ((gf_table->unlink_by_id)(gf_table, gf_id) > 0)
920 return;
921
922 if (gf != NULL)
923 vf_free(gf->font_path);
924 vf_free(gf);
925 GF_SetGFGlyph(NULL, NULL);
926 }
927
928
929 Private VF_BITMAP
930 GF_GetBitmap(int gf_id, long code_point)
/* [<][>][^][v][top][bottom][index][help] */
931 /* MEMO: CALLER MUST *NOT* 'FREE' THE BITMAP RETURNED BY THIS FUNC. */
932 {
933 GF_GLYPH go;
934 GF gf;
935
936 gf = GF_GetGF(gf_id);
937 if ((go = GF_GetGFGlyph(gf->font_path)) == NULL)
938 return NULL;
939
940 if ((go->code_min <= code_point) && (code_point <= go->code_max))
941 return &go->bm_table[code_point - go->code_min];
942
943 return NULL;
944 }
945
946 Private int
947 GF_GetMetric(int gf_id, long code_point, VF_METRIC1 me,
/* [<][>][^][v][top][bottom][index][help] */
948 double *ret_dpi_x, double *ret_dpi_y, double *ret_design_size)
949 {
950 VF_BITMAP bm;
951 GF_GLYPH go;
952 GF gf;
953
954 gf = GF_GetGF(gf_id);
955 if ((go = GF_GetGFGlyph(gf->font_path)) == NULL)
956 return -1;
957
958 if (code_point < 0)
959 code_point = go->code_min;
960 if ((code_point < go->code_min) || (go->code_max < code_point)){
961 vf_error = VF_ERR_ILL_CODE_POINT;
962 return -1;
963 }
964
965 if ((bm = &go->bm_table[code_point - go->code_min]) == NULL){
966 vf_error = VF_ERR_ILL_CODE_POINT;
967 return -1;
968 }
969
970 if (me != NULL){
971 me->bbx_width = bm->bbx_width / go->hppp;
972 me->bbx_height = bm->bbx_height / go->vppp;
973 me->off_x = bm->off_x / go->hppp;
974 me->off_y = bm->off_y / go->vppp;
975 me->mv_x = bm->mv_x / go->hppp;
976 me->mv_y = bm->mv_y / go->vppp;
977 }
978
979 if (ret_dpi_x != NULL)
980 *ret_dpi_x = go->hppp * 72.27;
981 if (ret_dpi_y != NULL)
982 *ret_dpi_y = go->vppp * 72.27;
983 if (ret_design_size != NULL)
984 *ret_design_size = go->ds;
985
986 return 0;
987 }
988
989 Private void
990 GF_GetFontBBX(int gf_id, int *bbx_w_p, int *bbx_h_p,
/* [<][>][^][v][top][bottom][index][help] */
991 int *bbx_xoff_p, int *bbx_yoff_p)
992 {
993 GF_GLYPH go;
994 GF gf;
995
996 gf = GF_GetGF(gf_id);
997 if ((go = GF_GetGFGlyph(gf->font_path)) == NULL)
998 return;
999
1000 if (bbx_w_p != NULL)
1001 *bbx_w_p = go->font_bbx_w;
1002 if (bbx_h_p != NULL)
1003 *bbx_h_p = go->font_bbx_h;
1004 if (bbx_xoff_p != NULL)
1005 *bbx_xoff_p = go->font_bbx_xoff;
1006 if (bbx_yoff_p != NULL)
1007 *bbx_yoff_p = go->font_bbx_yoff;
1008 }
1009
1010
1011 /*
1012 * GF file interface
1013 */
1014
1015 #include "gf.c"
1016
1017
1018 Private GF
1019 GF_GetGF(int gf_id)
/* [<][>][^][v][top][bottom][index][help] */
1020 {
1021 if (gf_id < 0)
1022 abort();
1023 return (gf_table->get_obj_by_id)(gf_table, gf_id);
1024 }
1025
1026
1027 static char *gf_last_go_path = NULL;
1028 static GF_GLYPH gf_last_go = NULL;
1029
1030 Private void
1031 GF_SetGFGlyph(char *path, GF_GLYPH go)
/* [<][>][^][v][top][bottom][index][help] */
1032 {
1033 gf_last_go_path = path;
1034 gf_last_go = go;
1035 }
1036
1037 Private GF_GLYPH
1038 GF_GetGFGlyph(char *path)
/* [<][>][^][v][top][bottom][index][help] */
1039 {
1040 GF_GLYPH go;
1041
1042 if (path == NULL){
1043 gf_last_go_path = NULL;
1044 gf_last_go = NULL;
1045 return NULL;
1046 }
1047 if ((gf_last_go_path != NULL)
1048 && (strcmp(gf_last_go_path, path) == 0)
1049 && (gf_last_go != NULL) ){
1050 return gf_last_go;
1051 }
1052
1053 go = (gf_glyph_cache->get)(gf_glyph_cache, path, strlen(path)+1);
1054 gf_last_go_path = path;
1055 gf_last_go = go;
1056
1057 return go;
1058 }
1059
1060
1061 Private int
1062 debug_on(char type)
/* [<][>][^][v][top][bottom][index][help] */
1063 {
1064 char *p;
1065
1066 if (default_debug_mode == NULL)
1067 return FALSE;
1068 if ((p = vf_sexp_get_cstring(default_debug_mode)) == NULL)
1069 return FALSE;
1070
1071 while (*p != '\0'){
1072 if (*p == type)
1073 return TRUE;
1074 p++;
1075 }
1076
1077 while (*p != '\0'){
1078 if (*p == '*')
1079 return TRUE;
1080 p++;
1081 }
1082
1083 return TRUE;
1084 }
1085
1086
1087 /*EOF*/