8 static int o_f
, o_s
, o_m
; /* font and size */
9 static int o_h
, o_v
; /* current user position */
10 static int p_f
, p_s
, p_m
; /* output postscript font */
11 static int o_qtype
; /* queued character type */
12 static int o_qv
, o_qh
, o_qend
; /* queued character position */
13 static int o_rh
, o_rv
, o_rdeg
; /* previous rotation position and degree */
14 static int o_gname
; /* use glyphshow for all glyphs */
16 static char o_fonts
[FNLEN
* NFONTS
] = " ";
18 static void outvf(char *s
, va_list ap
)
20 vfprintf(stdout
, s
, ap
);
23 static void outf(char *s
, ...)
31 static void o_flush(void)
34 outf(") %d %d w\n", o_qh
, o_qv
);
36 outf("] %d %d g\n", o_qh
, o_qv
);
56 static void o_queue(struct glyph
*g
)
58 int type
= 1 + (g
->pos
<= 0 || o_gname
);
59 if (o_qtype
!= type
|| o_qend
!= o_h
|| o_qv
!= o_v
) {
64 outf(type
== 1 ? "(" : "[");
67 if (g
->pos
>= ' ' && g
->pos
<= '~')
68 outf("%s%c", strchr("()\\", g
->pos
) ? "\\" : "", g
->pos
);
70 outf("\\%d%d%d", (g
->pos
>> 6) & 7,
71 (g
->pos
>> 3) & 7, g
->pos
& 7);
75 o_qend
= o_h
+ font_wid(g
->font
, o_s
, g
->wid
);
78 /* calls o_flush() if necessary */
79 void out(char *s
, ...)
88 static void out_fontup(int fid
)
93 out("%d %d %d rgb\n", CLR_R(o_m
), CLR_G(o_m
), CLR_B(o_m
));
96 if (fid
!= p_f
|| o_s
!= p_s
) {
98 out("%d /%s f\n", o_s
, font_name(fn
));
101 sprintf(fnname
, " %s ", font_name(fn
));
102 if (!strstr(o_fonts
, fnname
))
103 sprintf(strchr(o_fonts
, '\0'), "%s ", font_name(fn
));
111 g
= dev_glyph(c
, o_f
);
112 fn
= g
? g
->font
: dev_font(o_f
);
114 outrel(*c
== ' ' && fn
? font_swid(fn
, o_s
) : 1, 0);
117 out_fontup(dev_fontid(fn
));
131 void outrel(int h
, int v
)
143 /* a font was mounted at pos f */
161 void outrotate(int deg
)
166 outf("%d %d %d rot\n", -o_rdeg
, o_rh
, o_rv
);
170 outf("%d %d %d rot\n", deg
, o_h
, o_v
);
173 static int draw_path
; /* number of path segments */
174 static int draw_point
; /* point was set for postscript newpath */
176 static void drawmv(void)
179 outf("%d %d m ", o_h
, o_v
);
183 /* start a multi-segment path */
184 void drawmbeg(char *s
)
189 outf("gsave newpath %s\n", s
);
192 /* end a multi-segment path */
193 void drawmend(char *s
)
197 outf("%s grestore\n", s
);
209 void drawend(int close
, int fill
)
222 void drawl(int h
, int v
)
226 outf("%d %d drawl ", o_h
, o_v
);
233 outf("%d %d drawe ", c
, c
);
236 void drawe(int h
, int v
)
240 outf("%d %d drawe ", h
, v
);
243 void drawa(int h1
, int v1
, int h2
, int v2
)
246 outf("%d %d %d %d drawa ", h1
, v1
, h2
, v2
);
247 outrel(h1
+ h2
, v1
+ v2
);
250 void draws(int h1
, int v1
, int h2
, int v2
)
253 outf("%d %d %d %d %d %d draws ", o_h
, o_v
, o_h
+ h1
, o_v
+ v1
,
254 o_h
+ h1
+ h2
, o_v
+ v1
+ v2
);
258 static char *strcut(char *dst
, char *src
)
260 while (*src
== ' ' || *src
== '\n')
264 while (*src
&& (src
[0] != '"' || src
[1] == '"')) {
272 while (*src
&& *src
!= ' ' && *src
!= '\n')
279 void outeps(char *spec
)
283 int llx
, lly
, urx
, ury
;
287 spec
= strcut(eps
, spec
);
290 nspec
= sscanf(spec
, "%d %d", &hwid
, &vwid
);
295 if (!(filp
= fopen(eps
, "r")))
297 if (!fgets(buf
, sizeof(buf
), filp
) ||
298 (strcmp(buf
, "%!PS-Adobe-2.0 EPSF-1.2\n") &&
299 strcmp(buf
, "%!PS-Adobe-2.0 EPSF-2.0\n") &&
300 strcmp(buf
, "%!PS-Adobe-3.0 EPSF-3.0\n"))) {
305 while (fgets(buf
, sizeof(buf
), filp
))
306 if (!strncmp(buf
, "%%BoundingBox: ", 15))
307 if ((nbb
= sscanf(buf
+ 15, "%d %d %d %d",
308 &llx
, &lly
, &urx
, &ury
)) == 4)
311 if (nbb
< 4) /* no BoundingBox comment */
313 if (hwid
<= 0 && vwid
<= 0)
314 hwid
= (urx
- llx
) * dev_res
/ 72;
316 vwid
= (ury
- lly
) * hwid
/ (urx
- llx
);
318 hwid
= (urx
- llx
) * vwid
/ (ury
- lly
);
319 /* output the EPS file */
322 outf("%d %d %d %d %d %d %d %d EPSFBEG\n",
323 llx
, lly
, hwid
, urx
- llx
, vwid
, ury
- lly
, o_h
, o_v
);
324 outf("%%%%BeginDocument: %s\n", eps
);
325 filp
= fopen(eps
, "r");
326 while (fgets(buf
, sizeof(buf
), filp
))
329 outf("%%%%EndDocument\n");
333 void outlink(char *spec
)
338 spec
= strcut(lnk
, spec
);
339 if (!lnk
[0] || (nspec
= sscanf(spec
, "%d %d", &hwid
, &vwid
)) != 2)
342 if (lnk
[0] == '#' || isdigit((unsigned char) lnk
[0])) {
343 outf("[ /Rect [ %d %d t %d %d t ] %s%s "
344 "/Subtype /Link /LNK pdfmark\n",
345 o_h
, o_v
, o_h
+ hwid
, o_v
+ vwid
,
346 lnk
[0] == '#' ? "/Dest /" : "/Page ",
347 lnk
[0] == '#' ? lnk
+ 1 : lnk
);
349 outf("[ /Rect [ %d %d t %d %d t ] "
350 "/Action << /Subtype /URI /URI (%s) >> /Open true "
351 "/Subtype /Link /LNK pdfmark\n",
352 o_h
, o_v
, o_h
+ hwid
, o_v
+ vwid
, lnk
);
356 void ps_pagebeg(int n
)
358 out("%%%%Page: %d %d\n", n
, n
);
359 out("/saveobj save def\n");
361 out("%d pagesetup\n", n
);
364 void ps_pageend(int n
)
366 out("cleartomark\n");
368 out("saveobj restore\n");
371 void ps_trailer(int pages
)
373 out("%%%%Trailer\n");
375 out("%%%%DocumentFonts: %s\n", o_fonts
);
376 out("%%%%Pages: %d\n", pages
);
380 static char *prolog
=
382 " counttomark 2 idiv {def} repeat pop\n"
383 " /scaling 72 resolution div def\n"
384 " linewidth setlinewidth\n"
386 " 0 pagesize 1 get translate\n"
387 " scaling scaling scale\n"
393 " currentdict /pagedict known currentdict page known and {\n"
394 " page load pagedict exch get cvx exec\n"
399 " { pop globaldict /?pdfmark /exec load put }\n"
400 " { globaldict begin\n"
401 " /?pdfmark /pop load def\n"
402 " /pdfmark /cleartomark load def\n"
406 "/t {neg} bind def\n"
407 "/w {neg moveto show} bind def\n"
408 "/m {neg moveto} bind def\n"
409 "/g {neg moveto {glyphshow} forall} bind def\n"
410 "/rgb {255 div 3 1 roll 255 div 3 1 roll 255 div 3 1 roll setrgbcolor} bind def\n"
411 "/rot {/y exch def /x exch def x y neg translate rotate x neg y translate} bind def\n"
412 "/done {/lastpage where {pop lastpage} if} def\n"
414 "% caching fonts, as selectfont is supposed to be doing\n"
415 "/fncache 16 dict def\n"
416 "/selectfont_append { fncache exch dup findfont put } bind def\n"
417 "/selectfont_cached {\n"
418 " exch dup fncache exch known not { dup selectfont_append } if\n"
419 " fncache exch get exch scalefont setfont\n"
422 " exch dup 3 1 roll scaling div selectfont_cached\n"
423 " linewidth mul scaling 10 mul div setlinewidth\n"
426 "/savedmatrix matrix def\n"
431 " savedmatrix currentmatrix pop scale\n"
432 " .5 0 rmoveto currentpoint .5 0 rmoveto .5 0 360 arc\n"
433 " savedmatrix setmatrix\n"
440 " currentpoint dy1 neg add exch dx1 add exch\n"
441 " dx1 dx1 mul dy1 dy1 mul add sqrt\n"
442 " dy1 dx1 neg atan\n"
443 " dy2 neg dx2 atan\n"
453 " x0 5 x1 mul add 6 div\n"
454 " y0 5 y1 mul add -6 div\n"
455 " x2 5 x1 mul add 6 div\n"
456 " y2 5 y1 mul add -6 div\n"
458 " y1 y2 add -2 div\n"
461 "% including EPS files\n"
463 " /epsf_state save def\n"
465 " div 3 1 roll div exch scale\n"
466 " neg exch neg exch translate\n"
467 " /dict_count countdictstack def\n"
468 " /op_count count 1 sub def\n"
470 " /showpage { } def\n"
471 " 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin\n"
472 " 10 setmiterlimit [ ] 0 setdash newpath\n"
475 " count op_count sub {pop} repeat\n"
476 " countdictstack dict_count sub {end} repeat\n"
477 " epsf_state restore\n"
480 /* pagewidth and pageheight are in tenths of a millimetre */
481 void ps_header(char *title
, int pagewidth
, int pageheight
, int linewidth
)
483 out("%%!PS-Adobe-2.0\n");
484 out("%%%%Version: 1.0\n");
486 out("%%%%Title: %s\n", title
);
487 out("%%%%Creator: Neatroff\n");
488 out("%%%%DocumentFonts: (atend)\n");
489 out("%%%%Pages: (atend)\n");
490 out("%%%%EndComments\n");
492 out("%%%%BeginProlog\n");
493 out("/resolution %d def\n", dev_res
);
494 out("/pagesize [%d %d] def\n", (pagewidth
* 72 + 127) / 254,
495 (pageheight
* 72 + 127) / 254);
496 out("/linewidth %d.%02d def\n\n", linewidth
/ 100, linewidth
% 100);
498 out("%%%%EndProlog\n");
499 out("%%%%BeginSetup\n");
500 out("<< /PageSize pagesize /ImagingBBox null >> setpagedevice\n");
503 out("%%%%EndSetup\n");