ref: dfde766d2764c91c7c28c43d8c3b8244cd3b4fb1
parent: daf293759b5de8bc70c2a0e22b9e6516af7b6967
author: Ali Gholami Rudi <[email protected]>
date: Sat Jun 16 07:13:21 EDT 2018
mkfn: support OpenType font collections
--- a/afm.c
+++ b/afm.c
@@ -3,7 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "trfn.h"
+#include "mkfn.h"
#define TOKLEN 256
@@ -17,6 +17,11 @@
return s;
}
+static int uwid(int w)
+{
+ long div = 72000 / mkfn_res;
+ return (w < 0 ? w - div / 20 : w + div / 20) * (long) 10 / div;
+}
int afm_read(void)
{
char ln[1024];
@@ -25,13 +30,13 @@
char wid[TOKLEN] = "", field[TOKLEN] = "";
char llx[TOKLEN] = "0", lly[TOKLEN] = "0";
char urx[TOKLEN] = "0", ury[TOKLEN] = "0";
+ char fontname[128];
char *s;
while (fgets(ln, sizeof(ln), stdin)) {
if (ln[0] == '#')
continue;
if (!strncmp("FontName ", ln, 8)) {
- sscanf(ln, "FontName %s", ch);
- trfn_psfont(ch);
+ sscanf(ln, "FontName %s", fontname);
continue;
}
if (!strncmp("StartCharMetrics", ln, 16))
@@ -72,9 +77,11 @@
break;
}
if (ch[0] && pos[0] && wid[0])
- trfn_char(ch, atoi(pos), 0, atoi(wid),
- atoi(llx), atoi(lly), atoi(urx), atoi(ury));
+ mkfn_char(ch, atoi(pos), 0, uwid(atoi(wid)),
+ uwid(atoi(llx)), uwid(atoi(lly)),
+ uwid(atoi(urx)), uwid(atoi(ury)));
}
+ mkfn_header(fontname);
while (fgets(ln, sizeof(ln), stdin)) {
if (ln[0] == '#')
continue;
@@ -87,7 +94,7 @@
if (!strncmp("EndKernPairs", ln, 12))
break;
if (sscanf(ln, "KPX %s %s %s", c1, c2, wid) == 3)
- trfn_kern(c1, c2, atoi(wid));
+ mkfn_kern(c1, c2, uwid(atoi(wid)));
}
return 0;
}
--- a/mkfn.c
+++ b/mkfn.c
@@ -15,15 +15,29 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include "trfn.h"
+#include "mkfn.h"
#define LEN(a) ((sizeof(a) / sizeof((a)[0])))
-static char *trfn_scripts; /* filtered scripts */
-static char *trfn_langs; /* filtered languages */
+static char *mkfn_scripts; /* filtered scripts */
+static char *mkfn_langs; /* filtered languages */
+static char *mkfn_subfont; /* filtered font */
+static char *mkfn_trname; /* font troff name */
+static char *mkfn_psname; /* font ps name */
+static char *mkfn_path; /* font path */
+int mkfn_res = 720; /* device resolution */
+int mkfn_warn; /* warn about unsupported features */
+int mkfn_kmin; /* minimum kerning value */
+int mkfn_swid; /* space width */
+int mkfn_special; /* special flag */
+int mkfn_bbox; /* include bounding box */
+int mkfn_noligs; /* suppress ligatures */
+int mkfn_pos = 1; /* include glyph positions */
+int mkfn_dry; /* generate no output */
/* OpenType specifies a specific feature order for different scripts */
static char *scriptorder[][2] = {
@@ -60,40 +74,55 @@
};
/* return 1 if the given script is to be included */
-int trfn_script(char *script, int nscripts)
+int mkfn_script(char *script, int nscripts)
{
- /* fill trfn_scripts (if unspecified) in the first call */
- if (!trfn_scripts) {
+ /* fill mkfn_scripts (if unspecified) in the first call */
+ if (!mkfn_scripts) {
if (nscripts == 1 || !script)
return 1;
if (!strcmp("DFLT", script))
- trfn_scripts = "DFLT";
+ mkfn_scripts = "DFLT";
else
- trfn_scripts = "latn";
+ mkfn_scripts = "latn";
}
- if (!strcmp("help", trfn_scripts))
- fprintf(stderr, "script: %s\n", script ? script : "");
+ if (!strcmp("list", mkfn_scripts))
+ printf("%s\n", script ? script : "");
if (strchr(script, ' '))
*strchr(script, ' ') = '\0';
- return !!strstr(trfn_scripts, script);
+ return !!strstr(mkfn_scripts, script);
}
/* return 1 if the given language is to be included */
-int trfn_lang(char *lang, int nlangs)
+int mkfn_lang(char *lang, int nlangs)
{
- if (!trfn_langs)
+ if (!mkfn_langs)
return 1;
if (!lang)
lang = "";
- if (!strcmp("help", trfn_langs))
- fprintf(stderr, "lang: %s\n", lang);
+ if (!strcmp("list", mkfn_langs))
+ printf("%s\n", lang);
if (strchr(lang, ' '))
*strchr(lang, ' ') = '\0';
- return !!strstr(trfn_langs, lang);
+ return !!strstr(mkfn_langs, lang);
}
+/* return 1 if the given font is to be included */
+int mkfn_font(char *font)
+{
+ static int idx; /* font index */
+ idx++;
+ if (!mkfn_subfont)
+ return idx == 1;
+ if (!strcmp("list", mkfn_subfont))
+ printf("%s\n", font);
+ if (mkfn_subfont[0] && isdigit((unsigned char) mkfn_subfont[0]))
+ if (atoi(mkfn_subfont) == idx)
+ return 1;
+ return !strcmp(mkfn_subfont, font);
+}
+
/* return the rank of the given feature, for the current script */
-int trfn_featrank(char *scrp, char *feat)
+int mkfn_featrank(char *scrp, char *feat)
{
static char **order;
int i;
@@ -108,9 +137,26 @@
return 1000;
}
+void mkfn_header(char *fontname)
+{
+ if (mkfn_dry)
+ return;
+ if (mkfn_trname)
+ printf("name %s\n", mkfn_trname);
+ if (mkfn_psname)
+ printf("fontname %s\n", mkfn_psname);
+ if (!mkfn_psname && fontname && fontname[0])
+ printf("fontname %s\n", fontname);
+ if (mkfn_path)
+ printf("fontpath %s\n", mkfn_path);
+ trfn_header();
+ if (mkfn_special)
+ printf("special\n");
+ trfn_cdefs();
+}
+
int otf_read(void);
int afm_read(void);
-void otf_feat(int res, int kmin, int warn);
static char *usage =
"Usage: mktrfn [options] <input >output\n"
@@ -126,20 +172,14 @@
" -b \tinclude glyph bounding boxes\n"
" -l \tsuppress the ligatures line\n"
" -n \tsuppress glyph positions\n"
- " -S scrs \tcomma-separated list of scripts to include (help to list)\n"
- " -L langs\tcomma-separated list of languages to include (help to list)\n"
+ " -S scrs \tcomma-separated list of scripts to include (list to list)\n"
+ " -L langs\tcomma-separated list of languages to include (list to list)\n"
+ " -F font \tfont name or index in a font collection (list to list)\n"
" -w \twarn about unsupported font features\n";
int main(int argc, char *argv[])
{
int afm = 1;
- int res = 720;
- int spc = 0;
- int kmin = 0;
- int bbox = 0;
- int warn = 0;
- int ligs = 1;
- int pos = 1;
int i;
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
switch (argv[i][1]) {
@@ -147,43 +187,49 @@
afm = 1;
break;
case 'b':
- bbox = 1;
+ mkfn_bbox = 1;
break;
case 'f':
- trfn_pspath(argv[i][2] ? argv[i] + 2 : argv[++i]);
+ mkfn_path = argv[i][2] ? argv[i] + 2 : argv[++i];
break;
+ case 'F':
+ mkfn_subfont = argv[i][2] ? argv[i] + 2 : argv[++i];
+ mkfn_dry = !strcmp("list", mkfn_subfont);
+ break;
case 'k':
- kmin = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
+ mkfn_kmin = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
break;
case 'l':
- ligs = 0;
+ mkfn_noligs = 1;
break;
case 'L':
- trfn_langs = argv[i][2] ? argv[i] + 2 : argv[++i];
+ mkfn_langs = argv[i][2] ? argv[i] + 2 : argv[++i];
+ mkfn_dry = !strcmp("list", mkfn_langs);
break;
case 'n':
- pos = 0;
+ mkfn_pos = 0;
break;
case 'o':
afm = 0;
break;
case 'p':
- trfn_psfont(argv[i][2] ? argv[i] + 2 : argv[++i]);
+ mkfn_psname = argv[i][2] ? argv[i] + 2 : argv[++i];
break;
case 'r':
- res = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
+ mkfn_res = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
break;
case 's':
- spc = 1;
+ mkfn_special = 1;
break;
case 'S':
- trfn_scripts = argv[i][2] ? argv[i] + 2 : argv[++i];
+ mkfn_scripts = argv[i][2] ? argv[i] + 2 : argv[++i];
+ mkfn_dry = !strcmp("list", mkfn_scripts);
break;
case 't':
- trfn_trfont(argv[i][2] ? argv[i] + 2 : argv[++i]);
+ mkfn_trname = argv[i][2] ? argv[i] + 2 : argv[++i];
break;
case 'w':
- warn = 1;
+ mkfn_warn = 1;
break;
default:
printf("%s", usage);
@@ -190,14 +236,12 @@
return 0;
}
}
- trfn_init(res, spc, kmin, bbox, ligs, pos);
- if (afm)
- afm_read();
- else
- otf_read();
- trfn_print();
- if (!afm)
- otf_feat(res, kmin, warn);
+ trfn_init();
+ if ((afm ? afm_read() : otf_read())) {
+ fprintf(stderr, "neatmkfn: cannot parse the font\n");
+ trfn_done();
+ return 1;
+ }
trfn_done();
return 0;
}
--- /dev/null
+++ b/mkfn.h
@@ -1,0 +1,42 @@
+/* functions used by afm.c and otf.c */
+void mkfn_trfont(char *name);
+void mkfn_psfont(char *fontname);
+void mkfn_header(char *fontname);
+void mkfn_char(char *c, int n, int u, int wid, int llx, int lly, int urx, int ury);
+void mkfn_kern(char *c1, char *c2, int x);
+int mkfn_font(char *font);
+int mkfn_script(char *script, int nscripts);
+int mkfn_lang(char *lang, int nlangs);
+int mkfn_featrank(char *scrp, char *feat);
+
+/* functions defined in trfn.c and used by mkfn.c */
+void trfn_init(void);
+void trfn_cdefs(void);
+void trfn_header(void);
+void trfn_done(void);
+
+/* global variables */
+extern int mkfn_res; /* device resolution */
+extern int mkfn_warn; /* warn about unsupported features */
+extern int mkfn_kmin; /* minimum kerning value */
+extern int mkfn_swid; /* space width */
+extern int mkfn_special; /* special flag */
+extern int mkfn_bbox; /* include bounding box */
+extern int mkfn_noligs; /* suppress ligatures */
+extern int mkfn_pos; /* include glyph positions */
+extern int mkfn_dry; /* generate no output */
+
+/* variable length string buffer */
+struct sbuf *sbuf_make(void);
+void sbuf_free(struct sbuf *sb);
+char *sbuf_done(struct sbuf *sb);
+void sbuf_str(struct sbuf *sbuf, char *s);
+void sbuf_mem(struct sbuf *sbuf, char *s, int len);
+char *sbuf_buf(struct sbuf *sb);
+void sbuf_printf(struct sbuf *sbuf, char *s, ...);
+
+/* dictionary */
+struct tab *tab_alloc(int sz);
+void tab_free(struct tab *tab);
+void tab_put(struct tab *tab, char *k, void *v);
+void *tab_get(struct tab *tab, char *k);
--- a/otf.c
+++ b/otf.c
@@ -5,8 +5,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "sbuf.h"
-#include "trfn.h"
+#include "mkfn.h"
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a) / sizeof((a)[0]))
@@ -36,10 +35,13 @@
static int glyph_wid[NGLYPHS];
static int glyph_n;
static int upm; /* units per em */
-static int res; /* device resolution */
-static int kmin; /* minimum kerning value */
-static int warn; /* report unsupported tables */
+struct otf {
+ void *otf; /* TTC header or offset table */
+ void *off; /* offset table */
+ char name[128]; /* font name */
+};
+
static char *macset[];
static char *stdset[];
@@ -50,7 +52,7 @@
static int uwid(int w)
{
- int d = 72000 / res;
+ int d = 72000 / mkfn_res;
return (w < 0 ? owid(w) - d / 20 : owid(w) + d / 20) * 10 / d;
}
@@ -64,7 +66,7 @@
/* report unsupported otf tables */
static void otf_unsupported(char *sub, int type, int fmt)
{
- if (warn) {
+ if (mkfn_warn) {
fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
if (fmt > 0)
fprintf(stderr, " format %d", fmt);
@@ -73,20 +75,20 @@
}
/* find the otf table with the given name */
-static void *otf_table(void *otf, char *name)
+static void *otf_table(struct otf *otf, char *name)
{
- int nrecs = U16(otf, 4);
+ int nrecs = U16(otf->off, 4);
int i;
for (i = 0; i < nrecs; i++) {
- void *rec = otf + 12 + i * 16; /* an otf table record */
+ void *rec = otf->off + 12 + i * 16; /* an otf table record */
if (!strncmp(rec, name, 4))
- return otf + U32(rec, 8);
+ return otf->otf + U32(rec, 8);
}
return NULL;
}
/* obtain postscript font name from name table */
-static void otf_name(void *otf, void *tab)
+static void otf_name(struct otf *otf, void *tab)
{
char name[256];
void *str = tab + U16(tab, 4); /* storage area */
@@ -103,13 +105,13 @@
if (pid == 1 && eid == 0 && lid == 0 && nid == 6) {
memcpy(name, str + off, len);
name[len] = '\0';
- trfn_psfont(name);
+ snprintf(otf->name, sizeof(otf->name), "%s", name);
}
}
}
/* parse otf cmap format 4 subtable */
-static void otf_cmap4(void *otf, void *cmap4)
+static void otf_cmap4(struct otf *otf, void *cmap4)
{
int nsegs;
void *ends, *begs, *deltas, *offsets;
@@ -137,7 +139,7 @@
}
/* parse otf cmap header */
-static void otf_cmap(void *otf, void *cmap)
+static void otf_cmap(struct otf *otf, void *cmap)
{
int nrecs = U16(cmap, 2);
int i;
@@ -152,7 +154,7 @@
}
}
-static void otf_post(void *otf, void *post)
+static void otf_post(struct otf *otf, void *post)
{
void *post2; /* version 2.0 header */
void *index; /* glyph name indices */
@@ -178,7 +180,7 @@
}
}
-static void otf_glyf(void *otf, void *glyf)
+static void otf_glyf(struct otf *otf, void *glyf)
{
void *maxp = otf_table(otf, "maxp");
void *head = otf_table(otf, "head");
@@ -204,7 +206,7 @@
}
}
-static void otf_hmtx(void *otf, void *hmtx)
+static void otf_hmtx(struct otf *otf, void *hmtx)
{
void *hhea = otf_table(otf, "hhea");
int n;
@@ -216,7 +218,7 @@
glyph_wid[i] = glyph_wid[n - 1];
}
-static void otf_kern(void *otf, void *kern)
+static void otf_kern(struct otf *otf, void *kern)
{
int off = 4;
int i, j;
@@ -231,8 +233,8 @@
int c1 = U16(tab, 14 + 6 * j);
int c2 = U16(tab, 14 + 6 * j + 2);
int val = S16(tab, 14 + 6 * j + 4);
- trfn_kern(glyph_name[c1], glyph_name[c2],
- owid(val));
+ mkfn_kern(glyph_name[c1], glyph_name[c2],
+ uwid(val));
}
}
}
@@ -350,7 +352,7 @@
int i;
for (i = 0; i < 8; i++) {
if (fmt & (1 << i)) {
- if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
+ if (abs(uwid(S16(rec, off))) >= MAX(1, mkfn_kmin))
return 0;
off += 2;
}
@@ -359,7 +361,7 @@
}
/* single adjustment positioning */
-static void otf_gpostype1(void *otf, void *sub, char *feat)
+static void otf_gpostype1(struct otf *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int vfmt = U16(sub, 4);
@@ -391,7 +393,7 @@
}
/* pair adjustment positioning */
-static void otf_gpostype2(void *otf, void *sub, char *feat)
+static void otf_gpostype2(struct otf *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int vfmt1 = U16(sub, 4); /* valuerecord 1 */
@@ -454,7 +456,7 @@
}
/* cursive attachment positioning */
-static void otf_gpostype3(void *otf, void *sub, char *feat)
+static void otf_gpostype3(struct otf *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int *cov, *icov, *ocov;
@@ -484,9 +486,8 @@
if (prev) {
int dx = -uwid(S16(sub, prev + 2));
int dy = -uwid(S16(sub, prev + 4));
- if (otf_r2l(feat)) {
+ if (otf_r2l(feat))
dx += uwid(glyph_wid[cov[i]]);
- }
printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
feat, igrp, glyph_name[cov[i]],
0, 0, dx, dy);
@@ -506,7 +507,7 @@
}
/* mark-to-base attachment positioning */
-static void otf_gpostype4(void *otf, void *sub, char *feat)
+static void otf_gpostype4(struct otf *otf, void *sub, char *feat)
{
int fmt = U16(sub, 0);
int *mcov; /* mark coverage */
@@ -601,7 +602,7 @@
}
/* single substitution */
-static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
+static void otf_gsubtype1(struct otf *otf, void *sub, char *feat, struct gctx *ctx)
{
int *cov;
int fmt = U16(sub, 0);
@@ -635,7 +636,7 @@
}
/* alternate substitution */
-static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
+static void otf_gsubtype3(struct otf *otf, void *sub, char *feat, struct gctx *ctx)
{
int *cov;
int fmt = U16(sub, 0);
@@ -660,7 +661,7 @@
}
/* ligature substitution */
-static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
+static void otf_gsubtype4(struct otf *otf, void *sub, char *feat, struct gctx *ctx)
{
int fmt = U16(sub, 0);
int *cov;
@@ -689,7 +690,7 @@
}
/* chaining contextual substitution */
-static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
+static void otf_gsubtype6(struct otf *otf, void *sub, char *feat, void *gsub)
{
struct gctx ctx = {{0}};
void *lookups = gsub + U16(gsub, 8);
@@ -755,7 +756,7 @@
};
/* parse the given gsub/gpos feature table */
-static int otf_featrec(void *otf, void *gtab, void *featrec,
+static int otf_featrec(struct otf *otf, void *gtab, void *featrec,
char *stag, char *ltag,
struct otflookup *lookups, int lookups_n)
{
@@ -783,7 +784,7 @@
}
/* parse the given language table and its feature tables */
-static int otf_lang(void *otf, void *gtab, void *lang, char *stag, char *ltag,
+static int otf_lang(struct otf *otf, void *gtab, void *lang, char *stag, char *ltag,
struct otflookup *lookups, int lookups_n)
{
void *feats = gtab + U16(gtab, 6);
@@ -815,13 +816,13 @@
struct otflookup *l2 = v2;
if (strcmp(l1->scrp, l2->scrp))
return strcmp(l1->scrp, l2->scrp);
- if (trfn_featrank(l1->scrp, l1->feat) != trfn_featrank(l1->scrp, l2->feat))
- return trfn_featrank(l1->scrp, l1->feat) - trfn_featrank(l1->scrp, l2->feat);
+ if (mkfn_featrank(l1->scrp, l1->feat) != mkfn_featrank(l1->scrp, l2->feat))
+ return mkfn_featrank(l1->scrp, l1->feat) - mkfn_featrank(l1->scrp, l2->feat);
return l1->lookup - l2->lookup;
}
/* extract lookup tables for all features of the given gsub/gpos table */
-static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
+static int otf_gtab(struct otf *otf, void *gpos, struct otflookup *lookups)
{
void *scripts = gpos + U16(gpos, 4);
int nscripts, nlangs;
@@ -834,11 +835,11 @@
void *grec = scripts + 2 + 6 * i;
memcpy(stag, grec, 4);
stag[4] = '\0';
- if (!trfn_script(stag, nscripts))
+ if (!mkfn_script(stag, nscripts))
continue;
script = scripts + U16(grec, 4);
nlangs = U16(script, 2);
- if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
+ if (U16(script, 0) && mkfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
n = otf_lang(otf, gpos, script + U16(script, 0),
stag, "", lookups, n);
for (j = 0; j < nlangs; j++) {
@@ -845,7 +846,7 @@
void *lrec = script + 4 + 6 * j;
memcpy(ltag, lrec, 4);
ltag[4] = '\0';
- if (trfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
+ if (mkfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
n = otf_lang(otf, gpos, script + U16(lrec, 4),
stag, ltag, lookups, n);
}
@@ -854,12 +855,14 @@
return n;
}
-static void otf_gpos(void *otf, void *gpos)
+static void otf_gpos(struct otf *otf, void *gpos)
{
struct otflookup lookups[NLOOKUPS];
void *lookuplist = gpos + U16(gpos, 8);
int nlookups = otf_gtab(otf, gpos, lookups);
int i, j;
+ if (mkfn_dry)
+ return;
for (i = 0; i < nlookups; i++) {
void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
int ltype = U16(lookup, 0);
@@ -892,12 +895,14 @@
}
}
-static void otf_gsub(void *otf, void *gsub)
+static void otf_gsub(struct otf *otf, void *gsub)
{
struct otflookup lookups[NLOOKUPS];
void *lookuplist = gsub + U16(gsub, 8);
int nlookups = otf_gtab(otf, gsub, lookups);
int i, j;
+ if (mkfn_dry)
+ return;
for (i = 0; i < nlookups; i++) {
void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
int ltype = U16(lookup, 0);
@@ -1040,7 +1045,7 @@
dst[len] = '\0';
}
-static void otf_cff(void *otf, void *cff)
+static void otf_cff(struct otf *otf, void *cff)
{
void *nameidx; /* name index */
void *topidx; /* top dict index */
@@ -1067,8 +1072,8 @@
if (cffidx_cnt(nameidx) > 0) {
char name[256] = "";
memcpy(name, cffidx_get(nameidx, 0), cffidx_len(nameidx, 0));
- if (name[0])
- trfn_psfont(name);
+ if (name[0] && !otf->name[0])
+ snprintf(otf->name, sizeof(otf->name), "%s", name);
}
/* read charset: glyph to character name */
if (!badcff && U8(charset, 0) == 0) {
@@ -1100,20 +1105,30 @@
return sbuf_done(sb);
}
-static char *otf_buf;
+static void otf_feat(struct otf *otf)
+{
+ if (otf_table(otf, "GSUB"))
+ otf_gsub(otf, otf_table(otf, "GSUB"));
+ if (otf_table(otf, "GPOS"))
+ otf_gpos(otf, otf_table(otf, "GPOS"));
+}
-int otf_read(void)
+int otf_offsettable(void *otf_otf, void *otf_off)
{
int i;
- otf_buf = otf_input(0);
- upm = U16(otf_table(otf_buf, "head"), 18);
- otf_name(otf_buf, otf_table(otf_buf, "name"));
- otf_cmap(otf_buf, otf_table(otf_buf, "cmap"));
- otf_post(otf_buf, otf_table(otf_buf, "post"));
- if (otf_table(otf_buf, "glyf"))
- otf_glyf(otf_buf, otf_table(otf_buf, "glyf"));
- if (otf_table(otf_buf, "CFF "))
- otf_cff(otf_buf, otf_table(otf_buf, "CFF "));
+ unsigned tag = U32(otf_off, 0);
+ struct otf otf_cur = {otf_otf, otf_off};
+ struct otf *otf = &otf_cur;
+ if (tag != 0x00010000 && tag != 0x4F54544F)
+ return 1;
+ upm = U16(otf_table(otf, "head"), 18);
+ otf_name(otf, otf_table(otf, "name"));
+ otf_cmap(otf, otf_table(otf, "cmap"));
+ otf_post(otf, otf_table(otf, "post"));
+ if (otf_table(otf, "glyf"))
+ otf_glyf(otf, otf_table(otf, "glyf"));
+ if (otf_table(otf, "CFF "))
+ otf_cff(otf, otf_table(otf, "CFF "));
for (i = 0; i < glyph_n; i++) {
if (!glyph_name[i][0]) {
if (glyph_code[i])
@@ -1122,28 +1137,39 @@
sprintf(glyph_name[i], "gl%05X", i);
}
}
- otf_hmtx(otf_buf, otf_table(otf_buf, "hmtx"));
+ otf_hmtx(otf, otf_table(otf, "hmtx"));
+ if (!mkfn_font(otf->name))
+ return 0;
for (i = 0; i < glyph_n; i++) {
- trfn_char(glyph_name[i], -1,
+ mkfn_char(glyph_name[i], -1,
glyph_code[i] != 0xffff ? glyph_code[i] : 0,
- owid(glyph_wid[i]),
- owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
- owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
+ uwid(glyph_wid[i]),
+ uwid(glyph_bbox[i][0]), uwid(glyph_bbox[i][1]),
+ uwid(glyph_bbox[i][2]), uwid(glyph_bbox[i][3]));
}
- if (otf_table(otf_buf, "kern"))
- otf_kern(otf_buf, otf_table(otf_buf, "kern"));
+ mkfn_header(otf->name);
+ if (otf_table(otf, "kern"))
+ otf_kern(otf, otf_table(otf, "kern"));
+ otf_feat(otf);
return 0;
}
-void otf_feat(int r, int k, int w)
+int otf_read(void)
{
- res = r;
- kmin = k;
- warn = w;
- if (otf_table(otf_buf, "GSUB"))
- otf_gsub(otf_buf, otf_table(otf_buf, "GSUB"));
- if (otf_table(otf_buf, "GPOS"))
- otf_gpos(otf_buf, otf_table(otf_buf, "GPOS"));
+ char *otf_buf = otf_input(0);
+ unsigned tag = U32(otf_buf, 0);
+ int n, i;
+ if (tag == 0x00010000 || tag == 0x4F54544F)
+ return otf_offsettable(otf_buf, otf_buf);
+ if (tag != 0x74746366)
+ return 1;
+ /* OpenType Collections */
+ n = U32(otf_buf, 8);
+ for (i = 0; i < n; i++) {
+ void *off = otf_buf + U32(otf_buf, 12 + i * 4);
+ otf_offsettable(otf_buf, off);
+ }
+ return 0;
}
/* glyph groups */
--- a/sbuf.c
+++ b/sbuf.c
@@ -3,7 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "sbuf.h"
+#include "mkfn.h"
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
--- a/sbuf.h
+++ /dev/null
@@ -1,8 +1,0 @@
-/* variable length string buffer */
-struct sbuf *sbuf_make(void);
-void sbuf_free(struct sbuf *sb);
-char *sbuf_done(struct sbuf *sb);
-void sbuf_str(struct sbuf *sbuf, char *s);
-void sbuf_mem(struct sbuf *sbuf, char *s, int len);
-char *sbuf_buf(struct sbuf *sb);
-void sbuf_printf(struct sbuf *sbuf, char *s, ...);
--- a/tab.c
+++ b/tab.c
@@ -1,7 +1,7 @@
/* A Dictionary */
#include <stdlib.h>
#include <string.h>
-#include "tab.h"
+#include "mkfn.h"
struct tab {
char **keys;
--- a/tab.h
+++ /dev/null
@@ -1,4 +1,0 @@
-struct tab *tab_alloc(int sz);
-void tab_free(struct tab *tab);
-void tab_put(struct tab *tab, char *k, void *v);
-void *tab_get(struct tab *tab, char *k);
--- a/trfn.c
+++ b/trfn.c
@@ -2,37 +2,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "sbuf.h"
-#include "tab.h"
-#include "trfn.h"
+#include "mkfn.h"
#include "trfn_agl.h"
#include "trfn_ch.h"
-#define WX(w) (((w) < 0 ? (w) - trfn_div / 20 : (w) + trfn_div / 20) * (long) 10 / trfn_div)
#define LEN(a) ((sizeof(a) / sizeof((a)[0])))
#define HEXDIGS "0123456789ABCDEF"
#define NCHAR 8 /* number of characters per glyph */
#define GNLEN 64 /* glyph name length */
-#define AGLLEN 8192 /* adobe glyphlist length */
-static struct sbuf *sbuf_char; /* characters */
-static struct sbuf *sbuf_kern; /* kerning pairs */
-static int trfn_div; /* divisor of widths x 10 */
-static int trfn_swid; /* space width */
-static int trfn_special; /* special flag */
-static int trfn_kmin; /* minimum kerning value */
-static int trfn_bbox; /* include bounding box */
-static int trfn_noligs; /* suppress ligatures */
-static int trfn_pos; /* include glyph positions */
-static char trfn_ligs[8192]; /* font ligatures */
-static char trfn_ligs2[8192]; /* font ligatures, whose length is two */
-static char trfn_trname[256]; /* font troff name */
-static char trfn_psname[256]; /* font ps name */
-static char trfn_path[4096]; /* font path */
+/* for buffering the output */
+static struct sbuf *sbuf_char; /* character definitions */
+/* handling ligatures */
+static char mkfn_ligs[8192]; /* font ligatures */
+static char mkfn_ligs2[8192]; /* font ligatures, whose length is two */
/* character type */
-static int trfn_asc; /* minimum height of glyphs with ascender */
-static int trfn_desc; /* minimum depth of glyphs with descender */
-
+static int mkfn_asc; /* minimum height of glyphs with ascender */
+static int mkfn_desc; /* minimum depth of glyphs with descender */
/* lookup tables */
static struct tab *tab_agl; /* adobe glyph list table */
static struct tab *tab_alts; /* character aliases table */
@@ -224,7 +210,7 @@
static void trfn_ligput(char *c)
{
- char *dst = strlen(c) == 2 ? trfn_ligs2 : trfn_ligs;
+ char *dst = strlen(c) == 2 ? mkfn_ligs2 : mkfn_ligs;
sprintf(strchr(dst, '\0'), "%s ", c);
}
@@ -247,25 +233,25 @@
{
int typ = 0;
int c = !s[0] || s[1] ? 0 : (unsigned char) *s;
- if (c == 't' && !trfn_asc)
- trfn_asc = ury;
+ if (c == 't' && !mkfn_asc)
+ mkfn_asc = ury;
if ((c == 'g' || c == 'j' || c == 'p' || c == 'q' || c == 'y') &&
- (!trfn_desc || trfn_desc < lly))
- trfn_desc = lly;
- if (!trfn_desc || !trfn_asc) {
+ (!mkfn_desc || mkfn_desc < lly))
+ mkfn_desc = lly;
+ if (!mkfn_desc || !mkfn_asc) {
if (c > 0 && c < 128)
return ctype_ascii[c];
return 3;
}
- if (!trfn_desc || lly <= trfn_desc)
+ if (!mkfn_desc || lly <= mkfn_desc)
typ |= 1;
- if (!trfn_asc || ury >= trfn_asc)
+ if (!mkfn_asc || ury >= mkfn_asc)
typ |= 2;
return typ;
}
/* n is the position and u is the unicode codepoint */
-void trfn_char(char *psname, int n, int u, int wid,
+void mkfn_char(char *psname, int n, int u, int wid,
int llx, int lly, int urx, int ury)
{
char uc[GNLEN]; /* mapping unicode character */
@@ -276,23 +262,22 @@
if (trfn_name(uc, psname, u))
strcpy(uc, "---");
trfn_aglexceptions(uc);
- if (trfn_pos && n >= 0 && n < 256)
+ if (mkfn_pos && n >= 0 && n < 256)
sprintf(pos, "%d", n);
- if (trfn_pos && n < 0 && !uc[1] && uc[0] >= 32 && uc[0] <= 125)
+ if (mkfn_pos && n < 0 && !uc[1] && uc[0] >= 32 && uc[0] <= 125)
if (!strchr(psname, '.'))
sprintf(pos, "%d", uc[0]);
typ = trfn_type(!strchr(psname, '.') ? uc : "", lly, ury);
- if (!trfn_swid && (!strcmp(" ", uc) || !strcmp(" ", uc)))
- trfn_swid = WX(wid);
+ if (!mkfn_swid && (!strcmp(" ", uc) || !strcmp(" ", uc)))
+ mkfn_swid = wid;
/* printing troff charset */
if (isspace((unsigned char) uc[0]) || strchr(uc, ' '))
strcpy(uc, "---"); /* space not allowed in char names */
if (strcmp("---", uc))
trfn_lig(uc);
- sbuf_printf(sbuf_char, "char %s\t%d", uc, WX(wid));
- if (trfn_bbox && (llx || lly || urx || ury))
- sbuf_printf(sbuf_char, ",%d,%d,%d,%d",
- WX(llx), WX(lly), WX(urx), WX(ury));
+ sbuf_printf(sbuf_char, "char %s\t%d", uc, wid);
+ if (mkfn_bbox && (llx || lly || urx || ury))
+ sbuf_printf(sbuf_char, ",%d,%d,%d,%d", llx, lly, urx, ury);
sbuf_printf(sbuf_char, "\t%d\t%s\t%s\n", typ, psname, pos);
a_tr = tab_get(tab_alts, uc);
while (a_tr && *a_tr)
@@ -299,58 +284,31 @@
sbuf_printf(sbuf_char, "char %s\t\"\n", *a_tr++);
}
-void trfn_kern(char *c1, char *c2, int x)
+void mkfn_kern(char *c1, char *c2, int x)
{
- if (WX(x) && abs(WX(x)) >= trfn_kmin)
- sbuf_printf(sbuf_kern, "kern %s\t%s\t%d\n", c1, c2, WX(x));
+ if (x && abs(x) >= mkfn_kmin)
+ if (!mkfn_dry)
+ printf("kern %s\t%s\t%d\n", c1, c2, x);
}
-void trfn_trfont(char *name)
+/* print spacewidth and ligature lines */
+void trfn_header(void)
{
- if (!trfn_trname[0])
- strcpy(trfn_trname, name);
+ printf("spacewidth %d\n", mkfn_swid);
+ if (!mkfn_noligs)
+ printf("ligatures %s%s0\n", mkfn_ligs, mkfn_ligs2);
}
-void trfn_psfont(char *name)
+/* print character definitions */
+void trfn_cdefs(void)
{
- if (!trfn_psname[0])
- strcpy(trfn_psname, name);
-}
-
-void trfn_pspath(char *name)
-{
- if (!trfn_path[0])
- strcpy(trfn_path, name);
-}
-
-void trfn_print(void)
-{
- if (trfn_trname[0])
- printf("name %s\n", trfn_trname);
- if (trfn_psname[0])
- printf("fontname %s\n", trfn_psname);
- if (trfn_path[0])
- printf("fontpath %s\n", trfn_path);
- printf("spacewidth %d\n", trfn_swid);
- if (!trfn_noligs)
- printf("ligatures %s%s0\n", trfn_ligs, trfn_ligs2);
- if (trfn_special)
- printf("special\n");
fputs(sbuf_buf(sbuf_char), stdout);
- fputs(sbuf_buf(sbuf_kern), stdout);
}
-void trfn_init(int res, int spc, int kmin, int bbox, int ligs, int pos)
+void trfn_init(void)
{
int i;
- trfn_div = 72000 / res;
- trfn_special = spc;
- trfn_kmin = kmin;
- trfn_bbox = bbox;
- trfn_noligs = !ligs;
- trfn_pos = pos;
sbuf_char = sbuf_make();
- sbuf_kern = sbuf_make();
tab_agl = tab_alloc(LEN(agl));
for (i = 0; i < LEN(agl); i++)
tab_put(tab_agl, agl[i][0], agl[i][1]);
@@ -362,7 +320,6 @@
void trfn_done(void)
{
sbuf_free(sbuf_char);
- sbuf_free(sbuf_kern);
tab_free(tab_alts);
if (tab_agl)
tab_free(tab_agl);
--- a/trfn.h
+++ /dev/null
@@ -1,11 +1,0 @@
-void trfn_init(int res, int special, int kmin, int bbox, int ligs, int pos);
-void trfn_done(void);
-void trfn_trfont(char *name);
-void trfn_psfont(char *fontname);
-void trfn_print(void);
-void trfn_char(char *c, int n, int u, int wid, int llx, int lly, int urx, int ury);
-void trfn_kern(char *c1, char *c2, int x);
-int trfn_script(char *script, int nscripts);
-int trfn_lang(char *lang, int nlangs);
-int trfn_featrank(char *scrp, char *feat);
-void trfn_pspath(char *name);