shithub: neatroff

Download patch

ref: 91209e2dd54a7563a6e5ac4ce613c1ec9049054c
parent: 65a15243b12b41bf4bb4c1795aea9587dacb660b
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Mar 5 21:16:22 EST 2014

wb: report the bounding box for \w

The bounding box is reported via bbllx, bblly, bburx and bbury
number registers.

--- a/font.c
+++ b/font.c
@@ -143,7 +143,6 @@
 	char name[ILNLEN];
 	char id[ILNLEN];
 	struct glyph *glyph = NULL;
-	int llx = 0, lly = 0, urx = 0, ury = 0;
 	int type;
 	if (fn->n >= NGLYPHS)
 		return 1;
@@ -160,9 +159,7 @@
 		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);
+				&glyph->llx, &glyph->lly, &glyph->urx, &glyph->ury);
 		}
 	}
 	strcpy(fn->c[fn->n], name);
--- a/ren.c
+++ b/ren.c
@@ -784,7 +784,7 @@
 	}
 	odiv_end();
 	n = wb_wid(&wb);
-	wb_wconf(&wb, &n_ct, &n_st, &n_sb);
+	wb_wconf(&wb, &n_ct, &n_st, &n_sb, &n_llx, &n_lly, &n_urx, &n_ury);
 	wb_done(&wb);
 	return n;
 }
--- a/roff.h
+++ b/roff.h
@@ -120,7 +120,7 @@
 	struct font *font;	/* glyph font */
 	int wid;		/* character width */
 	int type;		/* character type; ascender/descender */
-	int ic, icleft;		/* italic and left italic correction */
+	int llx, lly, urx, ury;	/* character bounding box */
 };
 
 struct font {
@@ -236,6 +236,7 @@
 	int els_neg, els_pos;	/* extra line spacing */
 	int h, v;		/* buffer vertical and horizontal positions */
 	int ct, sb, st;		/* \w registers */
+	int llx, lly, urx, ury;	/* bounding box */
 	int icleft_ll;		/* len after the pending left italic correction */
 	/* saving previous characters added via wb_put() */
 	char prev_c[LIGLEN][GNLEN];
@@ -269,7 +270,8 @@
 int wb_wid(struct wb *wb);
 int wb_empty(struct wb *wb);
 int wb_eos(struct wb *wb);
-void wb_wconf(struct wb *wb, int *ct, int *st, int *sb);
+void wb_wconf(struct wb *wb, int *ct, int *st, int *sb,
+		int *llx, int *lly, int *urx, int *ury);
 int wb_lig(struct wb *wb, char *c);
 int wb_kern(struct wb *wb, char *c);
 
@@ -462,6 +464,10 @@
 #define n_lt		(*nreg(map(".lt")))	/* .lt value */
 #define n_t0		(*nreg(map(".lt0")))	/* previous .lt value */
 #define n_v0		(*nreg(map(".v0")))	/* last .v */
+#define n_llx		(*nreg(map("bbllx")))	/* \w bounding box */
+#define n_lly		(*nreg(map("bblly")))	/* \w bounding box */
+#define n_urx		(*nreg(map("bburx")))	/* \w bounding box */
+#define n_ury		(*nreg(map("bbury")))	/* \w bounding box */
 
 /* functions for implementing read-only registers */
 int f_nexttrap(void);	/* .t */
--- a/wb.c
+++ b/wb.c
@@ -4,9 +4,18 @@
 #include <string.h>
 #include "roff.h"
 
+/* the current font, size and color */
 #define R_F(wb)		((wb)->r_f >= 0 ? (wb)->r_f : n_f)	/* current font */
 #define R_S(wb)		((wb)->r_s >= 0 ? (wb)->r_s : n_s)	/* current size */
 #define R_M(wb)		((wb)->r_m >= 0 ? (wb)->r_m : n_m)	/* current color */
+/* italic correction */
+#define glyph_ic(g)	(MAX(0, (g)->urx - (g)->wid))
+#define glyph_icleft(g)	(MAX(0, -(g)->llx))
+/* like DEVWID() but handles negative w */
+#define SDEVWID(sz, w)	((w) >= 0 ? DEVWID((sz), (w)) : -DEVWID((sz), -(w)))
+/* the maximum and minimum values of bounding box coordinates */
+#define BBMAX		(1 << 29)
+#define BBMIN		-BBMAX
 
 void wb_init(struct wb *wb)
 {
@@ -19,6 +28,10 @@
 	wb->r_s = -1;
 	wb->r_m = -1;
 	wb->icleft_ll = -1;
+	wb->llx = BBMAX;
+	wb->lly = BBMAX;
+	wb->urx = BBMIN;
+	wb->ury = BBMIN;
 }
 
 void wb_done(struct wb *wb)
@@ -29,10 +42,19 @@
 /* update wb->st and wb->sb */
 static void wb_stsb(struct wb *wb)
 {
-	wb->st = MIN(wb->st, wb->v - SC_EM);
+	wb->st = MIN(wb->st, wb->v - (wb->s * SC_IN / 72));
 	wb->sb = MAX(wb->sb, wb->v);
 }
 
+/* update bounding box */
+static void wb_bbox(struct wb *wb, int llx, int lly, int urx, int ury)
+{
+	wb->llx = MIN(wb->llx, wb->h + llx);
+	wb->lly = MIN(wb->lly, -wb->v + lly);
+	wb->urx = MAX(wb->urx, wb->h + urx);
+	wb->ury = MAX(wb->ury, -wb->v + ury);
+}
+
 /* append font and size to the buffer if needed */
 static void wb_font(struct wb *wb)
 {
@@ -161,8 +183,9 @@
 		memmove(c, c + 1, strlen(c));
 		g = dev_glyph(c, R_F(wb));
 	}
-	if (g && !zerowidth && g->icleft && wb->icleft_ll == sbuf_len(&wb->sbuf))
-		wb_hmov(wb, DEVWID(R_S(wb), g->icleft));
+	if (g && !zerowidth && wb->icleft_ll == sbuf_len(&wb->sbuf))
+		if (glyph_icleft(g))
+			wb_hmov(wb, SDEVWID(R_S(wb), glyph_icleft(g)));
 	wb->icleft_ll = -1;
 	wb_font(wb);
 	wb_prevcheck(wb);		/* make sure wb->prev_c[] is valid */
@@ -180,7 +203,12 @@
 	}
 	if (!zerowidth) {
 		wb_prevput(wb, c, ll);
-		wb->h += charwid(R_F(wb), R_S(wb), g ? g->wid : SC_DW);
+		if (!n_cp && g)
+			wb_bbox(wb, SDEVWID(wb->s, g->llx),
+				SDEVWID(wb->s, g->lly),
+				SDEVWID(wb->s, g->urx),
+				SDEVWID(wb->s, g->ury));
+		wb->h += charwid(wb->f, wb->s, g ? g->wid : SC_DW);
 		wb->ct |= g ? g->type : 0;
 		wb_stsb(wb);
 	}
@@ -365,11 +393,16 @@
 	return wb_prev(wb, i) && strchr(".?!", wb_prev(wb, i)[0]);
 }
 
-void wb_wconf(struct wb *wb, int *ct, int *st, int *sb)
+void wb_wconf(struct wb *wb, int *ct, int *st, int *sb,
+		int *llx, int *lly, int *urx, int *ury)
 {
 	*ct = wb->ct;
 	*st = -wb->st;
 	*sb = -wb->sb;
+	*llx = wb->llx < BBMAX ? wb->llx : 0;
+	*lly = wb->lly < BBMAX ? -wb->lly : 0;
+	*urx = wb->urx > BBMIN ? wb->urx : 0;
+	*ury = wb->ury > BBMIN ? -wb->ury : 0;
 }
 
 /* skip troff requests; return 1 if read c_hc */
@@ -508,8 +541,8 @@
 void wb_italiccorrection(struct wb *wb)
 {
 	struct glyph *g = wb_prevglyph(wb);
-	if (g && g->ic)
-		wb_hmov(wb, DEVWID(wb->s, g->ic));
+	if (g && glyph_ic(g))
+		wb_hmov(wb, SDEVWID(wb->s, glyph_ic(g)));
 }
 
 void wb_italiccorrectionleft(struct wb *wb)