#include <assert.h>
#include "halibut.h"
#include "paper.h"
+#include "deflate.h"
-#define TREE_BRANCH 2 /* max branching factor in page tree */
+#define TREE_BRANCH 8 /* max branching factor in page tree */
paragraph *pdf_config_filename(char *filename)
{
static object *new_object(objlist *list);
static void objtext(object *o, char const *text);
static void objstream(object *o, char const *text);
+static void objstream_len(object *o, char const *text, size_t len);
static void pdf_string(void (*add)(object *, char const *),
object *, char const *);
static void pdf_string_len(void (*add)(object *, char const *),
object *, char const *, int);
static void objref(object *o, object *dest);
-static char *pdf_outline_convert(wchar_t *s, int *len);
+static void objdest(object *o, page_data *p);
static int is_std_font(char const *name);
for (i = 0; i < 256; i++) {
char buf[20];
- if (!fe->vector[i])
+ if (fe->vector[i] == NOGLYPH)
continue;
if (i != prev + 1) {
sprintf(buf, "\n%d", i);
objtext(font, buf);
}
objtext(font, i % 8 ? "/" : "\n/");
- objtext(font, fe->vector[i]);
+ objtext(font, glyph_extern(fe->vector[i]));
prev = i;
}
font_info const *fi = fe->font->info;
int flags;
for (i = 0; i < 256; i++)
- if (fe->indices[i] >= 0) {
+ if (fe->vector[i] != NOGLYPH) {
if (firstchar < 0) firstchar = i;
lastchar = i;
}
objtext(widths, "[\n");
for (i = firstchar; i <= lastchar; i++) {
double width;
- if (fe->indices[i] < 0)
+ if (fe->vector[i] == NOGLYPH)
width = 0.0;
else
- width = fi->widths[fe->indices[i]];
+ width = find_width(fe->font, fe->vector[i]);
sprintf(buf, "%g\n", 1000.0 * width / FUNITS_PER_PT);
objtext(widths, buf);
}
objtext(fontdesc, buf);
sprintf(buf, "/StemV %g\n", fi->stemv);
objtext(fontdesc, buf);
- if (fi->fp) {
+ if (fi->fontfile && fi->filetype == TYPE1) {
object *fontfile = new_object(&olist);
- char buf[513];
size_t len;
- rewind(fi->fp);
- do {
- len = fread(buf, 1, sizeof(buf)-1, fi->fp);
- buf[len] = 0;
- objstream(fontfile, buf);
- } while (len == sizeof(buf)-1);
+ char *ffbuf;
+
+ pf_part1((font_info *)fi, &ffbuf, &len);
+ objstream_len(fontfile, ffbuf, len);
+ sfree(ffbuf);
+ sprintf(buf, "<<\n/Length1 %lu\n", (unsigned long)len);
+ objtext(fontfile, buf);
+ pf_part2((font_info *)fi, &ffbuf, &len);
+ objstream_len(fontfile, ffbuf, len);
+ sfree(ffbuf);
+ sprintf(buf, "/Length2 %lu\n", (unsigned long)len);
+ objtext(fontfile, buf);
+ objtext(fontfile, "/Length3 0\n");
objtext(fontdesc, "/FontFile ");
objref(fontdesc, fontfile);
}
objtext(opage, "]/Border[0 0 0]\n");
if (xr->dest.type == PAGE) {
- objtext(opage, "/Dest[");
- objref(opage, (object *)xr->dest.page->spare);
- objtext(opage, "/XYZ null null null]");
+ objtext(opage, "/Dest");
+ objdest(opage, xr->dest.page);
} else {
objtext(opage, "/A<</S/URI/URI");
pdf_string(objtext, opage, xr->dest.url);
for (o = olist.head; o; o = o->next) {
rdstringc rs = {0, 0, NULL};
char text[80];
+ deflate_compress_ctx *zcontext;
+ void *zbuf;
+ int zlen;
sprintf(text, "%d 0 obj\n", o->number);
rdaddsc(&rs, text);
- if (!o->main.text && o->stream.text) {
- sprintf(text, "<<\n/Length %d\n>>\n", o->stream.pos);
+ if (o->stream.text) {
+ if (!o->main.text)
+ rdaddsc(&o->main, "<<\n");
+#ifdef PDF_NOCOMPRESS
+ zlen = o->stream.pos;
+ zbuf = snewn(zlen, char);
+ memcpy(zbuf, o->stream.text, zlen);
+ sprintf(text, "/Length %d\n>>\n", zlen);
+#else
+ zcontext = deflate_compress_new(DEFLATE_TYPE_ZLIB);
+ deflate_compress_data(zcontext, o->stream.text, o->stream.pos,
+ DEFLATE_END_OF_DATA, &zbuf, &zlen);
+ deflate_compress_free(zcontext);
+ sprintf(text, "/Filter/FlateDecode\n/Length %d\n>>\n", zlen);
+#endif
rdaddsc(&o->main, text);
}
rdaddc(&rs, '\n');
if (o->stream.text) {
- /*
- * FIXME: If we ever start compressing stream data then
- * it will have zero bytes in it, so we'll have to be
- * more careful than this.
- */
rdaddsc(&rs, "stream\n");
- rdaddsc(&rs, o->stream.text);
+ rdaddsn(&rs, zbuf, zlen);
rdaddsc(&rs, "\nendstream\n");
sfree(o->stream.text);
+ sfree(zbuf);
}
rdaddsc(&rs, "endobj\n");
/*
* Header. I'm going to put the version IDs in the header as
- * well, simply in PDF comments.
+ * well, simply in PDF comments. The PDF Reference also suggests
+ * that binary PDF files contain four top-bit-set characters in
+ * the second line.
*/
- fileoff = fprintf(fp, "%%PDF-1.3\n");
+ fileoff = fprintf(fp, "%%PDF-1.3\n%% L\xc3\xba\xc3\xb0""a\n");
for (p = sourceform; p; p = p->next)
if (p->type == para_VersionID)
fileoff += pdf_versionid(fp, p->words);
rdaddsc(&o->main, text);
}
+static void objstream_len(object *o, char const *text, size_t len)
+{
+ rdaddsn(&o->stream, text, len);
+}
+
static void objstream(object *o, char const *text)
{
rdaddsc(&o->stream, text);
rdaddsc(&o->main, buf);
}
+static void objdest(object *o, page_data *p) {
+ objtext(o, "[");
+ objref(o, (object *)p->spare);
+ objtext(o, "/XYZ null null null]");
+}
+
static char const * const stdfonts[] = {
"Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",
"Helvetica", "Helvetica-Bold", "Helvetica-Oblique","Helvetica-BoldOblique",
* encodes in either PDFDocEncoding (a custom superset of
* ISO-8859-1) or UTF-16BE.
*/
-static char *pdf_outline_convert(wchar_t *s, int *len) {
+char *pdf_outline_convert(wchar_t *s, int *len) {
char *ret;
ret = utoa_careful_dup(s, CS_PDF);
sfree(title);
objtext(curr, "\n/Parent ");
objref(curr, parent);
- objtext(curr, "\n/Dest [");
- objref(curr, (object *)items->pdata->first->page->spare);
- objtext(curr, " /XYZ null null null]\n");
+ objtext(curr, "\n/Dest");
+ objdest(curr, items->pdata->first->page);
+ objtext(curr, "\n");
if (prev) {
objtext(curr, "/Prev ");
objref(curr, prev);