shithub: neatpost

Download patch

ref: e3f0cb74b1e84495b6e8f6e76c601074755dab14
parent: 800f77dcdb74497de6a64d48069b8c701ab98dff
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Apr 15 15:26:15 EDT 2018

pdf: scaling PDF images

--- a/pdf.c
+++ b/pdf.c
@@ -55,13 +55,6 @@
 }
 
 /* print pdf output */
-static void pdfouts(char *s)
-{
-	fputs(s, stdout);
-	pdf_pos += strlen(s);
-}
-
-/* print pdf output */
 static void pdfmem(char *s, int len)
 {
 	fwrite(s, len, 1, stdout);
@@ -260,7 +253,7 @@
 				pdfout("  /Length3 %d\n", l3);
 			pdfout(">>\n");
 			pdfout("stream\n");
-			pdfouts(sbuf_buf(sb));
+			pdfmem(sbuf_buf(sb), sbuf_len(sb));
 			pdfout("endstream\n");
 			obj_end();
 		}
@@ -622,13 +615,26 @@
 	sbuf_printf(sb, "  >>\n");
 }
 
-static int pdfext(char *pdf, int len)
+static int pdfbbox(char *pdf, int len, int pos, int dim[4])
 {
+	int val;
+	int i;
+	for (i = 0; i < 4; i++) {
+		if ((val = pdf_lval(pdf, len, pos, i)) < 0)
+			return -1;
+		dim[i] = atoi(pdf + val);
+	}
+	return 0;
+}
+
+static int pdfext(char *pdf, int len, int hwid, int vwid)
+{
 	char *cont_fields[] = {"/Filter", "/DecodeParms"};
 	int trailer, root, cont, pages, page1, res;
-	int kids_val, page1_val, val;
+	int kids_val, page1_val, val, bbox;
 	int xobj_id, length;
-	int bbox;
+	int dim[4];
+	int hzoom = 100, vzoom = 100;
 	struct sbuf *sb;
 	int i;
 	if ((trailer = pdf_trailer(pdf, len)) < 0)
@@ -652,6 +658,16 @@
 	bbox = pdf_dval_val(pdf, len, page1, "/MediaBox");
 	if (bbox < 0)
 		bbox = pdf_dval_val(pdf, len, pages, "/MediaBox");
+	if (bbox >= 0 && !pdfbbox(pdf, len, bbox, dim)) {
+		if (hwid > 0)
+			hzoom = hwid / (dim[2] - dim[0]);
+		if (vwid > 0)
+			vzoom = vwid / (dim[3] - dim[1]);
+		if (vwid <= 0)
+			vzoom = hzoom;
+		if (hwid <= 0)
+			hzoom = vzoom;
+	}
 	sb = sbuf_make();
 	sbuf_printf(sb, "<<\n");
 	sbuf_printf(sb, "  /Type /XObject\n");
@@ -659,7 +675,9 @@
 	sbuf_printf(sb, "  /FormType 1\n");
 	if (bbox >= 0)
 		sbuf_printf(sb, "  /BBox %s\n", pdf_copy(pdf, len, bbox));
-	sbuf_printf(sb, "  /Matrix [1 0 0 1 %s]\n", pdfpos(o_h, o_v));
+	sbuf_printf(sb, "  /Matrix [%d.%02d 0 0 %d.%02d %s]\n",
+		hzoom / 100, hzoom % 100, vzoom / 100, vzoom % 100,
+		pdfpos(o_h, o_v));
 	if (res >= 0)
 		pdf_rescopy(pdf, len, res, sb);
 	sbuf_printf(sb, "  /Length %d\n", length);
@@ -686,11 +704,18 @@
 	char pdf[1 << 12];
 	char buf[1 << 12];
 	struct sbuf *sb;
+	int hwid, vwid, nspec;
 	int xobj_id;
 	int fd, nr;
 	spec = strcut(pdf, spec);
 	if (!pdf[0])
 		return;
+	/* requested image dimensions */
+	nspec = sscanf(spec, "%d %d", &hwid, &vwid);
+	if (nspec < 1)
+		hwid = 0;
+	if (nspec < 2)
+		vwid = 0;
 	/* reading the pdf file */
 	sb = sbuf_make();
 	fd = open(pdf, O_RDONLY);
@@ -698,7 +723,7 @@
 		sbuf_mem(sb, buf, nr);
 	close(fd);
 	/* the XObject */
-	xobj_id = pdfext(sbuf_buf(sb), sbuf_len(sb));
+	xobj_id = pdfext(sbuf_buf(sb), sbuf_len(sb), hwid, vwid);
 	sbuf_free(sb);
 	o_flush();
 	out_fontup();