I wrote a test program to merge multiple PDF files into one new PDF file. Each input PDF file has only one page. The rule is every two input PDF file's first pages (also the only page) should be put into one page of the new output file, arranging vertically.
The program arguments are output file and multiple input file. If the number of input files are odd number, then the last page of the output PDF file should only contain that odd page on the upper part. Reading the docs, I think `PdfStreamedDocument` should be used to manipulate my output PDF file, and `PdfMemDocument` should be used to read input PDF files. But the result is beyond my expectations: If I input more than two input PDF files, the first page of the output PDF file is alright, containing the first two PDF file page contents on the upper and lower part of the page. But the rest of pages cannot display input PDF file page content. I tried to add a border around every upper and lower part of the page, and the border did show up on every page, but the content still couldn't show up. If I use Adobe Reader DC to open the output PDF file, it would report a 109 error when scrolling across the first page. I'm guessing `PdfPainter`'s `DrawXObject` method did something that cannot be handled by `PdfStreamedDocument`. Here's my code: #include <cstdio> #include <cstdlib> #include <iostream> #include <utility> #include "podofo/podofo.h" using PdfPair = std::pair<PoDoFo::PdfMemDocument, PoDoFo::PdfMemDocument>; constexpr double kA4Width = 595.0; constexpr double kA4Height = 842.0; constexpr double kMarginLeft = 64.0; constexpr double kMarginRight = 64.0; constexpr double kMarginTop = 64.0; constexpr double kMarginBottom = 64.0; constexpr double kMarginInBetween = 108.0; int main(int argc, char* argv[]) { if (argc < 3) { printf("USAGE:\n\t%s /path/to/output.pdf /path/to/input.pdf1 /path/to/input.pdf2 ...\n", __FILE__); exit(EXIT_FAILURE); } const double kInvoiceWidth = kA4Width - kMarginLeft - kMarginRight; const double kInvoiceHeight = (kA4Height - kMarginTop - kMarginBottom - kMarginInBetween) / 2; const double kInvoiceLeft = kMarginLeft; const double kInvoiceUpperBottom = kMarginBottom + kInvoiceHeight + kMarginInBetween; const double kInvoiceLowerBottom = kMarginBottom; // NOTE: If I use this PdfStreamedDocument, then only the first page would display the right content, other pages would only display the border. // PoDoFo::PdfStreamedDocument output(argv[1]); PoDoFo::PdfMemDocument output; std::vector<PdfPair> input_pair_list((argc - 1) / 2); printf("input %zu pair(s)\n", input_pair_list.size()); for (size_t i = 0; i < input_pair_list.size(); i++) { PdfPair& pdf_pair = input_pair_list[i]; pdf_pair.first.Load(argv[i * 2 + 2]); if (pdf_pair.first.GetPageCount() <= 0) { fprintf(stderr, "pdf_pair first part empty\n"); break; } PoDoFo::PdfPage* target_page = output.CreatePage(PoDoFo::PdfPage::CreateStandardPageSize(PoDoFo::ePdfPageSize_A4)); if (!target_page) { PODOFO_RAISE_ERROR(PoDoFo::ePdfError_InvalidHandle); } PoDoFo::PdfPainter painter; painter.SetPage(target_page); painter.SetStrokingColor(164.0 / 255, 164.0 / 255, 164.0 / 255); painter.SetStrokeWidth(1.0); painter.SetLineCapStyle(PoDoFo::ePdfLineCapStyle_Square); // upper_part printf("first pdf has %d page(s)\n", pdf_pair.first.GetPageCount()); PoDoFo::PdfPage* upper_part_first_page = pdf_pair.first.GetPage(0); PoDoFo::PdfXObject upper_part(pdf_pair.first, 0, &output, "XOb", true); painter.DrawXObject(kInvoiceLeft, kInvoiceUpperBottom, &upper_part, kInvoiceWidth / upper_part_first_page->GetTrimBox().GetWidth(), kInvoiceHeight / upper_part_first_page->GetTrimBox().GetHeight()); // upper_part border painter.DrawLine(kInvoiceLeft, kInvoiceUpperBottom, kInvoiceLeft, kInvoiceUpperBottom + kInvoiceHeight); painter.DrawLine(kInvoiceLeft, kInvoiceUpperBottom + kInvoiceHeight, kInvoiceLeft + kInvoiceWidth, kInvoiceUpperBottom + kInvoiceHeight); painter.DrawLine(kInvoiceLeft + kInvoiceWidth, kInvoiceUpperBottom + kInvoiceHeight, kInvoiceLeft + kInvoiceWidth, kInvoiceUpperBottom); painter.DrawLine(kInvoiceLeft + kInvoiceWidth, kInvoiceUpperBottom, kInvoiceLeft, kInvoiceUpperBottom); // lower_part if (argc > i * 2 + 3) { printf("loading lower_part pdf: %s\n", argv[i * 2 + 3]); pdf_pair.second.Load(argv[i * 2 + 3]); if (pdf_pair.second.GetPageCount() <= 0) { fprintf(stderr, "pdf_pair second part empty\n"); painter.FinishPage(); break; } printf("second pdf has %d page(s)\n", pdf_pair.second.GetPageCount()); PoDoFo::PdfPage* lower_part_first_page = pdf_pair.second.GetPage(0); PoDoFo::PdfXObject lower_part(pdf_pair.second, 0, &output, "XOb", true); painter.DrawXObject(kInvoiceLeft, kInvoiceLowerBottom, &lower_part, kInvoiceWidth / lower_part_first_page->GetTrimBox().GetWidth(), kInvoiceHeight / lower_part_first_page->GetTrimBox().GetHeight()); // lower_part border painter.DrawLine(kInvoiceLeft, kInvoiceLowerBottom, kInvoiceLeft, kInvoiceLowerBottom + kInvoiceHeight); painter.DrawLine(kInvoiceLeft, kInvoiceLowerBottom + kInvoiceHeight, kInvoiceLeft + kInvoiceWidth, kInvoiceLowerBottom + kInvoiceHeight); painter.DrawLine(kInvoiceLeft + kInvoiceWidth, kInvoiceLowerBottom + kInvoiceHeight, kInvoiceLeft + kInvoiceWidth, kInvoiceLowerBottom); painter.DrawLine(kInvoiceLeft + kInvoiceWidth, kInvoiceLowerBottom, kInvoiceLeft, kInvoiceLowerBottom); } else { printf("lower_part not present\n"); } painter.FinishPage(); } // output.Close(); output.Write((argv[1])); return 0; }
_______________________________________________ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users