8 static char ps_title
[256]; /* document title */
9 static char ps_author
[256]; /* document author */
10 static int ps_height
; /* document height in basic units */
11 static int o_f
, o_s
, o_m
; /* font and size */
12 static int o_h
, o_v
; /* current user position */
13 static int p_f
, p_s
, p_m
; /* output postscript font */
14 static int o_qtype
; /* queued character type */
15 static int o_qv
, o_qh
, o_qend
; /* queued character position */
16 static int o_rh
, o_rv
, o_rdeg
; /* previous rotation position and degree */
17 static int o_gname
; /* use glyphshow for all glyphs */
19 static char o_fonts
[FNLEN
* NFONTS
] = " ";
21 static void outvf(char *s
, va_list ap
)
23 vfprintf(stdout
, s
, ap
);
26 static void outf(char *s
, ...)
34 static void o_flush(void)
37 outf(") %d %d w\n", o_qh
, o_qv
);
39 outf("] %d %d g\n", o_qh
, o_qv
);
59 static void o_queue(struct glyph
*g
)
61 int type
= 1 + (g
->pos
<= 0 || o_gname
);
62 if (o_qtype
!= type
|| o_qend
!= o_h
|| o_qv
!= o_v
) {
67 outf(type
== 1 ? "(" : "[");
70 if (g
->pos
>= ' ' && g
->pos
<= '~')
71 outf("%s%c", strchr("()\\", g
->pos
) ? "\\" : "", g
->pos
);
73 outf("\\%d%d%d", (g
->pos
>> 6) & 7,
74 (g
->pos
>> 3) & 7, g
->pos
& 7);
78 o_qend
= o_h
+ font_wid(g
->font
, o_s
, g
->wid
);
81 /* calls o_flush() if necessary */
82 void out(char *s
, ...)
91 static void out_fontup(int fid
)
96 out("%d %d %d rgb\n", CLR_R(o_m
), CLR_G(o_m
), CLR_B(o_m
));
99 if (fid
!= p_f
|| o_s
!= p_s
) {
101 out("%d /%s f\n", o_s
, font_name(fn
));
104 sprintf(fnname
, " %s ", font_name(fn
));
105 if (!strstr(o_fonts
, fnname
))
106 sprintf(strchr(o_fonts
, '\0'), "%s ", font_name(fn
));
114 g
= dev_glyph(c
, o_f
);
115 fn
= g
? g
->font
: dev_font(o_f
);
117 outrel(*c
== ' ' && fn
? font_swid(fn
, o_s
) : 1, 0);
120 out_fontup(dev_fontid(fn
));
134 void outrel(int h
, int v
)
146 /* a font was mounted at pos f */
164 void outrotate(int deg
)
169 outf("%d %d %d rot\n", -o_rdeg
, o_rh
, o_rv
);
173 outf("%d %d %d rot\n", deg
, o_h
, o_v
);
176 static int draw_path
; /* number of path segments */
177 static int draw_point
; /* point was set for postscript newpath */
179 static void drawmv(void)
182 outf("%d %d m ", o_h
, o_v
);
186 /* start a multi-segment path */
187 void drawmbeg(char *s
)
192 outf("gsave newpath %s\n", s
);
195 /* end a multi-segment path */
196 void drawmend(char *s
)
200 outf("%s grestore\n", s
);
212 void drawend(int close
, int fill
)
225 void drawl(int h
, int v
)
229 outf("%d %d drawl ", o_h
, o_v
);
236 outf("%d %d drawe ", c
, c
);
239 void drawe(int h
, int v
)
243 outf("%d %d drawe ", h
, v
);
246 void drawa(int h1
, int v1
, int h2
, int v2
)
249 outf("%d %d %d %d drawa ", h1
, v1
, h2
, v2
);
250 outrel(h1
+ h2
, v1
+ v2
);
253 void draws(int h1
, int v1
, int h2
, int v2
)
256 outf("%d %d %d %d %d %d draws ", o_h
, o_v
, o_h
+ h1
, o_v
+ v1
,
257 o_h
+ h1
+ h2
, o_v
+ v1
+ v2
);
261 void outeps(char *eps
, int hwid
, int vwid
)
264 int llx
, lly
, urx
, ury
;
267 if (!(filp
= fopen(eps
, "r")))
269 if (!fgets(buf
, sizeof(buf
), filp
)) {
270 fprintf(stderr
, "warning: file %s is empty\n", eps
);
274 if (sscanf(buf
, "%%!PS-Adobe-%d.%d EPSF-%d.%d", &ver
, &ver
, &ver
, &ver
) != 4) {
275 fprintf(stderr
, "warning: unsupported EPSF header in %s\n", eps
);
280 while (fgets(buf
, sizeof(buf
), filp
))
281 if (!strncmp(buf
, "%%BoundingBox: ", 15))
282 if ((nbb
= sscanf(buf
+ 15, "%d %d %d %d",
283 &llx
, &lly
, &urx
, &ury
)) == 4)
286 if (nbb
< 4) /* no BoundingBox comment */
288 if (hwid
<= 0 && vwid
<= 0)
289 hwid
= (urx
- llx
) * dev_res
/ 72;
291 vwid
= (ury
- lly
) * hwid
/ (urx
- llx
);
293 hwid
= (urx
- llx
) * vwid
/ (ury
- lly
);
294 /* output the EPS file */
297 outf("%d %d %d %d %d %d %d %d EPSFBEG\n",
298 llx
, lly
, hwid
, urx
- llx
, vwid
, ury
- lly
, o_h
, o_v
);
299 outf("%%%%BeginDocument: %s\n", eps
);
300 filp
= fopen(eps
, "r");
301 while (fgets(buf
, sizeof(buf
), filp
))
304 outf("%%%%EndDocument\n");
308 void outpdf(char *pdf
, int hwid
, int vwid
)
312 void outlink(char *lnk
, int hwid
, int vwid
)
315 if (lnk
[0] == '#' || isdigit((unsigned char) lnk
[0])) {
316 outf("[ /Rect [ %d %d t %d %d t ] %s%s "
317 "/Subtype /Link /LNK pdfmark\n",
318 o_h
, o_v
, o_h
+ hwid
, o_v
+ vwid
,
319 lnk
[0] == '#' ? "/Dest /" : "/Page ",
320 lnk
[0] == '#' ? lnk
+ 1 : lnk
);
322 outf("[ /Rect [ %d %d t %d %d t ] "
323 "/Action << /Subtype /URI /URI %s >> /Open true "
324 "/Subtype /Link /LNK pdfmark\n",
325 o_h
, o_v
, o_h
+ hwid
, o_v
+ vwid
, pdftext_static(lnk
));
329 void outname(int n
, char (*desc
)[64], int *page
, int *off
)
333 for (i
= 0; i
< n
; i
++) {
334 outf("[ /Dest /%s", desc
[i
]);
335 outf(" /Page %d", page
[i
]);
337 outf(" /View [/XYZ null %d null]",
338 (ps_height
- off
[i
]) * 72 / dev_res
);
339 outf(" /DEST pdfmark\n");
343 void outmark(int n
, char (*desc
)[256], int *page
, int *off
, int *level
)
347 for (i
= 0; i
< n
; i
++) {
349 for (j
= i
+ 1; j
< n
&& level
[j
] > level
[i
]; j
++)
350 if (level
[j
] == level
[i
] + 1)
352 outf("[ /Title %s", pdftext_static(desc
[i
]));
354 outf(" /Page %d", page
[i
]);
356 outf(" /Count %d", cnt
);
358 outf(" /View [/XYZ null %d null]",
359 (ps_height
- off
[i
]) * 72 / dev_res
);
360 outf(" /OUT pdfmark\n");
364 void outinfo(char *kwd
, char *val
)
366 if (!strcmp("Author", kwd
))
367 snprintf(ps_author
, sizeof(ps_author
), "%s", val
);
368 if (!strcmp("Title", kwd
))
369 snprintf(ps_title
, sizeof(ps_title
), "%s", val
);
372 void outset(char *var
, char *val
)
376 void docpagebeg(int n
)
378 out("%%%%Page: %d %d\n", n
, n
);
379 out("/saveobj save def\n");
381 out("%d pagesetup\n", n
);
384 void docpageend(int n
)
386 out("cleartomark\n");
388 out("saveobj restore\n");
391 void doctrailer(int pages
)
395 out(" /Title %s", pdftext_static(ps_title
));
397 out(" /Author %s", pdftext_static(ps_author
));
398 out(" /Creator (Neatroff) /DOCINFO pdfmark\n");
399 out("%%%%Trailer\n");
401 out("%%%%DocumentFonts: %s\n", o_fonts
);
402 out("%%%%Pages: %d\n", pages
);
406 static char *prolog
=
408 " counttomark 2 idiv {def} repeat pop\n"
409 " /scaling 72 resolution div def\n"
410 " linewidth setlinewidth\n"
412 " 0 pagesize 1 get translate\n"
413 " scaling scaling scale\n"
419 " currentdict /pagedict known currentdict page known and {\n"
420 " page load pagedict exch get cvx exec\n"
425 " { pop globaldict /?pdfmark /exec load put }\n"
426 " { globaldict begin\n"
427 " /?pdfmark /pop load def\n"
428 " /pdfmark /cleartomark load def\n"
432 "/t {neg} bind def\n"
433 "/w {neg moveto show} bind def\n"
434 "/m {neg moveto} bind def\n"
435 "/g {neg moveto {glyphshow} forall} bind def\n"
436 "/rgb {255 div 3 1 roll 255 div 3 1 roll 255 div 3 1 roll setrgbcolor} bind def\n"
437 "/rot {/y exch def /x exch def x y neg translate rotate x neg y translate} bind def\n"
438 "/done {/lastpage where {pop lastpage} if} def\n"
440 "% caching fonts, as selectfont is supposed to be doing\n"
441 "/fncache 16 dict def\n"
442 "/selectfont_append { fncache exch dup findfont put } bind def\n"
443 "/selectfont_cached {\n"
444 " exch dup fncache exch known not { dup selectfont_append } if\n"
445 " fncache exch get exch scalefont setfont\n"
448 " exch dup 3 1 roll scaling div selectfont_cached\n"
449 " linewidth mul scaling 10 mul div setlinewidth\n"
452 "/savedmatrix matrix def\n"
457 " savedmatrix currentmatrix pop scale\n"
458 " .5 0 rmoveto currentpoint .5 0 rmoveto .5 0 360 arc\n"
459 " savedmatrix setmatrix\n"
466 " currentpoint dy1 neg add exch dx1 add exch\n"
467 " dx1 dx1 mul dy1 dy1 mul add sqrt\n"
468 " dy1 dx1 neg atan\n"
469 " dy2 neg dx2 atan\n"
479 " x0 5 x1 mul add 6 div\n"
480 " y0 5 y1 mul add -6 div\n"
481 " x2 5 x1 mul add 6 div\n"
482 " y2 5 y1 mul add -6 div\n"
484 " y1 y2 add -2 div\n"
487 "% including EPS files\n"
489 " /epsf_state save def\n"
491 " div 3 1 roll div exch scale\n"
492 " neg exch neg exch translate\n"
493 " /dict_count countdictstack def\n"
494 " /op_count count 1 sub def\n"
496 " /showpage { } def\n"
497 " 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin\n"
498 " 10 setmiterlimit [ ] 0 setdash newpath\n"
501 " count op_count sub {pop} repeat\n"
502 " countdictstack dict_count sub {end} repeat\n"
503 " epsf_state restore\n"
506 /* pagewidth and pageheight are in tenths of a millimetre */
507 void docheader(char *title
, int pagewidth
, int pageheight
, int linewidth
)
509 ps_height
= pageheight
* dev_res
/ 254;
510 out("%%!PS-Adobe-2.0\n");
511 out("%%%%Version: 1.0\n");
513 out("%%%%Title: %s\n", title
);
514 out("%%%%Creator: Neatroff\n");
515 out("%%%%DocumentFonts: (atend)\n");
516 out("%%%%Pages: (atend)\n");
517 out("%%%%EndComments\n");
519 out("%%%%BeginProlog\n");
520 out("/resolution %d def\n", dev_res
);
521 out("/pagesize [%d %d] def\n", (pagewidth
* 72 + 127) / 254,
522 (pageheight
* 72 + 127) / 254);
523 out("/linewidth %d.%02d def\n\n", linewidth
/ 100, linewidth
% 100);
525 out("%%%%EndProlog\n");
526 out("%%%%BeginSetup\n");
527 out("<< /PageSize pagesize /ImagingBBox null >> setpagedevice\n");
530 out("%%%%EndSetup\n");