ref: 2ee5253d1d503d7a4df868624a44447ac6e0e414
parent: 5a8e4a87bfb94588190b39bf2032ed03f66afc8e
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Aug 16 16:17:04 EDT 2014
font: allow .fmap to shadow characters
--- a/font.c
+++ b/font.c
@@ -38,12 +38,8 @@
struct glyph gl[NGLYPHS]; /* glyphs present in the font */
int gl_n; /* number of glyphs in the font */
struct dict gl_dict; /* mapping from gl[i].id to i */
- /* charset mapping */
- char ch[NGLYPHS][GNLEN]; /* character names in charset */
- short ch_g[NGLYPHS]; /* ch[i] is mapped to ch_g[i] */
- short ch_map[NGLYPHS]; /* character remapped via font_map() */
- int ch_n; /* number of characters in charset */
- struct dict ch_dict; /* mapping from ch[i] to i */
+ struct dict ch_dict; /* charset mapping */
+ struct dict ch_map; /* characters mapped via font_map() */
/* font features */
char feat_name[NFEATS][8]; /* feature names */
int feat_set[NFEATS]; /* feature enabled */
@@ -60,10 +56,10 @@
/* find a glyph by its name */
struct glyph *font_find(struct font *fn, char *name)
{
- int i = dict_get(&fn->ch_dict, name);
- if (i < 0)
- return NULL;
- return fn->gl + (fn->ch_map[i] >= 0 ? fn->ch_map[i] : fn->ch_g[i]);
+ int i = dict_get(&fn->ch_map, name);
+ if (i == -1)
+ i = dict_get(&fn->ch_dict, name);
+ return i >= 0 ? fn->gl + i : NULL;
}
/* find a glyph by its device-dependent identifier */
@@ -86,20 +82,13 @@
return g;
}
-/* map character name to the given glyph */
-int font_map(struct font *fn, char *name, struct glyph *g)
+/* map character name to the given glyph; remove the mapping if id is NULL */
+int font_map(struct font *fn, char *name, char *id)
{
- int i = dict_get(&fn->ch_dict, name);
- if (g && g->font != fn)
- return 1;
- if (i < 0) {
- if (fn->ch_n >= NGLYPHS)
- return 1;
- i = fn->ch_n++;
- strcpy(fn->ch[i], name);
- dict_put(&fn->ch_dict, fn->ch[i], i);
- }
- fn->ch_map[i] = g - fn->gl;
+ int gidx = -1;
+ if (id)
+ gidx = font_glyph(fn, id) ? font_glyph(fn, id) - fn->gl : -2;
+ dict_put(&fn->ch_map, name, gidx);
return 0;
}
@@ -106,8 +95,7 @@
/* return nonzero if character name has been mapped with font_map() */
int font_mapped(struct font *fn, char *name)
{
- int i = dict_get(&fn->ch_dict, name);
- return i >= 0 && fn->ch_map[i] >= 0;
+ return dict_get(&fn->ch_map, name) != -1;
}
/* enable/disable ligatures; first bit for liga and the second bit for rlig */
@@ -346,39 +334,32 @@
return ndst;
}
-static int font_readchar(struct font *fn, FILE *fin)
+static int font_readchar(struct font *fn, FILE *fin, int *n, struct glyph **g)
{
char tok[ILNLEN];
char name[ILNLEN];
char id[ILNLEN];
- struct glyph *glyph = NULL;
int type;
- if (fn->ch_n + 1 == NGLYPHS)
+ if (*n + 1 == NGLYPHS)
errmsg("neatroff: NGLYPHS too low\n");
- if (fn->ch_n >= NGLYPHS)
+ if (*n >= NGLYPHS)
return 0;
if (fscanf(fin, "%s %s", name, tok) != 2)
return 1;
if (!strcmp("---", name))
- sprintf(name, "c%04d", fn->ch_n);
- if (!strcmp("\"", tok)) {
- glyph = fn->gl + fn->ch_g[fn->ch_n - 1];
- } else {
+ sprintf(name, "c%04d", *n);
+ if (strcmp("\"", tok)) {
if (fscanf(fin, "%d %s", &type, id) != 2)
return 1;
- glyph = font_glyph(fn, id);
- if (!glyph) {
- glyph = font_glyphput(fn, id, name, type);
- sscanf(tok, "%hd,%hd,%hd,%hd,%hd", &glyph->wid,
- &glyph->llx, &glyph->lly,
- &glyph->urx, &glyph->ury);
+ *g = font_glyph(fn, id);
+ if (!*g) {
+ *g = font_glyphput(fn, id, name, type);
+ sscanf(tok, "%hd,%hd,%hd,%hd,%hd", &(*g)->wid,
+ &(*g)->llx, &(*g)->lly, &(*g)->urx, &(*g)->ury);
}
}
- strcpy(fn->ch[fn->ch_n], name);
- fn->ch_g[fn->ch_n] = glyph - fn->gl;
- fn->ch_map[fn->ch_n] = -1;
- dict_put(&fn->ch_dict, fn->ch[fn->ch_n], fn->ch_n);
- fn->ch_n++;
+ dict_put(&fn->ch_dict, name, *g - fn->gl);
+ (*n)++;
return 0;
}
@@ -566,6 +547,8 @@
struct font *font_open(char *path)
{
struct font *fn;
+ struct glyph *ch_g = NULL; /* last glyph in the charset */
+ int ch_n = 0; /* number of glyphs in the charset */
char tok[ILNLEN];
FILE *fin;
char ligs[512][GNLEN];
@@ -581,10 +564,11 @@
}
memset(fn, 0, sizeof(*fn));
dict_init(&fn->gl_dict, NGLYPHS, -1, 0, 0);
- dict_init(&fn->ch_dict, NGLYPHS, -1, 0, 0);
+ dict_init(&fn->ch_dict, NGLYPHS, -1, 1, 0);
+ dict_init(&fn->ch_map, NGLYPHS, -1, 1, 0);
while (fscanf(fin, "%s", tok) == 1) {
if (!strcmp("char", tok)) {
- font_readchar(fn, fin);
+ font_readchar(fn, fin, &ch_n, &ch_g);
} else if (!strcmp("kern", tok)) {
font_readkern(fn, fin);
} else if (!strcmp("ligatures", tok)) {
@@ -609,7 +593,7 @@
} else if (!strcmp("fontname", tok)) {
fscanf(fin, "%s", fn->fontname);
} else if (!strcmp("charset", tok)) {
- while (!font_readchar(fn, fin))
+ while (!font_readchar(fn, fin, &ch_n, &ch_g))
;
break;
}
@@ -642,6 +626,7 @@
free(fn->ggrp[i]);
dict_done(&fn->gl_dict);
dict_done(&fn->ch_dict);
+ dict_done(&fn->ch_map);
free(fn);
}
--- a/roff.h
+++ b/roff.h
@@ -132,7 +132,6 @@
void dict_done(struct dict *d);
void dict_put(struct dict *d, char *key, long val);
long dict_get(struct dict *d, char *key);
-long dict_pop(struct dict *d, char *key);
int dict_idx(struct dict *d, char *key);
char *dict_key(struct dict *d, int idx);
long dict_val(struct dict *d, int idx);
@@ -167,7 +166,7 @@
void font_close(struct font *fn);
struct glyph *font_glyph(struct font *fn, char *id);
struct glyph *font_find(struct font *fn, char *name);
-int font_map(struct font *fn, char *name, struct glyph *gl);
+int font_map(struct font *fn, char *name, char *id);
int font_mapped(struct font *fn, char *name);
int font_special(struct font *fn);
int font_wid(struct font *fn, int sz, int w);
--- a/tr.c
+++ b/tr.c
@@ -682,12 +682,9 @@
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);
+ struct font *fn = args[1] ? dev_font(dev_pos(args[1])) : NULL;
+ if (fn && args[2])
+ font_map(fn, args[2], args[3]);
}
static void arg_regname(struct sbuf *sbuf)