summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-03-25 16:42:46 +0000
committerRobin Watts <robin.watts@artifex.com>2013-06-21 17:39:41 +0100
commit0afe72e5fc386aa0ebceec9618f2b681f9bfdc3d (patch)
tree1e294cef2b4b01e1311b90286c7675a87ca3a9f4 /source
parent82131246a46ed4547c978b0081d4e0db9d6f3942 (diff)
downloadmupdf-0afe72e5fc386aa0ebceec9618f2b681f9bfdc3d.tar.xz
Initial PDF editing/page creation commit
Diffstat (limited to 'source')
-rw-r--r--source/pdf/pdf-device.c67
-rw-r--r--source/pdf/pdf-page.c129
-rw-r--r--source/pdf/pdf-write.c98
-rw-r--r--source/pdf/pdf-xref.c45
-rw-r--r--source/tools/mudraw.c62
5 files changed, 376 insertions, 25 deletions
diff --git a/source/pdf/pdf-device.c b/source/pdf/pdf-device.c
index 602a778f..29d2556d 100644
--- a/source/pdf/pdf-device.c
+++ b/source/pdf/pdf-device.c
@@ -118,6 +118,9 @@ send_image(pdf_device *pdev, fz_image *image, int mask, int smask)
int bpc = 8;
fz_colorspace *colorspace = image->colorspace;
+ /* If we can maintain compression, do so */
+ cbuffer = image->buffer;
+
fz_var(pixmap);
fz_var(buffer);
fz_var(imobj);
@@ -125,7 +128,12 @@ send_image(pdf_device *pdev, fz_image *image, int mask, int smask)
fz_try(ctx)
{
- if (cbuffer == NULL)
+ if (cbuffer != NULL && cbuffer->params.type != FZ_IMAGE_PNG && cbuffer->params.type != FZ_IMAGE_TIFF)
+ {
+ buffer = fz_keep_buffer(ctx, cbuffer->buffer);
+ cp = &cbuffer->params;
+ }
+ else
{
unsigned int size;
int n;
@@ -156,11 +164,6 @@ send_image(pdf_device *pdev, fz_image *image, int mask, int smask)
}
}
}
- else
- {
- buffer = fz_keep_buffer(ctx, cbuffer->buffer);
- cp = &cbuffer->params;
- }
fz_md5_init(&state);
fz_md5_update(&state, buffer->data, buffer->len);
@@ -202,9 +205,11 @@ send_image(pdf_device *pdev, fz_image *image, int mask, int smask)
pdf_dict_puts_drop(imobj, "ColorSpace", pdf_new_name(ctx, "DeviceRGB"));
else if (colorspace->n == 4)
pdf_dict_puts_drop(imobj, "ColorSpace", pdf_new_name(ctx, "DeviceCMYK"));
+ if (!mask)
+ pdf_dict_puts_drop(imobj, "BitsPerComponent", pdf_new_int(ctx, image->bpc));
switch (cp ? cp->type : FZ_IMAGE_UNKNOWN)
{
- case FZ_IMAGE_UNKNOWN:
+ case FZ_IMAGE_UNKNOWN: /* Unknown also means raw */
default:
break;
case FZ_IMAGE_JPEG:
@@ -251,6 +256,7 @@ send_image(pdf_device *pdev, fz_image *image, int mask, int smask)
if (cp->u.flate.bpc)
bpc = cp->u.flate.bpc;
pdf_dict_puts(imobj, "Filter", pdf_new_name(ctx, "FlateDecode"));
+ pdf_dict_puts_drop(imobj, "BitsPerComponent", pdf_new_int(ctx, image->bpc));
break;
case FZ_IMAGE_LZW:
if (cp->u.lzw.columns)
@@ -279,8 +285,6 @@ send_image(pdf_device *pdev, fz_image *image, int mask, int smask)
int smasknum = send_image(pdev, image->mask, 0, 1);
pdf_dict_puts(imobj, "SMask", pdev->images[smasknum].ref);
}
- if (bpc)
- pdf_dict_puts_drop(imobj, "BitsPerComponent", pdf_new_int(ctx, bpc));
imref = pdf_new_ref(pdev->xref, imobj);
pdf_update_stream(pdev->xref, pdf_to_num(imref), buffer);
@@ -371,23 +375,23 @@ pdf_dev_path(pdf_device *pdev, fz_path *path)
case FZ_MOVETO:
x = path->items[i++].v;
y = path->items[i++].v;
- fz_buffer_printf(ctx, gs->buf, "%g %g m\n", x, y);
+ fz_buffer_printf(ctx, gs->buf, "%f %f m\n", x, y);
break;
case FZ_LINETO:
x = path->items[i++].v;
y = path->items[i++].v;
- fz_buffer_printf(ctx, gs->buf, "%g %g l\n", x, y);
+ fz_buffer_printf(ctx, gs->buf, "%f %f l\n", x, y);
break;
case FZ_CURVETO:
x = path->items[i++].v;
y = path->items[i++].v;
- fz_buffer_printf(ctx, gs->buf, "%g %g ", x, y);
+ fz_buffer_printf(ctx, gs->buf, "%f %f ", x, y);
x = path->items[i++].v;
y = path->items[i++].v;
- fz_buffer_printf(ctx, gs->buf, "%g %g ", x, y);
+ fz_buffer_printf(ctx, gs->buf, "%f %f ", x, y);
x = path->items[i++].v;
y = path->items[i++].v;
- fz_buffer_printf(ctx, gs->buf, "%g %g c\n", x, y);
+ fz_buffer_printf(ctx, gs->buf, "%f %f c\n", x, y);
break;
case FZ_CLOSE_PATH:
fz_buffer_printf(ctx, gs->buf, "h\n");
@@ -589,7 +593,7 @@ pdf_dev_font(pdf_device *pdev, fz_font *font, float size)
}
pdev->num_fonts++;
}
- fz_buffer_printf(ctx, gs->buf, "/F%d %g Tf\n", i, size);
+ fz_buffer_printf(ctx, gs->buf, "/F%d %f Tf\n", i, size);
}
static void
@@ -677,7 +681,7 @@ pdf_dev_text(pdf_device *pdev, fz_text *text)
fz_transform_point(&delta, &inverse);
if (delta.x != 0 || delta.y != 0)
{
- fz_buffer_printf(pdev->ctx, gs->buf, "%g %g Td ", delta.x, delta.y);
+ fz_buffer_printf(pdev->ctx, gs->buf, "%f %f Td ", delta.x, delta.y);
trm.e = it->x;
trm.f = it->y;
}
@@ -901,6 +905,9 @@ pdf_dev_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
pdf_dev_begin_text(pdev, &text->trm, 0);
pdf_dev_font(pdev, text->font, 1);
+ pdf_dev_ctm(pdev, ctm);
+ pdf_dev_alpha(pdev, alpha, 0);
+ pdf_dev_color(pdev, colorspace, color, 0);
pdf_dev_text(pdev, text);
}
@@ -912,6 +919,9 @@ pdf_dev_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, cons
pdf_dev_begin_text(pdev, &text->trm, 1);
pdf_dev_font(pdev, text->font, 1);
+ pdf_dev_ctm(pdev, ctm);
+ pdf_dev_alpha(pdev, alpha, 1);
+ pdf_dev_color(pdev, colorspace, color, 1);
pdf_dev_text(pdev, text);
}
@@ -921,6 +931,7 @@ pdf_dev_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accum
pdf_device *pdev = dev->user;
pdf_dev_begin_text(pdev, &text->trm, 0);
+ pdf_dev_ctm(pdev, ctm);
pdf_dev_font(pdev, text->font, 7);
pdf_dev_text(pdev, text);
}
@@ -932,6 +943,7 @@ pdf_dev_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke,
pdf_dev_begin_text(pdev, &text->trm, 0);
pdf_dev_font(pdev, text->font, 5);
+ pdf_dev_ctm(pdev, ctm);
pdf_dev_text(pdev, text);
}
@@ -941,6 +953,7 @@ pdf_dev_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm)
pdf_device *pdev = dev->user;
pdf_dev_begin_text(pdev, &text->trm, 0);
+ pdf_dev_ctm(pdev, ctm);
pdf_dev_font(pdev, text->font, 3);
pdf_dev_text(pdev, text);
}
@@ -955,13 +968,12 @@ pdf_dev_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float
pdf_dev_end_text(pdev);
num = send_image(pdev, image, 0, 0);
- fz_buffer_printf(dev->ctx, gs->buf, "q\n");
pdf_dev_alpha(pdev, alpha, 0);
/* PDF images are upside down, so fiddle the ctm */
fz_pre_scale(&local_ctm, 1, -1);
fz_pre_translate(&local_ctm, 0, -1);
pdf_dev_ctm(pdev, &local_ctm);
- fz_buffer_printf(dev->ctx, gs->buf, "/Img%d Do Q\n", num);
+ fz_buffer_printf(dev->ctx, gs->buf, "/Img%d Do\n", num);
}
static void
@@ -1169,8 +1181,6 @@ pdf_dev_free_user(fz_device *dev)
pdf_dict_puts_drop(pdev->contents, "Length", pdf_new_int(ctx, gs->buf->len));
- pdf_update_stream(pdev->xref, pdf_to_num(pdev->contents), gs->buf);
-
for (i = pdev->num_gstates-1; i >= 0; i--)
{
fz_drop_stroke_state(ctx, pdev->gstates[i].stroke_state);
@@ -1186,6 +1196,9 @@ pdf_dev_free_user(fz_device *dev)
pdf_drop_obj(pdev->images[i].ref);
}
+ pdf_update_stream(pdev->xref, pdf_to_num(pdev->contents), pdev->gstates[0].buf);
+ fz_drop_buffer(ctx, pdev->gstates[0].buf);
+
pdf_drop_obj(pdev->contents);
pdf_drop_obj(pdev->resources);
@@ -1261,3 +1274,17 @@ fz_device *pdf_new_pdf_device(pdf_document *doc, pdf_obj *contents, pdf_obj *res
return dev;
}
+
+fz_device *pdf_page_write(pdf_document *doc, pdf_page *page)
+{
+ pdf_obj *resources = pdf_dict_gets(page->me, "Resources");
+ fz_matrix ctm;
+ fz_pre_translate(fz_scale(&ctm, 1, -1), 0, page->mediabox.y0-page->mediabox.y1);
+ if (resources == NULL)
+ {
+ resources = pdf_new_dict(doc->ctx, 0);
+ pdf_dict_puts_drop(page->me, "Resources", resources);
+ }
+
+ return pdf_new_pdf_device(doc, page->contents, resources, &ctm);
+}
diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c
index 8a12b67b..715f773e 100644
--- a/source/pdf/pdf-page.c
+++ b/source/pdf/pdf-page.c
@@ -487,3 +487,132 @@ pdf_free_page(pdf_document *xref, pdf_page *page)
pdf_drop_obj(page->me);
fz_free(xref->ctx, page);
}
+
+void
+pdf_delete_page(pdf_document *xref, int page)
+{
+ pdf_delete_page_range(xref, page, page+1);
+}
+
+void
+pdf_delete_page_range(pdf_document *xref, int start, int end)
+{
+ int i;
+
+ if (start > end)
+ {
+ int tmp = start;
+ start = end;
+ end = tmp;
+ }
+
+ if (!xref || start >= xref->page_len || end < 0)
+ return;
+
+ for (i=start; i < end; i++)
+ pdf_drop_obj(xref->page_refs[i]);
+ if (xref->page_len > end)
+ {
+ memmove(&xref->page_refs[start], &xref->page_refs[end], sizeof(pdf_page *) * (xref->page_len - end + start));
+ memmove(&xref->page_refs[start], &xref->page_refs[end], sizeof(pdf_page *) * (xref->page_len - end + start));
+ }
+
+ xref->page_len -= end - start;
+ xref->needs_page_tree_rebuild = 1;
+}
+
+void
+pdf_insert_page(pdf_document *xref, pdf_page *page, int at)
+{
+ if (!xref || !page)
+ return;
+ if (at < 0)
+ at = 0;
+ if (at > xref->page_len)
+ at = xref->page_len;
+
+ if (xref->page_len + 1 >= xref->page_cap)
+ {
+ int newmax = xref->page_cap * 2;
+ if (newmax == 0)
+ newmax = 4;
+ xref->page_refs = fz_resize_array(xref->ctx, xref->page_refs, newmax, sizeof(pdf_page *));
+ xref->page_objs = fz_resize_array(xref->ctx, xref->page_objs, newmax, sizeof(pdf_page *));
+ xref->page_cap = newmax;
+ }
+ if (xref->page_len > at)
+ {
+ memmove(&xref->page_objs[at+1], &xref->page_objs[at], xref->page_len - at);
+ memmove(&xref->page_refs[at+1], &xref->page_refs[at], xref->page_len - at);
+ }
+
+ xref->page_len++;
+ xref->page_objs[at] = pdf_keep_obj(page->me);
+ xref->page_refs[at] = NULL;
+ xref->page_refs[at] = pdf_new_ref(xref, page->me);
+ xref->needs_page_tree_rebuild = 1;
+}
+
+pdf_page *
+pdf_create_page(pdf_document *xref, fz_rect mediabox, int res, int rotate)
+{
+ pdf_page *page = NULL;
+ pdf_obj *pageobj, *obj;
+ float userunit = 1;
+ fz_context *ctx = xref->ctx;
+ fz_matrix ctm, tmp;
+ fz_rect realbox;
+
+ page = fz_malloc_struct(ctx, pdf_page);
+ obj = NULL;
+ fz_var(obj);
+
+ fz_try(ctx)
+ {
+ page->resources = NULL;
+ page->contents = NULL;
+ page->transparency = 0;
+ page->links = NULL;
+ page->annots = NULL;
+ page->me = pageobj = pdf_new_dict(ctx, 4);
+
+ pdf_dict_puts_drop(pageobj, "Type", pdf_new_name(ctx, "Page"));
+
+ page->mediabox.x0 = fz_min(mediabox.x0, mediabox.x1) * userunit;
+ page->mediabox.y0 = fz_min(mediabox.y0, mediabox.y1) * userunit;
+ page->mediabox.x1 = fz_max(mediabox.x0, mediabox.x1) * userunit;
+ page->mediabox.y1 = fz_max(mediabox.y0, mediabox.y1) * userunit;
+ pdf_dict_puts_drop(pageobj, "MediaBox", pdf_new_rect(ctx, &page->mediabox));
+
+ /* Snap page->rotate to 0, 90, 180 or 270 */
+ if (page->rotate < 0)
+ page->rotate = 360 - ((-page->rotate) % 360);
+ if (page->rotate >= 360)
+ page->rotate = page->rotate % 360;
+ page->rotate = 90*((page->rotate + 45)/90);
+ if (page->rotate > 360)
+ page->rotate = 0;
+ pdf_dict_puts_drop(pageobj, "Rotate", pdf_new_int(ctx, page->rotate));
+
+ fz_pre_rotate(fz_scale(&ctm, 1, -1), -page->rotate);
+ realbox = page->mediabox;
+ fz_transform_rect(&realbox, &ctm);
+ fz_pre_scale(fz_translate(&tmp, -realbox.x0, -realbox.y0), userunit, userunit);
+ fz_concat(&ctm, &ctm, &tmp);
+ page->ctm = ctm;
+ obj = pdf_new_dict(ctx, 4);
+ page->contents = pdf_new_ref(xref, obj);
+ pdf_drop_obj(obj);
+ obj = NULL;
+ pdf_dict_puts(pageobj, "Contents", page->contents);
+ }
+ fz_catch(ctx)
+ {
+ pdf_drop_obj(page->me);
+ pdf_drop_obj(obj);
+ fz_free(ctx, page);
+ fz_rethrow_message(ctx, "Failed to create page");
+ }
+
+ return page;
+}
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c
index a423edef..e211372b 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -2223,13 +2223,17 @@ void pdf_write_document(pdf_document *xref, char *filename, fz_write_options *fz
int num;
pdf_write_options opts = { 0 };
fz_context *ctx;
- int xref_len = pdf_xref_len(xref);
+ int xref_len;
if (!xref)
return;
ctx = xref->ctx;
+ pdf_finish_edit(xref);
+
+ xref_len = pdf_xref_len(xref);
+
opts.out = fopen(filename, "wb");
if (!opts.out)
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open output file '%s'", filename);
@@ -2361,3 +2365,95 @@ void pdf_write_document(pdf_document *xref, char *filename, fz_write_options *fz
fz_rethrow(ctx);
}
}
+
+#define KIDS_PER_LEVEL 32
+
+static pdf_obj *
+make_page_tree_node(pdf_document *xref, int l, int r, pdf_obj *parent_ref, int root)
+{
+ fz_context *ctx = xref->ctx;
+ int count_per_kid, spaces;
+ pdf_obj *a = NULL;
+ pdf_obj *me = NULL;
+ pdf_obj *o = NULL;
+ pdf_obj *me_ref = NULL;
+
+ count_per_kid = 1;
+ while(count_per_kid * KIDS_PER_LEVEL < r-l)
+ count_per_kid *= KIDS_PER_LEVEL;
+
+ fz_var(o);
+ fz_var(me);
+ fz_var(a);
+ fz_var(me_ref);
+
+ fz_try(ctx)
+ {
+ me = pdf_new_dict(ctx, 2);
+ pdf_dict_puts_drop(me, "Type", pdf_new_name(ctx, "Pages"));
+ pdf_dict_puts_drop(me, "Count", pdf_new_int(ctx, r-l));
+ if (!root)
+ pdf_dict_puts(me, "Parent", parent_ref);
+ a = pdf_new_array(ctx, KIDS_PER_LEVEL);
+ me_ref = pdf_new_ref(xref, me);
+
+ for (spaces = KIDS_PER_LEVEL; l < r; spaces--)
+ {
+ if (spaces >= r-l)
+ {
+ o = pdf_keep_obj(xref->page_refs[l++]);
+ pdf_dict_puts(o, "Parent", me_ref);
+ }
+ else
+ {
+ int j = l+count_per_kid;
+ if (j > r)
+ j = r;
+ o = make_page_tree_node(xref, l, j, me_ref, 0);
+ l = j;
+ }
+ pdf_array_push(a, o);
+ pdf_drop_obj(o);
+ o = NULL;
+ }
+ pdf_dict_puts_drop(me, "Kids", a);
+ a = NULL;
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(me);
+ }
+ fz_catch(ctx)
+ {
+ pdf_drop_obj(a);
+ pdf_drop_obj(o);
+ pdf_drop_obj(me);
+ fz_rethrow_message(ctx, "Failed to synthesize new page tree");
+ }
+ return me_ref;
+}
+
+static void
+pdf_rebuild_page_tree(pdf_document *xref)
+{
+ pdf_obj *catalog;
+ pdf_obj *pages;
+
+ if (!xref || !xref->needs_page_tree_rebuild)
+ return;
+
+ catalog = pdf_dict_gets(pdf_trailer(xref), "Root");
+ pages = make_page_tree_node(xref, 0, xref->page_len, catalog, 1);
+ pdf_dict_puts_drop(catalog, "Pages", pages);
+
+ xref->needs_page_tree_rebuild = 0;
+}
+
+
+void pdf_finish_edit(pdf_document *xref)
+{
+ if (!xref)
+ return;
+
+ pdf_rebuild_page_tree(xref);
+}
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index 9224d515..d4b94e3f 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -1550,3 +1550,48 @@ pdf_document *pdf_specifics(fz_document *doc)
{
return (pdf_document *)(doc->close == (void *)pdf_close_document ? doc : NULL);
}
+
+pdf_document *pdf_create_document(fz_context *ctx)
+{
+ pdf_document *xref;
+ pdf_obj *o = NULL;
+ pdf_obj *root;
+ pdf_obj *pages;
+ pdf_obj *trailer = NULL;
+
+ fz_var(o);
+ fz_var(trailer);
+
+ xref = pdf_new_document(ctx, NULL);
+ fz_try(ctx)
+ {
+ xref->version = 14;
+ xref->file_size = 0;
+ xref->startxref = 0;
+ xref->num_xref_sections = 0;
+ pdf_get_populating_xref_entry(xref, 0);
+ xref->xref_altered = 1;
+ trailer = pdf_new_dict(ctx, 2);
+ pdf_dict_puts_drop(trailer, "Size", pdf_new_int(ctx, 3));
+ o = root = pdf_new_dict(ctx, 2);
+ pdf_dict_puts_drop(trailer, "Root", pdf_new_ref(xref, o));
+ pdf_drop_obj(o);
+ o = NULL;
+ pdf_dict_puts_drop(root, "Type", pdf_new_name(ctx, "Catalog"));
+ o = pages = pdf_new_dict(ctx, 3);
+ pdf_dict_puts_drop(root, "Pages", pdf_new_ref(xref, o));
+ pdf_drop_obj(o);
+ o = NULL;
+ pdf_dict_puts_drop(pages, "Type", pdf_new_name(ctx, "Pages"));
+ pdf_dict_puts_drop(pages, "Count", pdf_new_int(ctx, 0));
+ pdf_dict_puts_drop(pages, "Kids", pdf_new_array(ctx, 1));
+ pdf_set_populating_xref_trailer(xref, trailer);
+ }
+ fz_catch(ctx)
+ {
+ pdf_drop_obj(trailer);
+ pdf_drop_obj(o);
+ fz_rethrow_message(ctx, "Failed to create empty document");
+ }
+ return xref;
+}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 57bd4be2..1803447b 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -14,7 +14,7 @@
enum { TEXT_PLAIN = 1, TEXT_HTML = 2, TEXT_XML = 3 };
-enum { OUT_PNG, OUT_PPM, OUT_PNM, OUT_PAM, OUT_PGM, OUT_PBM, OUT_SVG, OUT_PWG, OUT_PCL };
+enum { OUT_PNG, OUT_PPM, OUT_PNM, OUT_PAM, OUT_PGM, OUT_PBM, OUT_SVG, OUT_PWG, OUT_PCL, OUT_PDF };
enum { CS_INVALID, CS_UNSET, CS_MONO, CS_GRAY, CS_GRAYALPHA, CS_RGB, CS_RGBA };
@@ -34,7 +34,8 @@ static const suffix_t suffix_table[] =
{ ".pbm", OUT_PBM },
{ ".svg", OUT_SVG },
{ ".pwg", OUT_PWG },
- { ".pcl", OUT_PCL }
+ { ".pcl", OUT_PCL },
+ { ".pdf", OUT_PDF },
};
typedef struct
@@ -75,7 +76,8 @@ static const format_cs_table_t format_cs_table[] =
{ OUT_PBM, CS_MONO, { CS_MONO } },
{ OUT_SVG, CS_RGB, { CS_RGB } },
{ OUT_PWG, CS_RGB, { CS_MONO, CS_GRAY, CS_RGB } },
- { OUT_PCL, CS_MONO, { CS_MONO } }
+ { OUT_PCL, CS_MONO, { CS_MONO } },
+ { OUT_PDF, CS_RGB, { CS_RGB } }
};
/*
@@ -137,6 +139,7 @@ static int showxml = 0;
static int showtext = 0;
static int showtime = 0;
static int showmd5 = 0;
+static pdf_document *pdfout = NULL;
static int showoutline = 0;
static int uselist = 1;
static int alphabits = 8;
@@ -473,6 +476,44 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
if (showmd5 || showtime)
printf("page %s %d", filename, pagenum);
+ if (pdfout)
+ {
+ fz_matrix ctm;
+ fz_rect bounds, tbounds;
+ pdf_page *newpage;
+
+ fz_bound_page(doc, page, &bounds);
+ fz_rotate(&ctm, rotation);
+ tbounds = bounds;
+ fz_transform_rect(&tbounds, &ctm);
+
+ newpage = pdf_create_page(pdfout, bounds, 72, 0);
+
+ fz_try(ctx)
+ {
+ dev = pdf_page_write(pdfout, newpage);
+ if (list)
+ fz_run_display_list(list, dev, &ctm, &tbounds, &cookie);
+ else
+ fz_run_page(doc, page, dev, &ctm, &cookie);
+ fz_free_device(dev);
+ dev = NULL;
+ }
+ fz_always(ctx)
+ {
+ fz_free_device(dev);
+ dev = NULL;
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_display_list(ctx, list);
+ fz_free_page(doc, page);
+ fz_rethrow(ctx);
+ }
+ pdf_insert_page(pdfout, newpage, INT_MAX);
+ pdf_free_page(pdfout, newpage);
+ }
+
if (output && output_format == OUT_SVG)
{
float zoom;
@@ -519,7 +560,7 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
}
}
- if ((output && output_format != OUT_SVG)|| showmd5 || showtime)
+ if ((output && output_format != OUT_SVG && !pdfout)|| showmd5 || showtime)
{
float zoom;
fz_matrix ctm;
@@ -936,6 +977,11 @@ int main(int argc, char **argv)
break;
}
+ if (output_format == OUT_PDF)
+ {
+ pdfout = pdf_create_document(ctx);
+ }
+
timing.count = 0;
timing.total = 0;
timing.min = 1 << 30;
@@ -1037,6 +1083,14 @@ int main(int argc, char **argv)
errored = 1;
}
+ if (pdfout)
+ {
+ fz_write_options opts = { 0 };
+
+ pdf_write_document(pdfout, output, &opts);
+ pdf_close_document(pdfout);
+ }
+
if (showtext == TEXT_HTML)
{
fz_printf(out, "</body>\n");