shithub: neatpost

Download patch

ref: f231cb477ed4d7fc87702c5f4ee6d8a633a961be
parent: 1e7dc3a3cba0ff5539af424ffcd79badcb80ab2c
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed May 2 15:26:51 EDT 2018

pdf: external links

--- a/pdf.c
+++ b/pdf.c
@@ -1,4 +1,5 @@
 /* PDF post-processor functions */
+#include <ctype.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -26,8 +27,10 @@
 static int p_f, p_s, p_m;	/* output font */
 static int o_queued;		/* queued character type */
 static char o_iset[1024];	/* fonts accesssed in this page */
-static int *xobj;		/* page xobject object ids  */
-static int xobj_sz, xobj_n;	/* number of xobjects */
+static int xobj[128];		/* page xobject object ids */
+static int xobj_n;		/* number of xobjects in this page */
+static int ann[128];		/* page annotations */
+static int ann_n;		/* number of annotations in this page */
 
 /* loaded PDF fonts */
 struct pfont {
@@ -637,6 +640,8 @@
 	int hzoom = 100, vzoom = 100;
 	struct sbuf *sb;
 	int i;
+	if (xobj_n == LEN(xobj))
+		return -1;
 	if ((trailer = pdf_trailer(pdf, len)) < 0)
 		return -1;
 	if ((root = pdf_dval_obj(pdf, len, trailer, "/Root")) < 0)
@@ -691,10 +696,6 @@
 	pdfmem(sbuf_buf(sb), sbuf_len(sb));
 	obj_end();
 	sbuf_free(sb);
-	if (xobj_n == xobj_sz) {
-		xobj_sz += 8;
-		xobj = mextend(xobj, xobj_n, xobj_sz, sizeof(xobj[0]));
-	}
 	xobj[xobj_n++] = xobj_id;
 	return xobj_n - 1;
 }
@@ -727,7 +728,8 @@
 	sbuf_free(sb);
 	o_flush();
 	out_fontup();
-	sbuf_printf(pg, "ET /FO%d Do BT\n", xobj_id);
+	if (xobj_id >= 0)
+		sbuf_printf(pg, "ET /FO%d Do BT\n", xobj_id);
 	p_h = -1;
 	p_v = -1;
 }
@@ -734,6 +736,25 @@
 
 void outlink(char *spec)
 {
+	char lnk[1 << 12];
+	int hwid, vwid;
+	int nspec;
+	if (ann_n == LEN(ann))
+		return;
+	spec = strcut(lnk, spec);
+	if (!lnk[0] || (nspec = sscanf(spec, "%d %d", &hwid, &vwid)) != 2)
+		return;
+	o_flush();
+	ann[ann_n++] = obj_beg(0);
+	pdfout("<<\n");
+	pdfout("  /Type /Annot\n");
+	pdfout("  /Subtype /Link\n");
+	pdfout("  /Rect [%s", pdfpos(o_h, o_v));
+	pdfout(" %s]\n", pdfpos(o_h + hwid, o_v + vwid));
+	/* only external links are supported */
+	pdfout("  /A << /S /URI /URI (%s) >>\n", lnk);
+	pdfout(">>\n");
+	obj_end();
 }
 
 void outpage(void)
@@ -973,12 +994,16 @@
 	}
 	pdfout("  >>\n");
 	pdfout("  /Contents %d 0 R\n", cont_id);
+	if (ann_n) {
+		pdfout("  /Annots [");
+		for (i = 0; i < ann_n; i++)
+			pdfout(" %d 0 R", ann[i]);
+		pdfout(" ]\n");
+	}
 	pdfout(">>\n");
 	obj_end();
 	sbuf_free(pg);
 	memset(o_iset, 0, pfonts_n * sizeof(o_iset[0]));
-	free(xobj);
-	xobj = NULL;
 	xobj_n = 0;
-	xobj_sz = 0;
+	ann_n = 0;
 }