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 0\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 static void o_queue(struct glyph
*g
)
223 if (o_h
!= p_h
|| o_v
!= p_v
) {
224 long h
= o_h
* PREC
* 72 / dev_res
;
225 long v
= pdf_height
* PREC
- (o_v
* PREC
* 72 / dev_res
);
227 sbuf_printf(pg
, "1 0 0 1 %d.%0" PRECN
"d %d.%0" PRECN
"d Tm\n",
228 h
/ PREC
, h
% PREC
, v
/ PREC
, v
% PREC
);
233 sbuf_printf(pg
, "(");
235 pos
= font_glnum(g
->font
, g
) % 256;
236 sbuf_printf(pg
, "\\%d%d%d", (pos
>> 6) & 7, (pos
>> 3) & 7, pos
& 7);
237 p_h
+= font_wid(g
->font
, o_s
, g
->wid
);
240 static void out_fontup(void)
246 if (o_pf
!= p_pf
|| o_s
!= p_s
) {
249 sbuf_printf(pg
, "/%s.%d %d Tf\n", font_ps
[f
], font_ix
[f
], o_s
);
259 g
= dev_glyph(c
, o_f
);
260 fn
= g
? g
->font
: dev_font(o_f
);
262 outrel(*c
== ' ' && fn
? font_swid(fn
, o_s
) : 1, 0);
265 o_pf
= o_loadfont(g
);
280 void outrel(int h
, int v
)
303 void outrotate(int deg
)
307 void outeps(char *eps
)
311 void outlink(char *spec
)
340 void drawend(int close
, int fill
)
344 void drawmbeg(char *s
)
348 void drawmend(char *s
)
352 void drawl(int h
, int v
)
360 void drawe(int h
, int v
)
364 void drawa(int h1
, int v1
, int h2
, int v2
)
368 void draws(int h1
, int v1
, int h2
, int v2
)
372 void ps_header(char *title
, int pagewidth
, int pageheight
, int linewidth
)
376 pdf_root
= obj_map();
377 pdf_pages
= obj_map();
379 pdfout("%%PDF-1.6\n");
380 pdf_width
= (pagewidth
* 72 + 127) / 254;
381 pdf_height
= (pageheight
* 72 + 127) / 254;
384 void ps_trailer(int pages
)
389 /* pdf pages object */
392 pdfout(" /Type /Pages\n");
393 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width
, pdf_height
);
394 pdfout(" /Count %d\n", page_n
);
396 for (i
= 0; i
< page_n
; i
++)
397 pdfout(" %d 0 R", page_id
[i
]);
401 /* pdf root object */
404 pdfout(" /Type /Catalog\n");
405 pdfout(" /Pages %d 0 R\n", pdf_pages
);
409 info_id
= obj_beg(0);
412 pdfout(" /Title (%s)\n", pdf_title
);
413 pdfout(" /Creator (Neatroff)\n");
414 pdfout(" /Producer (Neatpost)\n");
420 pdfout("0 %d\n", obj_n
);
421 pdfout("0000000000 65535 f \n");
422 for (i
= 1; i
< obj_n
; i
++)
423 pdfout("%010d 00000 n \n", obj_off
[i
]);
427 pdfout(" /Size %d\n", obj_n
);
428 pdfout(" /Root %d 0 R\n", pdf_root
);
429 pdfout(" /Info %d 0 R\n", info_id
);
431 pdfout("startxref\n");
432 pdfout("%d\n", xref_off
);
436 for (i
= 0; i
< font_n
; i
++)
444 void ps_pagebeg(int n
)
447 sbuf_printf(pg
, "BT\n");
450 void ps_pageend(int n
)
455 sbuf_printf(pg
, "ET\n");
457 cont_id
= obj_beg(0);
459 pdfout(" /Length %d\n", sbuf_len(pg
));
462 pdfout("%s", sbuf_buf(pg
));
463 pdfout("endstream\n");
465 /* the page object */
466 if (page_n
== page_sz
) {
468 page_id
= mextend(page_id
, page_n
, page_sz
, sizeof(page_id
[0]));
470 page_id
[page_n
++] = obj_beg(0);
472 pdfout(" /Type /Page\n");
473 pdfout(" /Parent %d 0 R\n", pdf_pages
);
474 pdfout(" /Resources <<\n");
476 for (i
= 0; i
< o_fsn
; i
++)
477 pdfout(" /%s.%d %d 0 R",
478 font_ps
[o_fs
[i
]], font_ix
[o_fs
[i
]], font_id
[o_fs
[i
]]);
481 pdfout(" /Contents %d 0 R\n", cont_id
);