xref: /freebsd-src/contrib/mandoc/term_ps.c (revision 61d06d6bd19dafe8ea971dd43e8328fa1b473456)
1*61d06d6bSBaptiste Daroussin /*	$Id: term_ps.c,v 1.91 2017/11/10 23:42:52 schwarze Exp $ */
2*61d06d6bSBaptiste Daroussin /*
3*61d06d6bSBaptiste Daroussin  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*61d06d6bSBaptiste Daroussin  * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
5*61d06d6bSBaptiste Daroussin  * Copyright (c) 2017 Marc Espie <espie@openbsd.org>
6*61d06d6bSBaptiste Daroussin  *
7*61d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
8*61d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
9*61d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
10*61d06d6bSBaptiste Daroussin  *
11*61d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
12*61d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*61d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
14*61d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*61d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*61d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*61d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*61d06d6bSBaptiste Daroussin  */
19*61d06d6bSBaptiste Daroussin #include "config.h"
20*61d06d6bSBaptiste Daroussin 
21*61d06d6bSBaptiste Daroussin #include <sys/types.h>
22*61d06d6bSBaptiste Daroussin 
23*61d06d6bSBaptiste Daroussin #include <assert.h>
24*61d06d6bSBaptiste Daroussin #if HAVE_ERR
25*61d06d6bSBaptiste Daroussin #include <err.h>
26*61d06d6bSBaptiste Daroussin #endif
27*61d06d6bSBaptiste Daroussin #include <stdarg.h>
28*61d06d6bSBaptiste Daroussin #include <stdint.h>
29*61d06d6bSBaptiste Daroussin #include <stdio.h>
30*61d06d6bSBaptiste Daroussin #include <stdlib.h>
31*61d06d6bSBaptiste Daroussin #include <string.h>
32*61d06d6bSBaptiste Daroussin #include <unistd.h>
33*61d06d6bSBaptiste Daroussin 
34*61d06d6bSBaptiste Daroussin #include "mandoc_aux.h"
35*61d06d6bSBaptiste Daroussin #include "out.h"
36*61d06d6bSBaptiste Daroussin #include "term.h"
37*61d06d6bSBaptiste Daroussin #include "manconf.h"
38*61d06d6bSBaptiste Daroussin #include "main.h"
39*61d06d6bSBaptiste Daroussin 
40*61d06d6bSBaptiste Daroussin /* These work the buffer used by the header and footer. */
41*61d06d6bSBaptiste Daroussin #define	PS_BUFSLOP	  128
42*61d06d6bSBaptiste Daroussin 
43*61d06d6bSBaptiste Daroussin /* Convert PostScript point "x" to an AFM unit. */
44*61d06d6bSBaptiste Daroussin #define	PNT2AFM(p, x) \
45*61d06d6bSBaptiste Daroussin 	(size_t)((double)(x) * (1000.0 / (double)(p)->ps->scale))
46*61d06d6bSBaptiste Daroussin 
47*61d06d6bSBaptiste Daroussin /* Convert an AFM unit "x" to a PostScript points */
48*61d06d6bSBaptiste Daroussin #define	AFM2PNT(p, x) \
49*61d06d6bSBaptiste Daroussin 	((double)(x) / (1000.0 / (double)(p)->ps->scale))
50*61d06d6bSBaptiste Daroussin 
51*61d06d6bSBaptiste Daroussin struct	glyph {
52*61d06d6bSBaptiste Daroussin 	unsigned short	  wx; /* WX in AFM */
53*61d06d6bSBaptiste Daroussin };
54*61d06d6bSBaptiste Daroussin 
55*61d06d6bSBaptiste Daroussin struct	font {
56*61d06d6bSBaptiste Daroussin 	const char	 *name; /* FontName in AFM */
57*61d06d6bSBaptiste Daroussin #define	MAXCHAR		  95 /* total characters we can handle */
58*61d06d6bSBaptiste Daroussin 	struct glyph	  gly[MAXCHAR]; /* glyph metrics */
59*61d06d6bSBaptiste Daroussin };
60*61d06d6bSBaptiste Daroussin 
61*61d06d6bSBaptiste Daroussin struct	termp_ps {
62*61d06d6bSBaptiste Daroussin 	int		  flags;
63*61d06d6bSBaptiste Daroussin #define	PS_INLINE	 (1 << 0)	/* we're in a word */
64*61d06d6bSBaptiste Daroussin #define	PS_MARGINS	 (1 << 1)	/* we're in the margins */
65*61d06d6bSBaptiste Daroussin #define	PS_NEWPAGE	 (1 << 2)	/* new page, no words yet */
66*61d06d6bSBaptiste Daroussin #define	PS_BACKSP	 (1 << 3)	/* last character was backspace */
67*61d06d6bSBaptiste Daroussin 	size_t		  pscol;	/* visible column (AFM units) */
68*61d06d6bSBaptiste Daroussin 	size_t		  pscolnext;	/* used for overstrike */
69*61d06d6bSBaptiste Daroussin 	size_t		  psrow;	/* visible row (AFM units) */
70*61d06d6bSBaptiste Daroussin 	size_t		  lastrow;	/* psrow of the previous word */
71*61d06d6bSBaptiste Daroussin 	char		 *psmarg;	/* margin buf */
72*61d06d6bSBaptiste Daroussin 	size_t		  psmargsz;	/* margin buf size */
73*61d06d6bSBaptiste Daroussin 	size_t		  psmargcur;	/* cur index in margin buf */
74*61d06d6bSBaptiste Daroussin 	char		  last;		/* last non-backspace seen */
75*61d06d6bSBaptiste Daroussin 	enum termfont	  lastf;	/* last set font */
76*61d06d6bSBaptiste Daroussin 	enum termfont	  nextf;	/* building next font here */
77*61d06d6bSBaptiste Daroussin 	size_t		  scale;	/* font scaling factor */
78*61d06d6bSBaptiste Daroussin 	size_t		  pages;	/* number of pages shown */
79*61d06d6bSBaptiste Daroussin 	size_t		  lineheight;	/* line height (AFM units) */
80*61d06d6bSBaptiste Daroussin 	size_t		  top;		/* body top (AFM units) */
81*61d06d6bSBaptiste Daroussin 	size_t		  bottom;	/* body bottom (AFM units) */
82*61d06d6bSBaptiste Daroussin 	const char	 *medianame;	/* for DocumentMedia and PageSize */
83*61d06d6bSBaptiste Daroussin 	size_t		  height;	/* page height (AFM units */
84*61d06d6bSBaptiste Daroussin 	size_t		  width;	/* page width (AFM units) */
85*61d06d6bSBaptiste Daroussin 	size_t		  lastwidth;	/* page width before last ll */
86*61d06d6bSBaptiste Daroussin 	size_t		  left;		/* body left (AFM units) */
87*61d06d6bSBaptiste Daroussin 	size_t		  header;	/* header pos (AFM units) */
88*61d06d6bSBaptiste Daroussin 	size_t		  footer;	/* footer pos (AFM units) */
89*61d06d6bSBaptiste Daroussin 	size_t		  pdfbytes;	/* current output byte */
90*61d06d6bSBaptiste Daroussin 	size_t		  pdflastpg;	/* byte of last page mark */
91*61d06d6bSBaptiste Daroussin 	size_t		  pdfbody;	/* start of body object */
92*61d06d6bSBaptiste Daroussin 	size_t		 *pdfobjs;	/* table of object offsets */
93*61d06d6bSBaptiste Daroussin 	size_t		  pdfobjsz;	/* size of pdfobjs */
94*61d06d6bSBaptiste Daroussin };
95*61d06d6bSBaptiste Daroussin 
96*61d06d6bSBaptiste Daroussin static	int		  ps_hspan(const struct termp *,
97*61d06d6bSBaptiste Daroussin 				const struct roffsu *);
98*61d06d6bSBaptiste Daroussin static	size_t		  ps_width(const struct termp *, int);
99*61d06d6bSBaptiste Daroussin static	void		  ps_advance(struct termp *, size_t);
100*61d06d6bSBaptiste Daroussin static	void		  ps_begin(struct termp *);
101*61d06d6bSBaptiste Daroussin static	void		  ps_closepage(struct termp *);
102*61d06d6bSBaptiste Daroussin static	void		  ps_end(struct termp *);
103*61d06d6bSBaptiste Daroussin static	void		  ps_endline(struct termp *);
104*61d06d6bSBaptiste Daroussin static	void		  ps_growbuf(struct termp *, size_t);
105*61d06d6bSBaptiste Daroussin static	void		  ps_letter(struct termp *, int);
106*61d06d6bSBaptiste Daroussin static	void		  ps_pclose(struct termp *);
107*61d06d6bSBaptiste Daroussin static	void		  ps_plast(struct termp *);
108*61d06d6bSBaptiste Daroussin static	void		  ps_pletter(struct termp *, int);
109*61d06d6bSBaptiste Daroussin static	void		  ps_printf(struct termp *, const char *, ...)
110*61d06d6bSBaptiste Daroussin 				__attribute__((__format__ (__printf__, 2, 3)));
111*61d06d6bSBaptiste Daroussin static	void		  ps_putchar(struct termp *, char);
112*61d06d6bSBaptiste Daroussin static	void		  ps_setfont(struct termp *, enum termfont);
113*61d06d6bSBaptiste Daroussin static	void		  ps_setwidth(struct termp *, int, int);
114*61d06d6bSBaptiste Daroussin static	struct termp	 *pspdf_alloc(const struct manoutput *, enum termtype);
115*61d06d6bSBaptiste Daroussin static	void		  pdf_obj(struct termp *, size_t);
116*61d06d6bSBaptiste Daroussin 
117*61d06d6bSBaptiste Daroussin /*
118*61d06d6bSBaptiste Daroussin  * We define, for the time being, three fonts: bold, oblique/italic, and
119*61d06d6bSBaptiste Daroussin  * normal (roman).  The following table hard-codes the font metrics for
120*61d06d6bSBaptiste Daroussin  * ASCII, i.e., 32--127.
121*61d06d6bSBaptiste Daroussin  */
122*61d06d6bSBaptiste Daroussin 
123*61d06d6bSBaptiste Daroussin static	const struct font fonts[TERMFONT__MAX] = {
124*61d06d6bSBaptiste Daroussin 	{ "Times-Roman", {
125*61d06d6bSBaptiste Daroussin 		{ 250 },
126*61d06d6bSBaptiste Daroussin 		{ 333 },
127*61d06d6bSBaptiste Daroussin 		{ 408 },
128*61d06d6bSBaptiste Daroussin 		{ 500 },
129*61d06d6bSBaptiste Daroussin 		{ 500 },
130*61d06d6bSBaptiste Daroussin 		{ 833 },
131*61d06d6bSBaptiste Daroussin 		{ 778 },
132*61d06d6bSBaptiste Daroussin 		{ 333 },
133*61d06d6bSBaptiste Daroussin 		{ 333 },
134*61d06d6bSBaptiste Daroussin 		{ 333 },
135*61d06d6bSBaptiste Daroussin 		{ 500 },
136*61d06d6bSBaptiste Daroussin 		{ 564 },
137*61d06d6bSBaptiste Daroussin 		{ 250 },
138*61d06d6bSBaptiste Daroussin 		{ 333 },
139*61d06d6bSBaptiste Daroussin 		{ 250 },
140*61d06d6bSBaptiste Daroussin 		{ 278 },
141*61d06d6bSBaptiste Daroussin 		{ 500 },
142*61d06d6bSBaptiste Daroussin 		{ 500 },
143*61d06d6bSBaptiste Daroussin 		{ 500 },
144*61d06d6bSBaptiste Daroussin 		{ 500 },
145*61d06d6bSBaptiste Daroussin 		{ 500 },
146*61d06d6bSBaptiste Daroussin 		{ 500 },
147*61d06d6bSBaptiste Daroussin 		{ 500 },
148*61d06d6bSBaptiste Daroussin 		{ 500 },
149*61d06d6bSBaptiste Daroussin 		{ 500 },
150*61d06d6bSBaptiste Daroussin 		{ 500 },
151*61d06d6bSBaptiste Daroussin 		{ 278 },
152*61d06d6bSBaptiste Daroussin 		{ 278 },
153*61d06d6bSBaptiste Daroussin 		{ 564 },
154*61d06d6bSBaptiste Daroussin 		{ 564 },
155*61d06d6bSBaptiste Daroussin 		{ 564 },
156*61d06d6bSBaptiste Daroussin 		{ 444 },
157*61d06d6bSBaptiste Daroussin 		{ 921 },
158*61d06d6bSBaptiste Daroussin 		{ 722 },
159*61d06d6bSBaptiste Daroussin 		{ 667 },
160*61d06d6bSBaptiste Daroussin 		{ 667 },
161*61d06d6bSBaptiste Daroussin 		{ 722 },
162*61d06d6bSBaptiste Daroussin 		{ 611 },
163*61d06d6bSBaptiste Daroussin 		{ 556 },
164*61d06d6bSBaptiste Daroussin 		{ 722 },
165*61d06d6bSBaptiste Daroussin 		{ 722 },
166*61d06d6bSBaptiste Daroussin 		{ 333 },
167*61d06d6bSBaptiste Daroussin 		{ 389 },
168*61d06d6bSBaptiste Daroussin 		{ 722 },
169*61d06d6bSBaptiste Daroussin 		{ 611 },
170*61d06d6bSBaptiste Daroussin 		{ 889 },
171*61d06d6bSBaptiste Daroussin 		{ 722 },
172*61d06d6bSBaptiste Daroussin 		{ 722 },
173*61d06d6bSBaptiste Daroussin 		{ 556 },
174*61d06d6bSBaptiste Daroussin 		{ 722 },
175*61d06d6bSBaptiste Daroussin 		{ 667 },
176*61d06d6bSBaptiste Daroussin 		{ 556 },
177*61d06d6bSBaptiste Daroussin 		{ 611 },
178*61d06d6bSBaptiste Daroussin 		{ 722 },
179*61d06d6bSBaptiste Daroussin 		{ 722 },
180*61d06d6bSBaptiste Daroussin 		{ 944 },
181*61d06d6bSBaptiste Daroussin 		{ 722 },
182*61d06d6bSBaptiste Daroussin 		{ 722 },
183*61d06d6bSBaptiste Daroussin 		{ 611 },
184*61d06d6bSBaptiste Daroussin 		{ 333 },
185*61d06d6bSBaptiste Daroussin 		{ 278 },
186*61d06d6bSBaptiste Daroussin 		{ 333 },
187*61d06d6bSBaptiste Daroussin 		{ 469 },
188*61d06d6bSBaptiste Daroussin 		{ 500 },
189*61d06d6bSBaptiste Daroussin 		{ 333 },
190*61d06d6bSBaptiste Daroussin 		{ 444 },
191*61d06d6bSBaptiste Daroussin 		{ 500 },
192*61d06d6bSBaptiste Daroussin 		{ 444 },
193*61d06d6bSBaptiste Daroussin 		{  500},
194*61d06d6bSBaptiste Daroussin 		{  444},
195*61d06d6bSBaptiste Daroussin 		{  333},
196*61d06d6bSBaptiste Daroussin 		{  500},
197*61d06d6bSBaptiste Daroussin 		{  500},
198*61d06d6bSBaptiste Daroussin 		{  278},
199*61d06d6bSBaptiste Daroussin 		{  278},
200*61d06d6bSBaptiste Daroussin 		{  500},
201*61d06d6bSBaptiste Daroussin 		{  278},
202*61d06d6bSBaptiste Daroussin 		{  778},
203*61d06d6bSBaptiste Daroussin 		{  500},
204*61d06d6bSBaptiste Daroussin 		{  500},
205*61d06d6bSBaptiste Daroussin 		{  500},
206*61d06d6bSBaptiste Daroussin 		{  500},
207*61d06d6bSBaptiste Daroussin 		{  333},
208*61d06d6bSBaptiste Daroussin 		{  389},
209*61d06d6bSBaptiste Daroussin 		{  278},
210*61d06d6bSBaptiste Daroussin 		{  500},
211*61d06d6bSBaptiste Daroussin 		{  500},
212*61d06d6bSBaptiste Daroussin 		{  722},
213*61d06d6bSBaptiste Daroussin 		{  500},
214*61d06d6bSBaptiste Daroussin 		{  500},
215*61d06d6bSBaptiste Daroussin 		{  444},
216*61d06d6bSBaptiste Daroussin 		{  480},
217*61d06d6bSBaptiste Daroussin 		{  200},
218*61d06d6bSBaptiste Daroussin 		{  480},
219*61d06d6bSBaptiste Daroussin 		{  541},
220*61d06d6bSBaptiste Daroussin 	} },
221*61d06d6bSBaptiste Daroussin 	{ "Times-Bold", {
222*61d06d6bSBaptiste Daroussin 		{ 250  },
223*61d06d6bSBaptiste Daroussin 		{ 333  },
224*61d06d6bSBaptiste Daroussin 		{ 555  },
225*61d06d6bSBaptiste Daroussin 		{ 500  },
226*61d06d6bSBaptiste Daroussin 		{ 500  },
227*61d06d6bSBaptiste Daroussin 		{ 1000 },
228*61d06d6bSBaptiste Daroussin 		{ 833  },
229*61d06d6bSBaptiste Daroussin 		{ 333  },
230*61d06d6bSBaptiste Daroussin 		{ 333  },
231*61d06d6bSBaptiste Daroussin 		{ 333  },
232*61d06d6bSBaptiste Daroussin 		{ 500  },
233*61d06d6bSBaptiste Daroussin 		{ 570  },
234*61d06d6bSBaptiste Daroussin 		{ 250  },
235*61d06d6bSBaptiste Daroussin 		{ 333  },
236*61d06d6bSBaptiste Daroussin 		{ 250  },
237*61d06d6bSBaptiste Daroussin 		{ 278  },
238*61d06d6bSBaptiste Daroussin 		{ 500  },
239*61d06d6bSBaptiste Daroussin 		{ 500  },
240*61d06d6bSBaptiste Daroussin 		{ 500  },
241*61d06d6bSBaptiste Daroussin 		{ 500  },
242*61d06d6bSBaptiste Daroussin 		{ 500  },
243*61d06d6bSBaptiste Daroussin 		{ 500  },
244*61d06d6bSBaptiste Daroussin 		{ 500  },
245*61d06d6bSBaptiste Daroussin 		{ 500  },
246*61d06d6bSBaptiste Daroussin 		{ 500  },
247*61d06d6bSBaptiste Daroussin 		{ 500  },
248*61d06d6bSBaptiste Daroussin 		{ 333  },
249*61d06d6bSBaptiste Daroussin 		{ 333  },
250*61d06d6bSBaptiste Daroussin 		{ 570  },
251*61d06d6bSBaptiste Daroussin 		{ 570  },
252*61d06d6bSBaptiste Daroussin 		{ 570  },
253*61d06d6bSBaptiste Daroussin 		{ 500  },
254*61d06d6bSBaptiste Daroussin 		{ 930  },
255*61d06d6bSBaptiste Daroussin 		{ 722  },
256*61d06d6bSBaptiste Daroussin 		{ 667  },
257*61d06d6bSBaptiste Daroussin 		{ 722  },
258*61d06d6bSBaptiste Daroussin 		{ 722  },
259*61d06d6bSBaptiste Daroussin 		{ 667  },
260*61d06d6bSBaptiste Daroussin 		{ 611  },
261*61d06d6bSBaptiste Daroussin 		{ 778  },
262*61d06d6bSBaptiste Daroussin 		{ 778  },
263*61d06d6bSBaptiste Daroussin 		{ 389  },
264*61d06d6bSBaptiste Daroussin 		{ 500  },
265*61d06d6bSBaptiste Daroussin 		{ 778  },
266*61d06d6bSBaptiste Daroussin 		{ 667  },
267*61d06d6bSBaptiste Daroussin 		{ 944  },
268*61d06d6bSBaptiste Daroussin 		{ 722  },
269*61d06d6bSBaptiste Daroussin 		{ 778  },
270*61d06d6bSBaptiste Daroussin 		{ 611  },
271*61d06d6bSBaptiste Daroussin 		{ 778  },
272*61d06d6bSBaptiste Daroussin 		{ 722  },
273*61d06d6bSBaptiste Daroussin 		{ 556  },
274*61d06d6bSBaptiste Daroussin 		{ 667  },
275*61d06d6bSBaptiste Daroussin 		{ 722  },
276*61d06d6bSBaptiste Daroussin 		{ 722  },
277*61d06d6bSBaptiste Daroussin 		{ 1000 },
278*61d06d6bSBaptiste Daroussin 		{ 722  },
279*61d06d6bSBaptiste Daroussin 		{ 722  },
280*61d06d6bSBaptiste Daroussin 		{ 667  },
281*61d06d6bSBaptiste Daroussin 		{ 333  },
282*61d06d6bSBaptiste Daroussin 		{ 278  },
283*61d06d6bSBaptiste Daroussin 		{ 333  },
284*61d06d6bSBaptiste Daroussin 		{ 581  },
285*61d06d6bSBaptiste Daroussin 		{ 500  },
286*61d06d6bSBaptiste Daroussin 		{ 333  },
287*61d06d6bSBaptiste Daroussin 		{ 500  },
288*61d06d6bSBaptiste Daroussin 		{ 556  },
289*61d06d6bSBaptiste Daroussin 		{ 444  },
290*61d06d6bSBaptiste Daroussin 		{  556 },
291*61d06d6bSBaptiste Daroussin 		{  444 },
292*61d06d6bSBaptiste Daroussin 		{  333 },
293*61d06d6bSBaptiste Daroussin 		{  500 },
294*61d06d6bSBaptiste Daroussin 		{  556 },
295*61d06d6bSBaptiste Daroussin 		{  278 },
296*61d06d6bSBaptiste Daroussin 		{  333 },
297*61d06d6bSBaptiste Daroussin 		{  556 },
298*61d06d6bSBaptiste Daroussin 		{  278 },
299*61d06d6bSBaptiste Daroussin 		{  833 },
300*61d06d6bSBaptiste Daroussin 		{  556 },
301*61d06d6bSBaptiste Daroussin 		{  500 },
302*61d06d6bSBaptiste Daroussin 		{  556 },
303*61d06d6bSBaptiste Daroussin 		{  556 },
304*61d06d6bSBaptiste Daroussin 		{  444 },
305*61d06d6bSBaptiste Daroussin 		{  389 },
306*61d06d6bSBaptiste Daroussin 		{  333 },
307*61d06d6bSBaptiste Daroussin 		{  556 },
308*61d06d6bSBaptiste Daroussin 		{  500 },
309*61d06d6bSBaptiste Daroussin 		{  722 },
310*61d06d6bSBaptiste Daroussin 		{  500 },
311*61d06d6bSBaptiste Daroussin 		{  500 },
312*61d06d6bSBaptiste Daroussin 		{  444 },
313*61d06d6bSBaptiste Daroussin 		{  394 },
314*61d06d6bSBaptiste Daroussin 		{  220 },
315*61d06d6bSBaptiste Daroussin 		{  394 },
316*61d06d6bSBaptiste Daroussin 		{  520 },
317*61d06d6bSBaptiste Daroussin 	} },
318*61d06d6bSBaptiste Daroussin 	{ "Times-Italic", {
319*61d06d6bSBaptiste Daroussin 		{ 250  },
320*61d06d6bSBaptiste Daroussin 		{ 333  },
321*61d06d6bSBaptiste Daroussin 		{ 420  },
322*61d06d6bSBaptiste Daroussin 		{ 500  },
323*61d06d6bSBaptiste Daroussin 		{ 500  },
324*61d06d6bSBaptiste Daroussin 		{ 833  },
325*61d06d6bSBaptiste Daroussin 		{ 778  },
326*61d06d6bSBaptiste Daroussin 		{ 333  },
327*61d06d6bSBaptiste Daroussin 		{ 333  },
328*61d06d6bSBaptiste Daroussin 		{ 333  },
329*61d06d6bSBaptiste Daroussin 		{ 500  },
330*61d06d6bSBaptiste Daroussin 		{ 675  },
331*61d06d6bSBaptiste Daroussin 		{ 250  },
332*61d06d6bSBaptiste Daroussin 		{ 333  },
333*61d06d6bSBaptiste Daroussin 		{ 250  },
334*61d06d6bSBaptiste Daroussin 		{ 278  },
335*61d06d6bSBaptiste Daroussin 		{ 500  },
336*61d06d6bSBaptiste Daroussin 		{ 500  },
337*61d06d6bSBaptiste Daroussin 		{ 500  },
338*61d06d6bSBaptiste Daroussin 		{ 500  },
339*61d06d6bSBaptiste Daroussin 		{ 500  },
340*61d06d6bSBaptiste Daroussin 		{ 500  },
341*61d06d6bSBaptiste Daroussin 		{ 500  },
342*61d06d6bSBaptiste Daroussin 		{ 500  },
343*61d06d6bSBaptiste Daroussin 		{ 500  },
344*61d06d6bSBaptiste Daroussin 		{ 500  },
345*61d06d6bSBaptiste Daroussin 		{ 333  },
346*61d06d6bSBaptiste Daroussin 		{ 333  },
347*61d06d6bSBaptiste Daroussin 		{ 675  },
348*61d06d6bSBaptiste Daroussin 		{ 675  },
349*61d06d6bSBaptiste Daroussin 		{ 675  },
350*61d06d6bSBaptiste Daroussin 		{ 500  },
351*61d06d6bSBaptiste Daroussin 		{ 920  },
352*61d06d6bSBaptiste Daroussin 		{ 611  },
353*61d06d6bSBaptiste Daroussin 		{ 611  },
354*61d06d6bSBaptiste Daroussin 		{ 667  },
355*61d06d6bSBaptiste Daroussin 		{ 722  },
356*61d06d6bSBaptiste Daroussin 		{ 611  },
357*61d06d6bSBaptiste Daroussin 		{ 611  },
358*61d06d6bSBaptiste Daroussin 		{ 722  },
359*61d06d6bSBaptiste Daroussin 		{ 722  },
360*61d06d6bSBaptiste Daroussin 		{ 333  },
361*61d06d6bSBaptiste Daroussin 		{ 444  },
362*61d06d6bSBaptiste Daroussin 		{ 667  },
363*61d06d6bSBaptiste Daroussin 		{ 556  },
364*61d06d6bSBaptiste Daroussin 		{ 833  },
365*61d06d6bSBaptiste Daroussin 		{ 667  },
366*61d06d6bSBaptiste Daroussin 		{ 722  },
367*61d06d6bSBaptiste Daroussin 		{ 611  },
368*61d06d6bSBaptiste Daroussin 		{ 722  },
369*61d06d6bSBaptiste Daroussin 		{ 611  },
370*61d06d6bSBaptiste Daroussin 		{ 500  },
371*61d06d6bSBaptiste Daroussin 		{ 556  },
372*61d06d6bSBaptiste Daroussin 		{ 722  },
373*61d06d6bSBaptiste Daroussin 		{ 611  },
374*61d06d6bSBaptiste Daroussin 		{ 833  },
375*61d06d6bSBaptiste Daroussin 		{ 611  },
376*61d06d6bSBaptiste Daroussin 		{ 556  },
377*61d06d6bSBaptiste Daroussin 		{ 556  },
378*61d06d6bSBaptiste Daroussin 		{ 389  },
379*61d06d6bSBaptiste Daroussin 		{ 278  },
380*61d06d6bSBaptiste Daroussin 		{ 389  },
381*61d06d6bSBaptiste Daroussin 		{ 422  },
382*61d06d6bSBaptiste Daroussin 		{ 500  },
383*61d06d6bSBaptiste Daroussin 		{ 333  },
384*61d06d6bSBaptiste Daroussin 		{ 500  },
385*61d06d6bSBaptiste Daroussin 		{ 500  },
386*61d06d6bSBaptiste Daroussin 		{ 444  },
387*61d06d6bSBaptiste Daroussin 		{  500 },
388*61d06d6bSBaptiste Daroussin 		{  444 },
389*61d06d6bSBaptiste Daroussin 		{  278 },
390*61d06d6bSBaptiste Daroussin 		{  500 },
391*61d06d6bSBaptiste Daroussin 		{  500 },
392*61d06d6bSBaptiste Daroussin 		{  278 },
393*61d06d6bSBaptiste Daroussin 		{  278 },
394*61d06d6bSBaptiste Daroussin 		{  444 },
395*61d06d6bSBaptiste Daroussin 		{  278 },
396*61d06d6bSBaptiste Daroussin 		{  722 },
397*61d06d6bSBaptiste Daroussin 		{  500 },
398*61d06d6bSBaptiste Daroussin 		{  500 },
399*61d06d6bSBaptiste Daroussin 		{  500 },
400*61d06d6bSBaptiste Daroussin 		{  500 },
401*61d06d6bSBaptiste Daroussin 		{  389 },
402*61d06d6bSBaptiste Daroussin 		{  389 },
403*61d06d6bSBaptiste Daroussin 		{  278 },
404*61d06d6bSBaptiste Daroussin 		{  500 },
405*61d06d6bSBaptiste Daroussin 		{  444 },
406*61d06d6bSBaptiste Daroussin 		{  667 },
407*61d06d6bSBaptiste Daroussin 		{  444 },
408*61d06d6bSBaptiste Daroussin 		{  444 },
409*61d06d6bSBaptiste Daroussin 		{  389 },
410*61d06d6bSBaptiste Daroussin 		{  400 },
411*61d06d6bSBaptiste Daroussin 		{  275 },
412*61d06d6bSBaptiste Daroussin 		{  400 },
413*61d06d6bSBaptiste Daroussin 		{  541 },
414*61d06d6bSBaptiste Daroussin 	} },
415*61d06d6bSBaptiste Daroussin 	{ "Times-BoldItalic", {
416*61d06d6bSBaptiste Daroussin 		{  250 },
417*61d06d6bSBaptiste Daroussin 		{  389 },
418*61d06d6bSBaptiste Daroussin 		{  555 },
419*61d06d6bSBaptiste Daroussin 		{  500 },
420*61d06d6bSBaptiste Daroussin 		{  500 },
421*61d06d6bSBaptiste Daroussin 		{  833 },
422*61d06d6bSBaptiste Daroussin 		{  778 },
423*61d06d6bSBaptiste Daroussin 		{  333 },
424*61d06d6bSBaptiste Daroussin 		{  333 },
425*61d06d6bSBaptiste Daroussin 		{  333 },
426*61d06d6bSBaptiste Daroussin 		{  500 },
427*61d06d6bSBaptiste Daroussin 		{  570 },
428*61d06d6bSBaptiste Daroussin 		{  250 },
429*61d06d6bSBaptiste Daroussin 		{  333 },
430*61d06d6bSBaptiste Daroussin 		{  250 },
431*61d06d6bSBaptiste Daroussin 		{  278 },
432*61d06d6bSBaptiste Daroussin 		{  500 },
433*61d06d6bSBaptiste Daroussin 		{  500 },
434*61d06d6bSBaptiste Daroussin 		{  500 },
435*61d06d6bSBaptiste Daroussin 		{  500 },
436*61d06d6bSBaptiste Daroussin 		{  500 },
437*61d06d6bSBaptiste Daroussin 		{  500 },
438*61d06d6bSBaptiste Daroussin 		{  500 },
439*61d06d6bSBaptiste Daroussin 		{  500 },
440*61d06d6bSBaptiste Daroussin 		{  500 },
441*61d06d6bSBaptiste Daroussin 		{  500 },
442*61d06d6bSBaptiste Daroussin 		{  333 },
443*61d06d6bSBaptiste Daroussin 		{  333 },
444*61d06d6bSBaptiste Daroussin 		{  570 },
445*61d06d6bSBaptiste Daroussin 		{  570 },
446*61d06d6bSBaptiste Daroussin 		{  570 },
447*61d06d6bSBaptiste Daroussin 		{  500 },
448*61d06d6bSBaptiste Daroussin 		{  832 },
449*61d06d6bSBaptiste Daroussin 		{  667 },
450*61d06d6bSBaptiste Daroussin 		{  667 },
451*61d06d6bSBaptiste Daroussin 		{  667 },
452*61d06d6bSBaptiste Daroussin 		{  722 },
453*61d06d6bSBaptiste Daroussin 		{  667 },
454*61d06d6bSBaptiste Daroussin 		{  667 },
455*61d06d6bSBaptiste Daroussin 		{  722 },
456*61d06d6bSBaptiste Daroussin 		{  778 },
457*61d06d6bSBaptiste Daroussin 		{  389 },
458*61d06d6bSBaptiste Daroussin 		{  500 },
459*61d06d6bSBaptiste Daroussin 		{  667 },
460*61d06d6bSBaptiste Daroussin 		{  611 },
461*61d06d6bSBaptiste Daroussin 		{  889 },
462*61d06d6bSBaptiste Daroussin 		{  722 },
463*61d06d6bSBaptiste Daroussin 		{  722 },
464*61d06d6bSBaptiste Daroussin 		{  611 },
465*61d06d6bSBaptiste Daroussin 		{  722 },
466*61d06d6bSBaptiste Daroussin 		{  667 },
467*61d06d6bSBaptiste Daroussin 		{  556 },
468*61d06d6bSBaptiste Daroussin 		{  611 },
469*61d06d6bSBaptiste Daroussin 		{  722 },
470*61d06d6bSBaptiste Daroussin 		{  667 },
471*61d06d6bSBaptiste Daroussin 		{  889 },
472*61d06d6bSBaptiste Daroussin 		{  667 },
473*61d06d6bSBaptiste Daroussin 		{  611 },
474*61d06d6bSBaptiste Daroussin 		{  611 },
475*61d06d6bSBaptiste Daroussin 		{  333 },
476*61d06d6bSBaptiste Daroussin 		{  278 },
477*61d06d6bSBaptiste Daroussin 		{  333 },
478*61d06d6bSBaptiste Daroussin 		{  570 },
479*61d06d6bSBaptiste Daroussin 		{  500 },
480*61d06d6bSBaptiste Daroussin 		{  333 },
481*61d06d6bSBaptiste Daroussin 		{  500 },
482*61d06d6bSBaptiste Daroussin 		{  500 },
483*61d06d6bSBaptiste Daroussin 		{  444 },
484*61d06d6bSBaptiste Daroussin 		{  500 },
485*61d06d6bSBaptiste Daroussin 		{  444 },
486*61d06d6bSBaptiste Daroussin 		{  333 },
487*61d06d6bSBaptiste Daroussin 		{  500 },
488*61d06d6bSBaptiste Daroussin 		{  556 },
489*61d06d6bSBaptiste Daroussin 		{  278 },
490*61d06d6bSBaptiste Daroussin 		{  278 },
491*61d06d6bSBaptiste Daroussin 		{  500 },
492*61d06d6bSBaptiste Daroussin 		{  278 },
493*61d06d6bSBaptiste Daroussin 		{  778 },
494*61d06d6bSBaptiste Daroussin 		{  556 },
495*61d06d6bSBaptiste Daroussin 		{  500 },
496*61d06d6bSBaptiste Daroussin 		{  500 },
497*61d06d6bSBaptiste Daroussin 		{  500 },
498*61d06d6bSBaptiste Daroussin 		{  389 },
499*61d06d6bSBaptiste Daroussin 		{  389 },
500*61d06d6bSBaptiste Daroussin 		{  278 },
501*61d06d6bSBaptiste Daroussin 		{  556 },
502*61d06d6bSBaptiste Daroussin 		{  444 },
503*61d06d6bSBaptiste Daroussin 		{  667 },
504*61d06d6bSBaptiste Daroussin 		{  500 },
505*61d06d6bSBaptiste Daroussin 		{  444 },
506*61d06d6bSBaptiste Daroussin 		{  389 },
507*61d06d6bSBaptiste Daroussin 		{  348 },
508*61d06d6bSBaptiste Daroussin 		{  220 },
509*61d06d6bSBaptiste Daroussin 		{  348 },
510*61d06d6bSBaptiste Daroussin 		{  570 },
511*61d06d6bSBaptiste Daroussin 	} },
512*61d06d6bSBaptiste Daroussin };
513*61d06d6bSBaptiste Daroussin 
514*61d06d6bSBaptiste Daroussin void *
515*61d06d6bSBaptiste Daroussin pdf_alloc(const struct manoutput *outopts)
516*61d06d6bSBaptiste Daroussin {
517*61d06d6bSBaptiste Daroussin 	return pspdf_alloc(outopts, TERMTYPE_PDF);
518*61d06d6bSBaptiste Daroussin }
519*61d06d6bSBaptiste Daroussin 
520*61d06d6bSBaptiste Daroussin void *
521*61d06d6bSBaptiste Daroussin ps_alloc(const struct manoutput *outopts)
522*61d06d6bSBaptiste Daroussin {
523*61d06d6bSBaptiste Daroussin 	return pspdf_alloc(outopts, TERMTYPE_PS);
524*61d06d6bSBaptiste Daroussin }
525*61d06d6bSBaptiste Daroussin 
526*61d06d6bSBaptiste Daroussin static struct termp *
527*61d06d6bSBaptiste Daroussin pspdf_alloc(const struct manoutput *outopts, enum termtype type)
528*61d06d6bSBaptiste Daroussin {
529*61d06d6bSBaptiste Daroussin 	struct termp	*p;
530*61d06d6bSBaptiste Daroussin 	unsigned int	 pagex, pagey;
531*61d06d6bSBaptiste Daroussin 	size_t		 marginx, marginy, lineheight;
532*61d06d6bSBaptiste Daroussin 	const char	*pp;
533*61d06d6bSBaptiste Daroussin 
534*61d06d6bSBaptiste Daroussin 	p = mandoc_calloc(1, sizeof(*p));
535*61d06d6bSBaptiste Daroussin 	p->tcol = p->tcols = mandoc_calloc(1, sizeof(*p->tcol));
536*61d06d6bSBaptiste Daroussin 	p->maxtcol = 1;
537*61d06d6bSBaptiste Daroussin 	p->type = type;
538*61d06d6bSBaptiste Daroussin 
539*61d06d6bSBaptiste Daroussin 	p->enc = TERMENC_ASCII;
540*61d06d6bSBaptiste Daroussin 	p->fontq = mandoc_reallocarray(NULL,
541*61d06d6bSBaptiste Daroussin 	    (p->fontsz = 8), sizeof(*p->fontq));
542*61d06d6bSBaptiste Daroussin 	p->fontq[0] = p->fontl = TERMFONT_NONE;
543*61d06d6bSBaptiste Daroussin 	p->ps = mandoc_calloc(1, sizeof(*p->ps));
544*61d06d6bSBaptiste Daroussin 
545*61d06d6bSBaptiste Daroussin 	p->advance = ps_advance;
546*61d06d6bSBaptiste Daroussin 	p->begin = ps_begin;
547*61d06d6bSBaptiste Daroussin 	p->end = ps_end;
548*61d06d6bSBaptiste Daroussin 	p->endline = ps_endline;
549*61d06d6bSBaptiste Daroussin 	p->hspan = ps_hspan;
550*61d06d6bSBaptiste Daroussin 	p->letter = ps_letter;
551*61d06d6bSBaptiste Daroussin 	p->setwidth = ps_setwidth;
552*61d06d6bSBaptiste Daroussin 	p->width = ps_width;
553*61d06d6bSBaptiste Daroussin 
554*61d06d6bSBaptiste Daroussin 	/* Default to US letter (millimetres). */
555*61d06d6bSBaptiste Daroussin 
556*61d06d6bSBaptiste Daroussin 	p->ps->medianame = "Letter";
557*61d06d6bSBaptiste Daroussin 	pagex = 216;
558*61d06d6bSBaptiste Daroussin 	pagey = 279;
559*61d06d6bSBaptiste Daroussin 
560*61d06d6bSBaptiste Daroussin 	/*
561*61d06d6bSBaptiste Daroussin 	 * The ISO-269 paper sizes can be calculated automatically, but
562*61d06d6bSBaptiste Daroussin 	 * it would require bringing in -lm for pow() and I'd rather not
563*61d06d6bSBaptiste Daroussin 	 * do that.  So just do it the easy way for now.  Since this
564*61d06d6bSBaptiste Daroussin 	 * only happens once, I'm not terribly concerned.
565*61d06d6bSBaptiste Daroussin 	 */
566*61d06d6bSBaptiste Daroussin 
567*61d06d6bSBaptiste Daroussin 	pp = outopts->paper;
568*61d06d6bSBaptiste Daroussin 	if (pp != NULL && strcasecmp(pp, "letter") != 0) {
569*61d06d6bSBaptiste Daroussin 		if (strcasecmp(pp, "a3") == 0) {
570*61d06d6bSBaptiste Daroussin 			p->ps->medianame = "A3";
571*61d06d6bSBaptiste Daroussin 			pagex = 297;
572*61d06d6bSBaptiste Daroussin 			pagey = 420;
573*61d06d6bSBaptiste Daroussin 		} else if (strcasecmp(pp, "a4") == 0) {
574*61d06d6bSBaptiste Daroussin 			p->ps->medianame = "A4";
575*61d06d6bSBaptiste Daroussin 			pagex = 210;
576*61d06d6bSBaptiste Daroussin 			pagey = 297;
577*61d06d6bSBaptiste Daroussin 		} else if (strcasecmp(pp, "a5") == 0) {
578*61d06d6bSBaptiste Daroussin 			p->ps->medianame = "A5";
579*61d06d6bSBaptiste Daroussin 			pagex = 148;
580*61d06d6bSBaptiste Daroussin 			pagey = 210;
581*61d06d6bSBaptiste Daroussin 		} else if (strcasecmp(pp, "legal") == 0) {
582*61d06d6bSBaptiste Daroussin 			p->ps->medianame = "Legal";
583*61d06d6bSBaptiste Daroussin 			pagex = 216;
584*61d06d6bSBaptiste Daroussin 			pagey = 356;
585*61d06d6bSBaptiste Daroussin 		} else if (sscanf(pp, "%ux%u", &pagex, &pagey) == 2)
586*61d06d6bSBaptiste Daroussin 			p->ps->medianame = "CustomSize";
587*61d06d6bSBaptiste Daroussin 		else
588*61d06d6bSBaptiste Daroussin 			warnx("%s: Unknown paper", pp);
589*61d06d6bSBaptiste Daroussin 	}
590*61d06d6bSBaptiste Daroussin 
591*61d06d6bSBaptiste Daroussin 	/*
592*61d06d6bSBaptiste Daroussin 	 * This MUST be defined before any PNT2AFM or AFM2PNT
593*61d06d6bSBaptiste Daroussin 	 * calculations occur.
594*61d06d6bSBaptiste Daroussin 	 */
595*61d06d6bSBaptiste Daroussin 
596*61d06d6bSBaptiste Daroussin 	p->ps->scale = 11;
597*61d06d6bSBaptiste Daroussin 
598*61d06d6bSBaptiste Daroussin 	/* Remember millimetres -> AFM units. */
599*61d06d6bSBaptiste Daroussin 
600*61d06d6bSBaptiste Daroussin 	pagex = PNT2AFM(p, ((double)pagex * 72.0 / 25.4));
601*61d06d6bSBaptiste Daroussin 	pagey = PNT2AFM(p, ((double)pagey * 72.0 / 25.4));
602*61d06d6bSBaptiste Daroussin 
603*61d06d6bSBaptiste Daroussin 	/* Margins are 1/9 the page x and y. */
604*61d06d6bSBaptiste Daroussin 
605*61d06d6bSBaptiste Daroussin 	marginx = (size_t)((double)pagex / 9.0);
606*61d06d6bSBaptiste Daroussin 	marginy = (size_t)((double)pagey / 9.0);
607*61d06d6bSBaptiste Daroussin 
608*61d06d6bSBaptiste Daroussin 	/* Line-height is 1.4em. */
609*61d06d6bSBaptiste Daroussin 
610*61d06d6bSBaptiste Daroussin 	lineheight = PNT2AFM(p, ((double)p->ps->scale * 1.4));
611*61d06d6bSBaptiste Daroussin 
612*61d06d6bSBaptiste Daroussin 	p->ps->width = p->ps->lastwidth = (size_t)pagex;
613*61d06d6bSBaptiste Daroussin 	p->ps->height = (size_t)pagey;
614*61d06d6bSBaptiste Daroussin 	p->ps->header = pagey - (marginy / 2) - (lineheight / 2);
615*61d06d6bSBaptiste Daroussin 	p->ps->top = pagey - marginy;
616*61d06d6bSBaptiste Daroussin 	p->ps->footer = (marginy / 2) - (lineheight / 2);
617*61d06d6bSBaptiste Daroussin 	p->ps->bottom = marginy;
618*61d06d6bSBaptiste Daroussin 	p->ps->left = marginx;
619*61d06d6bSBaptiste Daroussin 	p->ps->lineheight = lineheight;
620*61d06d6bSBaptiste Daroussin 
621*61d06d6bSBaptiste Daroussin 	p->defrmargin = pagex - (marginx * 2);
622*61d06d6bSBaptiste Daroussin 	return p;
623*61d06d6bSBaptiste Daroussin }
624*61d06d6bSBaptiste Daroussin 
625*61d06d6bSBaptiste Daroussin static void
626*61d06d6bSBaptiste Daroussin ps_setwidth(struct termp *p, int iop, int width)
627*61d06d6bSBaptiste Daroussin {
628*61d06d6bSBaptiste Daroussin 	size_t	 lastwidth;
629*61d06d6bSBaptiste Daroussin 
630*61d06d6bSBaptiste Daroussin 	lastwidth = p->ps->width;
631*61d06d6bSBaptiste Daroussin 	if (iop > 0)
632*61d06d6bSBaptiste Daroussin 		p->ps->width += width;
633*61d06d6bSBaptiste Daroussin 	else if (iop == 0)
634*61d06d6bSBaptiste Daroussin 		p->ps->width = width ? (size_t)width : p->ps->lastwidth;
635*61d06d6bSBaptiste Daroussin 	else if (p->ps->width > (size_t)width)
636*61d06d6bSBaptiste Daroussin 		p->ps->width -= width;
637*61d06d6bSBaptiste Daroussin 	else
638*61d06d6bSBaptiste Daroussin 		p->ps->width = 0;
639*61d06d6bSBaptiste Daroussin 	p->ps->lastwidth = lastwidth;
640*61d06d6bSBaptiste Daroussin }
641*61d06d6bSBaptiste Daroussin 
642*61d06d6bSBaptiste Daroussin void
643*61d06d6bSBaptiste Daroussin pspdf_free(void *arg)
644*61d06d6bSBaptiste Daroussin {
645*61d06d6bSBaptiste Daroussin 	struct termp	*p;
646*61d06d6bSBaptiste Daroussin 
647*61d06d6bSBaptiste Daroussin 	p = (struct termp *)arg;
648*61d06d6bSBaptiste Daroussin 
649*61d06d6bSBaptiste Daroussin 	free(p->ps->psmarg);
650*61d06d6bSBaptiste Daroussin 	free(p->ps->pdfobjs);
651*61d06d6bSBaptiste Daroussin 
652*61d06d6bSBaptiste Daroussin 	free(p->ps);
653*61d06d6bSBaptiste Daroussin 	term_free(p);
654*61d06d6bSBaptiste Daroussin }
655*61d06d6bSBaptiste Daroussin 
656*61d06d6bSBaptiste Daroussin static void
657*61d06d6bSBaptiste Daroussin ps_printf(struct termp *p, const char *fmt, ...)
658*61d06d6bSBaptiste Daroussin {
659*61d06d6bSBaptiste Daroussin 	va_list		 ap;
660*61d06d6bSBaptiste Daroussin 	int		 pos, len;
661*61d06d6bSBaptiste Daroussin 
662*61d06d6bSBaptiste Daroussin 	va_start(ap, fmt);
663*61d06d6bSBaptiste Daroussin 
664*61d06d6bSBaptiste Daroussin 	/*
665*61d06d6bSBaptiste Daroussin 	 * If we're running in regular mode, then pipe directly into
666*61d06d6bSBaptiste Daroussin 	 * vprintf().  If we're processing margins, then push the data
667*61d06d6bSBaptiste Daroussin 	 * into our growable margin buffer.
668*61d06d6bSBaptiste Daroussin 	 */
669*61d06d6bSBaptiste Daroussin 
670*61d06d6bSBaptiste Daroussin 	if ( ! (PS_MARGINS & p->ps->flags)) {
671*61d06d6bSBaptiste Daroussin 		len = vprintf(fmt, ap);
672*61d06d6bSBaptiste Daroussin 		va_end(ap);
673*61d06d6bSBaptiste Daroussin 		p->ps->pdfbytes += len < 0 ? 0 : (size_t)len;
674*61d06d6bSBaptiste Daroussin 		return;
675*61d06d6bSBaptiste Daroussin 	}
676*61d06d6bSBaptiste Daroussin 
677*61d06d6bSBaptiste Daroussin 	/*
678*61d06d6bSBaptiste Daroussin 	 * XXX: I assume that the in-margin print won't exceed
679*61d06d6bSBaptiste Daroussin 	 * PS_BUFSLOP (128 bytes), which is reasonable but still an
680*61d06d6bSBaptiste Daroussin 	 * assumption that will cause pukeage if it's not the case.
681*61d06d6bSBaptiste Daroussin 	 */
682*61d06d6bSBaptiste Daroussin 
683*61d06d6bSBaptiste Daroussin 	ps_growbuf(p, PS_BUFSLOP);
684*61d06d6bSBaptiste Daroussin 
685*61d06d6bSBaptiste Daroussin 	pos = (int)p->ps->psmargcur;
686*61d06d6bSBaptiste Daroussin 	vsnprintf(&p->ps->psmarg[pos], PS_BUFSLOP, fmt, ap);
687*61d06d6bSBaptiste Daroussin 
688*61d06d6bSBaptiste Daroussin 	va_end(ap);
689*61d06d6bSBaptiste Daroussin 
690*61d06d6bSBaptiste Daroussin 	p->ps->psmargcur = strlen(p->ps->psmarg);
691*61d06d6bSBaptiste Daroussin }
692*61d06d6bSBaptiste Daroussin 
693*61d06d6bSBaptiste Daroussin static void
694*61d06d6bSBaptiste Daroussin ps_putchar(struct termp *p, char c)
695*61d06d6bSBaptiste Daroussin {
696*61d06d6bSBaptiste Daroussin 	int		 pos;
697*61d06d6bSBaptiste Daroussin 
698*61d06d6bSBaptiste Daroussin 	/* See ps_printf(). */
699*61d06d6bSBaptiste Daroussin 
700*61d06d6bSBaptiste Daroussin 	if ( ! (PS_MARGINS & p->ps->flags)) {
701*61d06d6bSBaptiste Daroussin 		putchar(c);
702*61d06d6bSBaptiste Daroussin 		p->ps->pdfbytes++;
703*61d06d6bSBaptiste Daroussin 		return;
704*61d06d6bSBaptiste Daroussin 	}
705*61d06d6bSBaptiste Daroussin 
706*61d06d6bSBaptiste Daroussin 	ps_growbuf(p, 2);
707*61d06d6bSBaptiste Daroussin 
708*61d06d6bSBaptiste Daroussin 	pos = (int)p->ps->psmargcur++;
709*61d06d6bSBaptiste Daroussin 	p->ps->psmarg[pos++] = c;
710*61d06d6bSBaptiste Daroussin 	p->ps->psmarg[pos] = '\0';
711*61d06d6bSBaptiste Daroussin }
712*61d06d6bSBaptiste Daroussin 
713*61d06d6bSBaptiste Daroussin static void
714*61d06d6bSBaptiste Daroussin pdf_obj(struct termp *p, size_t obj)
715*61d06d6bSBaptiste Daroussin {
716*61d06d6bSBaptiste Daroussin 
717*61d06d6bSBaptiste Daroussin 	assert(obj > 0);
718*61d06d6bSBaptiste Daroussin 
719*61d06d6bSBaptiste Daroussin 	if ((obj - 1) >= p->ps->pdfobjsz) {
720*61d06d6bSBaptiste Daroussin 		p->ps->pdfobjsz = obj + 128;
721*61d06d6bSBaptiste Daroussin 		p->ps->pdfobjs = mandoc_reallocarray(p->ps->pdfobjs,
722*61d06d6bSBaptiste Daroussin 		    p->ps->pdfobjsz, sizeof(size_t));
723*61d06d6bSBaptiste Daroussin 	}
724*61d06d6bSBaptiste Daroussin 
725*61d06d6bSBaptiste Daroussin 	p->ps->pdfobjs[(int)obj - 1] = p->ps->pdfbytes;
726*61d06d6bSBaptiste Daroussin 	ps_printf(p, "%zu 0 obj\n", obj);
727*61d06d6bSBaptiste Daroussin }
728*61d06d6bSBaptiste Daroussin 
729*61d06d6bSBaptiste Daroussin static void
730*61d06d6bSBaptiste Daroussin ps_closepage(struct termp *p)
731*61d06d6bSBaptiste Daroussin {
732*61d06d6bSBaptiste Daroussin 	int		 i;
733*61d06d6bSBaptiste Daroussin 	size_t		 len, base;
734*61d06d6bSBaptiste Daroussin 
735*61d06d6bSBaptiste Daroussin 	/*
736*61d06d6bSBaptiste Daroussin 	 * Close out a page that we've already flushed to output.  In
737*61d06d6bSBaptiste Daroussin 	 * PostScript, we simply note that the page must be shown.  In
738*61d06d6bSBaptiste Daroussin 	 * PDF, we must now create the Length, Resource, and Page node
739*61d06d6bSBaptiste Daroussin 	 * for the page contents.
740*61d06d6bSBaptiste Daroussin 	 */
741*61d06d6bSBaptiste Daroussin 
742*61d06d6bSBaptiste Daroussin 	assert(p->ps->psmarg && p->ps->psmarg[0]);
743*61d06d6bSBaptiste Daroussin 	ps_printf(p, "%s", p->ps->psmarg);
744*61d06d6bSBaptiste Daroussin 
745*61d06d6bSBaptiste Daroussin 	if (TERMTYPE_PS != p->type) {
746*61d06d6bSBaptiste Daroussin 		len = p->ps->pdfbytes - p->ps->pdflastpg;
747*61d06d6bSBaptiste Daroussin 		base = p->ps->pages * 4 + p->ps->pdfbody;
748*61d06d6bSBaptiste Daroussin 
749*61d06d6bSBaptiste Daroussin 		ps_printf(p, "endstream\nendobj\n");
750*61d06d6bSBaptiste Daroussin 
751*61d06d6bSBaptiste Daroussin 		/* Length of content. */
752*61d06d6bSBaptiste Daroussin 		pdf_obj(p, base + 1);
753*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%zu\nendobj\n", len);
754*61d06d6bSBaptiste Daroussin 
755*61d06d6bSBaptiste Daroussin 		/* Resource for content. */
756*61d06d6bSBaptiste Daroussin 		pdf_obj(p, base + 2);
757*61d06d6bSBaptiste Daroussin 		ps_printf(p, "<<\n/ProcSet [/PDF /Text]\n");
758*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/Font <<\n");
759*61d06d6bSBaptiste Daroussin 		for (i = 0; i < (int)TERMFONT__MAX; i++)
760*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/F%d %d 0 R\n", i, 3 + i);
761*61d06d6bSBaptiste Daroussin 		ps_printf(p, ">>\n>>\nendobj\n");
762*61d06d6bSBaptiste Daroussin 
763*61d06d6bSBaptiste Daroussin 		/* Page node. */
764*61d06d6bSBaptiste Daroussin 		pdf_obj(p, base + 3);
765*61d06d6bSBaptiste Daroussin 		ps_printf(p, "<<\n");
766*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/Type /Page\n");
767*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/Parent 2 0 R\n");
768*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/Resources %zu 0 R\n", base + 2);
769*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/Contents %zu 0 R\n", base);
770*61d06d6bSBaptiste Daroussin 		ps_printf(p, ">>\nendobj\n");
771*61d06d6bSBaptiste Daroussin 	} else
772*61d06d6bSBaptiste Daroussin 		ps_printf(p, "showpage\n");
773*61d06d6bSBaptiste Daroussin 
774*61d06d6bSBaptiste Daroussin 	p->ps->pages++;
775*61d06d6bSBaptiste Daroussin 	p->ps->psrow = p->ps->top;
776*61d06d6bSBaptiste Daroussin 	assert( ! (PS_NEWPAGE & p->ps->flags));
777*61d06d6bSBaptiste Daroussin 	p->ps->flags |= PS_NEWPAGE;
778*61d06d6bSBaptiste Daroussin }
779*61d06d6bSBaptiste Daroussin 
780*61d06d6bSBaptiste Daroussin static void
781*61d06d6bSBaptiste Daroussin ps_end(struct termp *p)
782*61d06d6bSBaptiste Daroussin {
783*61d06d6bSBaptiste Daroussin 	size_t		 i, xref, base;
784*61d06d6bSBaptiste Daroussin 
785*61d06d6bSBaptiste Daroussin 	ps_plast(p);
786*61d06d6bSBaptiste Daroussin 	ps_pclose(p);
787*61d06d6bSBaptiste Daroussin 
788*61d06d6bSBaptiste Daroussin 	/*
789*61d06d6bSBaptiste Daroussin 	 * At the end of the file, do one last showpage.  This is the
790*61d06d6bSBaptiste Daroussin 	 * same behaviour as groff(1) and works for multiple pages as
791*61d06d6bSBaptiste Daroussin 	 * well as just one.
792*61d06d6bSBaptiste Daroussin 	 */
793*61d06d6bSBaptiste Daroussin 
794*61d06d6bSBaptiste Daroussin 	if ( ! (PS_NEWPAGE & p->ps->flags)) {
795*61d06d6bSBaptiste Daroussin 		assert(0 == p->ps->flags);
796*61d06d6bSBaptiste Daroussin 		assert('\0' == p->ps->last);
797*61d06d6bSBaptiste Daroussin 		ps_closepage(p);
798*61d06d6bSBaptiste Daroussin 	}
799*61d06d6bSBaptiste Daroussin 
800*61d06d6bSBaptiste Daroussin 	if (TERMTYPE_PS == p->type) {
801*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%Trailer\n");
802*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%Pages: %zu\n", p->ps->pages);
803*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%EOF\n");
804*61d06d6bSBaptiste Daroussin 		return;
805*61d06d6bSBaptiste Daroussin 	}
806*61d06d6bSBaptiste Daroussin 
807*61d06d6bSBaptiste Daroussin 	pdf_obj(p, 2);
808*61d06d6bSBaptiste Daroussin 	ps_printf(p, "<<\n/Type /Pages\n");
809*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/MediaBox [0 0 %zu %zu]\n",
810*61d06d6bSBaptiste Daroussin 			(size_t)AFM2PNT(p, p->ps->width),
811*61d06d6bSBaptiste Daroussin 			(size_t)AFM2PNT(p, p->ps->height));
812*61d06d6bSBaptiste Daroussin 
813*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Count %zu\n", p->ps->pages);
814*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Kids [");
815*61d06d6bSBaptiste Daroussin 
816*61d06d6bSBaptiste Daroussin 	for (i = 0; i < p->ps->pages; i++)
817*61d06d6bSBaptiste Daroussin 		ps_printf(p, " %zu 0 R", i * 4 + p->ps->pdfbody + 3);
818*61d06d6bSBaptiste Daroussin 
819*61d06d6bSBaptiste Daroussin 	base = (p->ps->pages - 1) * 4 + p->ps->pdfbody + 4;
820*61d06d6bSBaptiste Daroussin 
821*61d06d6bSBaptiste Daroussin 	ps_printf(p, "]\n>>\nendobj\n");
822*61d06d6bSBaptiste Daroussin 	pdf_obj(p, base);
823*61d06d6bSBaptiste Daroussin 	ps_printf(p, "<<\n");
824*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Type /Catalog\n");
825*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Pages 2 0 R\n");
826*61d06d6bSBaptiste Daroussin 	ps_printf(p, ">>\nendobj\n");
827*61d06d6bSBaptiste Daroussin 	xref = p->ps->pdfbytes;
828*61d06d6bSBaptiste Daroussin 	ps_printf(p, "xref\n");
829*61d06d6bSBaptiste Daroussin 	ps_printf(p, "0 %zu\n", base + 1);
830*61d06d6bSBaptiste Daroussin 	ps_printf(p, "0000000000 65535 f \n");
831*61d06d6bSBaptiste Daroussin 
832*61d06d6bSBaptiste Daroussin 	for (i = 0; i < base; i++)
833*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%.10zu 00000 n \n",
834*61d06d6bSBaptiste Daroussin 		    p->ps->pdfobjs[(int)i]);
835*61d06d6bSBaptiste Daroussin 
836*61d06d6bSBaptiste Daroussin 	ps_printf(p, "trailer\n");
837*61d06d6bSBaptiste Daroussin 	ps_printf(p, "<<\n");
838*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Size %zu\n", base + 1);
839*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Root %zu 0 R\n", base);
840*61d06d6bSBaptiste Daroussin 	ps_printf(p, "/Info 1 0 R\n");
841*61d06d6bSBaptiste Daroussin 	ps_printf(p, ">>\n");
842*61d06d6bSBaptiste Daroussin 	ps_printf(p, "startxref\n");
843*61d06d6bSBaptiste Daroussin 	ps_printf(p, "%zu\n", xref);
844*61d06d6bSBaptiste Daroussin 	ps_printf(p, "%%%%EOF\n");
845*61d06d6bSBaptiste Daroussin }
846*61d06d6bSBaptiste Daroussin 
847*61d06d6bSBaptiste Daroussin static void
848*61d06d6bSBaptiste Daroussin ps_begin(struct termp *p)
849*61d06d6bSBaptiste Daroussin {
850*61d06d6bSBaptiste Daroussin 	size_t		 width, height;
851*61d06d6bSBaptiste Daroussin 	int		 i;
852*61d06d6bSBaptiste Daroussin 
853*61d06d6bSBaptiste Daroussin 	/*
854*61d06d6bSBaptiste Daroussin 	 * Print margins into margin buffer.  Nothing gets output to the
855*61d06d6bSBaptiste Daroussin 	 * screen yet, so we don't need to initialise the primary state.
856*61d06d6bSBaptiste Daroussin 	 */
857*61d06d6bSBaptiste Daroussin 
858*61d06d6bSBaptiste Daroussin 	if (p->ps->psmarg) {
859*61d06d6bSBaptiste Daroussin 		assert(p->ps->psmargsz);
860*61d06d6bSBaptiste Daroussin 		p->ps->psmarg[0] = '\0';
861*61d06d6bSBaptiste Daroussin 	}
862*61d06d6bSBaptiste Daroussin 
863*61d06d6bSBaptiste Daroussin 	/*p->ps->pdfbytes = 0;*/
864*61d06d6bSBaptiste Daroussin 	p->ps->psmargcur = 0;
865*61d06d6bSBaptiste Daroussin 	p->ps->flags = PS_MARGINS;
866*61d06d6bSBaptiste Daroussin 	p->ps->pscol = p->ps->left;
867*61d06d6bSBaptiste Daroussin 	p->ps->psrow = p->ps->header;
868*61d06d6bSBaptiste Daroussin 	p->ps->lastrow = 0; /* impossible row */
869*61d06d6bSBaptiste Daroussin 
870*61d06d6bSBaptiste Daroussin 	ps_setfont(p, TERMFONT_NONE);
871*61d06d6bSBaptiste Daroussin 
872*61d06d6bSBaptiste Daroussin 	(*p->headf)(p, p->argf);
873*61d06d6bSBaptiste Daroussin 	(*p->endline)(p);
874*61d06d6bSBaptiste Daroussin 
875*61d06d6bSBaptiste Daroussin 	p->ps->pscol = p->ps->left;
876*61d06d6bSBaptiste Daroussin 	p->ps->psrow = p->ps->footer;
877*61d06d6bSBaptiste Daroussin 
878*61d06d6bSBaptiste Daroussin 	(*p->footf)(p, p->argf);
879*61d06d6bSBaptiste Daroussin 	(*p->endline)(p);
880*61d06d6bSBaptiste Daroussin 
881*61d06d6bSBaptiste Daroussin 	p->ps->flags &= ~PS_MARGINS;
882*61d06d6bSBaptiste Daroussin 
883*61d06d6bSBaptiste Daroussin 	assert(0 == p->ps->flags);
884*61d06d6bSBaptiste Daroussin 	assert(p->ps->psmarg);
885*61d06d6bSBaptiste Daroussin 	assert('\0' != p->ps->psmarg[0]);
886*61d06d6bSBaptiste Daroussin 
887*61d06d6bSBaptiste Daroussin 	/*
888*61d06d6bSBaptiste Daroussin 	 * Print header and initialise page state.  Following this,
889*61d06d6bSBaptiste Daroussin 	 * stuff gets printed to the screen, so make sure we're sane.
890*61d06d6bSBaptiste Daroussin 	 */
891*61d06d6bSBaptiste Daroussin 
892*61d06d6bSBaptiste Daroussin 	if (TERMTYPE_PS == p->type) {
893*61d06d6bSBaptiste Daroussin 		width = AFM2PNT(p, p->ps->width);
894*61d06d6bSBaptiste Daroussin 		height = AFM2PNT(p, p->ps->height);
895*61d06d6bSBaptiste Daroussin 
896*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%!PS-Adobe-3.0\n");
897*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%DocumentData: Clean7Bit\n");
898*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%Orientation: Portrait\n");
899*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%Pages: (atend)\n");
900*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%PageOrder: Ascend\n");
901*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%DocumentMedia: man-%s %zu %zu 0 () ()\n",
902*61d06d6bSBaptiste Daroussin 		    p->ps->medianame, width, height);
903*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%DocumentNeededResources: font");
904*61d06d6bSBaptiste Daroussin 
905*61d06d6bSBaptiste Daroussin 		for (i = 0; i < (int)TERMFONT__MAX; i++)
906*61d06d6bSBaptiste Daroussin 			ps_printf(p, " %s", fonts[i].name);
907*61d06d6bSBaptiste Daroussin 
908*61d06d6bSBaptiste Daroussin 		ps_printf(p, "\n%%%%DocumentSuppliedResources: "
909*61d06d6bSBaptiste Daroussin 		    "procset MandocProcs 1.0 0\n");
910*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%EndComments\n");
911*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%BeginProlog\n");
912*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%BeginResource: procset MandocProcs "
913*61d06d6bSBaptiste Daroussin 		    "10170 10170\n");
914*61d06d6bSBaptiste Daroussin 		/* The font size is effectively hard-coded for now. */
915*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/fs %zu def\n", p->ps->scale);
916*61d06d6bSBaptiste Daroussin 		for (i = 0; i < (int)TERMFONT__MAX; i++)
917*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/f%d { /%s fs selectfont } def\n",
918*61d06d6bSBaptiste Daroussin 			    i, fonts[i].name);
919*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/s { 3 1 roll moveto show } bind def\n");
920*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/c { exch currentpoint exch pop "
921*61d06d6bSBaptiste Daroussin 		    "moveto show } bind def\n");
922*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%EndResource\n");
923*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%EndProlog\n");
924*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%BeginSetup\n");
925*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%BeginFeature: *PageSize %s\n",
926*61d06d6bSBaptiste Daroussin 		    p->ps->medianame);
927*61d06d6bSBaptiste Daroussin 		ps_printf(p, "<</PageSize [%zu %zu]>>setpagedevice\n",
928*61d06d6bSBaptiste Daroussin 		    width, height);
929*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%EndFeature\n");
930*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%%%EndSetup\n");
931*61d06d6bSBaptiste Daroussin 	} else {
932*61d06d6bSBaptiste Daroussin 		ps_printf(p, "%%PDF-1.1\n");
933*61d06d6bSBaptiste Daroussin 		pdf_obj(p, 1);
934*61d06d6bSBaptiste Daroussin 		ps_printf(p, "<<\n");
935*61d06d6bSBaptiste Daroussin 		ps_printf(p, ">>\n");
936*61d06d6bSBaptiste Daroussin 		ps_printf(p, "endobj\n");
937*61d06d6bSBaptiste Daroussin 
938*61d06d6bSBaptiste Daroussin 		for (i = 0; i < (int)TERMFONT__MAX; i++) {
939*61d06d6bSBaptiste Daroussin 			pdf_obj(p, (size_t)i + 3);
940*61d06d6bSBaptiste Daroussin 			ps_printf(p, "<<\n");
941*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/Type /Font\n");
942*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/Subtype /Type1\n");
943*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/Name /F%d\n", i);
944*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/BaseFont /%s\n", fonts[i].name);
945*61d06d6bSBaptiste Daroussin 			ps_printf(p, ">>\nendobj\n");
946*61d06d6bSBaptiste Daroussin 		}
947*61d06d6bSBaptiste Daroussin 	}
948*61d06d6bSBaptiste Daroussin 
949*61d06d6bSBaptiste Daroussin 	p->ps->pdfbody = (size_t)TERMFONT__MAX + 3;
950*61d06d6bSBaptiste Daroussin 	p->ps->pscol = p->ps->left;
951*61d06d6bSBaptiste Daroussin 	p->ps->psrow = p->ps->top;
952*61d06d6bSBaptiste Daroussin 	p->ps->flags |= PS_NEWPAGE;
953*61d06d6bSBaptiste Daroussin 	ps_setfont(p, TERMFONT_NONE);
954*61d06d6bSBaptiste Daroussin }
955*61d06d6bSBaptiste Daroussin 
956*61d06d6bSBaptiste Daroussin static void
957*61d06d6bSBaptiste Daroussin ps_pletter(struct termp *p, int c)
958*61d06d6bSBaptiste Daroussin {
959*61d06d6bSBaptiste Daroussin 	int		 f;
960*61d06d6bSBaptiste Daroussin 
961*61d06d6bSBaptiste Daroussin 	/*
962*61d06d6bSBaptiste Daroussin 	 * If we haven't opened a page context, then output that we're
963*61d06d6bSBaptiste Daroussin 	 * in a new page and make sure the font is correctly set.
964*61d06d6bSBaptiste Daroussin 	 */
965*61d06d6bSBaptiste Daroussin 
966*61d06d6bSBaptiste Daroussin 	if (PS_NEWPAGE & p->ps->flags) {
967*61d06d6bSBaptiste Daroussin 		if (TERMTYPE_PS == p->type) {
968*61d06d6bSBaptiste Daroussin 			ps_printf(p, "%%%%Page: %zu %zu\n",
969*61d06d6bSBaptiste Daroussin 			    p->ps->pages + 1, p->ps->pages + 1);
970*61d06d6bSBaptiste Daroussin 			ps_printf(p, "f%d\n", (int)p->ps->lastf);
971*61d06d6bSBaptiste Daroussin 		} else {
972*61d06d6bSBaptiste Daroussin 			pdf_obj(p, p->ps->pdfbody +
973*61d06d6bSBaptiste Daroussin 			    p->ps->pages * 4);
974*61d06d6bSBaptiste Daroussin 			ps_printf(p, "<<\n");
975*61d06d6bSBaptiste Daroussin 			ps_printf(p, "/Length %zu 0 R\n",
976*61d06d6bSBaptiste Daroussin 			    p->ps->pdfbody + 1 + p->ps->pages * 4);
977*61d06d6bSBaptiste Daroussin 			ps_printf(p, ">>\nstream\n");
978*61d06d6bSBaptiste Daroussin 		}
979*61d06d6bSBaptiste Daroussin 		p->ps->pdflastpg = p->ps->pdfbytes;
980*61d06d6bSBaptiste Daroussin 		p->ps->flags &= ~PS_NEWPAGE;
981*61d06d6bSBaptiste Daroussin 	}
982*61d06d6bSBaptiste Daroussin 
983*61d06d6bSBaptiste Daroussin 	/*
984*61d06d6bSBaptiste Daroussin 	 * If we're not in a PostScript "word" context, then open one
985*61d06d6bSBaptiste Daroussin 	 * now at the current cursor.
986*61d06d6bSBaptiste Daroussin 	 */
987*61d06d6bSBaptiste Daroussin 
988*61d06d6bSBaptiste Daroussin 	if ( ! (PS_INLINE & p->ps->flags)) {
989*61d06d6bSBaptiste Daroussin 		if (TERMTYPE_PS != p->type) {
990*61d06d6bSBaptiste Daroussin 			ps_printf(p, "BT\n/F%d %zu Tf\n",
991*61d06d6bSBaptiste Daroussin 			    (int)p->ps->lastf, p->ps->scale);
992*61d06d6bSBaptiste Daroussin 			ps_printf(p, "%.3f %.3f Td\n(",
993*61d06d6bSBaptiste Daroussin 			    AFM2PNT(p, p->ps->pscol),
994*61d06d6bSBaptiste Daroussin 			    AFM2PNT(p, p->ps->psrow));
995*61d06d6bSBaptiste Daroussin 		} else {
996*61d06d6bSBaptiste Daroussin 			ps_printf(p, "%.3f", AFM2PNT(p, p->ps->pscol));
997*61d06d6bSBaptiste Daroussin 			if (p->ps->psrow != p->ps->lastrow)
998*61d06d6bSBaptiste Daroussin 				ps_printf(p, " %.3f",
999*61d06d6bSBaptiste Daroussin 				    AFM2PNT(p, p->ps->psrow));
1000*61d06d6bSBaptiste Daroussin 			ps_printf(p, "(");
1001*61d06d6bSBaptiste Daroussin 		}
1002*61d06d6bSBaptiste Daroussin 		p->ps->flags |= PS_INLINE;
1003*61d06d6bSBaptiste Daroussin 	}
1004*61d06d6bSBaptiste Daroussin 
1005*61d06d6bSBaptiste Daroussin 	assert( ! (PS_NEWPAGE & p->ps->flags));
1006*61d06d6bSBaptiste Daroussin 
1007*61d06d6bSBaptiste Daroussin 	/*
1008*61d06d6bSBaptiste Daroussin 	 * We need to escape these characters as per the PostScript
1009*61d06d6bSBaptiste Daroussin 	 * specification.  We would also escape non-graphable characters
1010*61d06d6bSBaptiste Daroussin 	 * (like tabs), but none of them would get to this point and
1011*61d06d6bSBaptiste Daroussin 	 * it's superfluous to abort() on them.
1012*61d06d6bSBaptiste Daroussin 	 */
1013*61d06d6bSBaptiste Daroussin 
1014*61d06d6bSBaptiste Daroussin 	switch (c) {
1015*61d06d6bSBaptiste Daroussin 	case '(':
1016*61d06d6bSBaptiste Daroussin 	case ')':
1017*61d06d6bSBaptiste Daroussin 	case '\\':
1018*61d06d6bSBaptiste Daroussin 		ps_putchar(p, '\\');
1019*61d06d6bSBaptiste Daroussin 		break;
1020*61d06d6bSBaptiste Daroussin 	default:
1021*61d06d6bSBaptiste Daroussin 		break;
1022*61d06d6bSBaptiste Daroussin 	}
1023*61d06d6bSBaptiste Daroussin 
1024*61d06d6bSBaptiste Daroussin 	/* Write the character and adjust where we are on the page. */
1025*61d06d6bSBaptiste Daroussin 
1026*61d06d6bSBaptiste Daroussin 	f = (int)p->ps->lastf;
1027*61d06d6bSBaptiste Daroussin 
1028*61d06d6bSBaptiste Daroussin 	if (c <= 32 || c - 32 >= MAXCHAR)
1029*61d06d6bSBaptiste Daroussin 		c = 32;
1030*61d06d6bSBaptiste Daroussin 
1031*61d06d6bSBaptiste Daroussin 	ps_putchar(p, (char)c);
1032*61d06d6bSBaptiste Daroussin 	c -= 32;
1033*61d06d6bSBaptiste Daroussin 	p->ps->pscol += (size_t)fonts[f].gly[c].wx;
1034*61d06d6bSBaptiste Daroussin }
1035*61d06d6bSBaptiste Daroussin 
1036*61d06d6bSBaptiste Daroussin static void
1037*61d06d6bSBaptiste Daroussin ps_pclose(struct termp *p)
1038*61d06d6bSBaptiste Daroussin {
1039*61d06d6bSBaptiste Daroussin 
1040*61d06d6bSBaptiste Daroussin 	/*
1041*61d06d6bSBaptiste Daroussin 	 * Spit out that we're exiting a word context (this is a
1042*61d06d6bSBaptiste Daroussin 	 * "partial close" because we don't check the last-char buffer
1043*61d06d6bSBaptiste Daroussin 	 * or anything).
1044*61d06d6bSBaptiste Daroussin 	 */
1045*61d06d6bSBaptiste Daroussin 
1046*61d06d6bSBaptiste Daroussin 	if ( ! (PS_INLINE & p->ps->flags))
1047*61d06d6bSBaptiste Daroussin 		return;
1048*61d06d6bSBaptiste Daroussin 
1049*61d06d6bSBaptiste Daroussin 	if (TERMTYPE_PS != p->type)
1050*61d06d6bSBaptiste Daroussin 		ps_printf(p, ") Tj\nET\n");
1051*61d06d6bSBaptiste Daroussin 	else if (p->ps->psrow == p->ps->lastrow)
1052*61d06d6bSBaptiste Daroussin 		ps_printf(p, ")c\n");
1053*61d06d6bSBaptiste Daroussin 	else {
1054*61d06d6bSBaptiste Daroussin 		ps_printf(p, ")s\n");
1055*61d06d6bSBaptiste Daroussin 		p->ps->lastrow = p->ps->psrow;
1056*61d06d6bSBaptiste Daroussin 	}
1057*61d06d6bSBaptiste Daroussin 
1058*61d06d6bSBaptiste Daroussin 	p->ps->flags &= ~PS_INLINE;
1059*61d06d6bSBaptiste Daroussin }
1060*61d06d6bSBaptiste Daroussin 
1061*61d06d6bSBaptiste Daroussin /* If we have a `last' char that wasn't printed yet, print it now. */
1062*61d06d6bSBaptiste Daroussin static void
1063*61d06d6bSBaptiste Daroussin ps_plast(struct termp *p)
1064*61d06d6bSBaptiste Daroussin {
1065*61d06d6bSBaptiste Daroussin 	size_t	 wx;
1066*61d06d6bSBaptiste Daroussin 
1067*61d06d6bSBaptiste Daroussin 	if (p->ps->last == '\0')
1068*61d06d6bSBaptiste Daroussin 		return;
1069*61d06d6bSBaptiste Daroussin 
1070*61d06d6bSBaptiste Daroussin 	/* Check the font mode; open a new scope if it doesn't match. */
1071*61d06d6bSBaptiste Daroussin 
1072*61d06d6bSBaptiste Daroussin 	if (p->ps->nextf != p->ps->lastf) {
1073*61d06d6bSBaptiste Daroussin 		ps_pclose(p);
1074*61d06d6bSBaptiste Daroussin 		ps_setfont(p, p->ps->nextf);
1075*61d06d6bSBaptiste Daroussin 	}
1076*61d06d6bSBaptiste Daroussin 	p->ps->nextf = TERMFONT_NONE;
1077*61d06d6bSBaptiste Daroussin 
1078*61d06d6bSBaptiste Daroussin 	/*
1079*61d06d6bSBaptiste Daroussin 	 * For an overstrike, if a previous character
1080*61d06d6bSBaptiste Daroussin 	 * was wider, advance to center the new one.
1081*61d06d6bSBaptiste Daroussin 	 */
1082*61d06d6bSBaptiste Daroussin 
1083*61d06d6bSBaptiste Daroussin 	if (p->ps->pscolnext) {
1084*61d06d6bSBaptiste Daroussin 		wx = fonts[p->ps->lastf].gly[(int)p->ps->last-32].wx;
1085*61d06d6bSBaptiste Daroussin 		if (p->ps->pscol + wx < p->ps->pscolnext)
1086*61d06d6bSBaptiste Daroussin 			p->ps->pscol = (p->ps->pscol +
1087*61d06d6bSBaptiste Daroussin 			    p->ps->pscolnext - wx) / 2;
1088*61d06d6bSBaptiste Daroussin 	}
1089*61d06d6bSBaptiste Daroussin 
1090*61d06d6bSBaptiste Daroussin 	ps_pletter(p, p->ps->last);
1091*61d06d6bSBaptiste Daroussin 	p->ps->last = '\0';
1092*61d06d6bSBaptiste Daroussin 
1093*61d06d6bSBaptiste Daroussin 	/*
1094*61d06d6bSBaptiste Daroussin 	 * For an overstrike, if a previous character
1095*61d06d6bSBaptiste Daroussin 	 * was wider, advance to the end of the old one.
1096*61d06d6bSBaptiste Daroussin 	 */
1097*61d06d6bSBaptiste Daroussin 
1098*61d06d6bSBaptiste Daroussin 	if (p->ps->pscol < p->ps->pscolnext) {
1099*61d06d6bSBaptiste Daroussin 		ps_pclose(p);
1100*61d06d6bSBaptiste Daroussin 		p->ps->pscol = p->ps->pscolnext;
1101*61d06d6bSBaptiste Daroussin 	}
1102*61d06d6bSBaptiste Daroussin }
1103*61d06d6bSBaptiste Daroussin 
1104*61d06d6bSBaptiste Daroussin static void
1105*61d06d6bSBaptiste Daroussin ps_letter(struct termp *p, int arg)
1106*61d06d6bSBaptiste Daroussin {
1107*61d06d6bSBaptiste Daroussin 	size_t		savecol;
1108*61d06d6bSBaptiste Daroussin 	char		c;
1109*61d06d6bSBaptiste Daroussin 
1110*61d06d6bSBaptiste Daroussin 	c = arg >= 128 || arg <= 0 ? '?' : arg;
1111*61d06d6bSBaptiste Daroussin 
1112*61d06d6bSBaptiste Daroussin 	/*
1113*61d06d6bSBaptiste Daroussin 	 * When receiving a backspace, merely flag it.
1114*61d06d6bSBaptiste Daroussin 	 * We don't know yet whether it is
1115*61d06d6bSBaptiste Daroussin 	 * a font instruction or an overstrike.
1116*61d06d6bSBaptiste Daroussin 	 */
1117*61d06d6bSBaptiste Daroussin 
1118*61d06d6bSBaptiste Daroussin 	if (c == '\b') {
1119*61d06d6bSBaptiste Daroussin 		assert(p->ps->last != '\0');
1120*61d06d6bSBaptiste Daroussin 		assert( ! (p->ps->flags & PS_BACKSP));
1121*61d06d6bSBaptiste Daroussin 		p->ps->flags |= PS_BACKSP;
1122*61d06d6bSBaptiste Daroussin 		return;
1123*61d06d6bSBaptiste Daroussin 	}
1124*61d06d6bSBaptiste Daroussin 
1125*61d06d6bSBaptiste Daroussin 	/*
1126*61d06d6bSBaptiste Daroussin 	 * Decode font instructions.
1127*61d06d6bSBaptiste Daroussin 	 */
1128*61d06d6bSBaptiste Daroussin 
1129*61d06d6bSBaptiste Daroussin 	if (p->ps->flags & PS_BACKSP) {
1130*61d06d6bSBaptiste Daroussin 		if (p->ps->last == '_') {
1131*61d06d6bSBaptiste Daroussin 			switch (p->ps->nextf) {
1132*61d06d6bSBaptiste Daroussin 			case TERMFONT_BI:
1133*61d06d6bSBaptiste Daroussin 				break;
1134*61d06d6bSBaptiste Daroussin 			case TERMFONT_BOLD:
1135*61d06d6bSBaptiste Daroussin 				p->ps->nextf = TERMFONT_BI;
1136*61d06d6bSBaptiste Daroussin 				break;
1137*61d06d6bSBaptiste Daroussin 			default:
1138*61d06d6bSBaptiste Daroussin 				p->ps->nextf = TERMFONT_UNDER;
1139*61d06d6bSBaptiste Daroussin 			}
1140*61d06d6bSBaptiste Daroussin 			p->ps->last = c;
1141*61d06d6bSBaptiste Daroussin 			p->ps->flags &= ~PS_BACKSP;
1142*61d06d6bSBaptiste Daroussin 			return;
1143*61d06d6bSBaptiste Daroussin 		}
1144*61d06d6bSBaptiste Daroussin 		if (p->ps->last == c) {
1145*61d06d6bSBaptiste Daroussin 			switch (p->ps->nextf) {
1146*61d06d6bSBaptiste Daroussin 			case TERMFONT_BI:
1147*61d06d6bSBaptiste Daroussin 				break;
1148*61d06d6bSBaptiste Daroussin 			case TERMFONT_UNDER:
1149*61d06d6bSBaptiste Daroussin 				p->ps->nextf = TERMFONT_BI;
1150*61d06d6bSBaptiste Daroussin 				break;
1151*61d06d6bSBaptiste Daroussin 			default:
1152*61d06d6bSBaptiste Daroussin 				p->ps->nextf = TERMFONT_BOLD;
1153*61d06d6bSBaptiste Daroussin 			}
1154*61d06d6bSBaptiste Daroussin 			p->ps->flags &= ~PS_BACKSP;
1155*61d06d6bSBaptiste Daroussin 			return;
1156*61d06d6bSBaptiste Daroussin 		}
1157*61d06d6bSBaptiste Daroussin 
1158*61d06d6bSBaptiste Daroussin 		/*
1159*61d06d6bSBaptiste Daroussin 		 * This is not a font instruction, but rather
1160*61d06d6bSBaptiste Daroussin 		 * the next character.  Prepare for overstrike.
1161*61d06d6bSBaptiste Daroussin 		 */
1162*61d06d6bSBaptiste Daroussin 
1163*61d06d6bSBaptiste Daroussin 		savecol = p->ps->pscol;
1164*61d06d6bSBaptiste Daroussin 	} else
1165*61d06d6bSBaptiste Daroussin 		savecol = SIZE_MAX;
1166*61d06d6bSBaptiste Daroussin 
1167*61d06d6bSBaptiste Daroussin 	/*
1168*61d06d6bSBaptiste Daroussin 	 * We found the next character, so the font instructions
1169*61d06d6bSBaptiste Daroussin 	 * for the previous one are complete.
1170*61d06d6bSBaptiste Daroussin 	 * Use them and print it.
1171*61d06d6bSBaptiste Daroussin 	 */
1172*61d06d6bSBaptiste Daroussin 
1173*61d06d6bSBaptiste Daroussin 	ps_plast(p);
1174*61d06d6bSBaptiste Daroussin 
1175*61d06d6bSBaptiste Daroussin 	/*
1176*61d06d6bSBaptiste Daroussin 	 * Do not print the current character yet because font
1177*61d06d6bSBaptiste Daroussin 	 * instructions might follow; only remember the character.
1178*61d06d6bSBaptiste Daroussin 	 * It will get printed later from ps_plast().
1179*61d06d6bSBaptiste Daroussin 	 */
1180*61d06d6bSBaptiste Daroussin 
1181*61d06d6bSBaptiste Daroussin 	p->ps->last = c;
1182*61d06d6bSBaptiste Daroussin 
1183*61d06d6bSBaptiste Daroussin 	/*
1184*61d06d6bSBaptiste Daroussin 	 * For an overstrike, back up to the previous position.
1185*61d06d6bSBaptiste Daroussin 	 * If the previous character is wider than any it overstrikes,
1186*61d06d6bSBaptiste Daroussin 	 * remember the current position, because it might also be
1187*61d06d6bSBaptiste Daroussin 	 * wider than all that will overstrike it.
1188*61d06d6bSBaptiste Daroussin 	 */
1189*61d06d6bSBaptiste Daroussin 
1190*61d06d6bSBaptiste Daroussin 	if (savecol != SIZE_MAX) {
1191*61d06d6bSBaptiste Daroussin 		if (p->ps->pscolnext < p->ps->pscol)
1192*61d06d6bSBaptiste Daroussin 			p->ps->pscolnext = p->ps->pscol;
1193*61d06d6bSBaptiste Daroussin 		ps_pclose(p);
1194*61d06d6bSBaptiste Daroussin 		p->ps->pscol = savecol;
1195*61d06d6bSBaptiste Daroussin 		p->ps->flags &= ~PS_BACKSP;
1196*61d06d6bSBaptiste Daroussin 	} else
1197*61d06d6bSBaptiste Daroussin 		p->ps->pscolnext = 0;
1198*61d06d6bSBaptiste Daroussin }
1199*61d06d6bSBaptiste Daroussin 
1200*61d06d6bSBaptiste Daroussin static void
1201*61d06d6bSBaptiste Daroussin ps_advance(struct termp *p, size_t len)
1202*61d06d6bSBaptiste Daroussin {
1203*61d06d6bSBaptiste Daroussin 
1204*61d06d6bSBaptiste Daroussin 	/*
1205*61d06d6bSBaptiste Daroussin 	 * Advance some spaces.  This can probably be made smarter,
1206*61d06d6bSBaptiste Daroussin 	 * i.e., to have multiple space-separated words in the same
1207*61d06d6bSBaptiste Daroussin 	 * scope, but this is easier:  just close out the current scope
1208*61d06d6bSBaptiste Daroussin 	 * and readjust our column settings.
1209*61d06d6bSBaptiste Daroussin 	 */
1210*61d06d6bSBaptiste Daroussin 
1211*61d06d6bSBaptiste Daroussin 	ps_plast(p);
1212*61d06d6bSBaptiste Daroussin 	ps_pclose(p);
1213*61d06d6bSBaptiste Daroussin 	p->ps->pscol += len;
1214*61d06d6bSBaptiste Daroussin }
1215*61d06d6bSBaptiste Daroussin 
1216*61d06d6bSBaptiste Daroussin static void
1217*61d06d6bSBaptiste Daroussin ps_endline(struct termp *p)
1218*61d06d6bSBaptiste Daroussin {
1219*61d06d6bSBaptiste Daroussin 
1220*61d06d6bSBaptiste Daroussin 	/* Close out any scopes we have open: we're at eoln. */
1221*61d06d6bSBaptiste Daroussin 
1222*61d06d6bSBaptiste Daroussin 	ps_plast(p);
1223*61d06d6bSBaptiste Daroussin 	ps_pclose(p);
1224*61d06d6bSBaptiste Daroussin 
1225*61d06d6bSBaptiste Daroussin 	/*
1226*61d06d6bSBaptiste Daroussin 	 * If we're in the margin, don't try to recalculate our current
1227*61d06d6bSBaptiste Daroussin 	 * row.  XXX: if the column tries to be fancy with multiple
1228*61d06d6bSBaptiste Daroussin 	 * lines, we'll do nasty stuff.
1229*61d06d6bSBaptiste Daroussin 	 */
1230*61d06d6bSBaptiste Daroussin 
1231*61d06d6bSBaptiste Daroussin 	if (PS_MARGINS & p->ps->flags)
1232*61d06d6bSBaptiste Daroussin 		return;
1233*61d06d6bSBaptiste Daroussin 
1234*61d06d6bSBaptiste Daroussin 	/* Left-justify. */
1235*61d06d6bSBaptiste Daroussin 
1236*61d06d6bSBaptiste Daroussin 	p->ps->pscol = p->ps->left;
1237*61d06d6bSBaptiste Daroussin 
1238*61d06d6bSBaptiste Daroussin 	/* If we haven't printed anything, return. */
1239*61d06d6bSBaptiste Daroussin 
1240*61d06d6bSBaptiste Daroussin 	if (PS_NEWPAGE & p->ps->flags)
1241*61d06d6bSBaptiste Daroussin 		return;
1242*61d06d6bSBaptiste Daroussin 
1243*61d06d6bSBaptiste Daroussin 	/*
1244*61d06d6bSBaptiste Daroussin 	 * Put us down a line.  If we're at the page bottom, spit out a
1245*61d06d6bSBaptiste Daroussin 	 * showpage and restart our row.
1246*61d06d6bSBaptiste Daroussin 	 */
1247*61d06d6bSBaptiste Daroussin 
1248*61d06d6bSBaptiste Daroussin 	if (p->ps->psrow >= p->ps->lineheight + p->ps->bottom) {
1249*61d06d6bSBaptiste Daroussin 		p->ps->psrow -= p->ps->lineheight;
1250*61d06d6bSBaptiste Daroussin 		return;
1251*61d06d6bSBaptiste Daroussin 	}
1252*61d06d6bSBaptiste Daroussin 
1253*61d06d6bSBaptiste Daroussin 	ps_closepage(p);
1254*61d06d6bSBaptiste Daroussin 
1255*61d06d6bSBaptiste Daroussin 	p->tcol->offset -= p->ti;
1256*61d06d6bSBaptiste Daroussin 	p->ti = 0;
1257*61d06d6bSBaptiste Daroussin }
1258*61d06d6bSBaptiste Daroussin 
1259*61d06d6bSBaptiste Daroussin static void
1260*61d06d6bSBaptiste Daroussin ps_setfont(struct termp *p, enum termfont f)
1261*61d06d6bSBaptiste Daroussin {
1262*61d06d6bSBaptiste Daroussin 
1263*61d06d6bSBaptiste Daroussin 	assert(f < TERMFONT__MAX);
1264*61d06d6bSBaptiste Daroussin 	p->ps->lastf = f;
1265*61d06d6bSBaptiste Daroussin 
1266*61d06d6bSBaptiste Daroussin 	/*
1267*61d06d6bSBaptiste Daroussin 	 * If we're still at the top of the page, let the font-setting
1268*61d06d6bSBaptiste Daroussin 	 * be delayed until we actually have stuff to print.
1269*61d06d6bSBaptiste Daroussin 	 */
1270*61d06d6bSBaptiste Daroussin 
1271*61d06d6bSBaptiste Daroussin 	if (PS_NEWPAGE & p->ps->flags)
1272*61d06d6bSBaptiste Daroussin 		return;
1273*61d06d6bSBaptiste Daroussin 
1274*61d06d6bSBaptiste Daroussin 	if (TERMTYPE_PS == p->type)
1275*61d06d6bSBaptiste Daroussin 		ps_printf(p, "f%d\n", (int)f);
1276*61d06d6bSBaptiste Daroussin 	else
1277*61d06d6bSBaptiste Daroussin 		ps_printf(p, "/F%d %zu Tf\n",
1278*61d06d6bSBaptiste Daroussin 		    (int)f, p->ps->scale);
1279*61d06d6bSBaptiste Daroussin }
1280*61d06d6bSBaptiste Daroussin 
1281*61d06d6bSBaptiste Daroussin static size_t
1282*61d06d6bSBaptiste Daroussin ps_width(const struct termp *p, int c)
1283*61d06d6bSBaptiste Daroussin {
1284*61d06d6bSBaptiste Daroussin 
1285*61d06d6bSBaptiste Daroussin 	if (c <= 32 || c - 32 >= MAXCHAR)
1286*61d06d6bSBaptiste Daroussin 		c = 0;
1287*61d06d6bSBaptiste Daroussin 	else
1288*61d06d6bSBaptiste Daroussin 		c -= 32;
1289*61d06d6bSBaptiste Daroussin 
1290*61d06d6bSBaptiste Daroussin 	return (size_t)fonts[(int)TERMFONT_NONE].gly[c].wx;
1291*61d06d6bSBaptiste Daroussin }
1292*61d06d6bSBaptiste Daroussin 
1293*61d06d6bSBaptiste Daroussin static int
1294*61d06d6bSBaptiste Daroussin ps_hspan(const struct termp *p, const struct roffsu *su)
1295*61d06d6bSBaptiste Daroussin {
1296*61d06d6bSBaptiste Daroussin 	double		 r;
1297*61d06d6bSBaptiste Daroussin 
1298*61d06d6bSBaptiste Daroussin 	/*
1299*61d06d6bSBaptiste Daroussin 	 * All of these measurements are derived by converting from the
1300*61d06d6bSBaptiste Daroussin 	 * native measurement to AFM units.
1301*61d06d6bSBaptiste Daroussin 	 */
1302*61d06d6bSBaptiste Daroussin 	switch (su->unit) {
1303*61d06d6bSBaptiste Daroussin 	case SCALE_BU:
1304*61d06d6bSBaptiste Daroussin 		/*
1305*61d06d6bSBaptiste Daroussin 		 * Traditionally, the default unit is fixed to the
1306*61d06d6bSBaptiste Daroussin 		 * output media.  So this would refer to the point.  In
1307*61d06d6bSBaptiste Daroussin 		 * mandoc(1), however, we stick to the default terminal
1308*61d06d6bSBaptiste Daroussin 		 * scaling unit so that output is the same regardless
1309*61d06d6bSBaptiste Daroussin 		 * the media.
1310*61d06d6bSBaptiste Daroussin 		 */
1311*61d06d6bSBaptiste Daroussin 		r = PNT2AFM(p, su->scale * 72.0 / 240.0);
1312*61d06d6bSBaptiste Daroussin 		break;
1313*61d06d6bSBaptiste Daroussin 	case SCALE_CM:
1314*61d06d6bSBaptiste Daroussin 		r = PNT2AFM(p, su->scale * 72.0 / 2.54);
1315*61d06d6bSBaptiste Daroussin 		break;
1316*61d06d6bSBaptiste Daroussin 	case SCALE_EM:
1317*61d06d6bSBaptiste Daroussin 		r = su->scale *
1318*61d06d6bSBaptiste Daroussin 		    fonts[(int)TERMFONT_NONE].gly[109 - 32].wx;
1319*61d06d6bSBaptiste Daroussin 		break;
1320*61d06d6bSBaptiste Daroussin 	case SCALE_EN:
1321*61d06d6bSBaptiste Daroussin 		r = su->scale *
1322*61d06d6bSBaptiste Daroussin 		    fonts[(int)TERMFONT_NONE].gly[110 - 32].wx;
1323*61d06d6bSBaptiste Daroussin 		break;
1324*61d06d6bSBaptiste Daroussin 	case SCALE_IN:
1325*61d06d6bSBaptiste Daroussin 		r = PNT2AFM(p, su->scale * 72.0);
1326*61d06d6bSBaptiste Daroussin 		break;
1327*61d06d6bSBaptiste Daroussin 	case SCALE_MM:
1328*61d06d6bSBaptiste Daroussin 		r = su->scale *
1329*61d06d6bSBaptiste Daroussin 		    fonts[(int)TERMFONT_NONE].gly[109 - 32].wx / 100.0;
1330*61d06d6bSBaptiste Daroussin 		break;
1331*61d06d6bSBaptiste Daroussin 	case SCALE_PC:
1332*61d06d6bSBaptiste Daroussin 		r = PNT2AFM(p, su->scale * 12.0);
1333*61d06d6bSBaptiste Daroussin 		break;
1334*61d06d6bSBaptiste Daroussin 	case SCALE_PT:
1335*61d06d6bSBaptiste Daroussin 		r = PNT2AFM(p, su->scale * 1.0);
1336*61d06d6bSBaptiste Daroussin 		break;
1337*61d06d6bSBaptiste Daroussin 	case SCALE_VS:
1338*61d06d6bSBaptiste Daroussin 		r = su->scale * p->ps->lineheight;
1339*61d06d6bSBaptiste Daroussin 		break;
1340*61d06d6bSBaptiste Daroussin 	default:
1341*61d06d6bSBaptiste Daroussin 		r = su->scale;
1342*61d06d6bSBaptiste Daroussin 		break;
1343*61d06d6bSBaptiste Daroussin 	}
1344*61d06d6bSBaptiste Daroussin 
1345*61d06d6bSBaptiste Daroussin 	return r * 24.0;
1346*61d06d6bSBaptiste Daroussin }
1347*61d06d6bSBaptiste Daroussin 
1348*61d06d6bSBaptiste Daroussin static void
1349*61d06d6bSBaptiste Daroussin ps_growbuf(struct termp *p, size_t sz)
1350*61d06d6bSBaptiste Daroussin {
1351*61d06d6bSBaptiste Daroussin 	if (p->ps->psmargcur + sz <= p->ps->psmargsz)
1352*61d06d6bSBaptiste Daroussin 		return;
1353*61d06d6bSBaptiste Daroussin 
1354*61d06d6bSBaptiste Daroussin 	if (sz < PS_BUFSLOP)
1355*61d06d6bSBaptiste Daroussin 		sz = PS_BUFSLOP;
1356*61d06d6bSBaptiste Daroussin 
1357*61d06d6bSBaptiste Daroussin 	p->ps->psmargsz += sz;
1358*61d06d6bSBaptiste Daroussin 	p->ps->psmarg = mandoc_realloc(p->ps->psmarg, p->ps->psmargsz);
1359*61d06d6bSBaptiste Daroussin }
1360