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