shithub: neatroff

Download patch

ref: 0645b041fc978afa94f089c122c6745abfeffea6
parent: 5dce7fb843ac8985602e83074f64382ba36440d3
author: Ali Gholami Rudi <ali@rudi.ir>
date: Fri Aug 15 15:29:08 EDT 2014

font: .fzoom request

--- a/fmt.c
+++ b/fmt.c
@@ -200,7 +200,7 @@
 
 void fmt_space(struct fmt *fmt)
 {
-	fmt->gap += N_SS(n_f, n_s);
+	fmt->gap += font_swid(dev_font(n_f), n_s, n_ss);
 }
 
 int fmt_newline(struct fmt *f)
@@ -301,10 +301,11 @@
 static int fmt_wordgap(struct fmt *f)
 {
 	int nls = f->nls || f->nls_sup;
+	int swid = font_swid(dev_font(n_f), n_s, n_ss);
 	if (f->eos && f->nwords)
-		if ((nls && !f->gap) || (!nls && f->gap == 2 * N_SS(n_f, n_s)))
-			return N_SS(n_f, n_s) + N_SSS(n_f, n_s);
-	return (nls && !f->gap && f->nwords) ? N_SS(n_f, n_s) : f->gap;
+		if ((nls && !f->gap) || (!nls && f->gap == 2 * swid))
+			return swid + font_swid(dev_font(n_f), n_s, n_sss);
+	return (nls && !f->gap && f->nwords) ? swid : f->gap;
 }
 
 /* insert wb into fmt */
--- a/font.c
+++ b/font.c
@@ -4,6 +4,8 @@
 #include <string.h>
 #include "roff.h"
 
+/* convert wid in device unitwidth size to size sz */
+#define DEVWID(sz, wid)		(((wid) * (sz) + (dev_uwid / 2)) / dev_uwid)
 #define GHASH(g1, g2)		((((g2) + 1) << 16) | ((g1) + 1))
 
 #define GF_PAT		1	/* gsub/gpos pattern glyph */
@@ -32,7 +34,7 @@
 	char fontname[FNLEN];
 	int spacewid;
 	int special;
-	int cs, bd;			/* for .cs and .bd requests */
+	int cs, bd, zoom;		/* for .cs, .bd, .fzoom requests */
 	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 */
@@ -648,11 +650,27 @@
 	return fn->special;
 }
 
-int font_spacewid(struct font *fn)
+/* return width w for the given font and size */
+int font_wid(struct font *fn, int sz, int w)
 {
-	return fn->spacewid;
+	sz = font_zoom(fn, sz);
+	return w >= 0 ? DEVWID(sz, w) : -DEVWID(sz, -w);
 }
 
+/* glyph width, where cfn is the current font and fn is glyph's font */
+int font_gwid(struct font *fn, struct font *cfn, int sz, int w)
+{
+	if (cfn->cs)
+		return cfn->cs * (font_zoom(fn, sz) * SC_IN / 72) / 36;
+	return font_wid(fn, sz, w) + (font_getbd(cfn) ? font_getbd(cfn) - 1 : 0);
+}
+
+/* space width for the give word space or sentence space */
+int font_swid(struct font *fn, int sz, int ss)
+{
+	return font_gwid(fn, fn, sz, (fn->spacewid * ss + 6) / 12);
+}
+
 int font_getcs(struct font *fn)
 {
 	return fn->cs;
@@ -671,6 +689,16 @@
 void font_setbd(struct font *fn, int bd)
 {
 	fn->bd = bd;
+}
+
+int font_zoom(struct font *fn, int sz)
+{
+	return fn->zoom ? (sz * fn->zoom + 500) / 1000 : sz;
+}
+
+void font_setzoom(struct font *fn, int zoom)
+{
+	fn->zoom = zoom;
 }
 
 /* enable/disable font features; returns the previous value */
--- a/out.c
+++ b/out.c
@@ -111,15 +111,18 @@
 	outnn("\n");
 }
 
-static void outg(char *c, int fn)
+static void outg(char *c, int fn, int sz)
 {
 	int ofn = o_f;
+	int osz = o_s;
 	out_ft(fn);
+	out_ps(sz);
 	if (utf8one(c))
 		outnn("c%s%s", c, c[1] ? "\n" : "");
 	else
 		out("C%s\n", c[0] == c_ec && c[1] == '(' ? c + 2 : c);
 	out_ft(ofn);
+	out_ps(osz);
 }
 
 static void outc(char *c)
@@ -129,16 +132,16 @@
 	int cwid, bwid;
 	if (!g)
 		return;
-	cwid = charwid(o_f, o_s, g->wid);
-	bwid = DEVWID(o_s, g->wid);
+	cwid = font_gwid(g->font, dev_font(o_f), o_s, g->wid);
+	bwid = font_wid(g->font, o_s, g->wid);
 	if (font_mapped(g->font, c))
 		c = g->name;
 	if (font_getcs(fn))
 		outnn("h%d", (cwid - bwid) / 2);
-	outg(c, dev_fontpos(g->font));
+	outg(c, dev_fontpos(g->font), font_zoom(g->font, o_s));
 	if (font_getbd(fn)) {
 		outnn("h%d", font_getbd(fn) - 1);
-		outg(c, dev_fontpos(g->font));
+		outg(c, dev_fontpos(g->font), font_zoom(g->font, o_s));
 		outnn("h%d", -font_getbd(fn) + 1);
 	}
 	if (font_getcs(fn))
@@ -177,7 +180,7 @@
 				out_clr(clr_get(c));
 			break;
 		case 's':
-			out_ps(eval_re(c, o_s, '\0'));
+			out_ps(eval(c, 0));
 			break;
 		case 'v':
 			outnn("v%d", eval(c, 'v'));
--- a/ren.c
+++ b/ren.c
@@ -85,14 +85,6 @@
 	}
 }
 
-int charwid(int fn, int sz, int wid)
-{
-	struct font *f = dev_font(fn);
-	if (font_getcs(f))
-		return font_getcs(f) * SC_EM / 36;
-	return DEVWID(sz, wid) + (font_getbd(f) ? font_getbd(f) - 1 : 0);
-}
-
 int f_divreg(void)
 {
 	return cdiv ? cdiv->reg : -1;
@@ -270,7 +262,7 @@
 static int zwid(void)
 {
 	struct glyph *g = dev_glyph("0", n_f);
-	return charwid(n_f, n_s, g ? g->wid : 0);
+	return g ? font_gwid(g->font, dev_font(n_f), n_s, g->wid) : 0;
 }
 
 /* append the line number to the output line */
@@ -609,7 +601,7 @@
 {
 	switch (c) {
 	case ' ':
-		wb_hmov(wb, N_SS(n_f, n_s));
+		wb_hmov(wb, font_swid(dev_font(n_f), n_s, n_ss));
 		break;
 	case 'b':
 		ren_bcmd(wb, arg);
--- a/roff.h
+++ b/roff.h
@@ -160,6 +160,7 @@
 int dev_pos(char *id);
 struct font *dev_font(int pos);
 int dev_fontpos(struct font *fn);
+struct glyph *dev_glyph(char *c, int fn);
 
 /* font-related functions */
 struct font *font_open(char *path);
@@ -169,25 +170,19 @@
 int font_map(struct font *fn, char *name, struct glyph *gl);
 int font_mapped(struct font *fn, char *name);
 int font_special(struct font *fn);
-int font_spacewid(struct font *fn);
+int font_wid(struct font *fn, int sz, int w);
+int font_gwid(struct font *fn, struct font *cfn, int sz, int w);
+int font_swid(struct font *fn, int sz, int ss);
 void font_setcs(struct font *fn, int cs);
 int font_getcs(struct font *fn);
 void font_setbd(struct font *fn, int bd);
 int font_getbd(struct font *fn);
+void font_setzoom(struct font *fn, int zoom);
+int font_zoom(struct font *fn, int sz);
 int font_feat(struct font *fn, char *name, int val);
 int font_layout(struct font *fn, struct glyph **src, int nsrc, int sz,
 		struct glyph **dst, int *dmap,
 		int *x, int *y, int *xadv, int *yadv, int lg, int kn);
-
-/* glyph handling functions */
-struct glyph *dev_glyph(char *c, int fn);
-int charwid(int fn, int sz, int wid);
-
-/* convert wid in device unitwidth size to size sz */
-#define DEVWID(sz, wid)		(((wid) * (sz) + (dev_uwid / 2)) / dev_uwid)
-/* the amount of word and sentence space for the given font and size */
-#define N_SS(fn, sz)	(charwid((fn), (sz), (font_spacewid(dev_font(fn)) * n_ss + 6) / 12))
-#define N_SSS(fn, sz)	(charwid((fn), (sz), (font_spacewid(dev_font(fn)) * n_sss + 6) / 12))
 
 /* different layers of neatroff */
 int in_next(void);		/* input layer */
--- a/tr.c
+++ b/tr.c
@@ -450,18 +450,22 @@
 
 static void tr_cs(char **args)
 {
-	if (!args[1])
-		return;
-	font_setcs(dev_font(dev_pos(args[1])), args[2] ? eval(args[2], 0) : 0);
+	struct font *fn = args[1] ? dev_font(dev_pos(args[1])) : NULL;
+	if (fn)
+		font_setcs(fn, args[2] ? eval(args[2], 0) : 0);
 }
 
+static void tr_fzoom(char **args)
+{
+	struct font *fn = args[1] ? dev_font(dev_pos(args[1])) : NULL;
+	if (fn)
+		font_setzoom(fn, args[2] ? eval(args[2], 0) : 0);
+}
+
 static void tr_ff(char **args)
 {
-	struct font *fn;
+	struct font *fn = args[1] ? dev_font(dev_pos(args[1])) : NULL;
 	int i;
-	if (!args[2])
-		return;
-	fn = dev_font(dev_pos(args[1]));
 	for (i = 2; i <= NARGS; i++)
 		if (fn && args[i] && args[i][0] && args[i][1])
 			font_feat(fn, args[i] + 1, args[i][0] == '+');
@@ -888,6 +892,7 @@
 	{"fp", tr_fp},
 	{"fspecial", tr_fspecial},
 	{"ft", tr_ft},
+	{"fzoom", tr_fzoom},
 	{"hc", tr_hc},
 	{"hcode", tr_hcode},
 	{"hpf", tr_hpf},
--- a/wb.c
+++ b/wb.c
@@ -12,8 +12,6 @@
 /* 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
@@ -136,7 +134,7 @@
 		g = dev_glyph(c, wb->f);
 	}
 	if (g && !zerowidth && wb->icleft && glyph_icleft(g))
-		wb_hmov(wb, SDEVWID(wb->s, glyph_icleft(g)));
+		wb_hmov(wb, font_wid(g->font, wb->s, glyph_icleft(g)));
 	wb->icleft = 0;
 	if (!c[1] || c[0] == c_ec || c[0] == c_ni || utf8one(c)) {
 		if (c[0] == c_ni && c[1] == c_ec)
@@ -151,11 +149,11 @@
 	}
 	if (!zerowidth) {
 		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 : 0);
+			wb_bbox(wb, font_wid(g->font, wb->s, g->llx),
+				font_wid(g->font, wb->s, g->lly),
+				font_wid(g->font, wb->s, g->urx),
+				font_wid(g->font, wb->s, g->ury));
+		wb->h += g ? font_gwid(g->font, dev_font(wb->f), wb->s, g->wid) : 0;
 		wb->ct |= g ? g->type : 0;
 		wb_stsb(wb);
 	}
@@ -224,9 +222,9 @@
 			gdst, dmap, x, y, xadv, yadv, n_lg, n_kn);
 	for (i = 0; i < dst_n; i++) {
 		if (x[i])
-			wb_hmov(wb, SDEVWID(wb->s, x[i]));
+			wb_hmov(wb, font_wid(fn, wb->s, x[i]));
 		if (y[i])
-			wb_vmov(wb, SDEVWID(wb->s, y[i]));
+			wb_vmov(wb, font_wid(fn, wb->s, y[i]));
 		if (src_hyph[dmap[i]])
 			wb_putbuf(wb, c_hc);
 		if (gdst[i] == gsrc[dmap[i]])
@@ -234,9 +232,9 @@
 		else
 			wb_putbuf(wb, gdst[i]->name);
 		if (x[i] || xadv[i])
-			wb_hmov(wb, SDEVWID(wb->s, xadv[i] - x[i]));
+			wb_hmov(wb, font_wid(fn, wb->s, xadv[i] - x[i]));
 		if (y[i] || yadv[i])
-			wb_vmov(wb, SDEVWID(wb->s, yadv[i] - y[i]));
+			wb_vmov(wb, font_wid(fn, wb->s, yadv[i] - y[i]));
 	}
 	wb->sub_n = 0;
 	wb->icleft = 0;
@@ -251,7 +249,7 @@
 	}
 	if (c[0] == ' ') {
 		wb_flushsub(wb);
-		wb_hmov(wb, N_SS(R_F(wb), R_S(wb)));
+		wb_hmov(wb, font_swid(dev_font(R_F(wb)), R_S(wb), n_ss));
 		return;
 	}
 	if (wb_pendingfont(wb) || wb->sub_n == LEN(wb->sub_c))
@@ -468,7 +466,7 @@
 {
 	struct glyph *g = wb_prevglyph(wb);
 	if (g && glyph_ic(g))
-		wb_hmov(wb, SDEVWID(wb->s, glyph_ic(g)));
+		wb_hmov(wb, font_wid(g->font, wb->s, glyph_ic(g)));
 }
 
 void wb_italiccorrectionleft(struct wb *wb)
@@ -507,5 +505,5 @@
 int wb_dashwid(struct wb *wb)
 {
 	struct glyph *g = dev_glyph("hy", wb->f);
-	return charwid(wb->f, wb->s, g ? g->wid : 0);
+	return g ? font_gwid(g->font, dev_font(wb->f), wb->s, g->wid) : 0;
 }