static QPDF in_pdf;
static QPDF out_pdf;
-string page_out::new_resource(const string type)
+string out_context::new_resource(const string type)
{
return "/" + type + to_string(++res_cnt);
}
class in_page : public page {
QPDFObjectHandle pdf_page;
+ QPDFObjectHandle xobject;
public:
BBox media_box;
- void render(page_out *out, pdf_matrix xform);
+ void render(out_context *out, pdf_matrix xform);
in_page(QPDFObjectHandle inpg, int idx);
};
in_page::in_page(QPDFObjectHandle inpg, int idx)
{
pdf_page = inpg;
+ xobject = QPDFObjectHandle::newNull();
index = idx;
+
media_box = BBox(inpg.getKey("/MediaBox"));
width = media_box.width();
height = media_box.height();
+
+ QPDFObjectHandle art_box = inpg.getKey("/ArtBox");
+ if (art_box.isNull())
+ art_box = inpg.getKey("/CropBox");
+ if (art_box.isNull())
+ bbox = BBox(width, height);
+ else
+ {
+ bbox = BBox(art_box);
+ bbox.x_min -= media_box.x_min;
+ bbox.x_max -= media_box.x_min;
+ bbox.y_min -= media_box.y_min;
+ bbox.y_max -= media_box.y_min;
+ }
}
-void in_page::render(page_out *out, pdf_matrix xform)
+void in_page::render(out_context *out, pdf_matrix xform)
{
// Convert page to xobject
- QPDFObjectHandle page_copy = page_to_xobject(&out_pdf, out_pdf.copyForeignObject(pdf_page));
+ if (xobject.isNull())
+ xobject = out_pdf.makeIndirectObject( page_to_xobject(&out_pdf, out_pdf.copyForeignObject(pdf_page)) );
string xobj_res = out->new_resource("XO");
- out->xobjects.replaceKey(xobj_res, out_pdf.makeIndirectObject(page_copy));
+ out->xobjects.replaceKey(xobj_res, xobject);
pdf_matrix m;
m.shift(-media_box.x_min, -media_box.y_min);
m.concat(xform);
- out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q";
+ out->contents += "q " + m.to_string() + " cm " + xobj_res + " Do Q ";
}
-static int run_indent;
-
static void debug_pages(vector<page *> &pages)
{
if (!debug_mode)
return;
for (auto pg: pages)
- debug("%*sPage #%d: w=%.3f h=%.3f", run_indent, "", pg->index, pg->width, pg->height);
+ debug("Page #%d: media[%.3f %.3f] bbox[%.3f %.3f %.3f %.3f]",
+ pg->index,
+ pg->width, pg->height,
+ pg->bbox.x_min, pg->bbox.y_min, pg->bbox.x_max, pg->bbox.y_max);
}
vector<page *> run_command_list(list<cmd *> &cmds, vector<page *> &pages)
{
- debug("%*s# Input", run_indent, "");
+ debug("# Input");
debug_pages(pages);
for (auto c: cmds)
{
- debug("%*s# Executing %s", run_indent, "", c->def->name);
- run_indent += 4;
+ debug("# Executing %s", c->def->name);
+ debug_indent += 4;
pages = c->exec->process(pages);
- run_indent -= 4;
+ debug_indent -= 4;
debug_pages(pages);
}
return pages;
}
+static void find_bboxes(vector<page *> &pages, const char *in_name)
+{
+ vector<BBox> bboxes = gs_bboxes(in_name);
+ if (pages.size() != bboxes.size())
+ die("Ghostscript failed to produce the right number of bboxes");
+
+ for (size_t i=0; i<pages.size(); i++)
+ pages[i]->bbox = bboxes[i];
+}
+
static void process(list<cmd *> &cmds, const char *in_name, const char *out_name)
{
in_pdf.processFile(in_name);
for (auto inpg: in_pages)
pages.push_back(new in_page(inpg, ++cnt));
+ find_bboxes(pages, in_name);
+
pages = run_command_list(cmds, pages);
for (auto pg: pages)
{
- page_out out;
+ out_context out;
out.resources = QPDFObjectHandle::newDictionary();
- // FIXME: What if the source page requires a broader ProcSet?
- out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF /Text]"));
+ out.resources.replaceKey("/ProcSet", QPDFObjectHandle::parse("[/PDF]"));
out.xobjects = QPDFObjectHandle::newDictionary();
out.resources.replaceKey("/XObject", out.xobjects);
pg->render(&out, pdf_matrix());
QPDFObjectHandle out_page = out_pdf.makeIndirectObject(QPDFObjectHandle::newDictionary());
out_page.replaceKey("/Type", QPDFObjectHandle::newName("/Page"));
out_page.replaceKey("/MediaBox", BBox(pg->width, pg->height).to_array());
+ // FIXME:
+ // out_page.replaceKey("/CropBox", pg->bbox.to_array());
out_page.replaceKey("/Contents", contents);
out_page.replaceKey("/Resources", out.resources);
out_pdf.addPage(out_page, false);
int main(int argc, char **argv)
{
+ if (argc <= 1 || argc > 1 && !strcmp(argv[1], "--help"))
+ {
+ help();
+ return 0;
+ }
+
if (argc != 4)
{
fprintf(stderr, "Usage: paperjam <commands> <input> <output>\n");