From e59abf73546274ddadf77fed7eb9f9d452cdbb6a Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Sun, 24 Nov 2013 18:50:20 +0330 Subject: [PATCH] tr: add .fmap to map character names to glyphs --- font.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++---------------- out.c | 2 ++ roff.h | 3 +++ tr.c | 11 +++++++++++ 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/font.c b/font.c index aa91e3c..422b0c8 100644 --- a/font.c +++ b/font.c @@ -3,29 +3,39 @@ #include #include "roff.h" -struct glyph *font_find(struct font *fn, char *name) +/* look up a character in chead[]/cnext[] table */ +static int font_cidx(struct font *fn, char *name) { int i = fn->chead[(unsigned char) name[0]]; - while (i >= 0) { - if (!strcmp(name, fn->c[i])) - return fn->g[i]; + while (i >= 0 && strcmp(name, fn->c[i])) i = fn->cnext[i]; - } - return NULL; + return i; } -struct glyph *font_glyph(struct font *fn, char *id) +/* look up a character in ghead[]/gnext[] table */ +static int font_gidx(struct font *fn, char *id) { int i = fn->ghead[(unsigned char) id[0]]; - while (i >= 0) { - if (!strcmp(fn->glyphs[i].id, id)) - return &fn->glyphs[i]; + while (i >= 0 && strcmp(fn->glyphs[i].id, id)) i = fn->gnext[i]; - } - return NULL; + return i; +} + +struct glyph *font_find(struct font *fn, char *name) +{ + int i = font_cidx(fn, name); + if (i < 0) + return NULL; + return fn->g_map[i] ? fn->g_map[i] : fn->g[i]; +} + +struct glyph *font_glyph(struct font *fn, char *id) +{ + int i = font_gidx(fn, id); + return i >= 0 ? &fn->glyphs[i] : NULL; } -struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type) +static struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type) { int i = fn->nglyphs++; struct glyph *g; @@ -40,6 +50,31 @@ struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int return g; } +/* map character name to the given glyph */ +int font_map(struct font *fn, char *name, struct glyph *g) +{ + int i = font_cidx(fn, name); + if (g && g->font != fn) + return 1; + if (i < 0) { + if (fn->n >= NGLYPHS) + return 1; + i = fn->n++; + strcpy(fn->c[i], name); + fn->cnext[i] = fn->chead[(unsigned char) name[0]]; + fn->chead[(unsigned char) name[0]] = i; + } + fn->g_map[i] = g; + return 0; +} + +/* return nonzero if character name has been mapped with font_map() */ +int font_mapped(struct font *fn, char *name) +{ + int i = font_cidx(fn, name); + return i >= 0 && fn->g_map[i]; +} + /* glyph index in fn->glyphs[] */ static int font_idx(struct font *fn, struct glyph *g) { @@ -115,15 +150,15 @@ static int font_readchar(struct font *fn, FILE *fin) return 1; if (!strcmp("---", name)) sprintf(name, "c%04d", fn->n); - if (strcmp("\"", tok)) { + if (!strcmp("\"", tok)) { + glyph = fn->g[fn->n - 1]; + } else { wid = atoi(tok); if (fscanf(fin, "%d %s", &type, id) != 2) return 1; glyph = font_glyph(fn, id); if (!glyph) glyph = font_glyphput(fn, id, name, wid, type); - } else { - glyph = fn->g[fn->n - 1]; } strcpy(fn->c[fn->n], name); fn->g[fn->n] = glyph; diff --git a/out.c b/out.c index b097ff0..f9b339e 100644 --- a/out.c +++ b/out.c @@ -126,6 +126,8 @@ static void outc(char *c) struct glyph *g = dev_glyph(c, o_f); int cwid = charwid(o_f, o_s, g ? g->wid : SC_DW); int bwid = charwid_base(o_f, o_s, g ? g->wid : SC_DW); + if (g && font_mapped(g->font, c)) + c = g->name; if (dev_getcs(o_f)) outnn("h%d", (cwid - bwid) / 2); outg(c, g ? dev_fontpos(g->font) : o_f); diff --git a/roff.h b/roff.h index 5398f48..3dcae60 100644 --- a/roff.h +++ b/roff.h @@ -110,6 +110,7 @@ struct font { /* charset section characters */ char c[NGLYPHS][GNLEN]; /* character names in charset */ struct glyph *g[NGLYPHS]; /* character glyphs in charset */ + struct glyph *g_map[NGLYPHS]; /* character remapped via font_map() */ int n; /* number of characters in charset */ /* glyph table based on the first character of their id fields in glyphs[] */ int ghead[256]; /* glyph list heads */ @@ -148,6 +149,8 @@ struct glyph *font_find(struct font *fn, char *name); int font_lig(struct font *fn, char **c, int n); int font_kern(struct font *fn, char *c1, char *c2); int font_islig(struct font *fn, char *s); +int font_map(struct font *fn, char *name, struct glyph *gl); +int font_mapped(struct font *fn, char *name); /* glyph handling functions */ struct glyph *dev_glyph(char *c, int fn); diff --git a/tr.c b/tr.c index 42b7e31..dd547df 100644 --- a/tr.c +++ b/tr.c @@ -637,6 +637,16 @@ static void tr_ochar(char **args) cdef_add(args[1], args[2], args[3]); } +static void tr_fmap(char **args) +{ + struct font *fn; + if (!args[2]) + return; + fn = dev_font(dev_pos(args[1])); + if (fn) + font_map(fn, args[2], args[3] ? font_glyph(fn, args[3]) : NULL); +} + static char *arg_regname(char *s, int len) { char *e = n_cp ? s + 2 : s + len; @@ -838,6 +848,7 @@ static struct cmd { {"ex", tr_ex}, {"fc", tr_fc}, {"fi", tr_fi}, + {"fmap", tr_fmap}, {"fp", tr_fp}, {"fspecial", tr_fspecial}, {"ft", tr_ft}, -- 2.11.4.GIT