shithub: neatroff

Download patch

ref: acfc4e9fc9fd7cf704960d9d3182bea09e0ea681
parent: 9b80100cf16bf8bfa27209442d84544e209edacf
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Feb 19 16:37:48 EST 2014

ren: italic correction escapes

This patch also allows troff font description files to include the
bounding box of the glyphs; the third column in the charset section,
which contains glyph widths, may include four more numbers just like
groff.  However, in neatroff these numbers specify glyph bounding box.

--- a/font.c
+++ b/font.c
@@ -36,7 +36,7 @@
 	return i >= 0 ? &fn->glyphs[i] : NULL;
 }
 
-static 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 type)
 {
 	int i = fn->nglyphs++;
 	struct glyph *g;
@@ -43,7 +43,6 @@
 	g = &fn->glyphs[i];
 	strcpy(g->id, id);
 	strcpy(g->name, name);
-	g->wid = wid;
 	g->type = type;
 	g->font = fn;
 	fn->gnext[i] = fn->ghead[(unsigned char) id[0]];
@@ -144,7 +143,8 @@
 	char name[ILNLEN];
 	char id[ILNLEN];
 	struct glyph *glyph = NULL;
-	int wid, type;
+	int llx = 0, lly = 0, urx = 0, ury = 0;
+	int type;
 	if (fn->n >= NGLYPHS)
 		return 1;
 	if (fscanf(fin, "%s %s", name, tok) != 2)
@@ -154,12 +154,16 @@
 	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);
+		if (!glyph) {
+			glyph = font_glyphput(fn, id, name, type);
+			sscanf(tok, "%d,%d,%d,%d,%d", &glyph->wid,
+				&llx, &lly, &urx, &ury);
+			glyph->ic = MAX(0, urx - glyph->wid);
+			glyph->icleft = MAX(0, -llx);
+		}
 	}
 	strcpy(fn->c[fn->n], name);
 	fn->g[fn->n] = glyph;
--- a/ren.c
+++ b/ren.c
@@ -671,6 +671,12 @@
 	case '^':
 		wb_hmov(wb, SC_EM / 12);
 		break;
+	case '/':
+		wb_italiccorrection(wb);
+		break;
+	case ',':
+		wb_italiccorrectionleft(wb);
+		break;
 	case '{':
 	case '}':
 		break;
@@ -719,7 +725,7 @@
 			}
 			return;
 		}
-		if (strchr(" bCcDdfHhkLlmNoprSsuvXxz0^|{}&", c[1])) {
+		if (strchr(" bCcDdfHhkLlmNoprSsuvXxz0^|{}&/,", c[1])) {
 			argnext(arg, c[1], next, back);
 			if (c[1] == 'S' || c[1] == 'H')
 				return;			/* not implemented */
--- a/roff.h
+++ b/roff.h
@@ -121,6 +121,7 @@
 	struct font *font;	/* glyph font */
 	int wid;		/* character width */
 	int type;		/* character type; ascender/descender */
+	int ic, icleft;		/* italic and left italic correction */
 };
 
 struct font {
@@ -234,6 +235,7 @@
 	int els_neg, els_pos;	/* extra line spacing */
 	int h, v;		/* buffer vertical and horizontal positions */
 	int ct, sb, st;		/* \w registers */
+	int icleft_ll;		/* len after the pending left italic correction */
 	/* saving previous characters added via wb_put() */
 	char prev_c[LIGLEN][GNLEN];
 	int prev_l[LIGLEN];	/* sbuf_len(&wb->sbuf) before wb_put() calls */
@@ -259,6 +261,8 @@
 void wb_drawxbeg(struct wb *wb, int c);
 void wb_drawxdot(struct wb *wb, int h, int v);
 void wb_drawxend(struct wb *wb);
+void wb_italiccorrection(struct wb *wb);
+void wb_italiccorrectionleft(struct wb *wb);
 void wb_cat(struct wb *wb, struct wb *src);
 int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flg);
 int wb_wid(struct wb *wb);
--- a/wb.c
+++ b/wb.c
@@ -18,6 +18,7 @@
 	wb->r_f = -1;
 	wb->r_s = -1;
 	wb->r_m = -1;
+	wb->icleft_ll = -1;
 }
 
 void wb_done(struct wb *wb)
@@ -125,6 +126,11 @@
 	return i < wb->prev_n ? wb->prev_c[i] : NULL;
 }
 
+static struct glyph *wb_prevglyph(struct wb *wb)
+{
+	return wb_prev(wb, 0) ? dev_glyph(wb_prev(wb, 0), R_F(wb)) : NULL;
+}
+
 void wb_put(struct wb *wb, char *c)
 {
 	struct glyph *g;
@@ -149,6 +155,9 @@
 		g = dev_glyph(c, R_F(wb));
 	}
 	wb_font(wb);
+	if (g && !zerowidth && g->icleft && wb->icleft_ll == sbuf_len(&wb->sbuf))
+		wb_hmov(wb, charwid_base(R_F(wb), R_S(wb), g->icleft));
+	wb->icleft_ll = -1;
 	wb_prevcheck(wb);		/* make sure wb->prev_c[] is valid */
 	ll = sbuf_len(&wb->sbuf);	/* sbuf length before inserting c */
 	if (!c[1] || c[0] == c_ec || c[0] == c_ni || utf8one(c)) {
@@ -487,4 +496,17 @@
 	if (p)
 		dohyph(sbuf_buf(&wb->sbuf), p, p != dp, w1, w2);
 	return !p;
+}
+
+void wb_italiccorrection(struct wb *wb)
+{
+	struct glyph *g = wb_prevglyph(wb);
+	if (g && g->ic)
+		wb_hmov(wb, charwid_base(R_F(wb), R_S(wb), g->ic));
+}
+
+void wb_italiccorrectionleft(struct wb *wb)
+{
+	wb_font(wb);
+	wb->icleft_ll = sbuf_len(&wb->sbuf);
 }