pdf: do not include .notdef glyphs in the last sub-font
[neatpost.git] / pdf.c
blob191ca8b96a70df07065447002e34e92a9db84241
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 */
18 static struct sbuf *pg; /* current page contents */
19 static int o_f, o_s, o_m; /* font and size */
20 static int o_h, o_v; /* current user position */
21 static int p_h, p_v; /* current output position */
22 static int o_pf, p_pf; /* output and pdf fonts; indices into o_fs[] */
23 static int p_f, p_s, p_m; /* output font */
24 static int o_queued; /* queued character type */
25 static int *o_fs; /* page fonts */
26 static int o_fsn, o_fssz; /* page fonts */
28 #define PSFN_MK(fn, ix) (((fn) << 16) | (ix))
29 #define PSFN_FN(fi) ((fi) >> 16)
30 #define PSFN_IX(fi) ((fi) & 0xffff)
32 struct psfont {
33 char name[128]; /* font PostScript name */
34 char path[1024]; /* font path */
35 char desc[1024]; /* font descriptor path */
36 int *gmap; /* the sub-font assigned to each glyph */
37 int *gpos; /* the location of the glyph in its sub-font */
38 int gcnt; /* glyph count */
39 int lastfn; /* the last sub-font */
40 int lastgl; /* the number of glyphs in the last subfont */
41 int obj[64]; /* sub-font object ids */
42 int objdes; /* font descriptor object id */
45 static struct psfont *psfonts;
46 static int psfonts_n, psfonts_sz;
48 /* print pdf output */
49 static void pdfout(char *s, ...)
51 va_list ap;
52 va_start(ap, s);
53 pdf_pos += vprintf(s, ap);
54 va_end(ap);
57 /* allocate an object number */
58 static int obj_map(void)
60 if (obj_n == obj_sz) {
61 obj_sz += 1024;
62 obj_off = mextend(obj_off, obj_n, obj_sz, sizeof(obj_off[0]));
64 return obj_n++;
67 /* start the definition of an object */
68 static int obj_beg(int id)
70 if (id <= 0)
71 id = obj_map();
72 obj_off[id] = pdf_pos;
73 pdfout("%d 0 obj\n", id);
74 return id;
77 /* end an object definition */
78 static void obj_end(void)
80 pdfout("endobj\n\n");
83 void out(char *s, ...)
87 /* include font descriptor; returns object id */
88 static int psfont_writedesc(struct psfont *ps)
90 int c, i;
91 int str_obj = -1;
92 int des_obj;
93 char *ext = strrchr(ps->path, '.');
94 if (ext && !strcmp(".ttf", ext)) {
95 FILE *fp = fopen(ps->path, "r");
96 struct sbuf *sb = sbuf_make();
97 c = fgetc(fp);
98 for (i = 0; c != EOF; i++) {
99 sbuf_printf(sb, "%02x", c);
100 c = fgetc(fp);
101 if (i % 40 == 39 && c != EOF)
102 sbuf_chr(sb, '\n');
104 sbuf_str(sb, ">\n");
105 fclose(fp);
106 str_obj = obj_beg(0);
107 pdfout("<<\n");
108 pdfout(" /Filter /ASCIIHexDecode\n");
109 pdfout(" /Length %d\n", sbuf_len(sb));
110 pdfout(" /Length1 %d\n", i);
111 pdfout(">>\n");
112 pdfout("stream\n");
113 pdfout("%s", sbuf_buf(sb));
114 pdfout("endstream\n");
115 obj_end();
116 sbuf_free(sb);
118 /* the font descriptor */
119 des_obj = obj_beg(0);
120 pdfout("<<\n");
121 pdfout(" /Type /FontDescriptor\n");
122 pdfout(" /FontName /%s\n", ps->name);
123 pdfout(" /Flags 4\n");
124 pdfout(" /FontBBox [-1000 -1000 1000 1000]\n");
125 pdfout(" /MissingWidth 1000\n");
126 pdfout(" /StemV 100\n");
127 pdfout(" /ItalicAngle 0\n");
128 pdfout(" /CapHeight 100\n");
129 pdfout(" /Ascent 100\n");
130 pdfout(" /Descent 100\n");
131 if (str_obj >= 0)
132 pdfout(" /FontFile2 %d 0 R\n", str_obj);
133 pdfout(">>\n");
134 obj_end();
135 return des_obj;
138 /* write the object corresponding to font font_id[f] */
139 static void psfont_write(struct psfont *ps, int ix)
141 int i;
142 int enc_obj;
143 char *ext = strrchr(ps->path, '.');
144 struct font *fn = dev_fontopen(ps->desc);
145 int map[256] = {0};
146 char gcnt = ps->lastfn == ix ? ps->lastgl : 256;
147 /* finding out the mapping */
148 for (i = 0; i < 256; i++)
149 map[i] = -1;
150 for (i = 0; i < ps->gcnt; i++)
151 if (ps->gmap[i] == ix)
152 map[ps->gpos[i]] = i;
153 /* the encoding object */
154 enc_obj = obj_beg(0);
155 pdfout("<<\n");
156 pdfout(" /Type /Encoding\n");
157 pdfout(" /Differences [ 0");
158 for (i = 0; i < gcnt; i++)
159 pdfout(" /%s", map[i] >= 0 ? font_glget(fn, map[i])->id : ".notdef");
160 pdfout(" ]\n");
161 pdfout(">>\n");
162 obj_end();
163 /* the font object */
164 obj_beg(ps->obj[ix]);
165 pdfout("<<\n");
166 pdfout(" /Type /Font\n");
167 pdfout(" /Subtype /%s\n",
168 ext && !strcmp(".ttf", ext) ? "TrueType" : "Type1");
169 pdfout(" /BaseFont /%s\n", ps->name);
170 pdfout(" /FirstChar 0\n");
171 pdfout(" /LastChar %d\n", gcnt - 1);
172 pdfout(" /Widths [");
173 for (i = 0; i < gcnt; i++)
174 pdfout(" %d", (map[i] >= 0 ? font_glget(fn, map[i])->wid : 0)
175 * dev_res / 72);
176 pdfout(" ]\n");
177 pdfout(" /FontDescriptor %d 0 R\n", ps->objdes);
178 pdfout(" /Encoding %d 0 R\n", enc_obj);
179 pdfout(">>\n");
180 obj_end();
181 font_close(fn);
184 static int psfont_find(struct glyph *g)
186 struct font *fn = g->font;
187 char *name = font_name(fn);
188 struct psfont *ps = NULL;
189 int gidx;
190 int i;
191 for (i = 0; i < psfonts_n; i++)
192 if (!strcmp(name, psfonts[i].name))
193 break;
194 if (i == psfonts_n) {
195 if (psfonts_n == psfonts_sz) {
196 psfonts_sz += 16;
197 psfonts = mextend(psfonts, psfonts_n,
198 psfonts_sz, sizeof(psfonts[0]));
200 psfonts_n++;
201 ps = &psfonts[i];
202 snprintf(ps->name, sizeof(ps->name), "%s", name);
203 snprintf(ps->path, sizeof(ps->path), "%s", font_path(fn));
204 snprintf(ps->desc, sizeof(ps->desc), "%s", font_desc(fn));
205 while (font_glget(fn, ps->gcnt))
206 ps->gcnt++;
207 ps->gmap = calloc(ps->gcnt, sizeof(ps->gmap));
208 ps->gpos = calloc(ps->gcnt, sizeof(ps->gpos));
209 ps->lastfn = 0;
210 ps->lastgl = 256;
212 ps = &psfonts[i];
213 gidx = font_glnum(fn, g);
214 if (!ps->gmap[gidx]) {
215 if (ps->lastgl == 256) {
216 ps->lastgl = 0;
217 ps->lastfn++;
218 ps->obj[ps->lastfn] = obj_map();
220 ps->gmap[gidx] = ps->lastfn;
221 ps->gpos[gidx] = ps->lastgl++;
223 return PSFN_MK(i, ps->gmap[gidx]);
226 static int psfont_gpos(struct glyph *g)
228 int fn = psfont_find(g);
229 return psfonts[PSFN_FN(fn)].gpos[font_glnum(g->font, g)];
232 static void psfont_done(void)
234 int i, j;
235 for (i = 0; i < psfonts_n; i++) {
236 struct psfont *ps = &psfonts[i];
237 ps->objdes = psfont_writedesc(ps);
238 for (j = 1; j <= ps->lastfn; j++)
239 psfont_write(ps, j);
241 for (i = 0; i < psfonts_n; i++) {
242 free(psfonts[i].gmap);
243 free(psfonts[i].gpos);
245 free(psfonts);
248 static void o_flush(void)
250 if (o_queued == 1)
251 sbuf_printf(pg, "> Tj\n");
252 o_queued = 0;
255 static int o_loadfont(struct glyph *g)
257 int fn = psfont_find(g);
258 int i;
259 for (i = 0; i < o_fsn; i++)
260 if (o_fs[i] == fn)
261 return i;
262 if (o_fsn == o_fssz) {
263 o_fssz += 128;
264 o_fs = mextend(o_fs, o_fsn, o_fssz, sizeof(o_fs[0]));
266 o_fs[o_fsn++] = fn;
267 return o_fsn - 1;
270 #define PREC 1000
271 #define PRECN "3"
273 /* convert troff position to pdf position; returns a static buffer */
274 static char *pdfpos(int uh, int uv)
276 static char buf[64];
277 int h = uh * PREC * 72 / dev_res;
278 int v = pdf_height * PREC - (uv * PREC * 72 / dev_res);
279 sprintf(buf, "%d.%0" PRECN "d %d.%0" PRECN "d",
280 h / PREC, h % PREC, v / PREC, v % PREC);
281 return buf;
284 /* convert troff color to pdf color; returns a static buffer */
285 static char *pdfcolor(int m)
287 static char buf[64];
288 int r = CLR_R(m) * 1000 / 255;
289 int g = CLR_G(m) * 1000 / 255;
290 int b = CLR_B(m) * 1000 / 255;
291 sbuf_printf(pg, "%d.%03d %d.%03d %d.%03d",
292 r / 1000, r % 1000, g / 1000, g % 1000, b / 1000, b % 1000);
293 return buf;
296 static void o_queue(struct glyph *g)
298 if (o_h != p_h || o_v != p_v) {
299 o_flush();
300 sbuf_printf(pg, "1 0 0 1 %s Tm\n", pdfpos(o_h, o_v));
301 p_h = o_h;
302 p_v = o_v;
304 if (!o_queued)
305 sbuf_printf(pg, "<");
306 o_queued = 1;
307 sbuf_printf(pg, "%02x", psfont_gpos(g));
308 p_h += font_wid(g->font, o_s, g->wid);
311 static void out_fontup(void)
313 if (o_m != p_m) {
314 o_flush();
315 sbuf_printf(pg, "%s rg\n", pdfcolor(o_m));
316 p_m = o_m;
318 if (o_pf != p_pf || o_s != p_s) {
319 int fn = PSFN_FN(o_fs[o_pf]);
320 int ix = PSFN_IX(o_fs[o_pf]);
321 o_flush();
322 sbuf_printf(pg, "/%s.%d %d Tf\n", psfonts[fn].name, ix, o_s);
323 p_pf = o_pf;
324 p_s = o_s;
328 void outc(char *c)
330 struct glyph *g;
331 struct font *fn;
332 g = dev_glyph(c, o_f);
333 fn = g ? g->font : dev_font(o_f);
334 if (!g) {
335 outrel(*c == ' ' && fn ? font_swid(fn, o_s) : 1, 0);
336 return;
338 o_pf = o_loadfont(g);
339 out_fontup();
340 o_queue(g);
343 void outh(int h)
345 o_h = h;
348 void outv(int v)
350 o_v = v;
353 void outrel(int h, int v)
355 o_h += h;
356 o_v += v;
359 void outfont(int f)
361 if (dev_font(f))
362 o_f = f;
365 void outsize(int s)
367 if (s > 0)
368 o_s = s;
371 void outcolor(int c)
373 o_m = c;
376 void outrotate(int deg)
380 void outeps(char *eps)
384 void outlink(char *spec)
388 void outpage(void)
390 o_v = 0;
391 o_h = 0;
392 p_v = 0;
393 p_h = 0;
394 p_s = 0;
395 p_f = 0;
396 p_m = 0;
399 void outmnt(int f)
401 if (p_f == f)
402 p_f = -1;
405 void outgname(int g)
409 static int draw_path; /* number of path segments */
410 static int draw_point; /* point was set for postscript newpath */
412 void drawbeg(void)
414 o_flush();
415 out_fontup();
416 if (draw_path)
417 return;
418 sbuf_printf(pg, "%s m\n", pdfpos(o_h, o_v));
421 void drawend(int close, int fill)
423 if (draw_path)
424 return;
425 draw_point = 0;
426 if (!fill) /* stroking color */
427 sbuf_printf(pg, "%s RG\n", pdfcolor(o_m));
428 if (fill)
429 sbuf_printf(pg, "f\n");
430 else
431 sbuf_printf(pg, close ? "s\n" : "S\n");
434 void drawmbeg(char *s)
438 void drawmend(char *s)
442 void drawl(int h, int v)
444 o_flush();
445 outrel(h, v);
446 sbuf_printf(pg, "%s l\n", pdfpos(o_h, o_v));
449 void drawc(int c)
451 outrel(c, 0);
454 void drawe(int h, int v)
456 outrel(h, 0);
459 void drawa(int h1, int v1, int h2, int v2)
461 outrel(h1 + h2, v1 + v2);
464 void draws(int h1, int v1, int h2, int v2)
466 outrel(h1, v1);
469 void ps_header(char *title, int pagewidth, int pageheight, int linewidth)
471 pdf_title = title;
472 obj_map();
473 pdf_root = obj_map();
474 pdf_pages = obj_map();
475 pdf_title = title;
476 pdfout("%%PDF-1.6\n");
477 pdf_width = (pagewidth * 72 + 127) / 254;
478 pdf_height = (pageheight * 72 + 127) / 254;
481 void ps_trailer(int pages)
483 int i;
484 int xref_off;
485 int info_id;
486 /* pdf pages object */
487 obj_beg(pdf_pages);
488 pdfout("<<\n");
489 pdfout(" /Type /Pages\n");
490 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width, pdf_height);
491 pdfout(" /Count %d\n", page_n);
492 pdfout(" /Kids [");
493 for (i = 0; i < page_n; i++)
494 pdfout(" %d 0 R", page_id[i]);
495 pdfout(" ]\n");
496 pdfout(">>\n");
497 obj_end();
498 /* pdf root object */
499 obj_beg(pdf_root);
500 pdfout("<<\n");
501 pdfout(" /Type /Catalog\n");
502 pdfout(" /Pages %d 0 R\n", pdf_pages);
503 pdfout(">>\n");
504 obj_end();
505 /* fonts */
506 psfont_done();
507 /* info object */
508 info_id = obj_beg(0);
509 pdfout("<<\n");
510 if (pdf_title)
511 pdfout(" /Title (%s)\n", pdf_title);
512 pdfout(" /Creator (Neatroff)\n");
513 pdfout(" /Producer (Neatpost)\n");
514 pdfout(">>\n");
515 obj_end();
516 /* the xref */
517 xref_off = pdf_pos;
518 pdfout("xref\n");
519 pdfout("0 %d\n", obj_n);
520 pdfout("0000000000 65535 f \n");
521 for (i = 1; i < obj_n; i++)
522 pdfout("%010d 00000 n \n", obj_off[i]);
523 /* the trailer */
524 pdfout("trailer\n");
525 pdfout("<<\n");
526 pdfout(" /Size %d\n", obj_n);
527 pdfout(" /Root %d 0 R\n", pdf_root);
528 pdfout(" /Info %d 0 R\n", info_id);
529 pdfout(">>\n");
530 pdfout("startxref\n");
531 pdfout("%d\n", xref_off);
532 pdfout("%%%%EOF\n");
533 free(page_id);
534 free(obj_off);
537 void ps_pagebeg(int n)
539 pg = sbuf_make();
540 sbuf_printf(pg, "BT\n");
543 void ps_pageend(int n)
545 int cont_id;
546 int i;
547 o_flush();
548 sbuf_printf(pg, "ET\n");
549 /* page contents */
550 cont_id = obj_beg(0);
551 pdfout("<<\n");
552 pdfout(" /Length %d\n", sbuf_len(pg));
553 pdfout(">>\n");
554 pdfout("stream\n");
555 pdfout("%s", sbuf_buf(pg));
556 pdfout("endstream\n");
557 obj_end();
558 /* the page object */
559 if (page_n == page_sz) {
560 page_sz += 1024;
561 page_id = mextend(page_id, page_n, page_sz, sizeof(page_id[0]));
563 page_id[page_n++] = obj_beg(0);
564 pdfout("<<\n");
565 pdfout(" /Type /Page\n");
566 pdfout(" /Parent %d 0 R\n", pdf_pages);
567 pdfout(" /Resources <<\n");
568 pdfout(" /Font <<");
569 for (i = 0; i < o_fsn; i++) {
570 int fn = PSFN_FN(o_fs[i]);
571 int ix = PSFN_IX(o_fs[i]);
572 pdfout(" /%s.%d %d 0 R",
573 psfonts[fn].name, ix, psfonts[fn].obj[ix]);
575 pdfout(" >>\n");
576 pdfout(" >>\n");
577 pdfout(" /Contents %d 0 R\n", cont_id);
578 pdfout(">>\n");
579 obj_end();
580 sbuf_free(pg);
581 free(o_fs);
582 o_fs = NULL;
583 o_fsn = 0;
584 o_fssz = 0;