7 static char *pdf_title
; /* document title */
8 static int pdf_width
; /* page width */
9 static int pdf_height
; /* page height */
10 static int pdf_pages
; /* pages object id */
11 static int pdf_root
; /* root object id */
12 static int pdf_pos
; /* current pdf file offset */
13 static int *obj_off
; /* object offsets */
14 static int obj_sz
, obj_n
; /* number of pdf objects */
15 static int *page_id
; /* page object ids */
16 static int page_sz
, page_n
; /* number of pages */
17 static char **font_ps
; /* document font names */
18 static int *font_id
; /* font object */
19 static int *font_ct
; /* font content stream object */
20 static int *font_ix
; /* font index */
21 static int font_sz
, font_n
; /* number of fonts */
23 static struct sbuf
*pg
; /* current page contents */
24 static int o_f
, o_s
, o_m
; /* font and size */
25 static int o_h
, o_v
; /* current user position */
26 static int p_h
, p_v
; /* current output position */
27 static int o_pf
, p_pf
; /* output and pdf fonts; indices into o_fs[] */
28 static int p_f
, p_s
, p_m
; /* output font */
29 static int o_queued
; /* queued character type */
30 static int *o_fs
; /* page fonts */
31 static int o_fsn
, o_fssz
; /* page fonts */
33 /* print pdf output */
34 static void pdfout(char *s
, ...)
38 pdf_pos
+= vprintf(s
, ap
);
42 /* allocate an object number */
43 static int obj_map(void)
45 if (obj_n
== obj_sz
) {
47 obj_off
= mextend(obj_off
, obj_n
, obj_sz
, sizeof(obj_off
[0]));
52 /* start the definition of an object */
53 static int obj_beg(int id
)
57 obj_off
[id
] = pdf_pos
;
58 pdfout("%d 0 obj\n", id
);
62 /* end an object definition */
63 static void obj_end(void)
68 /* embed font; return stream object identifier */
69 static int font_outdat(char *path
, char *name
, int ix
)
74 for (i
= 0; i
< font_n
; i
++)
75 if (!strcmp(name
, font_ps
[i
]) && font_ct
[i
] >= 0)
77 fp
= fopen(path
, "r");
82 for (i
= 0; c
!= EOF
; i
++) {
83 sbuf_printf(sb
, "%02x", c
);
85 if (i
% 40 == 39 && c
!= EOF
)
92 pdfout(" /Filter /ASCIIHexDecode\n");
93 pdfout(" /Length %d\n", sbuf_len(sb
));
94 pdfout(" /Length1 %d\n", i
);
97 pdfout("%s", sbuf_buf(sb
));
98 pdfout("endstream\n");
104 /* write the object corresponding to font font_id[f] */
105 static void font_out(struct font
*fn
, int f
)
108 int enc_obj
, des_obj
;
109 char *path
= font_path(fn
);
110 char *ext
= path
? strrchr(path
, '.') : NULL
;
111 /* the encoding object */
112 enc_obj
= obj_beg(0);
114 pdfout(" /Type /Encoding\n");
115 pdfout(" /Differences [ 0");
116 for (i
= 0; i
< 256; i
++) {
117 struct glyph
*g
= font_glget(fn
, font_ix
[f
] * 256 + i
);
118 pdfout(" /%s", g
? g
->id
: ".notdef");
123 /* embedding the font */
124 if (ext
&& !strcmp(".ttf", ext
))
125 font_ct
[f
] = font_outdat(path
, font_ps
[f
], font_ix
[f
]);
126 /* the font descriptor */
127 des_obj
= obj_beg(0);
129 pdfout(" /Type /FontDescriptor\n");
130 pdfout(" /FontName /%s\n", font_ps
[f
]);
131 pdfout(" /Flags 4\n");
132 pdfout(" /MissingWidth 255\n");
133 pdfout(" /StemV 100\n");
134 pdfout(" /StemH 100\n");
135 pdfout(" /CapHeight 100\n");
136 pdfout(" /Ascent 100\n");
137 pdfout(" /Descent 100\n");
139 pdfout(" /FontFile2 %d 0 R\n", font_ct
[f
]);
142 /* the font object */
145 pdfout(" /Type /Font\n");
146 pdfout(" /Subtype /%s\n",
147 ext
&& !strcmp(".ttf", ext
) ? "TrueType" : "Type1");
148 pdfout(" /BaseFont /%s\n", font_ps
[f
]);
149 pdfout(" /FirstChar 0\n");
150 pdfout(" /LastChar 255\n");
151 pdfout(" /Widths [");
152 for (i
= 0; i
< 256; i
++) {
153 struct glyph
*g
= font_glget(fn
, font_ix
[f
] * 256 + i
);
154 pdfout(" %d", (g
? g
->wid
: 0) * dev_res
/ 72);
157 pdfout(" /FontDescriptor %d 0 R\n", des_obj
);
158 pdfout(" /Encoding %d 0 R\n", enc_obj
);
163 static int font_put(struct font
*fn
, int ix
)
166 char *name
= font_name(fn
);
167 for (i
= 0; i
< font_n
; i
++)
168 if (!strcmp(font_ps
[i
], font_name(fn
)) && font_ix
[i
] == ix
)
170 if (font_n
== font_sz
) {
172 font_id
= mextend(font_id
, font_n
, font_sz
, sizeof(font_id
[0]));
173 font_ps
= mextend(font_ps
, font_n
, font_sz
, sizeof(font_ps
[0]));
174 font_ix
= mextend(font_ix
, font_n
, font_sz
, sizeof(font_ix
[0]));
175 font_ct
= mextend(font_ct
, font_n
, font_sz
, sizeof(font_ct
[0]));
177 font_id
[font_n
] = obj_map();
178 font_ix
[font_n
] = ix
;
179 font_ps
[font_n
] = malloc(strlen(name
) + 1);
180 font_ct
[font_n
] = -1;
181 strcpy(font_ps
[font_n
], name
);
183 font_out(fn
, font_n
- 1);
187 void out(char *s
, ...)
191 static void o_flush(void)
194 sbuf_printf(pg
, ") Tj\n");
198 static int o_loadfont(struct glyph
*g
)
200 struct font
*fn
= g
? g
->font
: dev_font(o_f
);
201 int ix
= font_glnum(fn
, g
) / 256;
202 char *name
= font_name(fn
);
205 for (i
= 0; i
< o_fsn
; i
++)
206 if (!strcmp(name
, font_ps
[o_fs
[i
]]) && font_ix
[o_fs
[i
]] == ix
)
208 id
= font_put(fn
, ix
);
209 if (o_fsn
== o_fssz
) {
211 o_fs
= mextend(o_fs
, o_fsn
, o_fssz
, sizeof(o_fs
[0]));
220 /* convert troff position to pdf position; returns a static buffer */
221 static char *pdfpos(int uh
, int uv
)
224 int h
= uh
* PREC
* 72 / dev_res
;
225 int v
= pdf_height
* PREC
- (uv
* PREC
* 72 / dev_res
);
226 sprintf(buf
, "%d.%0" PRECN
"d %d.%0" PRECN
"d",
227 h
/ PREC
, h
% PREC
, v
/ PREC
, v
% PREC
);
231 /* convert troff color to pdf color; returns a static buffer */
232 static char *pdfcolor(int m
)
235 int r
= CLR_R(m
) * 1000 / 255;
236 int g
= CLR_G(m
) * 1000 / 255;
237 int b
= CLR_B(m
) * 1000 / 255;
238 sbuf_printf(pg
, "%d.%03d %d.%03d %d.%03d",
239 r
/ 1000, r
% 1000, g
/ 1000, g
% 1000, b
/ 1000, b
% 1000);
243 static void o_queue(struct glyph
*g
)
246 if (o_h
!= p_h
|| o_v
!= p_v
) {
248 sbuf_printf(pg
, "1 0 0 1 %s Tm\n", pdfpos(o_h
, o_v
));
253 sbuf_printf(pg
, "(");
255 pos
= font_glnum(g
->font
, g
) % 256;
256 sbuf_printf(pg
, "\\%d%d%d", (pos
>> 6) & 7, (pos
>> 3) & 7, pos
& 7);
257 p_h
+= font_wid(g
->font
, o_s
, g
->wid
);
260 static void out_fontup(void)
264 sbuf_printf(pg
, "%s rg\n", pdfcolor(o_m
));
267 if (o_pf
!= p_pf
|| o_s
!= p_s
) {
270 sbuf_printf(pg
, "/%s.%d %d Tf\n", font_ps
[f
], font_ix
[f
], o_s
);
280 g
= dev_glyph(c
, o_f
);
281 fn
= g
? g
->font
: dev_font(o_f
);
283 outrel(*c
== ' ' && fn
? font_swid(fn
, o_s
) : 1, 0);
286 o_pf
= o_loadfont(g
);
301 void outrel(int h
, int v
)
324 void outrotate(int deg
)
328 void outeps(char *eps
)
332 void outlink(char *spec
)
357 static int draw_path
; /* number of path segments */
358 static int draw_point
; /* point was set for postscript newpath */
360 static void drawmv(void)
363 sbuf_printf(pg
, "%d %d m ", o_h
, o_v
);
373 sbuf_printf(pg
, "%s m\n", pdfpos(o_h
, o_v
));
376 void drawend(int close
, int fill
)
381 if (!fill
) /* stroking color */
382 sbuf_printf(pg
, "%s RG\n", pdfcolor(o_m
));
384 sbuf_printf(pg
, "f\n");
386 sbuf_printf(pg
, close
? "s\n" : "S\n");
389 void drawmbeg(char *s
)
393 void drawmend(char *s
)
397 void drawl(int h
, int v
)
401 sbuf_printf(pg
, "%s l\n", pdfpos(o_h
, o_v
));
409 void drawe(int h
, int v
)
414 void drawa(int h1
, int v1
, int h2
, int v2
)
416 outrel(h1
+ h2
, v1
+ v2
);
419 void draws(int h1
, int v1
, int h2
, int v2
)
424 void ps_header(char *title
, int pagewidth
, int pageheight
, int linewidth
)
428 pdf_root
= obj_map();
429 pdf_pages
= obj_map();
431 pdfout("%%PDF-1.6\n");
432 pdf_width
= (pagewidth
* 72 + 127) / 254;
433 pdf_height
= (pageheight
* 72 + 127) / 254;
436 void ps_trailer(int pages
)
441 /* pdf pages object */
444 pdfout(" /Type /Pages\n");
445 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width
, pdf_height
);
446 pdfout(" /Count %d\n", page_n
);
448 for (i
= 0; i
< page_n
; i
++)
449 pdfout(" %d 0 R", page_id
[i
]);
453 /* pdf root object */
456 pdfout(" /Type /Catalog\n");
457 pdfout(" /Pages %d 0 R\n", pdf_pages
);
461 info_id
= obj_beg(0);
464 pdfout(" /Title (%s)\n", pdf_title
);
465 pdfout(" /Creator (Neatroff)\n");
466 pdfout(" /Producer (Neatpost)\n");
472 pdfout("0 %d\n", obj_n
);
473 pdfout("0000000000 65535 f \n");
474 for (i
= 1; i
< obj_n
; i
++)
475 pdfout("%010d 00000 n \n", obj_off
[i
]);
479 pdfout(" /Size %d\n", obj_n
);
480 pdfout(" /Root %d 0 R\n", pdf_root
);
481 pdfout(" /Info %d 0 R\n", info_id
);
483 pdfout("startxref\n");
484 pdfout("%d\n", xref_off
);
488 for (i
= 0; i
< font_n
; i
++)
496 void ps_pagebeg(int n
)
499 sbuf_printf(pg
, "BT\n");
502 void ps_pageend(int n
)
507 sbuf_printf(pg
, "ET\n");
509 cont_id
= obj_beg(0);
511 pdfout(" /Length %d\n", sbuf_len(pg
));
514 pdfout("%s", sbuf_buf(pg
));
515 pdfout("endstream\n");
517 /* the page object */
518 if (page_n
== page_sz
) {
520 page_id
= mextend(page_id
, page_n
, page_sz
, sizeof(page_id
[0]));
522 page_id
[page_n
++] = obj_beg(0);
524 pdfout(" /Type /Page\n");
525 pdfout(" /Parent %d 0 R\n", pdf_pages
);
526 pdfout(" /Resources <<\n");
528 for (i
= 0; i
< o_fsn
; i
++)
529 pdfout(" /%s.%d %d 0 R",
530 font_ps
[o_fs
[i
]], font_ix
[o_fs
[i
]], font_id
[o_fs
[i
]]);
533 pdfout(" /Contents %d 0 R\n", cont_id
);