src/vf.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- STACK
- vf_vf_init
- vf_vf_open
- vf_read_info
- vf_vf_close
- vf_vf_get_design_size
- vf_vf_get_vf
- vf_cache_loader
- vf_cache_disposer
- vf_vf_get_metric
- vf_vf_get_bitmap
- vf_do_glyph_style
- vf_run_dvi_program
- vf_dvi_interp
- vf_dvi_interp_put_char
- vf_dvi_interp_put_rule
- vf_dvi_interp_font_select
- vf_dvi_stack_init
- vf_dvi_stack_deinit
- vf_dvi_stack_push
- vf_dvi_stack_pop
1 /* this is included by drv_vf.c */
2 /*
3 * vf.c - A vf (virtual font) interface
4 * by Hirotsugu Kakugawa
5 *
6 * 30 Jan 1997 First implementation.
7 * 7 Aug 1997 VFlib 3.3 Changed API.
8 * 2 Feb 1998 VFlib 3.4
9 *
10 */
11 /*
12 * Copyright (C) 1997-1998 Hirotsugu Kakugawa.
13 * All rights reserved.
14 *
15 * This file is part of the VFlib Library. This library is free
16 * software; you can redistribute it and/or modify it under the terms of
17 * the GNU Library General Public License as published by the Free
18 * Software Foundation; either version 2 of the License, or (at your
19 * option) any later version. This library is distributed in the hope
20 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 * PURPOSE. See the GNU Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28
29
30 Private VF_TABLE vf_font_table = NULL;
31 Private VF_CACHE vf_font_cache = NULL;
32
33
34 struct s_vf_dvi_stack {
35 long h, v, w, x, y, z;
36 int f;
37 int font_id;
38 struct s_vf_dvi_stack *next;
39 };
40 typedef struct s_vf_dvi_stack *VF_DVI_STACK;
41
42 #define STACK(X) dvi_stack->next->X
/* [<][>][^][v][top][bottom][index][help] */
43
44
45 Private int vf_read_info(VF,FILE*,int,VF_FONT);
46 Private void vf_do_glyph_style(VF_BITMAP,int);
47 Private VF_BITMAP vf_run_dvi_program(VF,VF_CHAR_PACKET,int,double,double);
48 Private VF_CHAR_PACKET_TBL vf_cache_loader(VF_CACHE,VF_CACHE_KEY,int);
49 Private void vf_cache_disposer(VF_CHAR_PACKET_TBL);
50
51 Private int vf_dvi_interp(VF_BITMAPLIST,VF,
52 int,double,double,unsigned char*,int);
53 Private void vf_dvi_interp_font_select(VF,VF_DVI_STACK,long,double*);
54 Private void vf_dvi_interp_put_char(VF_BITMAPLIST,VF,VF_DVI_STACK,long,
55 int,double,double);
56 Private void vf_dvi_interp_put_rule(VF_BITMAPLIST,VF,VF_DVI_STACK,long,long,
57 double,double);
58 Private int vf_dvi_stack_init(VF,VF_DVI_STACK);
59 Private int vf_dvi_stack_deinit(VF,VF_DVI_STACK);
60 Private int vf_dvi_stack_push(VF,VF_DVI_STACK);
61 Private int vf_dvi_stack_pop(VF,VF_DVI_STACK);
62
63
64
65 Private int
66 vf_vf_init(void)
/* [<][>][^][v][top][bottom][index][help] */
67 {
68 static int init_flag = 0;
69
70 if (init_flag == 1)
71 return 0;
72
73 init_flag = 1;
74 vf_font_cache
75 = vf_cache_create(VF_CACHE_SIZE, VF_HASH_SIZE,
76 (void*(*)(VF_CACHE,void*,int))vf_cache_loader,
77 (void(*)(void*))vf_cache_disposer);
78 vf_font_table = vf_table_create();
79 vf_vf_get_vf(-1);
80
81 return 0;
82 }
83
84
85 Private int
86 vf_vf_open(VF_FONT font, FONT_VF font_vf, int implicit)
/* [<][>][^][v][top][bottom][index][help] */
87 {
88 int vf_id;
89 char *vf_path, *tfm_path;
90 double dpi_x, dpi_y = 0.0;
91 VF vf;
92 FILE *fp;
93 char key[2*1024];
94
95 vf_path = NULL;
96 tfm_path = NULL;
97
98 sprintf(key, "%s %.6f %.6f %.6f %.6f %.6f %.6f %.6f",
99 font_vf->font_file,
100 font->dpi_x, font->dpi_y, font->mag_x, font->mag_y,
101 font_vf->dpi_x, font_vf->dpi_y, font_vf->mag);
102
103 vf_id = (vf_font_table->get_id_by_key)(vf_font_table, key, strlen(key)+1);
104 if (vf_id >= 0){
105 (vf_font_table->link_by_id)(vf_font_table, vf_id);
106 return vf_id;
107 }
108
109 vf_path = vf_tex_search_file_misc(font_vf->font_file, implicit,
110 FSEARCH_FORMAT_TYPE_VF,
111 default_fontdirs, default_extensions);
112 if (vf_path == NULL)
113 return -1;
114
115
116 if (vf_debug('f'))
117 printf("VFlib Virtual Font: font file %s\n ==> %s\n",
118 font_vf->font_file, vf_path);
119
120
121 tfm_path = vf_tex_search_file_tfm(font_vf->font_file,
122 default_tfm_dirs, default_tfm_extensions);
123 if (tfm_path == NULL){
124 vf_free(vf_path);
125 return -1;
126 }
127
128 if (vf_debug('f'))
129 printf("VFlib Virtual Font: TFM font file %s\n ==> %s\n",
130 font_vf->font_file, tfm_path);
131
132 if ((vf_path == NULL) || (tfm_path == NULL)){
133 vf_free(vf_path);
134 vf_free(tfm_path);
135 return -1;
136 }
137
138 if (((dpi_x = font->dpi_x) < 0) || ((dpi_y = font->dpi_y) < 0)){
139 if (((dpi_x = font_vf->dpi_x) < 0) || (dpi_x = font_vf->dpi_x)){
140 dpi_x = dpi_y = vf_tex_default_dpi();
141 }
142 }
143
144 ALLOC_IF_ERR(vf, struct s_vf){
145 vf_error = VF_ERR_NO_MEMORY;
146 return -1;
147 }
148 vf->vf_path = vf_path;
149 vf->cs = 0;
150 vf->ds = 0;
151 vf->design_size = 0;
152 vf->dpi_x = dpi_x;
153 vf->dpi_y = dpi_y;
154 vf->mag_x = font->mag_x * font_vf->mag;
155 vf->mag_y = font->mag_y * font_vf->mag;
156 vf->tfm_path = tfm_path;
157 vf->tfm = NULL;
158 vf->subfonts = NULL;
159 vf->subfonts_opened = 1;
160 vf->offs_char_packet = 0;
161
162 if ((vf->tfm = vf_tfm_open(vf->tfm_path)) == NULL)
163 goto Error;
164
165 if ((fp = vf_fm_OpenBinaryFileStream(vf->vf_path)) == NULL){
166 if (vf_error != VF_ERR_NO_MEMORY)
167 vf_error = VF_ERR_NO_FONT_FILE;
168 goto Error;
169 }
170
171 if (vf_read_info(vf, fp, font_vf->open_style, font) < 0){
172 vf_error = VF_ERR_ILL_FONT_FILE;
173 goto Error;
174 }
175
176 if ((vf_id = (vf_font_table->put)(vf_font_table, vf,
177 key, strlen(key)+1)) < 0){
178 vf_error = VF_ERR_NO_MEMORY;
179 goto Error;
180 }
181
182 return vf_id;
183
184
185 Error:
186 if (vf != NULL){
187 vf_free(vf->vf_path);
188 vf_free(vf->tfm_path);
189 vf_tfm_free(vf->tfm);
190 vf_free(vf);
191 }
192 return -1;
193 }
194
195
196 Private int
197 vf_read_info(VF vf, FILE *fp, int open_style, VF_FONT font)
/* [<][>][^][v][top][bottom][index][help] */
198 {
199 UINT1 id, a, l;
200 UINT4 k, c, s, d;
201 VF_SUBFONT sf, sf0, sf_next;
202 struct s_vf_subfont subfont;
203 double scale;
204 int fid, name_len, i;
205 char subfont_name[1024];
206
207 if (READ_UINT1(fp) != VFINST_PRE)
208 return -1;
209 id = READ_UINT1(fp);
210 switch (id){
211 case VFINST_ID_BYTE:
212 break;
213 default:
214 return -1;
215 }
216
217 k = READ_UINT1(fp);
218 SKIP_N(fp,k);
219
220 vf->cs = READ_UINT4(fp);
221 vf->ds = READ_UINT4(fp);
222 if ((vf->cs != vf->tfm->cs) || (vf->ds != vf->tfm->ds)){
223 vf_error = VF_ERR_ILL_FONT_FILE;
224 return -1;
225 }
226
227 vf->design_size = (double)(vf->ds)/(double)(1<<20);
228 vf->subfonts_opened = 1;
229 vf->default_subfont = -1;
230
231 subfont.next = NULL;
232 for (sf0 = &subfont; ; sf0 = sf){
233 ALLOC_IF_ERR(sf, struct s_vf_subfont){
234 vf_error = VF_ERR_NO_MEMORY;
235 goto error_exit;
236 }
237 sf0->next = sf;
238 switch (READ_UINT1(fp)){
239 default:
240 vf->offs_char_packet = ftell(fp)-1;
241 sf0->next = NULL;
242 vf_free(sf);
243 goto end_fontdef;
244 case VFINST_FNTDEF1:
245 k = (UINT4)READ_UINT1(fp);
246 c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
247 a = READ_UINT1(fp); l = READ_UINT1(fp);
248 break;
249 case VFINST_FNTDEF2:
250 k = (UINT4)READ_UINT2(fp);
251 c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
252 a = READ_UINT1(fp); l = READ_UINT1(fp);
253 break;
254 case VFINST_FNTDEF3:
255 k = (UINT4)READ_UINT3(fp);
256 c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
257 a = READ_UINT1(fp); l = READ_UINT1(fp);
258 break;
259 case VFINST_FNTDEF4:
260 k = (UINT4)READ_UINT4(fp);
261 c = READ_UINT4(fp); s = READ_UINT4(fp); d = READ_UINT4(fp);
262 a = READ_UINT1(fp); l = READ_UINT1(fp);
263 break;
264 }
265
266 name_len = a + l;
267 sf->k = k;
268 sf->s = s;
269 sf->d = d;
270 sf->a = a;
271 sf->l = l;
272 sf->next = NULL;
273
274 scale = (double)sf->s/(double)(1<<20);
275
276 if ((sf->n = (char*)malloc(name_len + 1)) == NULL){
277 vf_error = VF_ERR_NO_MEMORY;
278 goto error_exit;
279 }
280 for (i = 0; i < name_len; i++)
281 sf->n[i] = (char)READ_UINT1(fp);
282 sf->n[i] = '\0';
283
284
285 sprintf(subfont_name, "%s", &sf->n[sf->a]);
286
287 if (vf_debug('s')){
288 printf("VFlib Virtual Font: subfont %d: %s, scaled %f\n",
289 (int)sf->k, subfont_name, scale);
290 }
291
292 if (open_style != TEX_OPEN_STYLE_NONE){
293 fid = vf_tex_try_map_and_open_font(font, subfont_name,
294 default_font_mapping,
295 vf->tfm->design_size, NULL, NULL,
296 scale);
297 if (fid >= 0){
298 sf->font_id = fid;
299 if (vf->default_subfont < 0)
300 vf->default_subfont = sf->k;
301 if (vf_debug('s'))
302 printf("VFlib Virtual Font: subfont is opened: font id %d\n", fid);
303 } else {
304 sf->font_id = -1;
305 vf->subfonts_opened = 0;
306 if (vf_debug('s'))
307 printf("VFlib Virtual Font: subfont %d is not opened\n", (int)sf->k);
308 }
309 } else {
310 if (vf_debug('s'))
311 printf("VFlib Virtual Font: subfont %d is not requested to open\n",
312 (int)sf->k);
313 }
314 }
315
316 end_fontdef:
317 if (vf->subfonts_opened == 0){
318 if (open_style == TEX_OPEN_STYLE_REQUIRE){
319 if (vf_debug('s'))
320 printf("VFlib Virtual Font: all subfonts are required but failed\n");
321 goto error_exit;
322 } else {
323 if (vf_debug('s'))
324 printf("VFlib Virtual Font: not all fonts are opened; continue.\n");
325 }
326 }
327
328 vf->subfonts = subfont.next;
329 return 0;
330
331
332 error_exit:
333 for (sf = subfont.next; sf != NULL; sf = sf_next){
334 sf_next = sf->next;
335 vf_free(sf->n);
336 vf_free(sf);
337 }
338 vf->subfonts = NULL;
339 return -1;
340 }
341
342
343 Private void
344 vf_vf_close(int vf_id)
/* [<][>][^][v][top][bottom][index][help] */
345 {
346 VF vf;
347 VF_SUBFONT sf, sf_next;
348
349 vf = vf_vf_get_vf(vf_id);
350
351 if ((vf_font_table->unlink_by_id)(vf_font_table, vf_id) > 0)
352 return;
353
354 if (vf != NULL){
355 vf_free(vf->vf_path);
356 vf_free(vf->tfm_path);
357 vf_tfm_free(vf->tfm);
358 for (sf = vf->subfonts; sf != NULL; sf = sf_next){
359 sf_next = sf->next;
360 vf_free(sf->n);
361 vf_free(sf);
362 }
363 }
364
365 vf_vf_get_vf(-1);
366 vf_free(vf);
367 }
368
369
370 Private double
371 vf_vf_get_design_size(int vf_id)
/* [<][>][^][v][top][bottom][index][help] */
372 {
373 VF vf;
374
375 vf = vf_vf_get_vf(vf_id);
376 if ((vf == NULL) || (vf->tfm == NULL)){
377 fprintf(stderr, "VFlib internal error in vf_vf_get_design_size()\n");
378 abort();
379 }
380 return vf->tfm->design_size;
381 }
382
383
384 #if 0
385 static VF last_vf = NULL;
386 static int last_vf_id = -1;
387 #endif
388
389 Private VF
390 vf_vf_get_vf(int vf_id)
/* [<][>][^][v][top][bottom][index][help] */
391 {
392 VF vf;
393
394 #if 1
395 vf = NULL;
396 if (vf_id >= 0)
397 vf = (vf_font_table->get_obj_by_id)(vf_font_table, vf_id);
398 #else
399 if (vf_id < 0){
400 last_vf = NULL;
401 last_vf_id = -1;
402 return NULL;
403 }
404
405 if (vf_id == last_vf_id){
406 vf = last_vf;
407 } else {
408 vf = (vf_font_table->get_obj_by_id)(vf_font_table, vf_id);
409 if (vf != NULL){
410 last_vf = vf;
411 last_vf_id = vf_id;
412 } else {
413 last_vf = NULL;
414 last_vf_id = -1;
415 }
416 }
417 #endif
418
419 return vf;
420 }
421
422
423
424
425 Private VF_CHAR_PACKET_TBL
426 vf_cache_loader(VF_CACHE c, VF_CACHE_KEY ck, int l)
/* [<][>][^][v][top][bottom][index][help] */
427 {
428 VF_CHAR_PACKET_TBL vf_char_packets;
429 VF_CHAR_PACKET packets;
430 int npackets, ch;
431 FILE *fp;
432 int b;
433 long n;
434 unsigned char *cp;
435
436 #if 0
437 printf("* VF cache_load %s\n", ck->font_path);
438 #endif
439 npackets = ck->tfm->end_char - ck->tfm->begin_char + 1;
440
441 if (ck->font_path == NULL)
442 return NULL;
443 if ((fp = vf_fm_OpenBinaryFileStream(ck->font_path)) == NULL)
444 return NULL;
445
446 ALLOC_IF_ERR(vf_char_packets, struct s_vf_char_packet_tbl){
447 vf_error = VF_ERR_NO_MEMORY;
448 return NULL;
449 }
450 ALLOCN_IF_ERR(packets, struct s_vf_char_packet,
451 npackets+1){ /* one more element for sentinel.
452 See vf_get_bitmap(). */
453 vf_free(vf_char_packets);
454 vf_error = VF_ERR_NO_MEMORY;
455 return NULL;
456 }
457 vf_char_packets->npackets = npackets;
458 vf_char_packets->packets = packets;
459 for (ch = 0; ch < npackets; ch++){
460 vf_char_packets->packets[ch].pl = 0;
461 vf_char_packets->packets[ch].cc = 0;
462 vf_char_packets->packets[ch].tfm = 0;
463 vf_char_packets->packets[ch].dvi = NULL;
464 }
465
466 fseek(fp, ck->offs_char_packet, SEEK_SET);
467 for (ch = 0; ch < npackets; ch++){
468 b = (int)READ_UINT1(fp);
469 if (((int)VFINST_CP_SHORT_CHAR0 <= b)
470 && (b <= (int)VFINST_CP_SHORT_CHAR241)){
471 vf_char_packets->packets[ch].pl = (UINT4)b;
472 vf_char_packets->packets[ch].cc = (UINT4)READ_UINT1(fp);
473 vf_char_packets->packets[ch].tfm = (UINT4)READ_UINT3(fp);
474 } else if (b == (int)VFINST_CP_LONG_CHAR){
475 vf_char_packets->packets[ch].pl = READ_UINT4(fp);
476 vf_char_packets->packets[ch].cc = READ_UINT4(fp);
477 vf_char_packets->packets[ch].tfm = READ_UINT4(fp);
478 } else if (b == VFINST_POST){
479 break;
480 } else {
481 fprintf(stderr, "VFlib warning: Broken VF file: %s\n", ck->font_path);
482 break;
483 }
484 #if 0
485 printf(" 0x%02x: pl 0x%04lx: cc 0x%04lx\n", b,
486 vf_char_packets->packets[ch].pl,
487 vf_char_packets->packets[ch].cc);
488 #endif
489
490 if (vf_char_packets->packets[ch].pl > 0){
491 vf_char_packets->packets[ch].dvi
492 = (unsigned char*)malloc(vf_char_packets->packets[ch].pl);
493 if (vf_char_packets->packets[ch].dvi == NULL){
494 vf_free(vf_char_packets->packets);
495 vf_free(vf_char_packets);
496 vf_error = VF_ERR_NO_MEMORY;
497 return NULL;
498 }
499 n = vf_char_packets->packets[ch].pl;
500 for (cp = vf_char_packets->packets[ch].dvi; n > 0; cp++, n--)
501 *cp = READ_UINT1(fp);
502 }
503 }
504
505 return vf_char_packets;
506 }
507
508
509 Private void
510 vf_cache_disposer(VF_CHAR_PACKET_TBL vf_char_packets)
/* [<][>][^][v][top][bottom][index][help] */
511 {
512 int ch;
513
514 #if 0
515 printf("* VF cache_disposer\n");
516 #endif
517 if (vf_char_packets != NULL){
518 if (vf_char_packets->packets != NULL){
519 for (ch = vf_char_packets->npackets-1; ch >= 0; ch--)
520 vf_free(vf_char_packets->packets[ch].dvi);
521 }
522 vf_free(vf_char_packets->packets);
523 }
524 vf_free(vf_char_packets);
525 }
526
527
528 Private int
529 vf_vf_get_metric(int vf_id, long code_point, VF_METRIC1 met,
/* [<][>][^][v][top][bottom][index][help] */
530 double *ret_design_size)
531 {
532 VF vf;
533 struct vf_s_metric1 metric1;
534
535 if ( ((vf = vf_vf_get_vf(vf_id)) == NULL)
536 || (vf->tfm == NULL) ){
537 fprintf(stderr, "VFlib internal error in vf_vf_get_metric()\n");
538 abort();
539 }
540
541 if (ret_design_size != NULL)
542 *ret_design_size = vf->tfm->design_size;
543
544 if (met == NULL)
545 met = &metric1;
546
547 if (vf_tfm_metric(vf->tfm, code_point, met) == NULL)
548 return -1;
549
550 return 0;
551 }
552
553 Private VF_BITMAP
554 vf_vf_get_bitmap(int vf_id, int mode, long code_point,
/* [<][>][^][v][top][bottom][index][help] */
555 double mag_x, double mag_y,
556 int open_style, int glyph_style)
557 {
558 VF vf;
559 VF_BITMAP bm;
560 VF_CHAR_PACKET_TBL cptbl;
561 struct vf_s_metric1 met1;
562 struct vf_s_metric2 met2;
563 struct s_vf_cache_key ck;
564 int idx;
565
566 if ( ((vf = vf_vf_get_vf(vf_id)) == NULL)
567 || (vf->tfm == NULL) ){
568 fprintf(stderr, "VFlib internal error in vf_vf_get_bitmap()\n");
569 abort();
570 }
571
572 switch (open_style){
573 default:
574 case TEX_OPEN_STYLE_NONE:
575 if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL)
576 return NULL;
577 #if 0 /*XXX*/
578 bm = vf_alloc_bitmap_with_metric1(&met1,
579 vf->dpi_x * vf->mag_x * mag_x,
580 vf->dpi_y * vf->mag_y * mag_y);
581 #else
582 bm = vf_alloc_bitmap_with_metric1(&met1,
583 vf->dpi_x * mag_x,
584 vf->dpi_y * mag_y);
585 #endif
586 vf_do_glyph_style(bm, glyph_style);
587 return bm;
588 case TEX_OPEN_STYLE_TRY:
589 if (vf->subfonts_opened == 0){
590 if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL)
591 return NULL;
592 #if 0 /*XXX*/
593 bm = vf_alloc_bitmap_with_metric1(&met1,
594 vf->dpi_x * vf->mag_x * mag_x,
595 vf->dpi_y * vf->mag_y * mag_y);
596 #else
597 bm = vf_alloc_bitmap_with_metric1(&met1,
598 vf->dpi_x * mag_x,
599 vf->dpi_y * mag_y);
600 #endif
601 vf_do_glyph_style(bm, glyph_style);
602 return bm;
603 }
604 break;
605 case TEX_OPEN_STYLE_REQUIRE:
606 if (vf->subfonts_opened == 0)
607 return NULL;
608 break;
609 }
610
611 ck.font_path = vf->vf_path;
612 ck.tfm = vf->tfm;
613 ck.offs_char_packet = vf->offs_char_packet;
614 if ((cptbl = (vf_font_cache->get)(vf_font_cache, &ck, sizeof(ck))) == NULL)
615 return NULL;
616
617 idx = 0;
618 cptbl->packets[cptbl->npackets].cc = code_point; /* sentinel */
619 while ((long)cptbl->packets[idx].cc != code_point)
620 idx++;
621
622 if (idx == cptbl->npackets){
623 vf_error = VF_ERR_ILL_CODE_POINT;
624 return NULL;
625 }
626
627 bm = vf_run_dvi_program(vf, &cptbl->packets[idx], mode, mag_x, mag_y);
628 if (bm != NULL){
629 if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL){
630 VF_FreeBitmap(bm);
631 return NULL;
632 }
633 #if 0 /*XXX*/
634 vf_metric1_to_metric2(&met1, (double)vf->dpi_y * vf->mag_y * mag_y, &met2);
635 #else
636 vf_metric1_to_metric2(&met1, (double)vf->dpi_y * mag_y, &met2);
637 #endif
638 bm->mv_x = met2.mv_x;
639 bm->mv_y = met2.mv_y;
640 } else {
641 if (vf_tfm_metric(vf->tfm, code_point, &met1) == NULL)
642 return NULL;
643 #if 0 /*XXX*/
644 bm = vf_alloc_bitmap_with_metric1(&met1,
645 vf->dpi_x * vf->mag_x * mag_x,
646 vf->dpi_y * vf->mag_y * mag_y);
647 #else
648 bm = vf_alloc_bitmap_with_metric1(&met1,
649 vf->dpi_x * mag_x,
650 vf->dpi_y * mag_y);
651 #endif
652 vf_do_glyph_style(bm, glyph_style);
653 }
654
655 return bm;
656 }
657
658 Private void
659 vf_do_glyph_style(VF_BITMAP bm, int glyph_style)
/* [<][>][^][v][top][bottom][index][help] */
660 {
661 switch (glyph_style){
662 default:
663 case TEX_GLYPH_STYLE_EMPTY:
664 break;
665 case TEX_GLYPH_STYLE_FILL:
666 VF_FillBitmap(bm);
667 break;
668 }
669 }
670
671
672 Private VF_BITMAP
673 vf_run_dvi_program(VF vf, VF_CHAR_PACKET packet,
/* [<][>][^][v][top][bottom][index][help] */
674 int mode, double mag_x, double mag_y)
675 {
676 struct vf_s_bitmaplist the_bmlist;
677 VF_BITMAP bm;
678
679 vf_bitmaplist_init(&the_bmlist);
680 vf_dvi_interp(&the_bmlist, vf, mode, mag_x, mag_y, packet->dvi, packet->pl);
681 bm = vf_bitmaplist_compose(&the_bmlist);
682 vf_bitmaplist_finish(&the_bmlist);
683
684 return bm;
685 }
686
687 Private int
688 vf_dvi_interp(VF_BITMAPLIST bmlist, VF vf,
/* [<][>][^][v][top][bottom][index][help] */
689 int mode, double mag_x, double mag_y,
690 unsigned char *dvi_prog, int prog_len)
691 {
692 int pc, instr, n, ret;
693 long code_point, h, w, f, length;
694 double fmag;
695 double r_mv_x, r_mv_y;
696 struct vf_s_metric1 met, *m;
697 struct s_vf_dvi_stack the_dvi_stack, *dvi_stack;
698
699 fmag = 1.0;
700 dvi_stack = &the_dvi_stack;
701 vf_dvi_stack_init(vf, dvi_stack);
702
703 pc = 0;
704 ret = 0;
705 while (pc < prog_len){
706 if (vf_debug('d')){
707 printf("VFlib Virtual Font\n ");
708 printf("DVI CODE PC=0x%04x: INSTR=0x%02x (%d) H=0x%08x V=0x%08x\n",
709 pc, (int)dvi_prog[pc], (int)dvi_prog[pc],
710 (int)STACK(h), (int)STACK(v));
711 }
712 instr = (int)dvi_prog[pc++];
713 if (instr <= VFINST_SET4){ /* SETCHAR0 ... SETCHAR127, SET1, ... ,SET4 */
714 if ((code_point = instr) > VFINST_SETCHAR127){
715 n = instr - VFINST_SET1 + 1;
716 code_point = GET_UINTN(&dvi_prog[pc], n);
717 pc += n;
718 }
719 vf_dvi_interp_put_char(bmlist, vf, dvi_stack, code_point,
720 mode, fmag * mag_x, fmag * mag_y);
721 m = VF_GetMetric1(STACK(font_id), code_point, &met,
722 fmag * mag_x, fmag * mag_y);
723 if (m == NULL)
724 continue;
725 r_mv_x = (met.mv_x / vf->design_size) * (double)(1<<20);
726 r_mv_y = (met.mv_y / vf->design_size) * (double)(1<<20);
727 STACK(h) = STACK(h) + toint(r_mv_x);
728 STACK(v) = STACK(v) + toint(r_mv_y);
729 } else if ((VFINST_FNTNUM0 <= instr) && (instr <= (VFINST_FNTNUM63))){
730 f = instr - VFINST_FNTNUM0;
731 vf_dvi_interp_font_select(vf, dvi_stack, f, &fmag);
732 } else {
733 switch (instr){
734 case VFINST_PUT1: case VFINST_PUT2: case VFINST_PUT3: case VFINST_PUT4:
735 n = instr - VFINST_SET1 + 1;
736 code_point = (UINT4)GET_UINTN(&dvi_prog[pc], n); pc += n;
737 vf_dvi_interp_put_char(bmlist, vf, dvi_stack, code_point,
738 mode, fmag * mag_x, fmag * mag_y);
739 break;
740 case VFINST_SETRULE:
741 h = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
742 w = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
743 vf_dvi_interp_put_rule(bmlist, vf, dvi_stack, w, h, mag_x, mag_y);
744 STACK(h) += w;
745 break;
746 case VFINST_PUTRULE:
747 h = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
748 w = (long)GET_INT4(&dvi_prog[pc]); pc += 4;
749 vf_dvi_interp_put_rule(bmlist, vf, dvi_stack, w, h, mag_x, mag_y);
750 break;
751 case VFINST_RIGHT1: case VFINST_RIGHT2:
752 case VFINST_RIGHT3: case VFINST_RIGHT4:
753 n = instr - VFINST_RIGHT1 + 1;
754 STACK(h) += (long)GET_INTN(&dvi_prog[pc], n); pc += n;
755 break;
756 case VFINST_X1: case VFINST_X2: case VFINST_X3: case VFINST_X4:
757 n = instr - VFINST_X0;
758 STACK(x) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
759 case VFINST_X0:
760 STACK(h) += STACK(x);
761 break;
762 case VFINST_W1: case VFINST_W2: case VFINST_W3: case VFINST_W4:
763 n = instr - VFINST_W0;
764 STACK(w) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
765 case VFINST_W0:
766 STACK(h) += STACK(w);
767 break;
768 case VFINST_Y1: case VFINST_Y2: case VFINST_Y3: case VFINST_Y4:
769 n = instr - VFINST_Y0;
770 STACK(y) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
771 case VFINST_Y0:
772 STACK(v) += STACK(y);
773 break;
774 case VFINST_Z1: case VFINST_Z2: case VFINST_Z3: case VFINST_Z4:
775 n = instr - VFINST_Z0;
776 STACK(z) = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
777 case VFINST_Z0:
778 STACK(v) += STACK(z);
779 break;
780 case VFINST_DOWN1: case VFINST_DOWN2:
781 case VFINST_DOWN3: case VFINST_DOWN4:
782 n = instr - VFINST_DOWN1 + 1;
783 STACK(v) += (long)GET_INTN(&dvi_prog[pc], n);
784 break;
785 case VFINST_XXX1: case VFINST_XXX2: case VFINST_XXX3: case VFINST_XXX4:
786 n = instr - VFINST_XXX1 + 1;
787 length = (long)GET_INTN(&dvi_prog[pc], n); pc += n;
788 pc += length;
789 break;
790 case VFINST_FNT1: case VFINST_FNT2: case VFINST_FNT3: case VFINST_FNT4:
791 n = instr - VFINST_FNT1 + 1;
792 f = GET_UINTN(&dvi_prog[pc], n); pc += n;
793 vf_dvi_interp_font_select(vf, dvi_stack, f, &fmag);
794 break;
795 case VFINST_PUSH:
796 vf_dvi_stack_push(vf, dvi_stack);
797 break;
798 case VFINST_POP:
799 vf_dvi_stack_pop(vf, dvi_stack);
800 break;
801 case VFINST_NOP:
802 break;
803 default:
804 vf_error = VF_ERR_ILL_FONT_FILE;
805 ret = -1;
806 goto ExitInterp;
807 }
808 }
809 }
810
811 ExitInterp:
812 vf_dvi_stack_deinit(vf, dvi_stack);
813 return ret;
814 }
815
816 Private void
817 vf_dvi_interp_put_char(VF_BITMAPLIST bmlist, VF vf, VF_DVI_STACK dvi_stack,
/* [<][>][^][v][top][bottom][index][help] */
818 long code_point, int mode, double mag_x, double mag_y)
819 {
820 VF_BITMAP bm;
821 double rx, ry, ds;
822 long off_x, off_y;
823
824 if (STACK(font_id) < 0)
825 return;
826 if (mode == 1){
827 bm = VF_GetBitmap1(STACK(font_id), code_point, mag_x, mag_y);
828 } else {
829 bm = VF_GetBitmap2(STACK(font_id), code_point, mag_x, mag_y);
830 }
831 #if 0
832 printf("** VF_GetBitmap(%d, 0x%lx, %.2f %.2f) = %p\n",
833 STACK(font_id), code_point, mag_x, mag_y, bm);
834 VF_DumpBitmap(bm);
835 #endif
836 if (bm == NULL)
837 return;
838
839 ds = vf->design_size / (double)(1<<20);
840 #if 0 /*XXX*/
841 rx = vf->mag_x * mag_x * (vf->dpi_x/72.27) * ds;
842 ry = vf->mag_y * mag_y * (vf->dpi_y/72.27) * ds;
843 #else
844 rx = (vf->dpi_x/72.27) * ds;
845 ry = (vf->dpi_y/72.27) * ds;
846 #endif
847 off_x = rx * (double)STACK(h);
848 off_y = -ry * (double)STACK(v);
849
850 vf_bitmaplist_put(bmlist, bm, off_x, off_y);
851 }
852
853 Private void
854 vf_dvi_interp_put_rule(VF_BITMAPLIST bmlist, VF vf, VF_DVI_STACK dvi_stack,
/* [<][>][^][v][top][bottom][index][help] */
855 long w, long h, double mag_x, double mag_y)
856 {
857 VF_BITMAP bm;
858 double rx, ry, ds;
859 int bm_w, bm_h;
860 long off_x, off_y;
861
862 ds = vf->design_size / (double)(1<<20);
863 rx = vf->mag_x * mag_x * vf->dpi_x/72.27 * ds;
864 ry = vf->mag_y * mag_y * vf->dpi_y/72.27 * ds;
865
866 bm_w = rx * w;
867 bm_h = ry * h;
868 if (bm_w <= 0)
869 bm_w = 1;
870 if (bm_h <= 0)
871 bm_h = 1;
872
873 bm = vf_alloc_bitmap(bm_w, bm_h);
874 if (bm == NULL)
875 return;
876 VF_FillBitmap(bm);
877
878 bm->off_x = 0;
879 bm->off_y = bm_h - 1;
880 off_x = rx * (double)STACK(h);
881 off_y = -ry * (double)STACK(v);
882
883 vf_bitmaplist_put(bmlist, bm, off_x, off_y);
884 }
885
886 Private void
887 vf_dvi_interp_font_select(VF vf, VF_DVI_STACK dvi_stack, long f,
/* [<][>][^][v][top][bottom][index][help] */
888 double *fmag_p)
889 {
890 VF_SUBFONT sf;
891
892 STACK(f) = f;
893 STACK(font_id) = -1;
894 for (sf = vf->subfonts; sf != NULL; sf = sf->next){
895 if (sf->k == f){
896 STACK(font_id) = sf->font_id;
897 if (fmag_p != NULL)
898 *fmag_p = 1;
899 break;
900 }
901 }
902 }
903
904
905 Private int
906 vf_dvi_stack_init(VF vf, VF_DVI_STACK stack)
/* [<][>][^][v][top][bottom][index][help] */
907 {
908 VF_DVI_STACK top;
909
910 ALLOC_IF_ERR(top, struct s_vf_dvi_stack){
911 vf_error = VF_ERR_NO_MEMORY;
912 return -1;
913 }
914 top->h = top->v = top->w = top->x = top->y = top->z = 0;
915 top->f = vf->default_subfont;
916 top->font_id = vf->subfonts->font_id;
917 top->next = NULL;
918 stack->next = top;
919 return 0;
920 }
921
922 Private int
923 vf_dvi_stack_deinit(VF vf, VF_DVI_STACK stack)
/* [<][>][^][v][top][bottom][index][help] */
924 {
925 VF_DVI_STACK elem, elem_next;
926
927 elem = stack->next;
928 while (elem != NULL){
929 elem_next = elem->next;
930 vf_free(elem);
931 elem = elem_next;
932 }
933 return 0;
934 }
935
936 Private int
937 vf_dvi_stack_push(VF vf, VF_DVI_STACK stack)
/* [<][>][^][v][top][bottom][index][help] */
938 {
939 VF_DVI_STACK new_elem, top;
940
941 ALLOC_IF_ERR(new_elem, struct s_vf_dvi_stack){
942 vf_error = VF_ERR_NO_MEMORY;
943 return -1;
944 }
945
946 top = stack->next;
947 new_elem->h = top->h;
948 new_elem->v = top->v;
949 new_elem->w = top->w;
950 new_elem->x = top->x;
951 new_elem->y = top->y;
952 new_elem->z = top->z;
953 new_elem->f = top->f;
954 new_elem->font_id = top->font_id;
955 new_elem->next = top;
956 stack->next = new_elem;
957
958 return 0;
959 }
960
961 Private int
962 vf_dvi_stack_pop(VF vf, VF_DVI_STACK stack)
/* [<][>][^][v][top][bottom][index][help] */
963 {
964 VF_DVI_STACK top;
965
966 top = stack->next;
967 if (top == NULL){
968 fprintf(stderr, "VFlib warning: VF DVI stack under flow: %s\n",
969 vf->vf_path);
970 return -1;
971 }
972
973 stack->next = top->next;
974 vf_free(top);
975
976 return 0;
977 }
978
979
980 /*EOF*/