pdf: embedding Type 1 fonts
[neatpost.git] / pdf.c
blobb72838f1473d56c2a7d8457294d3c3ea5d2c06af
1 #include <fcntl.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include "post.h"
9 static char *pdf_title; /* document title */
10 static int pdf_width; /* page width */
11 static int pdf_height; /* page height */
12 static int pdf_pages; /* pages object id */
13 static int pdf_root; /* root object id */
14 static int pdf_pos; /* current pdf file offset */
15 static int *obj_off; /* object offsets */
16 static int obj_sz, obj_n; /* number of pdf objects */
17 static int *page_id; /* page object ids */
18 static int page_sz, page_n; /* number of pages */
20 static struct sbuf *pg; /* current page contents */
21 static int o_f, o_s, o_m; /* font and size */
22 static int o_h, o_v; /* current user position */
23 static int p_h, p_v; /* current output position */
24 static int o_pf, p_pf; /* output and pdf fonts; indices into o_fs[] */
25 static int p_f, p_s, p_m; /* output font */
26 static int o_queued; /* queued character type */
27 static int *o_fs; /* page fonts */
28 static int o_fsn, o_fssz; /* page fonts */
30 #define PSFN_MK(fn, ix) (((fn) << 16) | (ix))
31 #define PSFN_FN(fi) ((fi) >> 16)
32 #define PSFN_IX(fi) ((fi) & 0xffff)
34 struct psfont {
35 char name[128]; /* font PostScript name */
36 char path[1024]; /* font path */
37 char desc[1024]; /* font descriptor path */
38 int *gmap; /* the sub-font assigned to each glyph */
39 int *gpos; /* the location of the glyph in its sub-font */
40 int gcnt; /* glyph count */
41 int lastfn; /* the last sub-font */
42 int lastgl; /* the number of glyphs in the last subfont */
43 int obj[64]; /* sub-font object ids */
44 int objdes; /* font descriptor object id */
47 static struct psfont *psfonts;
48 static int psfonts_n, psfonts_sz;
50 /* print pdf output */
51 static void pdfout(char *s, ...)
53 va_list ap;
54 va_start(ap, s);
55 pdf_pos += vprintf(s, ap);
56 va_end(ap);
59 /* allocate an object number */
60 static int obj_map(void)
62 if (obj_n == obj_sz) {
63 obj_sz += 1024;
64 obj_off = mextend(obj_off, obj_n, obj_sz, sizeof(obj_off[0]));
66 return obj_n++;
69 /* start the definition of an object */
70 static int obj_beg(int id)
72 if (id <= 0)
73 id = obj_map();
74 obj_off[id] = pdf_pos;
75 pdfout("%d 0 obj\n", id);
76 return id;
79 /* end an object definition */
80 static void obj_end(void)
82 pdfout("endobj\n\n");
85 void out(char *s, ...)
89 /* the length of the clear-text, encrypted, and fixed-content portions */
90 static int type1lengths(char *t1, int l, int *l1, int *l2, int *l3)
92 int i;
93 char *cleartext = t1;
94 char *encrypted = NULL;
95 char *fixedcont = NULL;
96 for (i = 0; i < l - 5 && !encrypted; i++)
97 if (t1[i] == 'e' && !memcmp("eexec", t1 + i, 5))
98 encrypted = t1 + i;
99 if (!encrypted)
100 return 1;
101 for (; i < l - 512 && !fixedcont; i++)
102 if (t1[i] == '0' && !memcmp("00000", t1 + i, 5))
103 fixedcont = t1 + i;
104 *l1 = encrypted - cleartext;
105 *l2 = fixedcont ? fixedcont - cleartext : 0;
106 return 0;
109 /* return font type: 't': TrueType, '1': Type 1, 'o': OpenType */
110 static int fonttype(char *path)
112 char *ext = strrchr(path, '.');
113 if (ext && !strcmp(".ttf", ext))
114 return 't';
115 if (ext && !strcmp(".otf", ext))
116 return 'o';
117 return '1';
120 /* include font descriptor; returns object id */
121 static int psfont_writedesc(struct psfont *ps)
123 int str_obj = -1;
124 int des_obj;
125 char buf[1 << 10];
126 int i;
127 if (fonttype(ps->path) == '1' || fonttype(ps->path) == 't') {
128 int fd = open(ps->path, O_RDONLY);
129 struct sbuf *ffsb = sbuf_make();
130 struct sbuf *sb = sbuf_make();
131 int l1 = 0, l2 = 0, l3 = 0;
132 int nr;
133 /* reading the font file */
134 while ((nr = read(fd, buf, sizeof(buf))) > 0)
135 sbuf_mem(ffsb, buf, nr);
136 close(fd);
137 l1 = sbuf_len(ffsb);
138 /* initialize Type 1 lengths */
139 if (fonttype(ps->path) == '1') {
140 if (type1lengths(sbuf_buf(ffsb), sbuf_len(ffsb),
141 &l1, &l2, &l3))
142 l1 = 0;
143 /* remove the fixed-content portion of the font */
144 if (l3)
145 sbuf_cut(ffsb, l1 + l2);
146 l1 -= l3;
148 /* encoding file contents */
149 for (i = 0; i < sbuf_len(ffsb); i++) {
150 sbuf_printf(sb, "%02x", (unsigned char) sbuf_buf(ffsb)[i]);
151 if (i % 40 == 39 && i + 1 < sbuf_len(ffsb))
152 sbuf_chr(sb, '\n');
154 sbuf_str(sb, ">\n");
155 /* write font data if it has nonzero length */
156 if (l1) {
157 str_obj = obj_beg(0);
158 pdfout("<<\n");
159 pdfout(" /Filter /ASCIIHexDecode\n");
160 pdfout(" /Length %d\n", sbuf_len(sb));
161 pdfout(" /Length1 %d\n", l1);
162 if (fonttype(ps->path) == '1')
163 pdfout(" /Length2 %d\n", l2);
164 if (fonttype(ps->path) == '1')
165 pdfout(" /Length3 %d\n", l3);
166 pdfout(">>\n");
167 pdfout("stream\n");
168 pdfout("%s", sbuf_buf(sb));
169 pdfout("endstream\n");
170 obj_end();
172 sbuf_free(ffsb);
173 sbuf_free(sb);
175 /* the font descriptor */
176 des_obj = obj_beg(0);
177 pdfout("<<\n");
178 pdfout(" /Type /FontDescriptor\n");
179 pdfout(" /FontName /%s\n", ps->name);
180 pdfout(" /Flags 4\n");
181 pdfout(" /FontBBox [-1000 -1000 1000 1000]\n");
182 pdfout(" /MissingWidth 1000\n");
183 pdfout(" /StemV 100\n");
184 pdfout(" /ItalicAngle 0\n");
185 pdfout(" /CapHeight 100\n");
186 pdfout(" /Ascent 100\n");
187 pdfout(" /Descent 100\n");
188 if (str_obj >= 0)
189 pdfout(" /FontFile%s %d 0 R\n",
190 fonttype(ps->path) == 't' ? "2" : "", str_obj);
191 pdfout(">>\n");
192 obj_end();
193 return des_obj;
196 /* write the object corresponding to font font_id[f] */
197 static void psfont_write(struct psfont *ps, int ix)
199 int i;
200 int enc_obj;
201 struct font *fn = dev_fontopen(ps->desc);
202 int map[256];
203 int gcnt = ix < ps->lastfn ? 256 : ps->lastgl;
204 /* finding out the mapping */
205 for (i = 0; i < 256; i++)
206 map[i] = -1;
207 for (i = 0; i < ps->gcnt; i++)
208 if (ps->gmap[i] == ix)
209 map[ps->gpos[i]] = i;
210 /* the encoding object */
211 enc_obj = obj_beg(0);
212 pdfout("<<\n");
213 pdfout(" /Type /Encoding\n");
214 pdfout(" /Differences [ 0");
215 for (i = 0; i < gcnt; i++)
216 pdfout(" /%s", map[i] >= 0 ? font_glget(fn, map[i])->id : ".notdef");
217 pdfout(" ]\n");
218 pdfout(">>\n");
219 obj_end();
220 /* the font object */
221 obj_beg(ps->obj[ix]);
222 pdfout("<<\n");
223 pdfout(" /Type /Font\n");
224 if (fonttype(ps->path) == 't')
225 pdfout(" /Subtype /TrueType\n");
226 else
227 pdfout(" /Subtype /Type1\n");
228 pdfout(" /BaseFont /%s\n", ps->name);
229 pdfout(" /FirstChar 0\n");
230 pdfout(" /LastChar %d\n", gcnt - 1);
231 pdfout(" /Widths [");
232 for (i = 0; i < gcnt; i++)
233 pdfout(" %d", (long) (map[i] >= 0 ? font_glget(fn, map[i])->wid : 0)
234 * 100 * 72 / dev_res);
235 pdfout(" ]\n");
236 pdfout(" /FontDescriptor %d 0 R\n", ps->objdes);
237 pdfout(" /Encoding %d 0 R\n", enc_obj);
238 pdfout(">>\n");
239 obj_end();
240 font_close(fn);
243 static int psfont_find(struct glyph *g)
245 struct font *fn = g->font;
246 char *name = font_name(fn);
247 struct psfont *ps = NULL;
248 int gidx;
249 int i;
250 for (i = 0; i < psfonts_n; i++)
251 if (!strcmp(name, psfonts[i].name))
252 break;
253 if (i == psfonts_n) {
254 if (psfonts_n == psfonts_sz) {
255 psfonts_sz += 16;
256 psfonts = mextend(psfonts, psfonts_n,
257 psfonts_sz, sizeof(psfonts[0]));
259 psfonts_n++;
260 ps = &psfonts[i];
261 snprintf(ps->name, sizeof(ps->name), "%s", name);
262 snprintf(ps->path, sizeof(ps->path), "%s", font_path(fn));
263 snprintf(ps->desc, sizeof(ps->desc), "%s", font_desc(fn));
264 while (font_glget(fn, ps->gcnt))
265 ps->gcnt++;
266 ps->gmap = calloc(ps->gcnt, sizeof(ps->gmap));
267 ps->gpos = calloc(ps->gcnt, sizeof(ps->gpos));
268 ps->lastfn = 0;
269 ps->lastgl = 256;
271 ps = &psfonts[i];
272 gidx = font_glnum(fn, g);
273 if (!ps->gmap[gidx]) {
274 if (ps->lastgl == 256) {
275 ps->lastgl = 0;
276 ps->lastfn++;
277 ps->obj[ps->lastfn] = obj_map();
279 ps->gmap[gidx] = ps->lastfn;
280 ps->gpos[gidx] = ps->lastgl++;
282 return PSFN_MK(i, ps->gmap[gidx]);
285 static int psfont_gpos(struct glyph *g)
287 int fn = psfont_find(g);
288 return psfonts[PSFN_FN(fn)].gpos[font_glnum(g->font, g)];
291 static void psfont_done(void)
293 int i, j;
294 for (i = 0; i < psfonts_n; i++) {
295 struct psfont *ps = &psfonts[i];
296 ps->objdes = psfont_writedesc(ps);
297 for (j = 1; j <= ps->lastfn; j++)
298 psfont_write(ps, j);
300 for (i = 0; i < psfonts_n; i++) {
301 free(psfonts[i].gmap);
302 free(psfonts[i].gpos);
304 free(psfonts);
307 static void o_flush(void)
309 if (o_queued == 1)
310 sbuf_printf(pg, ">] TJ\n");
311 o_queued = 0;
314 static int o_loadfont(struct glyph *g)
316 int fn = psfont_find(g);
317 int i;
318 for (i = 0; i < o_fsn; i++)
319 if (o_fs[i] == fn)
320 return i;
321 if (o_fsn == o_fssz) {
322 o_fssz += 128;
323 o_fs = mextend(o_fs, o_fsn, o_fssz, sizeof(o_fs[0]));
325 o_fs[o_fsn++] = fn;
326 return o_fsn - 1;
329 /* like pdfpos() but assume that uh and uv are multiplied by 100 */
330 static char *pdfpos00(int uh, int uv)
332 static char buf[64];
333 int h = (long) uh * 72 / dev_res;
334 int v = (long) pdf_height * 100 - (long) uv * 72 / dev_res;
335 sprintf(buf, "%s%d.%02d %s%d.%02d",
336 h < 0 ? "-" : "", abs(h) / 100, abs(h) % 100,
337 v < 0 ? "-" : "", abs(v) / 100, abs(v) % 100);
338 return buf;
341 /* convert troff position to pdf position; returns a static buffer */
342 static char *pdfpos(int uh, int uv)
344 return pdfpos00(uh * 100, uv * 100);
347 /* troff length to thousands of a unit of text space; returns a static buffer */
348 static char *pdfunit(int uh, int sz)
350 static char buf[64];
351 int h = (long) uh * 1000 * 72 / sz / dev_res;
352 sprintf(buf, "%s%d", h < 0 ? "-" : "", abs(h));
353 return buf;
356 /* convert troff color to pdf color; returns a static buffer */
357 static char *pdfcolor(int m)
359 static char buf[64];
360 int r = CLR_R(m) * 1000 / 255;
361 int g = CLR_G(m) * 1000 / 255;
362 int b = CLR_B(m) * 1000 / 255;
363 sbuf_printf(pg, "%d.%03d %d.%03d %d.%03d",
364 r / 1000, r % 1000, g / 1000, g % 1000, b / 1000, b % 1000);
365 return buf;
368 static void o_queue(struct glyph *g)
370 if (o_v != p_v) {
371 o_flush();
372 sbuf_printf(pg, "1 0 0 1 %s Tm\n", pdfpos(o_h, o_v));
373 p_h = o_h;
374 p_v = o_v;
376 if (!o_queued)
377 sbuf_printf(pg, "[<");
378 o_queued = 1;
379 if (o_h != p_h)
380 sbuf_printf(pg, "> %s <", pdfunit(p_h - o_h, o_s));
381 sbuf_printf(pg, "%02x", psfont_gpos(g));
382 p_h = o_h + font_wid(g->font, o_s, g->wid);
385 static void out_fontup(void)
387 if (o_m != p_m) {
388 o_flush();
389 sbuf_printf(pg, "%s rg\n", pdfcolor(o_m));
390 p_m = o_m;
392 if (o_pf >= 0 && (o_pf != p_pf || o_s != p_s)) {
393 int fn = PSFN_FN(o_fs[o_pf]);
394 int ix = PSFN_IX(o_fs[o_pf]);
395 o_flush();
396 sbuf_printf(pg, "/%s.%d %d Tf\n", psfonts[fn].name, ix, o_s);
397 p_pf = o_pf;
398 p_s = o_s;
402 void outc(char *c)
404 struct glyph *g;
405 struct font *fn;
406 g = dev_glyph(c, o_f);
407 fn = g ? g->font : dev_font(o_f);
408 if (!g) {
409 outrel(*c == ' ' && fn ? font_swid(fn, o_s) : 1, 0);
410 return;
412 o_pf = o_loadfont(g);
413 out_fontup();
414 o_queue(g);
417 void outh(int h)
419 o_h = h;
422 void outv(int v)
424 o_v = v;
427 void outrel(int h, int v)
429 o_h += h;
430 o_v += v;
433 void outfont(int f)
435 if (dev_font(f))
436 o_f = f;
439 void outsize(int s)
441 if (s > 0)
442 o_s = s;
445 void outcolor(int c)
447 o_m = c;
450 void outrotate(int deg)
454 void outeps(char *eps)
458 void outlink(char *spec)
462 void outpage(void)
464 o_v = 0;
465 o_h = 0;
466 p_pf = 0;
467 p_v = 0;
468 p_h = 0;
469 p_s = 0;
470 p_f = 0;
471 p_m = 0;
472 o_pf = -1;
475 void outmnt(int f)
477 if (p_f == f)
478 p_f = -1;
481 void outgname(int g)
485 static int draw_path; /* number of path segments */
486 static int draw_point; /* point was set for postscript newpath */
488 void drawbeg(void)
490 o_flush();
491 out_fontup();
492 if (draw_path)
493 return;
494 sbuf_printf(pg, "%s m\n", pdfpos(o_h, o_v));
497 void drawend(int close, int fill)
499 if (draw_path)
500 return;
501 draw_point = 0;
502 if (!fill) /* stroking color */
503 sbuf_printf(pg, "%s RG\n", pdfcolor(o_m));
504 if (fill)
505 sbuf_printf(pg, "f\n");
506 else
507 sbuf_printf(pg, close ? "s\n" : "S\n");
510 void drawmbeg(char *s)
514 void drawmend(char *s)
518 void drawl(int h, int v)
520 outrel(h, v);
521 sbuf_printf(pg, "%s l\n", pdfpos(o_h, o_v));
524 /* draw circle/ellipse quadrant */
525 static void drawquad(int ch, int cv)
527 long b = 551915;
528 long x0 = o_h * 1000;
529 long y0 = o_v * 1000;
530 long x3 = x0 + ch * 1000 / 2;
531 long y3 = y0 + cv * 1000 / 2;
532 long x1 = x0;
533 long y1 = y0 + cv * b / 1000 / 2;
534 long x2 = x0 + ch * b / 1000 / 2;
535 long y2 = y3;
536 if (ch * cv < 0) {
537 x1 = x3 - ch * b / 1000 / 2;
538 y1 = y0;
539 x2 = x3;
540 y2 = y3 - cv * b / 1000 / 2;
542 sbuf_printf(pg, "%s ", pdfpos00(x1 / 10, y1 / 10));
543 sbuf_printf(pg, "%s ", pdfpos00(x2 / 10, y2 / 10));
544 sbuf_printf(pg, "%s c\n", pdfpos00(x3 / 10, y3 / 10));
545 outrel(ch / 2, cv / 2);
548 /* draw a circle */
549 void drawc(int c)
551 drawquad(+c, +c);
552 drawquad(+c, -c);
553 drawquad(-c, -c);
554 drawquad(-c, +c);
555 outrel(c, 0);
558 /* draw an ellipse */
559 void drawe(int h, int v)
561 drawquad(+h, +v);
562 drawquad(+h, -v);
563 drawquad(-h, -v);
564 drawquad(-h, +v);
565 outrel(h, 0);
568 /* draw an arc */
569 void drawa(int h1, int v1, int h2, int v2)
571 drawl(h1 + h2, v1 + v2);
574 /* draw an spline */
575 void draws(int h1, int v1, int h2, int v2)
577 outrel(h1, v1);
578 sbuf_printf(pg, "%s l\n", pdfpos(o_h, o_v));
581 void ps_header(char *title, int pagewidth, int pageheight, int linewidth)
583 pdf_title = title;
584 obj_map();
585 pdf_root = obj_map();
586 pdf_pages = obj_map();
587 pdf_title = title;
588 pdfout("%%PDF-1.6\n");
589 pdf_width = (pagewidth * 72 + 127) / 254;
590 pdf_height = (pageheight * 72 + 127) / 254;
593 void ps_trailer(int pages)
595 int i;
596 int xref_off;
597 int info_id;
598 /* pdf pages object */
599 obj_beg(pdf_pages);
600 pdfout("<<\n");
601 pdfout(" /Type /Pages\n");
602 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width, pdf_height);
603 pdfout(" /Count %d\n", page_n);
604 pdfout(" /Kids [");
605 for (i = 0; i < page_n; i++)
606 pdfout(" %d 0 R", page_id[i]);
607 pdfout(" ]\n");
608 pdfout(">>\n");
609 obj_end();
610 /* pdf root object */
611 obj_beg(pdf_root);
612 pdfout("<<\n");
613 pdfout(" /Type /Catalog\n");
614 pdfout(" /Pages %d 0 R\n", pdf_pages);
615 pdfout(">>\n");
616 obj_end();
617 /* fonts */
618 psfont_done();
619 /* info object */
620 info_id = obj_beg(0);
621 pdfout("<<\n");
622 if (pdf_title)
623 pdfout(" /Title (%s)\n", pdf_title);
624 pdfout(" /Creator (Neatroff)\n");
625 pdfout(" /Producer (Neatpost)\n");
626 pdfout(">>\n");
627 obj_end();
628 /* the xref */
629 xref_off = pdf_pos;
630 pdfout("xref\n");
631 pdfout("0 %d\n", obj_n);
632 pdfout("0000000000 65535 f \n");
633 for (i = 1; i < obj_n; i++)
634 pdfout("%010d 00000 n \n", obj_off[i]);
635 /* the trailer */
636 pdfout("trailer\n");
637 pdfout("<<\n");
638 pdfout(" /Size %d\n", obj_n);
639 pdfout(" /Root %d 0 R\n", pdf_root);
640 pdfout(" /Info %d 0 R\n", info_id);
641 pdfout(">>\n");
642 pdfout("startxref\n");
643 pdfout("%d\n", xref_off);
644 pdfout("%%%%EOF\n");
645 free(page_id);
646 free(obj_off);
649 void ps_pagebeg(int n)
651 pg = sbuf_make();
652 sbuf_printf(pg, "BT\n");
655 void ps_pageend(int n)
657 int cont_id;
658 int i;
659 o_flush();
660 sbuf_printf(pg, "ET\n");
661 /* page contents */
662 cont_id = obj_beg(0);
663 pdfout("<<\n");
664 pdfout(" /Length %d\n", sbuf_len(pg));
665 pdfout(">>\n");
666 pdfout("stream\n");
667 pdfout("%s", sbuf_buf(pg));
668 pdfout("endstream\n");
669 obj_end();
670 /* the page object */
671 if (page_n == page_sz) {
672 page_sz += 1024;
673 page_id = mextend(page_id, page_n, page_sz, sizeof(page_id[0]));
675 page_id[page_n++] = obj_beg(0);
676 pdfout("<<\n");
677 pdfout(" /Type /Page\n");
678 pdfout(" /Parent %d 0 R\n", pdf_pages);
679 pdfout(" /Resources <<\n");
680 pdfout(" /Font <<");
681 for (i = 0; i < o_fsn; i++) {
682 int fn = PSFN_FN(o_fs[i]);
683 int ix = PSFN_IX(o_fs[i]);
684 pdfout(" /%s.%d %d 0 R",
685 psfonts[fn].name, ix, psfonts[fn].obj[ix]);
687 pdfout(" >>\n");
688 pdfout(" >>\n");
689 pdfout(" /Contents %d 0 R\n", cont_id);
690 pdfout(">>\n");
691 obj_end();
692 sbuf_free(pg);
693 free(o_fs);
694 o_fs = NULL;
695 o_fsn = 0;
696 o_fssz = 0;