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(" /FontBBox [-1000 -1000 1000 1000]\n");
133 pdfout(" /MissingWidth 1000\n");
134 pdfout(" /StemV 100\n");
135 pdfout(" /ItalicAngle 0\n");
136 pdfout(" /CapHeight 100\n");
137 pdfout(" /Ascent 100\n");
138 pdfout(" /Descent 100\n");
140 pdfout(" /FontFile2 %d 0 R\n", font_ct
[f
]);
143 /* the font object */
146 pdfout(" /Type /Font\n");
147 pdfout(" /Subtype /%s\n",
148 ext
&& !strcmp(".ttf", ext
) ? "TrueType" : "Type1");
149 pdfout(" /BaseFont /%s\n", font_ps
[f
]);
150 pdfout(" /FirstChar 0\n");
151 pdfout(" /LastChar 255\n");
152 pdfout(" /Widths [");
153 for (i
= 0; i
< 256; i
++) {
154 struct glyph
*g
= font_glget(fn
, font_ix
[f
] * 256 + i
);
155 pdfout(" %d", (g
? g
->wid
: 0) * dev_res
/ 72);
158 pdfout(" /FontDescriptor %d 0 R\n", des_obj
);
159 pdfout(" /Encoding %d 0 R\n", enc_obj
);
164 static int font_put(struct font
*fn
, int ix
)
167 char *name
= font_name(fn
);
168 for (i
= 0; i
< font_n
; i
++)
169 if (!strcmp(font_ps
[i
], font_name(fn
)) && font_ix
[i
] == ix
)
171 if (font_n
== font_sz
) {
173 font_id
= mextend(font_id
, font_n
, font_sz
, sizeof(font_id
[0]));
174 font_ps
= mextend(font_ps
, font_n
, font_sz
, sizeof(font_ps
[0]));
175 font_ix
= mextend(font_ix
, font_n
, font_sz
, sizeof(font_ix
[0]));
176 font_ct
= mextend(font_ct
, font_n
, font_sz
, sizeof(font_ct
[0]));
178 font_id
[font_n
] = obj_map();
179 font_ix
[font_n
] = ix
;
180 font_ps
[font_n
] = malloc(strlen(name
) + 1);
181 font_ct
[font_n
] = -1;
182 strcpy(font_ps
[font_n
], name
);
184 font_out(fn
, font_n
- 1);
188 void out(char *s
, ...)
192 static void o_flush(void)
195 sbuf_printf(pg
, ") Tj\n");
199 static int o_loadfont(struct glyph
*g
)
201 struct font
*fn
= g
? g
->font
: dev_font(o_f
);
202 int ix
= font_glnum(fn
, g
) / 256;
203 char *name
= font_name(fn
);
206 for (i
= 0; i
< o_fsn
; i
++)
207 if (!strcmp(name
, font_ps
[o_fs
[i
]]) && font_ix
[o_fs
[i
]] == ix
)
209 id
= font_put(fn
, ix
);
210 if (o_fsn
== o_fssz
) {
212 o_fs
= mextend(o_fs
, o_fsn
, o_fssz
, sizeof(o_fs
[0]));
221 /* convert troff position to pdf position; returns a static buffer */
222 static char *pdfpos(int uh
, int uv
)
225 int h
= uh
* PREC
* 72 / dev_res
;
226 int v
= pdf_height
* PREC
- (uv
* PREC
* 72 / dev_res
);
227 sprintf(buf
, "%d.%0" PRECN
"d %d.%0" PRECN
"d",
228 h
/ PREC
, h
% PREC
, v
/ PREC
, v
% PREC
);
232 /* convert troff color to pdf color; returns a static buffer */
233 static char *pdfcolor(int m
)
236 int r
= CLR_R(m
) * 1000 / 255;
237 int g
= CLR_G(m
) * 1000 / 255;
238 int b
= CLR_B(m
) * 1000 / 255;
239 sbuf_printf(pg
, "%d.%03d %d.%03d %d.%03d",
240 r
/ 1000, r
% 1000, g
/ 1000, g
% 1000, b
/ 1000, b
% 1000);
244 static void o_queue(struct glyph
*g
)
247 if (o_h
!= p_h
|| o_v
!= p_v
) {
249 sbuf_printf(pg
, "1 0 0 1 %s Tm\n", pdfpos(o_h
, o_v
));
254 sbuf_printf(pg
, "(");
256 pos
= font_glnum(g
->font
, g
) % 256;
257 sbuf_printf(pg
, "\\%d%d%d", (pos
>> 6) & 7, (pos
>> 3) & 7, pos
& 7);
258 p_h
+= font_wid(g
->font
, o_s
, g
->wid
);
261 static void out_fontup(void)
265 sbuf_printf(pg
, "%s rg\n", pdfcolor(o_m
));
268 if (o_pf
!= p_pf
|| o_s
!= p_s
) {
271 sbuf_printf(pg
, "/%s.%d %d Tf\n", font_ps
[f
], font_ix
[f
], o_s
);
281 g
= dev_glyph(c
, o_f
);
282 fn
= g
? g
->font
: dev_font(o_f
);
284 outrel(*c
== ' ' && fn
? font_swid(fn
, o_s
) : 1, 0);
287 o_pf
= o_loadfont(g
);
302 void outrel(int h
, int v
)
325 void outrotate(int deg
)
329 void outeps(char *eps
)
333 void outlink(char *spec
)
358 static int draw_path
; /* number of path segments */
359 static int draw_point
; /* point was set for postscript newpath */
361 static void drawmv(void)
364 sbuf_printf(pg
, "%d %d m ", o_h
, o_v
);
374 sbuf_printf(pg
, "%s m\n", pdfpos(o_h
, o_v
));
377 void drawend(int close
, int fill
)
382 if (!fill
) /* stroking color */
383 sbuf_printf(pg
, "%s RG\n", pdfcolor(o_m
));
385 sbuf_printf(pg
, "f\n");
387 sbuf_printf(pg
, close
? "s\n" : "S\n");
390 void drawmbeg(char *s
)
394 void drawmend(char *s
)
398 void drawl(int h
, int v
)
402 sbuf_printf(pg
, "%s l\n", pdfpos(o_h
, o_v
));
410 void drawe(int h
, int v
)
415 void drawa(int h1
, int v1
, int h2
, int v2
)
417 outrel(h1
+ h2
, v1
+ v2
);
420 void draws(int h1
, int v1
, int h2
, int v2
)
425 void ps_header(char *title
, int pagewidth
, int pageheight
, int linewidth
)
429 pdf_root
= obj_map();
430 pdf_pages
= obj_map();
432 pdfout("%%PDF-1.6\n");
433 pdf_width
= (pagewidth
* 72 + 127) / 254;
434 pdf_height
= (pageheight
* 72 + 127) / 254;
437 void ps_trailer(int pages
)
442 /* pdf pages object */
445 pdfout(" /Type /Pages\n");
446 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width
, pdf_height
);
447 pdfout(" /Count %d\n", page_n
);
449 for (i
= 0; i
< page_n
; i
++)
450 pdfout(" %d 0 R", page_id
[i
]);
454 /* pdf root object */
457 pdfout(" /Type /Catalog\n");
458 pdfout(" /Pages %d 0 R\n", pdf_pages
);
462 info_id
= obj_beg(0);
465 pdfout(" /Title (%s)\n", pdf_title
);
466 pdfout(" /Creator (Neatroff)\n");
467 pdfout(" /Producer (Neatpost)\n");
473 pdfout("0 %d\n", obj_n
);
474 pdfout("0000000000 65535 f \n");
475 for (i
= 1; i
< obj_n
; i
++)
476 pdfout("%010d 00000 n \n", obj_off
[i
]);
480 pdfout(" /Size %d\n", obj_n
);
481 pdfout(" /Root %d 0 R\n", pdf_root
);
482 pdfout(" /Info %d 0 R\n", info_id
);
484 pdfout("startxref\n");
485 pdfout("%d\n", xref_off
);
489 for (i
= 0; i
< font_n
; i
++)
497 void ps_pagebeg(int n
)
500 sbuf_printf(pg
, "BT\n");
503 void ps_pageend(int n
)
508 sbuf_printf(pg
, "ET\n");
510 cont_id
= obj_beg(0);
512 pdfout(" /Length %d\n", sbuf_len(pg
));
515 pdfout("%s", sbuf_buf(pg
));
516 pdfout("endstream\n");
518 /* the page object */
519 if (page_n
== page_sz
) {
521 page_id
= mextend(page_id
, page_n
, page_sz
, sizeof(page_id
[0]));
523 page_id
[page_n
++] = obj_beg(0);
525 pdfout(" /Type /Page\n");
526 pdfout(" /Parent %d 0 R\n", pdf_pages
);
527 pdfout(" /Resources <<\n");
529 for (i
= 0; i
< o_fsn
; i
++)
530 pdfout(" /%s.%d %d 0 R",
531 font_ps
[o_fs
[i
]], font_ix
[o_fs
[i
]], font_id
[o_fs
[i
]]);
534 pdfout(" /Contents %d 0 R\n", cont_id
);