ref: 91209e2dd54a7563a6e5ac4ce613c1ec9049054c
parent: 65a15243b12b41bf4bb4c1795aea9587dacb660b
author: Ali Gholami Rudi <[email protected]>
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)