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)
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
, ...)
55 pdf_pos
+= vprintf(s
, ap
);
59 /* allocate an object number */
60 static int obj_map(void)
62 if (obj_n
== obj_sz
) {
64 obj_off
= mextend(obj_off
, obj_n
, obj_sz
, sizeof(obj_off
[0]));
69 /* start the definition of an object */
70 static int obj_beg(int id
)
74 obj_off
[id
] = pdf_pos
;
75 pdfout("%d 0 obj\n", id
);
79 /* end an object definition */
80 static void obj_end(void)
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
)
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))
101 for (; i
< l
- 512 && !fixedcont
; i
++)
102 if (t1
[i
] == '0' && !memcmp("00000", t1
+ i
, 5))
104 *l1
= encrypted
- cleartext
;
105 *l2
= fixedcont
? fixedcont
- cleartext
: 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
))
115 if (ext
&& !strcmp(".otf", ext
))
120 /* include font descriptor; returns object id */
121 static int psfont_writedesc(struct psfont
*ps
)
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;
133 /* reading the font file */
134 while ((nr
= read(fd
, buf
, sizeof(buf
))) > 0)
135 sbuf_mem(ffsb
, buf
, nr
);
138 /* initialize Type 1 lengths */
139 if (fonttype(ps
->path
) == '1') {
140 if (type1lengths(sbuf_buf(ffsb
), sbuf_len(ffsb
),
143 /* remove the fixed-content portion of the font */
145 sbuf_cut(ffsb
, l1
+ l2
);
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
))
155 /* write font data if it has nonzero length */
157 str_obj
= obj_beg(0);
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
);
168 pdfout("%s", sbuf_buf(sb
));
169 pdfout("endstream\n");
175 /* the font descriptor */
176 des_obj
= obj_beg(0);
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");
189 pdfout(" /FontFile%s %d 0 R\n",
190 fonttype(ps
->path
) == 't' ? "2" : "", str_obj
);
196 /* write the object corresponding to font font_id[f] */
197 static void psfont_write(struct psfont
*ps
, int ix
)
201 struct font
*fn
= dev_fontopen(ps
->desc
);
203 int gcnt
= ix
< ps
->lastfn
? 256 : ps
->lastgl
;
204 /* finding out the mapping */
205 for (i
= 0; i
< 256; i
++)
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);
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");
220 /* the font object */
221 obj_beg(ps
->obj
[ix
]);
223 pdfout(" /Type /Font\n");
224 if (fonttype(ps
->path
) == 't')
225 pdfout(" /Subtype /TrueType\n");
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
);
236 pdfout(" /FontDescriptor %d 0 R\n", ps
->objdes
);
237 pdfout(" /Encoding %d 0 R\n", enc_obj
);
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
;
250 for (i
= 0; i
< psfonts_n
; i
++)
251 if (!strcmp(name
, psfonts
[i
].name
))
253 if (i
== psfonts_n
) {
254 if (psfonts_n
== psfonts_sz
) {
256 psfonts
= mextend(psfonts
, psfonts_n
,
257 psfonts_sz
, sizeof(psfonts
[0]));
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
))
266 ps
->gmap
= calloc(ps
->gcnt
, sizeof(ps
->gmap
));
267 ps
->gpos
= calloc(ps
->gcnt
, sizeof(ps
->gpos
));
272 gidx
= font_glnum(fn
, g
);
273 if (!ps
->gmap
[gidx
]) {
274 if (ps
->lastgl
== 256) {
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)
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
++)
300 for (i
= 0; i
< psfonts_n
; i
++) {
301 free(psfonts
[i
].gmap
);
302 free(psfonts
[i
].gpos
);
307 static void o_flush(void)
310 sbuf_printf(pg
, ">] TJ\n");
314 static int o_loadfont(struct glyph
*g
)
316 int fn
= psfont_find(g
);
318 for (i
= 0; i
< o_fsn
; i
++)
321 if (o_fsn
== o_fssz
) {
323 o_fs
= mextend(o_fs
, o_fsn
, o_fssz
, sizeof(o_fs
[0]));
329 /* like pdfpos() but assume that uh and uv are multiplied by 100 */
330 static char *pdfpos00(int uh
, int uv
)
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);
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
)
351 int h
= (long) uh
* 1000 * 72 / sz
/ dev_res
;
352 sprintf(buf
, "%s%d", h
< 0 ? "-" : "", abs(h
));
356 /* convert troff color to pdf color; returns a static buffer */
357 static char *pdfcolor(int m
)
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);
368 static void o_queue(struct glyph
*g
)
372 sbuf_printf(pg
, "1 0 0 1 %s Tm\n", pdfpos(o_h
, o_v
));
377 sbuf_printf(pg
, "[<");
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)
389 sbuf_printf(pg
, "%s rg\n", pdfcolor(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
]);
396 sbuf_printf(pg
, "/%s.%d %d Tf\n", psfonts
[fn
].name
, ix
, o_s
);
406 g
= dev_glyph(c
, o_f
);
407 fn
= g
? g
->font
: dev_font(o_f
);
409 outrel(*c
== ' ' && fn
? font_swid(fn
, o_s
) : 1, 0);
412 o_pf
= o_loadfont(g
);
427 void outrel(int h
, int v
)
450 void outrotate(int deg
)
454 void outeps(char *eps
)
458 void outlink(char *spec
)
485 static int draw_path
; /* number of path segments */
486 static int draw_point
; /* point was set for postscript newpath */
494 sbuf_printf(pg
, "%s m\n", pdfpos(o_h
, o_v
));
497 void drawend(int close
, int fill
)
502 if (!fill
) /* stroking color */
503 sbuf_printf(pg
, "%s RG\n", pdfcolor(o_m
));
505 sbuf_printf(pg
, "f\n");
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
)
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
)
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;
533 long y1
= y0
+ cv
* b
/ 1000 / 2;
534 long x2
= x0
+ ch
* b
/ 1000 / 2;
537 x1
= x3
- ch
* b
/ 1000 / 2;
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);
558 /* draw an ellipse */
559 void drawe(int h
, int v
)
569 void drawa(int h1
, int v1
, int h2
, int v2
)
571 drawl(h1
+ h2
, v1
+ v2
);
575 void draws(int h1
, int v1
, int h2
, int v2
)
578 sbuf_printf(pg
, "%s l\n", pdfpos(o_h
, o_v
));
581 void ps_header(char *title
, int pagewidth
, int pageheight
, int linewidth
)
585 pdf_root
= obj_map();
586 pdf_pages
= obj_map();
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
)
598 /* pdf pages object */
601 pdfout(" /Type /Pages\n");
602 pdfout(" /MediaBox [ 0 0 %d %d ]\n", pdf_width
, pdf_height
);
603 pdfout(" /Count %d\n", page_n
);
605 for (i
= 0; i
< page_n
; i
++)
606 pdfout(" %d 0 R", page_id
[i
]);
610 /* pdf root object */
613 pdfout(" /Type /Catalog\n");
614 pdfout(" /Pages %d 0 R\n", pdf_pages
);
620 info_id
= obj_beg(0);
623 pdfout(" /Title (%s)\n", pdf_title
);
624 pdfout(" /Creator (Neatroff)\n");
625 pdfout(" /Producer (Neatpost)\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
]);
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
);
642 pdfout("startxref\n");
643 pdfout("%d\n", xref_off
);
649 void ps_pagebeg(int n
)
652 sbuf_printf(pg
, "BT\n");
655 void ps_pageend(int n
)
660 sbuf_printf(pg
, "ET\n");
662 cont_id
= obj_beg(0);
664 pdfout(" /Length %d\n", sbuf_len(pg
));
667 pdfout("%s", sbuf_buf(pg
));
668 pdfout("endstream\n");
670 /* the page object */
671 if (page_n
== page_sz
) {
673 page_id
= mextend(page_id
, page_n
, page_sz
, sizeof(page_id
[0]));
675 page_id
[page_n
++] = obj_beg(0);
677 pdfout(" /Type /Page\n");
678 pdfout(" /Parent %d 0 R\n", pdf_pages
);
679 pdfout(" /Resources <<\n");
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
]);
689 pdfout(" /Contents %d 0 R\n", cont_id
);