pdf: include other required fields of font descriptors
[neatpost.git] / pdf.c
blobc2b50b9b7e591312625dcb5b7a7e015a2337f108
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "post.h"
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, ...)
36 va_list ap;
37 va_start(ap, s);
38 pdf_pos += vprintf(s, ap);
39 va_end(ap);
42 /* allocate an object number */
43 static int obj_map(void)
45 if (obj_n == obj_sz) {
46 obj_sz += 1024;
47 obj_off = mextend(obj_off, obj_n, obj_sz, sizeof(obj_off[0]));
49 return obj_n++;
52 /* start the definition of an object */
53 static int obj_beg(int id)
55 if (id <= 0)
56 id = obj_map();
57 obj_off[id] = pdf_pos;
58 pdfout("%d 0 obj\n", id);
59 return id;
62 /* end an object definition */
63 static void obj_end(void)
65 pdfout("endobj\n\n");
68 /* embed font; return stream object identifier */
69 static int font_outdat(char *path, char *name, int ix)
71 struct sbuf *sb;
72 FILE *fp;
73 int c, i, id;
74 for (i = 0; i < font_n; i++)
75 if (!strcmp(name, font_ps[i]) && font_ct[i] >= 0)
76 return font_ct[i];
77 fp = fopen(path, "r");
78 if (!fp)
79 return -1;
80 sb = sbuf_make();
81 c = fgetc(fp);
82 for (i = 0; c != EOF; i++) {
83 sbuf_printf(sb, "%02x", c);
84 c = fgetc(fp);
85 if (i % 40 == 39 && c != EOF)
86 sbuf_chr(sb, '\n');
88 sbuf_str(sb, ">\n");
89 fclose(fp);
90 id = obj_beg(0);
91 pdfout("<<\n");
92 pdfout(" /Filter /ASCIIHexDecode\n");
93 pdfout(" /Length %d\n", sbuf_len(sb));
94 pdfout(" /Length1 %d\n", i);
95 pdfout(">>\n");
96 pdfout("stream\n");
97 pdfout("%s", sbuf_buf(sb));
98 pdfout("endstream\n");
99 obj_end();
100 sbuf_free(sb);
101 return id;
104 /* write the object corresponding to font font_id[f] */
105 static void font_out(struct font *fn, int f)
107 int i;
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);
113 pdfout("<<\n");
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");
120 pdfout(" ]\n");
121 pdfout(">>\n");
122 obj_end();
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);
128 pdfout("<<\n");
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");
139 if (font_ct[f] >= 0)
140 pdfout(" /FontFile2 %d 0 R\n", font_ct[f]);
141 pdfout(">>\n");
142 obj_end();
143 /* the font object */
144 obj_beg(font_id[f]);
145 pdfout("<<\n");
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);
157 pdfout(" ]\n");
158 pdfout(" /FontDescriptor %d 0 R\n", des_obj);
159 pdfout(" /Encoding %d 0 R\n", enc_obj);
160 pdfout(">>\n");
161 obj_end();
164 static int font_put(struct font *fn, int ix)
166 int i;
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)
170 return i;
171 if (font_n == font_sz) {
172 font_sz += 128;
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);
183 font_n++;
184 font_out(fn, font_n - 1);
185 return font_n - 1;
188 void out(char *s, ...)
192 static void o_flush(void)
194 if (o_queued == 1)
195 sbuf_printf(pg, ") Tj\n");
196 o_queued = 0;
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);
204 int i;
205 int id;
206 for (i = 0; i < o_fsn; i++)
207 if (!strcmp(name, font_ps[o_fs[i]]) && font_ix[o_fs[i]] == ix)
208 return i;
209 id = font_put(fn, ix);
210 if (o_fsn == o_fssz) {
211 o_fssz += 128;
212 o_fs = mextend(o_fs, o_fsn, o_fssz, sizeof(o_fs[0]));
214 o_fs[o_fsn++] = id;
215 return o_fsn - 1;
218 #define PREC 1000
219 #define PRECN "3"
221 /* convert troff position to pdf position; returns a static buffer */
222 static char *pdfpos(int uh, int uv)
224 static char buf[64];
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);
229 return buf;
232 /* convert troff color to pdf color; returns a static buffer */
233 static char *pdfcolor(int m)
235 static char buf[64];
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);
241 return buf;
244 static void o_queue(struct glyph *g)
246 int pos;
247 if (o_h != p_h || o_v != p_v) {
248 o_flush();
249 sbuf_printf(pg, "1 0 0 1 %s Tm\n", pdfpos(o_h, o_v));
250 p_h = o_h;
251 p_v = o_v;
253 if (!o_queued)
254 sbuf_printf(pg, "(");
255 o_queued = 1;
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)
263 if (o_m != p_m) {
264 o_flush();
265 sbuf_printf(pg, "%s rg\n", pdfcolor(o_m));
266 p_m = o_m;
268 if (o_pf != p_pf || o_s != p_s) {
269 int f = o_fs[o_pf];
270 o_flush();
271 sbuf_printf(pg, "/%s.%d %d Tf\n", font_ps[f], font_ix[f], o_s);
272 p_pf = o_pf;
273 p_s = o_s;
277 void outc(char *c)
279 struct glyph *g;
280 struct font *fn;
281 g = dev_glyph(c, o_f);
282 fn = g ? g->font : dev_font(o_f);
283 if (!g) {
284 outrel(*c == ' ' && fn ? font_swid(fn, o_s) : 1, 0);
285 return;
287 o_pf = o_loadfont(g);
288 out_fontup();
289 o_queue(g);
292 void outh(int h)
294 o_h = h;
297 void outv(int v)
299 o_v = v;
302 void outrel(int h, int v)
304 o_h += h;
305 o_v += v;
308 void outfont(int f)
310 if (dev_font(f))
311 o_f = f;
314 void outsize(int s)
316 if (s > 0)
317 o_s = s;
320 void outcolor(int c)
322 o_m = c;
325 void outrotate(int deg)
329 void outeps(char *eps)
333 void outlink(char *spec)
337 void outpage(void)
339 o_v = 0;
340 o_h = 0;
341 p_v = 0;
342 p_h = 0;
343 p_s = 0;
344 p_f = 0;
345 p_m = 0;
348 void outmnt(int f)
350 if (p_f == f)
351 p_f = -1;
354 void outgname(int g)
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)
363 if (!draw_point)
364 sbuf_printf(pg, "%d %d m ", o_h, o_v);
365 draw_point = 1;
368 void drawbeg(void)
370 o_flush();
371 out_fontup();
372 if (draw_path)
373 return;
374 sbuf_printf(pg, "%s m\n", pdfpos(o_h, o_v));
377 void drawend(int close, int fill)
379 if (draw_path)
380 return;
381 draw_point = 0;
382 if (!fill) /* stroking color */
383 sbuf_printf(pg, "%s RG\n", pdfcolor(o_m));
384 if (fill)
385 sbuf_printf(pg, "f\n");
386 else
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)
400 o_flush();
401 outrel(h, v);
402 sbuf_printf(pg, "%s l\n", pdfpos(o_h, o_v));
405 void drawc(int c)
407 outrel(c, 0);
410 void drawe(int h, int v)
412 outrel(h, 0);
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)
422 outrel(h1, v1);
425 void ps_header(char *title, int pagewidth, int pageheight, int linewidth)
427 pdf_title = title;
428 obj_map();
429 pdf_root = obj_map();
430 pdf_pages = obj_map();
431 pdf_title = title;
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)
439 int i;
440 int xref_off;
441 int info_id;
442 /* pdf pages object */
443 obj_beg(pdf_pages);
444 pdfout("<<\n");
445 pdfout(" /Type /Pages\n");
446 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width, pdf_height);
447 pdfout(" /Count %d\n", page_n);
448 pdfout(" /Kids [");
449 for (i = 0; i < page_n; i++)
450 pdfout(" %d 0 R", page_id[i]);
451 pdfout(" ]\n");
452 pdfout(">>\n");
453 obj_end();
454 /* pdf root object */
455 obj_beg(pdf_root);
456 pdfout("<<\n");
457 pdfout(" /Type /Catalog\n");
458 pdfout(" /Pages %d 0 R\n", pdf_pages);
459 pdfout(">>\n");
460 obj_end();
461 /* info object */
462 info_id = obj_beg(0);
463 pdfout("<<\n");
464 if (pdf_title)
465 pdfout(" /Title (%s)\n", pdf_title);
466 pdfout(" /Creator (Neatroff)\n");
467 pdfout(" /Producer (Neatpost)\n");
468 pdfout(">>\n");
469 obj_end();
470 /* the xref */
471 xref_off = pdf_pos;
472 pdfout("xref\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]);
477 /* the trailer */
478 pdfout("trailer\n");
479 pdfout("<<\n");
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);
483 pdfout(">>\n");
484 pdfout("startxref\n");
485 pdfout("%d\n", xref_off);
486 pdfout("%%%%EOF\n");
487 free(page_id);
488 free(obj_off);
489 for (i = 0; i < font_n; i++)
490 free(font_ps[i]);
491 free(font_ps);
492 free(font_ct);
493 free(font_id);
494 free(font_ix);
497 void ps_pagebeg(int n)
499 pg = sbuf_make();
500 sbuf_printf(pg, "BT\n");
503 void ps_pageend(int n)
505 int cont_id;
506 int i;
507 o_flush();
508 sbuf_printf(pg, "ET\n");
509 /* page contents */
510 cont_id = obj_beg(0);
511 pdfout("<<\n");
512 pdfout(" /Length %d\n", sbuf_len(pg));
513 pdfout(">>\n");
514 pdfout("stream\n");
515 pdfout("%s", sbuf_buf(pg));
516 pdfout("endstream\n");
517 obj_end();
518 /* the page object */
519 if (page_n == page_sz) {
520 page_sz += 1024;
521 page_id = mextend(page_id, page_n, page_sz, sizeof(page_id[0]));
523 page_id[page_n++] = obj_beg(0);
524 pdfout("<<\n");
525 pdfout(" /Type /Page\n");
526 pdfout(" /Parent %d 0 R\n", pdf_pages);
527 pdfout(" /Resources <<\n");
528 pdfout(" /Font <<");
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]]);
532 pdfout(" >>\n");
533 pdfout(" >>\n");
534 pdfout(" /Contents %d 0 R\n", cont_id);
535 pdfout(">>\n");
536 obj_end();
537 sbuf_free(pg);
538 free(o_fs);
539 o_fs = NULL;
540 o_fsn = 0;
541 o_fssz = 0;