2 * NEATMKFN - GENERATE NEATROFF FONT DESCRIPTIONS
4 * Copyright (C) 2012-2018 Ali Gholami Rudi <ali at rudi dot ir>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 #define LEN(a) ((sizeof(a) / sizeof((a)[0])))
26 static char *mkfn_scripts
; /* filtered scripts */
27 static char *mkfn_langs
; /* filtered languages */
28 static char *mkfn_subfont
; /* filtered font */
29 static char *mkfn_trname
; /* font troff name */
30 static char *mkfn_psname
; /* font ps name */
31 static char *mkfn_path
; /* font path */
32 int mkfn_res
= 720; /* device resolution */
33 int mkfn_warn
; /* warn about unsupported features */
34 int mkfn_kmin
; /* minimum kerning value */
35 int mkfn_swid
; /* space width */
36 int mkfn_special
; /* special flag */
37 int mkfn_bbox
; /* include bounding box */
38 int mkfn_noligs
; /* suppress ligatures */
39 int mkfn_pos
= 1; /* include glyph positions */
40 int mkfn_dry
; /* generate no output */
42 /* OpenType specifies a specific feature order for different scripts */
43 static char *scriptorder
[][2] = {
44 {"latn", "ccmp,liga,clig,dist,kern,mark,mkmk"},
45 {"cyrl", "ccmp,liga,clig,dist,kern,mark,mkmk"},
46 {"grek", "ccmp,liga,clig,dist,kern,mark,mkmk"},
47 {"armn", "ccmp,liga,clig,dist,kern,mark,mkmk"},
48 {"geor", "ccmp,liga,clig,dist,kern,mark,mkmk"},
49 {"runr", "ccmp,liga,clig,dist,kern,mark,mkmk"},
50 {"ogam", "ccmp,liga,clig,dist,kern,mark,mkmk"},
51 {"arab", "ccmp,isol,fina,medi,init,rlig,calt,liga,dlig,cswh,mset,curs,kern,mark,mkmk"},
52 {"bugi", "locl,ccmp,rlig,liga,clig,calt,kern,dist,mark,mkmk"},
53 {"hang", "ccmp,ljmo,vjmo,tjmo"},
54 {"hebr", "ccmp,dlig,kern,mark"},
55 {"bng2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
56 {"dev2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
57 {"gjr2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
58 {"gur2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
59 {"knd2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
60 {"mlym", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
61 {"ory2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
62 {"tml2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
63 {"tml2", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
64 {"telu", "locl,nukt,akhn,rphf,blwf,half,pstf,vatu,cjct,init,pres,abvs,blws,psts,haln,calt,kern,dist,abvm,blwm"},
65 {"java", "locl,pref,abvf,blwf,pstf,pres,abvs,blws,psts,ccmp,rlig,liga,clig,calt,kern,dist,mark,mkmk"},
66 {"khmr", "pref,blwf,abvf,pstf,pres,blws,abvs,psts,clig,dist,blwm,abvm,mkmk"},
67 {"lao ", "ccmp,kern,mark,mkmk"},
68 {"mym2", "locl,rphf,pref,blwf,pstf,pres,abvs,blws,psts,kern,dist,mark,mkmk"},
69 {"sinh", "locl,ccmp,akhn,rphf,vatu,pstf,pres,abvs,blws,psts,kern,dist,abvm,blwm"},
70 {"syrc", "stch,ccmp,isol,fina,fin2,fin3,medi,med2,init,rlig,calt,liga,dlig,kern,mark,mkmk"},
71 {"thaa", "kern,mark"},
72 {"thai", "ccmp,kern,mark,mkmk"},
73 {"tibt", "ccmp,abvs,blws,calt,liga,kern,abvm,blwm,mkmk"},
76 /* return 1 if the given script is to be included */
77 int mkfn_script(char *script
, int nscripts
)
79 /* fill mkfn_scripts (if unspecified) in the first call */
81 if (nscripts
== 1 || !script
)
83 if (!strcmp("DFLT", script
))
84 mkfn_scripts
= "DFLT";
86 mkfn_scripts
= "latn";
88 if (!strcmp("list", mkfn_scripts
))
89 printf("%s\n", script
? script
: "");
90 if (strchr(script
, ' '))
91 *strchr(script
, ' ') = '\0';
92 return !!strstr(mkfn_scripts
, script
);
95 /* return 1 if the given language is to be included */
96 int mkfn_lang(char *lang
, int nlangs
)
102 if (!strcmp("list", mkfn_langs
))
103 printf("%s\n", lang
);
104 if (strchr(lang
, ' '))
105 *strchr(lang
, ' ') = '\0';
106 return !!strstr(mkfn_langs
, lang
);
109 /* return 1 if the given font is to be included */
110 int mkfn_font(char *font
)
112 static int idx
; /* font index */
116 if (!strcmp("list", mkfn_subfont
))
117 printf("%s\n", font
);
118 if (mkfn_subfont
[0] && isdigit((unsigned char) mkfn_subfont
[0]))
119 if (atoi(mkfn_subfont
) == idx
)
121 return !strcmp(mkfn_subfont
, font
);
124 /* return the rank of the given feature, for the current script */
125 int mkfn_featrank(char *scrp
, char *feat
)
129 if (!order
|| strcmp(scrp
, order
[0])) {
131 for (i
= 0; i
< LEN(scriptorder
); i
++)
132 if (!strcmp(scrp
, scriptorder
[i
][0]))
133 order
= scriptorder
[i
];
135 if (order
&& strstr(order
[1], feat
))
136 return strstr(order
[1], feat
) - order
[1];
140 void mkfn_header(char *fontname
)
145 printf("name %s\n", mkfn_trname
);
147 printf("fontname %s\n", mkfn_psname
);
148 if (!mkfn_psname
&& fontname
&& fontname
[0])
149 printf("fontname %s\n", fontname
);
151 printf("fontpath %s\n", mkfn_path
);
162 "Usage: mktrfn [options] <input >output\n"
164 " -a \tread an AFM file (default)\n"
165 " -o \tread a TTF or an OTF file\n"
166 " -s \tspecial font\n"
167 " -p name \toverride font postscript name\n"
168 " -t name \tset font troff name\n"
169 " -f path \tset font path\n"
170 " -r res \tset device resolution (720)\n"
171 " -k kmin \tspecify the minimum amount of kerning (0)\n"
172 " -b \tinclude glyph bounding boxes\n"
173 " -l \tsuppress the ligatures line\n"
174 " -n \tsuppress glyph positions\n"
175 " -S scrs \tcomma-separated list of scripts to include (list to list)\n"
176 " -L langs\tcomma-separated list of languages to include (list to list)\n"
177 " -F font \tfont name or index in a font collection (list to list)\n"
178 " -w \twarn about unsupported font features\n";
180 int main(int argc
, char *argv
[])
184 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
185 switch (argv
[i
][1]) {
193 mkfn_path
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
196 mkfn_subfont
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
197 mkfn_dry
= !strcmp("list", mkfn_subfont
);
200 mkfn_kmin
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
206 mkfn_langs
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
207 mkfn_dry
= !strcmp("list", mkfn_langs
);
216 mkfn_psname
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
219 mkfn_res
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
225 mkfn_scripts
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
226 mkfn_dry
= !strcmp("list", mkfn_scripts
);
229 mkfn_trname
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
235 fprintf(stderr
, "%s", usage
);
240 if ((afm
? afm_read() : otf_read())) {
241 fprintf(stderr
, "neatmkfn: cannot parse the font\n");