1 /* $XConsortium: sptobdf.c,v 1.5 94/04/17 20:17:51 dpw Exp $ */
2 /*
3  * Copyright 1990, 1991 Network Computing Devices;
4  * Portions Copyright 1987 by Digital Equipment Corporation
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the names of Network Computing Devices and
11  * Digital not be used in advertising or publicity pertaining to
12  * distribution of the software without specific, written prior permission.
13  * Network Computing Devices and Digital make no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
18  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19  * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES OR DIGITAL BE
20  * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  * Dave Lemke
26  */
27 
28 /*
29 
30 Copyright (c) 1987, 1994  X Consortium
31 
32 Permission is hereby granted, free of charge, to any person obtaining
33 a copy of this software and associated documentation files (the
34 "Software"), to deal in the Software without restriction, including
35 without limitation the rights to use, copy, modify, merge, publish,
36 distribute, sublicense, and/or sell copies of the Software, and to
37 permit persons to whom the Software is furnished to do so, subject to
38 the following conditions:
39 
40 The above copyright notice and this permission notice shall be included
41 in all copies or substantial portions of the Software.
42 
43 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
44 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
45 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
46 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
47 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
48 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
49 OTHER DEALINGS IN THE SOFTWARE.
50 
51 Except as contained in this notice, the name of the X Consortium shall
52 not be used in advertising or otherwise to promote the sale, use or
53 other dealings in this Software without prior written authorization
54 from the X Consortium.
55 
56 */
57 
58 /*
59  * Speedo outline to BFD format converter
60  */
61 
62 #include	<stdio.h>
63 #include	"speedo.h"
64 
65 #ifdef EXTRAFONTS
66 #include	"ncdkeys.h"
67 #else
68 #include	"keys.h"
69 #endif
70 
71 #include	"iso8859.h"
72 
73 #define	MAX_BITS	1024
74 
75 #define	BBOX_CLIP
76 
77 static char line_of_bits[MAX_BITS + 1];
78 
79 static FILE *fp;
80 static ufix16 char_index,
81             char_id;
82 static buff_t font;
83 static buff_t char_data;
84 static ufix8 *f_buffer,
85            *c_buffer;
86 static ufix16 mincharsize;
87 static fix15 cur_y;
88 static fix15 bit_width,
89             bit_height;
90 
91 static ufix8 key[] =
92 {
93     KEY0,
94     KEY1,
95     KEY2,
96     KEY3,
97     KEY4,
98     KEY5,
99     KEY6,
100     KEY7,
101     KEY8
102 };				/* Font decryption key */
103 
104 
105 static char *progname;
106 static char *fontname = NULL;
107 static char *fontfile = NULL;
108 
109 static int  point_size = 120;
110 static int  x_res = 72;
111 static int  y_res = 72;
112 static int  quality = 0;
113 static int  iso_encoding = 1;
114 
115 static int  num_props = 7;
116 static int  stretch = 120;
117 
118 static specs_t specs;
119 
120 static void dump_header();
121 
122 static void
usage()123 usage()
124 {
125     fprintf(stderr, "Usage: %s [-xres x resolution] [-yres y resolution]\n\t[-ptsize pointsize] [-fn fontname] [-q quality (0-1)] fontfile\n", progname);
126     fprintf(stderr, "Where:\n");
127     fprintf(stderr, "-xres specifies the X resolution (72)\n");
128     fprintf(stderr, "-yres specifies the Y resolution (72)\n");
129     fprintf(stderr, "-pts specifies the pointsize in decipoints (120)\n");
130     fprintf(stderr, "-fn specifies the font name (full Bitstream name)\n");
131     fprintf(stderr, "-q specifies the font quality [0-1] (0)\n");
132     fprintf(stderr, "\n");
133     exit(0);
134 }
135 
136 static      fix15
read_2b(ptr)137 read_2b(ptr)
138     ufix8      *ptr;
139 {
140     fix15       tmp;
141 
142     tmp = *ptr++;
143     tmp = (tmp << 8) + *ptr;
144     return tmp;
145 }
146 
147 static      fix31
read_4b(ptr)148 read_4b(ptr)
149     ufix8      *ptr;
150 {
151     fix31       tmp;
152 
153     tmp = *ptr++;
154     tmp = (tmp << 8) + *ptr++;
155     tmp = (tmp << 8) + *ptr++;
156     tmp = (tmp << 8) + *ptr;
157     return tmp;
158 }
159 
160 static void
process_args(ac,av)161 process_args(ac, av)
162     int         ac;
163     char      **av;
164 {
165     int         i;
166 
167     for (i = 1; i < ac; i++) {
168 	if (!strncmp(av[i], "-xr", 3)) {
169 	    if (av[i + 1]) {
170 		x_res = atoi(av[++i]);
171 	    } else
172 		usage();
173 	} else if (!strncmp(av[i], "-yr", 3)) {
174 	    if (av[i + 1]) {
175 		y_res = atoi(av[++i]);
176 	    } else
177 		usage();
178 	} else if (!strncmp(av[i], "-pt", 3)) {
179 	    if (av[i + 1]) {
180 		point_size = atoi(av[++i]);
181 	    } else
182 		usage();
183 	} else if (!strncmp(av[i], "-fn", 3)) {
184 	    if (av[i + 1]) {
185 		fontname = av[++i];
186 	    } else
187 		usage();
188 	} else if (!strncmp(av[i], "-q", 2)) {
189 	    if (av[i + 1]) {
190 		quality = atoi(av[++i]);
191 	    } else
192 		usage();
193 	} else if (!strncmp(av[i], "-st", 3)) {
194 	    if (av[i + 1]) {
195 		stretch = atoi(av[++i]);
196 	    } else
197 		usage();
198 	} else if (!strncmp(av[i], "-noni", 5)) {
199 	    iso_encoding = 0;
200 	} else if (*av[i] == '-') {
201 	    usage();
202 	} else
203 	    fontfile = av[i];
204     }
205     if (!fontfile)
206 	usage();
207 }
208 
209 void
main(argc,argv)210 main(argc, argv)
211     int         argc;
212     char      **argv;
213 {
214     ufix32      i;
215     ufix8       tmp[16];
216     ufix32      minbufsize;
217     ufix16      cust_no;
218     int         first_char_index,
219                 num_chars;
220 
221     progname = argv[0];
222     process_args(argc, argv);
223     fp = fopen(fontfile, "r");
224     if (!fp) {
225 	fprintf(stderr, "No such font file, \"%s\"\n", fontfile);
226 	exit(-1);
227     }
228     if (fread(tmp, sizeof(ufix8), 16, fp) != 16) {
229 	fprintf(stderr, "error reading \"%s\"\n", fontfile);
230 	exit(-1);
231     }
232     minbufsize = (ufix32) read_4b(tmp + FH_FBFSZ);
233     f_buffer = (ufix8 *) malloc(minbufsize);
234     if (!f_buffer) {
235 	fprintf(stderr, "can't get %x bytes of memory\n", minbufsize);
236 	exit(-1);
237     }
238     fseek(fp, (ufix32) 0, 0);
239 
240     if (fread(f_buffer, sizeof(ufix8), (ufix16) minbufsize, fp) != minbufsize) {
241 	fprintf(stderr, "error reading file \"%s\"\n", fontfile);
242 	exit(-1);
243     }
244     mincharsize = read_2b(f_buffer + FH_CBFSZ);
245 
246     c_buffer = (ufix8 *) malloc(mincharsize);
247     if (!c_buffer) {
248 	fprintf(stderr, "can't get %x bytes for char buffer\n", mincharsize);
249 	exit(-1);
250     }
251     /* init */
252     sp_reset();
253 
254     font.org = f_buffer;
255     font.no_bytes = minbufsize;
256 
257     if ((cust_no = sp_get_cust_no(font)) != CUS0) {
258 	fprintf(stderr, "Non-standard encryption for \"%s\"\n", fontfile);
259 	exit(-1);
260     }
261     sp_set_key(key);
262 
263     first_char_index = read_2b(f_buffer + FH_FCHRF);
264     num_chars = read_2b(f_buffer + FH_NCHRL);
265 
266     /* set up specs */
267     /* Note that point size is in decipoints */
268     specs.pfont = &font;
269     /* XXX beware of overflow */
270     specs.xxmult = point_size * x_res / 720 * (1 << 16);
271     specs.xymult = 0L << 16;
272     specs.xoffset = 0L << 16;
273     specs.yxmult = 0L << 16;
274     specs.yymult = point_size * y_res / 720 * (1 << 16);
275     specs.yoffset = 0L << 16;
276     switch (quality) {
277     case 0:
278 	specs.flags = 0;
279 	break;
280     case 1:
281 	specs.flags = MODE_SCREEN;
282 	break;
283     case 2:
284 	specs.flags = MODE_2D;
285 	break;
286     default:
287 	fprintf(stderr, "bogus quality value %d\n", quality);
288 	break;
289     }
290     specs.out_info = NULL;
291 
292     if (!fontname) {
293 	fontname = (char *) (f_buffer + FH_FNTNM);
294     }
295     if (iso_encoding)
296 	num_chars = num_iso_chars;
297     dump_header(num_chars);
298 
299     if (!sp_set_specs(&specs)) {
300 	fprintf(stderr, "can't set specs\n");
301     } else {
302 	if (iso_encoding) {
303 	    for (i = 0; i < num_iso_chars * 2; i += 2) {
304 		char_index = iso_map[i + 1];
305 		char_id = iso_map[i];
306 		if (!sp_make_char(char_index)) {
307 		    fprintf(stderr, "can't make char %x\n", char_index);
308 		}
309 	    }
310 	} else {
311 	    for (i = 0; i < num_chars; i++) {
312 		char_index = i + first_char_index;
313 		char_id = sp_get_char_id(char_index);
314 		if (char_id) {
315 		    if (!sp_make_char(char_index)) {
316 			fprintf(stderr, "can't make char %x\n", char_index);
317 		    }
318 		}
319 	    }
320 	}
321     }
322 
323     (void) fclose(fp);
324 
325     printf("ENDFONT\n");
326     exit(0);
327 }
328 
329 static void
dump_header(num_chars)330 dump_header(num_chars)
331     ufix32      num_chars;
332 {
333     fix15       xmin,
334                 ymin,
335                 xmax,
336                 ymax;
337     fix15       ascent,
338                 descent;
339     fix15       pixel_size;
340 
341     xmin = read_2b(f_buffer + FH_FXMIN);
342     ymin = read_2b(f_buffer + FH_FYMIN);
343     xmax = read_2b(f_buffer + FH_FXMAX);
344     ymax = read_2b(f_buffer + FH_FYMAX);
345     pixel_size = point_size * x_res / 720;
346 
347     printf("STARTFONT 2.1\n");
348     printf("COMMENT\n");
349     printf("COMMENT Generated from Bitstream Speedo outlines via sptobdf\n");
350     printf("COMMENT\n");
351     printf("FONT %s\n", fontname);
352     printf("SIZE %d %d %d\n", pixel_size, x_res, y_res);
353     printf("FONTBOUNDINGBOX %d %d %d %d\n", xmin, ymin, xmax, ymax);
354     printf("STARTPROPERTIES %d\n", num_props);
355 
356     printf("RESOLUTION_X %d\n", x_res);
357     printf("RESOLUTION_Y %d\n", y_res);
358     printf("POINT_SIZE %d\n", point_size);
359     printf("PIXEL_SIZE %d\n", pixel_size);
360     printf("COPYRIGHT \"%s\"\n", f_buffer + FH_CPYRT);
361 
362     /* do some stretching here so that its isn't too tight */
363     pixel_size = pixel_size * stretch / 100;
364     ascent = pixel_size * 764 / 1000;	/* 764 == EM_TOP */
365     descent = pixel_size - ascent;
366     printf("FONT_ASCENT %d\n", ascent);
367     printf("FONT_DESCENT %d\n", descent);
368 
369     printf("ENDPROPERTIES\n");
370     printf("CHARS %d\n", num_chars);
371 }
372 
373 buff_t     *
sp_load_char_data(file_offset,num,cb_offset)374 sp_load_char_data(file_offset, num, cb_offset)
375     fix31       file_offset;
376     fix15       num;
377     fix15       cb_offset;
378 {
379     if (fseek(fp, (long) file_offset, (int) 0)) {
380 	fprintf(stderr, "can't seek to char\n");
381 	(void) fclose(fp);
382 	exit(-1);
383     }
384     if ((num + cb_offset) > mincharsize) {
385 	fprintf(stderr, "char buf overflow\n");
386 	(void) fclose(fp);
387 	exit(-2);
388     }
389     if (fread((c_buffer + cb_offset), sizeof(ufix8), num, fp) != num) {
390 	fprintf(stderr, "can't get char data\n");
391 	exit(-1);
392     }
393     char_data.org = (ufix8 *) c_buffer + cb_offset;
394     char_data.no_bytes = num;
395 
396     return &char_data;
397 }
398 
399 /*
400  * Called by Speedo character generator to report an error.
401  *
402  *  Since character data not available is one of those errors
403  *  that happens many times, don't report it to user
404  */
405 void
sp_report_error(n)406 sp_report_error(n)
407     fix15       n;
408 {
409     switch (n) {
410     case 1:
411 	fprintf(stderr, "Insufficient font data loaded\n");
412 	break;
413     case 3:
414 	fprintf(stderr, "Transformation matrix out of range\n");
415 	break;
416     case 4:
417 	fprintf(stderr, "Font format error\n");
418 	break;
419     case 5:
420 	fprintf(stderr, "Requested specs not compatible with output module\n");
421 	break;
422     case 7:
423 	fprintf(stderr, "Intelligent transformation requested but not supported\n");
424 	break;
425     case 8:
426 	fprintf(stderr, "Unsupported output mode requested\n");
427 	break;
428     case 9:
429 	fprintf(stderr, "Extended font loaded but only compact fonts supported\n");
430 	break;
431     case 10:
432 	fprintf(stderr, "Font specs not set prior to use of font\n");
433 	break;
434     case 12:
435 	break;
436     case 13:
437 	fprintf(stderr, "Track kerning data not available()\n");
438 	break;
439     case 14:
440 	fprintf(stderr, "Pair kerning data not available()\n");
441 	break;
442     default:
443 	fprintf(stderr, "report_error(%d)\n", n);
444 	break;
445     }
446 }
447 
448 void
sp_open_bitmap(x_set_width,y_set_width,xorg,yorg,xsize,ysize)449 sp_open_bitmap(x_set_width, y_set_width, xorg, yorg, xsize, ysize)
450     fix31       x_set_width;
451     fix31       y_set_width;
452     fix31       xorg;
453     fix31       yorg;
454     fix15       xsize;
455     fix15       ysize;
456 {
457     fix15       i;
458     fix15       off_horz;
459     fix15       off_vert;
460     fix31       width,
461                 pix_width;
462     bbox_t      bb;
463 
464     bit_width = xsize;
465 
466     bit_height = ysize;
467     off_horz = (fix15) ((xorg + 32768L) >> 16);
468     off_vert = (fix15) ((yorg + 32768L) >> 16);
469 
470     if (bit_width > MAX_BITS) {
471 
472 #ifdef DEBUG
473 	fprintf(stderr, "char wider than max bits -- truncated\n");
474 #endif
475 
476 	bit_width = MAX_BITS;
477     }
478     width = sp_get_char_width(char_index);
479     pix_width = width * (specs.xxmult / 65536L) +
480 	((ufix32) width * ((ufix32) specs.xxmult & 0xffff)) / 65536L;
481     pix_width /= 65536L;
482 
483     width = (pix_width * 7200L) / (point_size * y_res);
484 
485     (void) sp_get_char_bbox(char_index, &bb);
486     bb.xmin >>= 16;
487     bb.ymin >>= 16;
488     bb.xmax >>= 16;
489     bb.ymax >>= 16;
490 
491 #ifdef DEBUG
492     if ((bb.xmax - bb.xmin) != bit_width)
493 	fprintf(stderr, "bbox & width mismatch 0x%x (%d) (%d vs %d)\n",
494 		char_index, char_id, (bb.xmax - bb.xmin), bit_width);
495     if ((bb.ymax - bb.ymin) != bit_height)
496 	fprintf(stderr, "bbox & height mismatch 0x%x (%d) (%d vs %d)\n",
497 		char_index, char_id, (bb.ymax - bb.ymin), bit_height);
498     if (bb.xmin != off_horz)
499 	fprintf(stderr, "x min mismatch 0x%x (%d) (%d vs %d)\n",
500 		char_index, char_id, bb.xmin, off_horz);
501     if (bb.ymin != off_vert)
502 	fprintf(stderr, "y min mismatch 0x%x (%d) (%d vs %d)\n",
503 		char_index, char_id, bb.ymin, off_vert);
504 #endif
505 
506 #ifdef BBOX_CLIP
507     bit_width = bb.xmax - bb.xmin;
508     bit_height = bb.ymax - bb.ymin;
509     off_horz = bb.xmin;
510     off_vert = bb.ymin;
511 #endif
512 
513     /* XXX kludge to handle space */
514     if (bb.xmin == 0 && bb.ymin == 0 && bb.xmax == 0 && bb.ymax == 0 &&
515 	    width) {
516 	bit_width = 1;
517 	bit_height = 1;
518     }
519     printf("STARTCHAR %d\n", char_id);
520     printf("ENCODING %d\n", char_id);
521     printf("SWIDTH %d 0\n", width);
522     printf("DWIDTH %d 0\n", pix_width);
523     printf("BBX %d %d %d %d\n", bit_width, bit_height, off_horz, off_vert);
524     printf("BITMAP\n");
525 
526     for (i = 0; i < bit_width; i++) {
527 	line_of_bits[i] = '.';
528     }
529     line_of_bits[bit_width] = '\0';
530     cur_y = 0;
531 }
532 
533 static void
dump_line(line)534 dump_line(line)
535     ufix8      *line;
536 {
537     int         bit;
538     unsigned    byte;
539 
540     byte = 0;
541     for (bit = 0; bit < bit_width; bit++) {
542 	if (line[bit] == 'X')
543 	    byte |= (1 << (7 - (bit & 7)));
544 	if ((bit & 7) == 7) {
545 	    printf("%02X", byte);
546 	    byte = 0;
547 	}
548     }
549     if ((bit & 7) != 0)
550 	printf("%02X", byte);
551     printf("\n");
552 }
553 
554 #ifdef BBOX_CLIP
555 static fix15 last_y;
556 static int  trunc = 0;
557 
558 #endif
559 
560 void
sp_set_bitmap_bits(y,xbit1,xbit2)561 sp_set_bitmap_bits(y, xbit1, xbit2)
562     fix15       y;
563     fix15       xbit1;
564     fix15       xbit2;
565 {
566     fix15       i;
567 
568     if (xbit1 > MAX_BITS) {
569 
570 #ifdef DEBUG
571 	fprintf(stderr, "run wider than max bits -- truncated\n");
572 #endif
573 
574 	xbit1 = MAX_BITS;
575     }
576     if (xbit2 > MAX_BITS) {
577 
578 #ifdef DEBUG
579 	fprintf(stderr, "run wider than max bits -- truncated\n");
580 #endif
581 
582 	xbit2 = MAX_BITS;
583     }
584     while (cur_y != y) {
585 	dump_line(line_of_bits);
586 	for (i = 0; i < bit_width; i++) {
587 	    line_of_bits[i] = '.';
588 	}
589 	cur_y++;
590     }
591 
592 #ifdef BBOX_CLIP
593     last_y = y;
594     if (y >= bit_height) {
595 
596 #ifdef DEBUG
597 	fprintf(stderr,
598 		"y value is larger than height 0x%x (%d) -- truncated\n",
599 		char_index, char_id);
600 #endif
601 
602 	trunc = 1;
603 	return;
604     }
605 #endif				/* BBOX_CLIP */
606 
607     for (i = xbit1; i < xbit2; i++) {
608 	line_of_bits[i] = 'X';
609     }
610 }
611 
612 void
sp_close_bitmap()613 sp_close_bitmap()
614 {
615 
616 #ifdef BBOX_CLIP
617     int         i;
618 
619     if (!trunc)
620 	dump_line(line_of_bits);
621     trunc = 0;
622 
623 
624     last_y++;
625     while (last_y < bit_height) {
626 
627 #ifdef DEBUG
628 	fprintf(stderr, "padding out height for 0x%x (%d)\n",
629 		char_index, char_id);
630 #endif
631 
632 	for (i = 0; i < bit_width; i++) {
633 	    line_of_bits[i] = '.';
634 	}
635 	dump_line(line_of_bits);
636 	last_y++;
637     }
638 
639 #else
640     dump_line(line_of_bits);
641 #endif
642 
643     printf("ENDCHAR\n");
644 }
645 
646 /* outline stubs */
647 void
sp_open_outline()648 sp_open_outline()
649 {
650 }
651 
652 void
sp_start_new_char()653 sp_start_new_char()
654 {
655 }
656 
657 void
sp_start_contour()658 sp_start_contour()
659 {
660 }
661 
662 void
sp_curve_to()663 sp_curve_to()
664 {
665 }
666 
667 void
sp_line_to()668 sp_line_to()
669 {
670 }
671 
672 void
sp_close_contour()673 sp_close_contour()
674 {
675 }
676 
677 void
sp_close_outline()678 sp_close_outline()
679 {
680 }
681