shithub: neatpost

Download patch

ref: e02a200628b9f7e0b2a98d6d051e4a7610ecc739
parent: aac54a6c5e68705d99d817575b95a144f4749649
author: Ali Gholami Rudi <ali@rudi.ir>
date: Mon Apr 2 08:03:41 EDT 2018

pdf: embedding Type 1 fonts

--- a/pdf.c
+++ b/pdf.c
@@ -1,7 +1,9 @@
+#include <fcntl.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include "post.h"
 
 static char *pdf_title;		/* document title */
@@ -84,35 +86,90 @@
 {
 }
 
+/* the length of the clear-text, encrypted, and fixed-content portions */
+static int type1lengths(char *t1, int l, int *l1, int *l2, int *l3)
+{
+	int i;
+	char *cleartext = t1;
+	char *encrypted = NULL;
+	char *fixedcont = NULL;
+	for (i = 0; i < l - 5 && !encrypted; i++)
+		if (t1[i] == 'e' && !memcmp("eexec", t1 + i, 5))
+			encrypted = t1 + i;
+	if (!encrypted)
+		return 1;
+	for (; i < l - 512 && !fixedcont; i++)
+		if (t1[i] == '0' && !memcmp("00000", t1 + i, 5))
+			fixedcont = t1 + i;
+	*l1 = encrypted - cleartext;
+	*l2 = fixedcont ? fixedcont - cleartext : 0;
+	return 0;
+}
+
+/* return font type: 't': TrueType, '1': Type 1, 'o': OpenType */
+static int fonttype(char *path)
+{
+	char *ext = strrchr(path, '.');
+	if (ext && !strcmp(".ttf", ext))
+		return 't';
+	if (ext && !strcmp(".otf", ext))
+		return 'o';
+	return '1';
+}
+
 /* include font descriptor; returns object id */
 static int psfont_writedesc(struct psfont *ps)
 {
-	int c, i;
 	int str_obj = -1;
 	int des_obj;
-	char *ext = strrchr(ps->path, '.');
-	if (ext && !strcmp(".ttf", ext)) {
-		FILE *fp = fopen(ps->path, "r");
+	char buf[1 << 10];
+	int i;
+	if (fonttype(ps->path) == '1' || fonttype(ps->path) == 't') {
+		int fd = open(ps->path, O_RDONLY);
+		struct sbuf *ffsb = sbuf_make();
 		struct sbuf *sb = sbuf_make();
-		c = fgetc(fp);
-		for (i = 0; c != EOF; i++) {
-			sbuf_printf(sb, "%02x", c);
-			c = fgetc(fp);
-			if (i % 40 == 39 && c != EOF)
+		int l1 = 0, l2 = 0, l3 = 0;
+		int nr;
+		/* reading the font file */
+		while ((nr = read(fd, buf, sizeof(buf))) > 0)
+			sbuf_mem(ffsb, buf, nr);
+		close(fd);
+		l1 = sbuf_len(ffsb);
+		/* initialize Type 1 lengths */
+		if (fonttype(ps->path) == '1') {
+			if (type1lengths(sbuf_buf(ffsb), sbuf_len(ffsb),
+					&l1, &l2, &l3))
+				l1 = 0;
+			/* remove the fixed-content portion of the font */
+			if (l3)
+				sbuf_cut(ffsb, l1 + l2);
+			l1 -= l3;
+		}
+		/* encoding file contents */
+		for (i = 0; i < sbuf_len(ffsb); i++) {
+			sbuf_printf(sb, "%02x", (unsigned char) sbuf_buf(ffsb)[i]);
+			if (i % 40 == 39 && i + 1 < sbuf_len(ffsb))
 				sbuf_chr(sb, '\n');
 		}
 		sbuf_str(sb, ">\n");
-		fclose(fp);
-		str_obj = obj_beg(0);
-		pdfout("<<\n");
-		pdfout("  /Filter /ASCIIHexDecode\n");
-		pdfout("  /Length %d\n", sbuf_len(sb));
-		pdfout("  /Length1 %d\n", i);
-		pdfout(">>\n");
-		pdfout("stream\n");
-		pdfout("%s", sbuf_buf(sb));
-		pdfout("endstream\n");
-		obj_end();
+		/* write font data if it has nonzero length */
+		if (l1) {
+			str_obj = obj_beg(0);
+			pdfout("<<\n");
+			pdfout("  /Filter /ASCIIHexDecode\n");
+			pdfout("  /Length %d\n", sbuf_len(sb));
+			pdfout("  /Length1 %d\n", l1);
+			if (fonttype(ps->path) == '1')
+				pdfout("  /Length2 %d\n", l2);
+			if (fonttype(ps->path) == '1')
+				pdfout("  /Length3 %d\n", l3);
+			pdfout(">>\n");
+			pdfout("stream\n");
+			pdfout("%s", sbuf_buf(sb));
+			pdfout("endstream\n");
+			obj_end();
+		}
+		sbuf_free(ffsb);
 		sbuf_free(sb);
 	}
 	/* the font descriptor */
@@ -129,7 +186,8 @@
 	pdfout("  /Ascent 100\n");
 	pdfout("  /Descent 100\n");
 	if (str_obj >= 0)
-		pdfout("  /FontFile2 %d 0 R\n", str_obj);
+		pdfout("  /FontFile%s %d 0 R\n",
+			fonttype(ps->path) == 't' ? "2" : "", str_obj);
 	pdfout(">>\n");
 	obj_end();
 	return des_obj;
@@ -140,7 +198,6 @@
 {
 	int i;
 	int enc_obj;
-	char *ext = strrchr(ps->path, '.');
 	struct font *fn = dev_fontopen(ps->desc);
 	int map[256];
 	int gcnt = ix < ps->lastfn ? 256 : ps->lastgl;
@@ -164,8 +221,10 @@
 	obj_beg(ps->obj[ix]);
 	pdfout("<<\n");
 	pdfout("  /Type /Font\n");
-	pdfout("  /Subtype /%s\n",
-		ext && !strcmp(".ttf", ext) ? "TrueType" : "Type1");
+	if (fonttype(ps->path) == 't')
+		pdfout("  /Subtype /TrueType\n");
+	else
+		pdfout("  /Subtype /Type1\n");
 	pdfout("  /BaseFont /%s\n", ps->name);
 	pdfout("  /FirstChar 0\n");
 	pdfout("  /LastChar %d\n", gcnt - 1);
@@ -462,6 +521,7 @@
 	sbuf_printf(pg, "%s l\n", pdfpos(o_h, o_v));
 }
 
+/* draw circle/ellipse quadrant */
 static void drawquad(int ch, int cv)
 {
 	long b = 551915;
@@ -485,6 +545,7 @@
 	outrel(ch / 2, cv / 2);
 }
 
+/* draw a circle */
 void drawc(int c)
 {
 	drawquad(+c, +c);
@@ -494,6 +555,7 @@
 	outrel(c, 0);
 }
 
+/* draw an ellipse */
 void drawe(int h, int v)
 {
 	drawquad(+h, +v);
@@ -503,11 +565,13 @@
 	outrel(h, 0);
 }
 
+/* draw an arc */
 void drawa(int h1, int v1, int h2, int v2)
 {
-	outrel(h1 + h2, v1 + v2);
+	drawl(h1 + h2, v1 + v2);
 }
 
+/* draw an spline */
 void draws(int h1, int v1, int h2, int v2)
 {
 	outrel(h1, v1);
--- a/post.h
+++ b/post.h
@@ -117,3 +117,5 @@
 void sbuf_str(struct sbuf *sbuf, char *s);
 void sbuf_printf(struct sbuf *sbuf, char *s, ...);
 void sbuf_chr(struct sbuf *sbuf, int c);
+void sbuf_mem(struct sbuf *sbuf, char *s, int len);
+void sbuf_cut(struct sbuf *sb, int len);