3
* - a vflibcap entry generator for PostScript Type 1 fonts
5
* - This program read "font map" file (e.g. psfonts.map) of dvips,
6
* and prints vflibcap entries to standard output.
8
* - Useful for generating vflibcap for TeX DVI drivers
11
* by Hirotsugu Kakugawa
14
* 3 May 2001 Support for kpathsea.
15
* 9 May 2001 Support for font file substitution by Ghostscript fonts
16
* 10 May 2001 Support for font class geneeration, afm and encoding
20
* Copyright (C) 2001 Hirotsugu Kakugawa.
21
* All rights reserved.
23
* This program is free software; you can redistribute it and/or modify
24
* it under the terms of the GNU General Public License as published by
25
* the Free Software Foundation; either version 2, or (at your option)
28
* This program is distributed in the hope that it will be useful,
29
* but WITHOUT ANY WARRANTY; without even the implied warranty of
30
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
* GNU General Public License for more details.
33
* You should have received a copy of the GNU General Public License
34
* along with this program; if not, write to the Free Software
35
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
48
#include <sys/param.h>
52
# include "kpathsea/kpathsea.h"
55
#include "VFlib-3_6.h"
65
void gen_class_deafult(void);
66
void translate(FILE*,FILE*,char*);
67
int get_token(char *s, char *b, int *x);
70
int parse_pscmd(char *cmds, double *val);
72
void read_gs_fontmap(void);
73
char *find_gs_font(char *f);
74
int query_gs_db(char *s);
76
double tfm_read_ds(char *name);
86
char pscode[MAXPSCODE][BUFSIZ];
88
char *mode = DEFAULT_KPS_MODE;
90
int dpi_i = DEFAULT_KPS_DPI;
94
char *t1_fontdirs[NDIRS];
96
char *t1_encdirs[NDIRS];
98
char *t1_afmdirs[NDIRS];
100
char *gs_fontdirs[NDIRS];
103
#define NGSFONTS 1024
104
char *gs_db_f[NGSFONTS];
105
char *gs_db_d[NGSFONTS];
108
char *cmdline = NULL;
109
char *font_suffix = "";
118
main(int argc, char **argv)
130
sprintf(dpi, "%d", dpi_i);
132
cmdline = copy_cmdline(argc, argv);
134
n_t1f = n_t1a = n_t1e = 0;
135
for (i = 0; i < NDIRS; i++){
136
t1_fontdirs[i] = NULL;
137
t1_afmdirs[i] = NULL;
138
t1_encdirs[i] = NULL;
139
gs_fontdirs[i] = NULL;
144
for (i = 0; i < NGSFONTS; i++){
153
for (xargc--,xargv++; xargc > 0; xargc--,xargv++){
154
if ((strcmp(*xargv, "--help") == 0)
155
|| (strcmp(*xargv, "-help") == 0)){
156
printf("vflmkt1: generates vflibcap entries for Type1 fonts from\n");
157
printf(" a 'font map' file of dvips\n");
158
printf("Usage: vflmkt1 [options] [map-file ...]\n");
160
printf(" -d DIR : Type 1 font file directory\n");
161
printf(" -a DIR : AFM file directory\n");
162
printf(" -e DIR : T1Lib encoding vector directory\n");
163
printf(" -gf DIR : Ghostscript font file directory\n");
164
printf(" -gm FILE : Ghostscript font map file 'Fontmap' path\n");
165
printf(" -r DPI : Default device resolution\n");
166
printf(" -n MODE : Device mode name for kpathsea\n");
167
printf(" -f : Generate font entries\n");
168
printf(" -z : Generate font entries whose font file exists\n");
169
printf(" -t : Generate font entries with TeX TFM file\n");
170
printf(" -x STR : String added to the end of font name\n");
173
printf("Example: vflmkt1 -d TEXMF -f psfonts.map\n");
175
printf("Example: vflmkt1 -d TEXMF -f /usr/local/share/texmf/dvips/psfonts.map\n");
179
} else if (strcmp(*xargv, "-r") == 0){
182
dpi = strdup(*xargv);
184
} else if (strcmp(*xargv, "-n") == 0){
188
mode = x_strdup(*xargv);
190
} else if (strcmp(*xargv, "-d") == 0){
191
/* type 1 font dir */
193
fprintf(stderr, "Too many Type 1 font directories\n");
198
t1_fontdirs[n_t1f++] = x_strdup(*xargv);
200
} else if (strcmp(*xargv, "-a") == 0){
203
fprintf(stderr, "Too many AFM directories\n");
208
t1_afmdirs[n_t1a++] = x_strdup(*xargv);
210
} else if (strcmp(*xargv, "-e") == 0){
211
/* encoding vector dir */
213
fprintf(stderr, "Too many T1Lib Encoding Vector directories\n");
218
t1_encdirs[n_t1e++] = x_strdup(*xargv);
220
} else if (strcmp(*xargv, "-gf") == 0){
223
fprintf(stderr, "Too many Ghostscript font directories\n");
228
gs_fontdirs[n_gsf++] = x_strdup(*xargv);
230
} else if (strcmp(*xargv, "-gm") == 0){
234
gs_fontmap = x_strdup(*xargv);
236
} else if (strcmp(*xargv, "-f") == 0){
239
} else if (strcmp(*xargv, "-z") == 0){
242
} else if (strcmp(*xargv, "-t") == 0){
245
} else if (strcmp(*xargv, "-x") == 0){
248
font_suffix = strdup(*xargv);
251
if (*xargv[0] == '-'){
252
fprintf(stderr, "vflmkt1: unknown option %s\n", *xargv);
262
kpse_set_program_name (argv[0], progname);
263
kpse_init_prog (uppercasify(kpse_program_name), atoi(dpi), mode, NULL);
264
for (f = 0; f < kpse_last_format; f++) {
269
banner("Type 1", "vflmkt1", cmdline);
275
for ( ; xargc > 0; xargc--,xargv++){
279
if ((fp = fopen(s, "r")) == NULL){
281
s = kpse_find_file(*xargv, kpse_dvips_config_format, 0);
283
fprintf(stderr, "Cannot find: %s\n", *xargv);
287
if ((fp = fopen(s, "r")) == NULL){
289
fprintf(stderr, "Cannot open: %s\n", *xargv);
296
translate(fp, stdout, s);
301
translate(stdin, stdout, "<stdard input>");
312
gen_class_deafult(void)
317
VF_CAPE_VFLIBCAP_CLASS_DEFAULT_DEFINITION, FONTCLASS_NAME);
318
printf("\n (%s", VF_CAPE_FONT_DIRECTORIES);
319
for (i = 0; i < n_t1f; i++)
320
printf("\n \"%s\"", t1_fontdirs[i]);
321
for (i = 0; i < n_gsf; i++)
322
printf("\n \"%s\"", gs_fontdirs[i]);
324
printf("\n (%s", VF_CAPE_TYPE1_AFM_DIRECTORIES);
325
for (i = 0; i < n_t1a; i++)
326
printf("\n \"%s\"", t1_afmdirs[i]);
328
printf("\n (%s", VF_CAPE_TYPE1_ENC_DIRECTORIES);
329
for (i = 0; i < n_t1e; i++)
330
printf("\n \"%s\"", t1_encdirs[i]);
332
printf("\n (%s \"none\")", VF_CAPE_TYPE1_LOG_LEVEL);
333
printf("\n (%s %s)", VF_CAPE_DPI, dpi);
340
translate(FILE *in, FILE *out, char *map)
350
printf(";; dvips mapfile: %s\n", map);
353
while (fgets(buff, sizeof(buff), in) != NULL){
355
if (isspace(buff[0]))
371
*t1font = *encfile = *opt = '\0';
372
for (i = 0; i < MAXPSCODE; i++)
374
v = get_token(texfont, buff, &x);
375
v = get_token(psfont, buff, &x);
377
v = get_token(opt, buff, &x);
378
if (strncmp(opt, "<<", 2) == 0){
380
fprintf(stderr, "Error: line %d: %s\n", lno, buff);
381
strcpy(t1font, &opt[1]);
382
} else if (strncmp(opt, "<[", 2) == 0){
383
if (*encfile != '\0')
384
fprintf(stderr, "Error: line %d: %s\n", lno, buff);
385
strcpy(encfile, &opt[1]);
386
} else if (strncmp(opt, "<", 1) == 0){
387
if ((strlen(opt) >= 4) && (strcmp(".enc", &opt[strlen(opt)-4]) == 0)){
388
if (*encfile != '\0')
389
fprintf(stderr, "Error: line %d: %s\n", lno, buff);
390
strcpy(encfile, &opt[1]);
393
fprintf(stderr, "Error: line %d: %s\n", lno, buff);
394
strcpy(t1font, &opt[1]);
396
} else if (strncmp(opt, "\"", 1) == 0){
397
strcpy(pscode[npscode], &opt[1]);
398
pscode[npscode][strlen(pscode[npscode])-1] = '\0';
400
if (npscode == MAXPSCODE){
401
fprintf(stderr, "Error (Too many PS code): line %d: %s\n",
411
printf(";; end of %s\n", map);
415
get_token(char *s, char *b, int *x)
421
while (isspace(b[*x])){
436
if ((d == 0) && isspace(b[*x])){
440
if ((d == 1) && (b[*x] == '"'))
444
while (isspace(b[*x])){
460
if (*t1font != '\0'){
466
if (exist_only == 1){
467
f = check_font_exist(ff, t1_fontdirs, n_t1f, kpse_type1_format, NULL);
468
ds = tfm_read_ds(texfont);
474
/* search substitute font in Ghostscript font directory */
475
f = find_gs_font(ff); /* f is NULL if not found in gs Fontmap */
478
} else { /* ignore .gsf font files */
480
if ((l >= strlen(".gsf")) && (strcmp(&f[l-4], ".gsf") == 0)){
487
printf("(%s %s%s", VF_CAPE_VFLIBCAP_FONT_ENTRY_DEFINITION,
488
texfont, font_suffix);
489
printf("\t(%s %s)", VF_CAPE_FONT_CLASS, FONTCLASS_NAME);
490
if ((with_tfm == 1) && (ds > 0)){
491
printf("\n (%s %.2f)", VF_CAPE_POINT_SIZE, ds);
492
printf(" (%s \"%s\")", VF_CAPE_TYPE1_TFM, texfont);
494
printf(" (%s \"%s\")", VF_CAPE_FONT_FILE, f);
498
/* search substitute font in Ghostscript font directory */
499
f = find_gs_font(ff); /* f is NULL if not found in gs Fontmap */
500
ds = tfm_read_ds(texfont);
502
/* ignore .gsf font files */
504
if ((l >= strlen(".gsf")) && (strcmp(&f[l-4], ".gsf") == 0)){
508
printf("(%s %s%s", VF_CAPE_VFLIBCAP_FONT_ENTRY_DEFINITION,
509
texfont, font_suffix);
510
printf("\t(%s %s)", VF_CAPE_FONT_CLASS, FONTCLASS_NAME);
511
if ((with_tfm == 1) && (ds > 0)){
512
printf("\n (%s %.2f)", VF_CAPE_POINT_SIZE, ds);
513
printf(" (%s \"%s\")", VF_CAPE_TYPE1_TFM, texfont);
516
printf("\n (%s \"%s\" \"%s\")", VF_CAPE_FONT_FILE, ff, f);
518
printf("\n (%s \"%s\")", VF_CAPE_FONT_FILE, ff);
523
for (i = 0; i < MAXPSCODE; i++){
524
if (pscode[i][0] == '\0')
526
if ((type = parse_pscmd(pscode[i], &val)) < 0)
535
if (*encfile != '\0')
536
printf("(%s \"%s\")", VF_CAPE_TYPE1_ENC_VECT, encfile);
539
printf("(%s %.3f)", VF_CAPE_SLANT_FACTOR, val);
542
printf("(%s %.3f)", VF_CAPE_ASPECT_RATIO, val);
555
parse_pscmd(char *cmds, double *val)
559
if (sscanf(cmds, "%s %s", psc[0], psc[1]) == 2){
560
if (strcmp(psc[1], "ReEncodeFont") == 0){
563
if (strcmp(psc[1], "SlantFont") == 0){
567
if (strcmp(psc[1], "ExtendFont") == 0){
582
read_gs_fontmap(void)
585
char f[BUFSIZ], d[BUFSIZ];
593
if ((fp = fopen(gs_fontmap, "r")) == NULL){
594
fprintf(stderr, "Cannot open Ghostscript Fontmap file\n");
599
while (fgets(buff, sizeof(buff), fp) != NULL){
601
/* skip empty line */
602
if ((p = strchr(buff, '%')) != NULL)
604
for (i = 0; buff[i] != '\0'; i++){
605
if (!isspace(buff[i]))
611
for (j = 0; (buff[i] != '\0') && !isspace(buff[i]); i++, j++)
614
if (buff[i] == '\0'){
615
fprintf(stderr, "Unexpected file format: gs_fontmap\n");
620
for ( ; buff[i] != '\0'; i++){
621
if (!isspace(buff[i]))
624
if (buff[i] == '\0'){
625
fprintf(stderr, "Unexpected file format: Ghostscript Fontmap\n");
628
/* font file or alias */
629
for (j = 0; (buff[i] != '\0') && !isspace(buff[i]); i++, j++)
634
if (i_db == NGSFONTS){
635
fprintf(stderr, "Too many fonts in Ghostscript Fontmap\n");
639
printf("*** GS Fontmap db %d: %s\t%s\n", i_db, f, d);
641
gs_db_f[i_db] = x_strdup(f);
642
gs_db_d[i_db] = x_strdup(d);
652
find_gs_font(char *f)
657
if ((j = query_gs_db(f)) < 0)
660
while (gs_db_d[j][0] == '/'){ /* resolve alias */
661
if ((j = query_gs_db(&gs_db_d[j][1])) < 0)
665
s = x_strdup(&gs_db_d[j][1]);
666
s[strlen(s)-1] = '\0';
676
for (i = 0; i < i_db; i++){
677
if (strcmp(&gs_db_f[i][1], s) == 0)
680
return -1; /* font not in db. */
687
tfm_read_ds(char *name)
691
UINT4 lf, cs, ds, offset_header;
696
sprintf(tfm, "%s.%s", name, DEFAULT_EXTENSIONS_TFM);
698
s = kpse_find_file(tfm, kpse_tfm_format, 0);
704
if ((fp = fopen(s, "r")) == NULL)
707
lf = (UINT4)READ_UINT2(fp);
708
if ((lf == 11) || (lf == 9)){
709
/* JFM file of Japanese TeX by ASCII Coop. */
710
type = METRIC_TYPE_JFM;
711
(UINT4)READ_UINT2(fp);
712
(UINT4)READ_UINT2(fp);
713
(UINT4)READ_UINT2(fp);
716
/* Omega Metric File */
717
type = METRIC_TYPE_OFM;
718
aux = READ_INT2(fp); /* ofm_level */
721
if (aux == 0){ /* level 0 OFM */
722
offset_header = 4*14;
723
} else { /* level 1 OFM: *** NOT SUPPORTED YET *** */
724
offset_header = 4*29;
727
/* Traditional TeX Metric File */
728
type = METRIC_TYPE_TFM;
734
if (type == METRIC_TYPE_OFM){
749
(UINT4)READ_UINT2(fp);
750
(UINT4)READ_UINT2(fp);
751
(UINT4)READ_UINT2(fp);
752
(UINT4)READ_UINT2(fp);
753
(UINT4)READ_UINT2(fp);
754
(UINT4)READ_UINT2(fp);
755
(UINT4)READ_UINT2(fp);
756
(UINT4)READ_UINT2(fp);
759
fseek(fp, offset_header, SEEK_SET);
765
return (double)(ds)/(double)(1<<20);
769
vf_tex_read_uintn(FILE* fp, int size)
775
v = v*256L + (unsigned long)getc(fp);
782
vf_tex_read_intn(FILE* fp, int size)
786
v = (long)getc(fp) & 0xffL;
791
v = v*256L + (unsigned long)getc(fp);
799
vf_tex_skip_n(FILE* fp, int size)