Merge Pdf
A complete, runnable cpp program — 93 lines, shipped in your download.
Demonstrates Import & Output APIs
Same example, other languages: activex_cpp c cpp_linux csharp php python vbnet
examples/cpp/merge_pdf/merge_pdf.cpp
93 lines
// merge_pdf -- C++ port of examples\Vb6\merge_pdf\merge_pdf.bas
// Generic merge of arbitrary PDF files (with handling for forms / PDF collections).
#include <lumaspdf.h>
#include "repo_root.h"
#include <cstdio>
#include <string>
static std::string exeDir(const char* a0){ std::string s(a0); auto p=s.find_last_of("\\/"); return p==std::string::npos?".":s.substr(0,p); }
// The Delphi original passes Delphi `string` (UnicodeString) to CreateNewPDF,
// SetFont, WriteFTextEx, OpenImportFile, AttachFile and OpenOutputFile, so
// those calls resolve to the WIDE overloads rather than the *A twins used here
// before. LWCHAR is wchar_t on Windows and char16_t elsewhere, so literals must
// use the header's own LUMAS_TEXT() macro -- a bare u"..." does not convert to
// LWCHAR* under MSVC and a bare L"..." is 4 bytes wide off Windows.
#define W_(s) ((LWCHAR*)LUMAS_TEXT(s))
static std::basic_string<LWCHAR> WS(const std::string& s){
return std::basic_string<LWCHAR>(s.begin(), s.end());
}
static SI32 PDF_CALL PDFError(void* Data, SI32 ErrCode, const char* ErrMessage, SI32 ErrType){
if(ErrMessage) printf("%s\n", ErrMessage);
return 0;
}
static std::string ExtractFileName(const std::string& path){
auto p = path.find_last_of("\\/");
return p == std::string::npos ? path : path.substr(p + 1);
}
int main(int argc, char** argv){
PPDF pdf = pdfNewPDF();
pdfSetOnErrorProc(pdf, nullptr, PDFError);
pdfCreateNewPDFW(pdf, W_(""));
pdfSetPageCoords(pdf, pcTopDown);
pdfAppend(pdf);
pdfSetFontW(pdf, W_("Helvetica"), fsRegular, 14.0, 0, cp1252);
pdfWriteFTextExW(pdf, 50.0, 50.0, pdfGetPageWidth(pdf) - 100.0, -1.0, taJustify,
// Each fragment carries its own LUMAS_TEXT: the prefix has to be on
// every literal of a concatenation, since mixing a wide literal with
// a narrow one is only conditionally supported.
(LWCHAR*)(LUMAS_TEXT("The following pages were imported from different PDF files. LumasPDF adjusts the destinations of link annotations and bookmarks so that ")
LUMAS_TEXT("all destinations refer to the new page numbers after import.\r\r")
LUMAS_TEXT("Entire PDF files can be easily merged with ImportPDFFile() but it is also possible to import only specific pages of an arbitrary number ")
LUMAS_TEXT("of PDF files. You can also add further pages or edit imported pages if necessary. An existing page can be opened for editing with EditPage().")));
pdfEndPage(pdf);
bool first = true, haveXFA = false, isCollection = false;
SI32 destPage = 1;
std::string files[2] = { LUMAS_REPO_ROOT "/license.pdf", LUMAS_REPO_ROOT "/sample_multipage.pdf" };
for(int i = 0; i < 2; ++i){
if(pdfOpenImportFileW(pdf, (LWCHAR*)WS(files[i]).c_str(), ptOpen, "") < 0){ pdfDeletePDF(pdf); return 1; }
if(first){
first = false;
haveXFA = (pdfGetInIsXFAForm(pdf) != 0);
isCollection = (pdfGetInIsCollection(pdf) != 0);
destPage = pdfImportPDFFile(pdf, destPage + 1, 1.0, 1.0);
if(destPage < 0) break;
} else {
if(isCollection){
if(pdfGetInIsCollection(pdf) != 0){
pdfSetImportFlags(pdf, ifEmbeddedFiles);
if(pdfImportCatalogObjects(pdf) == 0) break;
} else {
pdfCloseImportFile(pdf);
pdfAttachFileW(pdf, (LWCHAR*)WS(files[i]).c_str(), (LWCHAR*)WS(ExtractFileName(files[i])).c_str(), 1);
}
} else {
if((pdfGetInIsCollection(pdf) != 0) ||
(((pdfGetInIsXFAForm(pdf) != 0) || (pdfGetInFieldCount(pdf) > 0)) &&
((pdfGetFieldCount(pdf) > 0) || haveXFA))) break;
pdfSetImportFlags(pdf, ifImportAll | ifImportAsPage);
pdfSetImportFlags2(pdf, if2UseProxy);
destPage = pdfImportPDFFile(pdf, destPage + 1, 1.0, 1.0);
if(destPage < 0) break;
}
}
pdfCloseImportFile(pdf);
}
if(pdfHaveOpenDoc(pdf) != 0){
std::string outFile = exeDir(argv[0]) + "/out.pdf";
if(pdfOpenOutputFileW(pdf, (LWCHAR*)WS(outFile).c_str()) == 0){ pdfDeletePDF(pdf); return 1; }
if(pdfCloseFile(pdf) != 0) printf("PDF file \"%s\" successfully created!\n", outFile.c_str());
}
pdfDeletePDF(pdf);
return 0;
}
This file is in the SDK at examples/cpp/merge_pdf/merge_pdf.cpp.
The build fails if this page and that file ever differ.