Print this page
9718 update mandoc to 1.14.4
@@ -1,9 +1,10 @@
-/* $Id: term_ps.c,v 1.85 2017/06/07 17:38:26 schwarze Exp $ */
+/* $Id: term_ps.c,v 1.91 2017/11/10 23:42:52 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2017 Marc Espie <espie@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@@ -64,10 +65,11 @@
#define PS_NEWPAGE (1 << 2) /* new page, no words yet */
#define PS_BACKSP (1 << 3) /* last character was backspace */
size_t pscol; /* visible column (AFM units) */
size_t pscolnext; /* used for overstrike */
size_t psrow; /* visible row (AFM units) */
+ size_t lastrow; /* psrow of the previous word */
char *psmarg; /* margin buf */
size_t psmargsz; /* margin buf size */
size_t psmargcur; /* cur index in margin buf */
char last; /* last non-backspace seen */
enum termfont lastf; /* last set font */
@@ -75,10 +77,11 @@
size_t scale; /* font scaling factor */
size_t pages; /* number of pages shown */
size_t lineheight; /* line height (AFM units) */
size_t top; /* body top (AFM units) */
size_t bottom; /* body bottom (AFM units) */
+ const char *medianame; /* for DocumentMedia and PageSize */
size_t height; /* page height (AFM units */
size_t width; /* page width (AFM units) */
size_t lastwidth; /* page width before last ll */
size_t left; /* body left (AFM units) */
size_t header; /* header pos (AFM units) */
@@ -106,11 +109,11 @@
static void ps_printf(struct termp *, const char *, ...)
__attribute__((__format__ (__printf__, 2, 3)));
static void ps_putchar(struct termp *, char);
static void ps_setfont(struct termp *, enum termfont);
static void ps_setwidth(struct termp *, int, int);
-static struct termp *pspdf_alloc(const struct manoutput *);
+static struct termp *pspdf_alloc(const struct manoutput *, enum termtype);
static void pdf_obj(struct termp *, size_t);
/*
* We define, for the time being, three fonts: bold, oblique/italic, and
* normal (roman). The following table hard-codes the font metrics for
@@ -509,40 +512,31 @@
};
void *
pdf_alloc(const struct manoutput *outopts)
{
- struct termp *p;
-
- if (NULL != (p = pspdf_alloc(outopts)))
- p->type = TERMTYPE_PDF;
-
- return p;
+ return pspdf_alloc(outopts, TERMTYPE_PDF);
}
void *
ps_alloc(const struct manoutput *outopts)
{
- struct termp *p;
-
- if (NULL != (p = pspdf_alloc(outopts)))
- p->type = TERMTYPE_PS;
-
- return p;
+ return pspdf_alloc(outopts, TERMTYPE_PS);
}
static struct termp *
-pspdf_alloc(const struct manoutput *outopts)
+pspdf_alloc(const struct manoutput *outopts, enum termtype type)
{
struct termp *p;
unsigned int pagex, pagey;
size_t marginx, marginy, lineheight;
const char *pp;
p = mandoc_calloc(1, sizeof(*p));
p->tcol = p->tcols = mandoc_calloc(1, sizeof(*p->tcol));
p->maxtcol = 1;
+ p->type = type;
p->enc = TERMENC_ASCII;
p->fontq = mandoc_reallocarray(NULL,
(p->fontsz = 8), sizeof(*p->fontq));
p->fontq[0] = p->fontl = TERMFONT_NONE;
@@ -557,10 +551,11 @@
p->setwidth = ps_setwidth;
p->width = ps_width;
/* Default to US letter (millimetres). */
+ p->ps->medianame = "Letter";
pagex = 216;
pagey = 279;
/*
* The ISO-269 paper sizes can be calculated automatically, but
@@ -568,24 +563,30 @@
* do that. So just do it the easy way for now. Since this
* only happens once, I'm not terribly concerned.
*/
pp = outopts->paper;
- if (pp && strcasecmp(pp, "letter")) {
- if (0 == strcasecmp(pp, "a3")) {
+ if (pp != NULL && strcasecmp(pp, "letter") != 0) {
+ if (strcasecmp(pp, "a3") == 0) {
+ p->ps->medianame = "A3";
pagex = 297;
pagey = 420;
- } else if (0 == strcasecmp(pp, "a4")) {
+ } else if (strcasecmp(pp, "a4") == 0) {
+ p->ps->medianame = "A4";
pagex = 210;
pagey = 297;
- } else if (0 == strcasecmp(pp, "a5")) {
+ } else if (strcasecmp(pp, "a5") == 0) {
+ p->ps->medianame = "A5";
pagex = 148;
pagey = 210;
- } else if (0 == strcasecmp(pp, "legal")) {
+ } else if (strcasecmp(pp, "legal") == 0) {
+ p->ps->medianame = "Legal";
pagex = 216;
pagey = 356;
- } else if (2 != sscanf(pp, "%ux%u", &pagex, &pagey))
+ } else if (sscanf(pp, "%ux%u", &pagex, &pagey) == 2)
+ p->ps->medianame = "CustomSize";
+ else
warnx("%s: Unknown paper", pp);
}
/*
* This MUST be defined before any PNT2AFM or AFM2PNT
@@ -594,12 +595,12 @@
p->ps->scale = 11;
/* Remember millimetres -> AFM units. */
- pagex = PNT2AFM(p, ((double)pagex * 2.834));
- pagey = PNT2AFM(p, ((double)pagey * 2.834));
+ pagex = PNT2AFM(p, ((double)pagex * 72.0 / 25.4));
+ pagey = PNT2AFM(p, ((double)pagey * 72.0 / 25.4));
/* Margins are 1/9 the page x and y. */
marginx = (size_t)((double)pagex / 9.0);
marginy = (size_t)((double)pagey / 9.0);
@@ -731,21 +732,19 @@
int i;
size_t len, base;
/*
* Close out a page that we've already flushed to output. In
- * PostScript, we simply note that the page must be showed. In
+ * PostScript, we simply note that the page must be shown. In
* PDF, we must now create the Length, Resource, and Page node
* for the page contents.
*/
assert(p->ps->psmarg && p->ps->psmarg[0]);
ps_printf(p, "%s", p->ps->psmarg);
if (TERMTYPE_PS != p->type) {
- ps_printf(p, "ET\n");
-
len = p->ps->pdfbytes - p->ps->pdflastpg;
base = p->ps->pages * 4 + p->ps->pdfbody;
ps_printf(p, "endstream\nendobj\n");
@@ -757,11 +756,11 @@
pdf_obj(p, base + 2);
ps_printf(p, "<<\n/ProcSet [/PDF /Text]\n");
ps_printf(p, "/Font <<\n");
for (i = 0; i < (int)TERMFONT__MAX; i++)
ps_printf(p, "/F%d %d 0 R\n", i, 3 + i);
- ps_printf(p, ">>\n>>\n");
+ ps_printf(p, ">>\n>>\nendobj\n");
/* Page node. */
pdf_obj(p, base + 3);
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Page\n");
@@ -822,11 +821,11 @@
ps_printf(p, "]\n>>\nendobj\n");
pdf_obj(p, base);
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Catalog\n");
ps_printf(p, "/Pages 2 0 R\n");
- ps_printf(p, ">>\n");
+ ps_printf(p, ">>\nendobj\n");
xref = p->ps->pdfbytes;
ps_printf(p, "xref\n");
ps_printf(p, "0 %zu\n", base + 1);
ps_printf(p, "0000000000 65535 f \n");
@@ -846,10 +845,11 @@
}
static void
ps_begin(struct termp *p)
{
+ size_t width, height;
int i;
/*
* Print margins into margin buffer. Nothing gets output to the
* screen yet, so we don't need to initialise the primary state.
@@ -863,10 +863,11 @@
/*p->ps->pdfbytes = 0;*/
p->ps->psmargcur = 0;
p->ps->flags = PS_MARGINS;
p->ps->pscol = p->ps->left;
p->ps->psrow = p->ps->header;
+ p->ps->lastrow = 0; /* impossible row */
ps_setfont(p, TERMFONT_NONE);
(*p->headf)(p, p->argf);
(*p->endline)(p);
@@ -887,25 +888,48 @@
* Print header and initialise page state. Following this,
* stuff gets printed to the screen, so make sure we're sane.
*/
if (TERMTYPE_PS == p->type) {
+ width = AFM2PNT(p, p->ps->width);
+ height = AFM2PNT(p, p->ps->height);
+
ps_printf(p, "%%!PS-Adobe-3.0\n");
ps_printf(p, "%%%%DocumentData: Clean7Bit\n");
ps_printf(p, "%%%%Orientation: Portrait\n");
ps_printf(p, "%%%%Pages: (atend)\n");
ps_printf(p, "%%%%PageOrder: Ascend\n");
- ps_printf(p, "%%%%DocumentMedia: "
- "Default %zu %zu 0 () ()\n",
- (size_t)AFM2PNT(p, p->ps->width),
- (size_t)AFM2PNT(p, p->ps->height));
+ ps_printf(p, "%%%%DocumentMedia: man-%s %zu %zu 0 () ()\n",
+ p->ps->medianame, width, height);
ps_printf(p, "%%%%DocumentNeededResources: font");
for (i = 0; i < (int)TERMFONT__MAX; i++)
ps_printf(p, " %s", fonts[i].name);
- ps_printf(p, "\n%%%%EndComments\n");
+ ps_printf(p, "\n%%%%DocumentSuppliedResources: "
+ "procset MandocProcs 1.0 0\n");
+ ps_printf(p, "%%%%EndComments\n");
+ ps_printf(p, "%%%%BeginProlog\n");
+ ps_printf(p, "%%%%BeginResource: procset MandocProcs "
+ "10170 10170\n");
+ /* The font size is effectively hard-coded for now. */
+ ps_printf(p, "/fs %zu def\n", p->ps->scale);
+ for (i = 0; i < (int)TERMFONT__MAX; i++)
+ ps_printf(p, "/f%d { /%s fs selectfont } def\n",
+ i, fonts[i].name);
+ ps_printf(p, "/s { 3 1 roll moveto show } bind def\n");
+ ps_printf(p, "/c { exch currentpoint exch pop "
+ "moveto show } bind def\n");
+ ps_printf(p, "%%%%EndResource\n");
+ ps_printf(p, "%%%%EndProlog\n");
+ ps_printf(p, "%%%%BeginSetup\n");
+ ps_printf(p, "%%%%BeginFeature: *PageSize %s\n",
+ p->ps->medianame);
+ ps_printf(p, "<</PageSize [%zu %zu]>>setpagedevice\n",
+ width, height);
+ ps_printf(p, "%%%%EndFeature\n");
+ ps_printf(p, "%%%%EndSetup\n");
} else {
ps_printf(p, "%%PDF-1.1\n");
pdf_obj(p, 1);
ps_printf(p, "<<\n");
ps_printf(p, ">>\n");
@@ -916,11 +940,11 @@
ps_printf(p, "<<\n");
ps_printf(p, "/Type /Font\n");
ps_printf(p, "/Subtype /Type1\n");
ps_printf(p, "/Name /F%d\n", i);
ps_printf(p, "/BaseFont /%s\n", fonts[i].name);
- ps_printf(p, ">>\n");
+ ps_printf(p, ">>\nendobj\n");
}
}
p->ps->pdfbody = (size_t)TERMFONT__MAX + 3;
p->ps->pscol = p->ps->left;
@@ -941,13 +965,11 @@
if (PS_NEWPAGE & p->ps->flags) {
if (TERMTYPE_PS == p->type) {
ps_printf(p, "%%%%Page: %zu %zu\n",
p->ps->pages + 1, p->ps->pages + 1);
- ps_printf(p, "/%s %zu selectfont\n",
- fonts[(int)p->ps->lastf].name,
- p->ps->scale);
+ ps_printf(p, "f%d\n", (int)p->ps->lastf);
} else {
pdf_obj(p, p->ps->pdfbody +
p->ps->pages * 4);
ps_printf(p, "<<\n");
ps_printf(p, "/Length %zu 0 R\n",
@@ -968,14 +990,17 @@
ps_printf(p, "BT\n/F%d %zu Tf\n",
(int)p->ps->lastf, p->ps->scale);
ps_printf(p, "%.3f %.3f Td\n(",
AFM2PNT(p, p->ps->pscol),
AFM2PNT(p, p->ps->psrow));
- } else
- ps_printf(p, "%.3f %.3f moveto\n(",
- AFM2PNT(p, p->ps->pscol),
+ } else {
+ ps_printf(p, "%.3f", AFM2PNT(p, p->ps->pscol));
+ if (p->ps->psrow != p->ps->lastrow)
+ ps_printf(p, " %.3f",
AFM2PNT(p, p->ps->psrow));
+ ps_printf(p, "(");
+ }
p->ps->flags |= PS_INLINE;
}
assert( ! (PS_NEWPAGE & p->ps->flags));
@@ -1019,14 +1044,18 @@
*/
if ( ! (PS_INLINE & p->ps->flags))
return;
- if (TERMTYPE_PS != p->type) {
+ if (TERMTYPE_PS != p->type)
ps_printf(p, ") Tj\nET\n");
- } else
- ps_printf(p, ") show\n");
+ else if (p->ps->psrow == p->ps->lastrow)
+ ps_printf(p, ")c\n");
+ else {
+ ps_printf(p, ")s\n");
+ p->ps->lastrow = p->ps->psrow;
+ }
p->ps->flags &= ~PS_INLINE;
}
/* If we have a `last' char that wasn't printed yet, print it now. */
@@ -1241,12 +1270,11 @@
if (PS_NEWPAGE & p->ps->flags)
return;
if (TERMTYPE_PS == p->type)
- ps_printf(p, "/%s %zu selectfont\n",
- fonts[(int)f].name, p->ps->scale);
+ ps_printf(p, "f%d\n", (int)f);
else
ps_printf(p, "/F%d %zu Tf\n",
(int)f, p->ps->scale);
}