All formats

PoDoFo

LanguageC++17
LicenseLGPL-2.0-or-later or MPL-2.0 (the command-line tools are GPL)
Repositorygithub.com/podofo/podofo
DocumentationAPI reference, examples in the repository
Depends onFreeType, OpenSSL, libxml2, zlib, fontconfig (Unix); optional libjpeg, libtiff, libpng
Read / writeyes / yes: create, edit, merge, text extraction, forms, annotations, encryption, digital signatures

PoDoFo is a C++ library for working with the PDF object model and for drawing new content: pages, text with embedded and subset fonts, images, vector graphics, annotations, form fields and digital signatures (including PAdES). Version 1.0 modernized the API (C++17, PdfMemDocument, PdfPainter with TextState) and added Unicode text extraction. It doesn’t render pages.

Choose PoDoFo when you need to both generate and modify PDFs from C++ under a library-friendly license. For structural tasks only (merge, split, encrypt), QPDF is simpler; for rendering use PDFium or MuPDF.

Installation#

Shell
# Debian / Ubuntu (check that the packaged version is 1.x)
sudo apt install libpodofo-dev
# macOS
brew install podofo
# Windows (vcpkg)
vcpkg install podofo
cmake
find_package(PoDoFo 1.0.0 REQUIRED)
target_link_libraries(myapp PRIVATE podofo::podofo)

Basic usage: create a PDF with text#

C++
#include <podofo/podofo.h>
#include <iostream>

using namespace PoDoFo;

int main() {
    try {
        PdfMemDocument doc;
        PdfPage &page = doc.GetPages().CreatePage(PdfPageSize::A4);

        PdfFont *font = doc.GetFonts().SearchFont("Arial");
        if (font == nullptr) throw std::runtime_error("font not found");

        PdfPainter painter;
        painter.SetCanvas(page);
        painter.TextState.SetFont(*font, 18);
        // origin is bottom-left; 56.69 points = 2 cm
        painter.DrawText("Hello, PDF!", 56.69, page.GetRect().Height - 56.69);
        painter.FinishDrawing();

        doc.GetMetadata().SetTitle(PdfString("Hello"));
        doc.Save("hello.pdf");
    } catch (const PdfError &e) {
        std::cerr << "error: " << e.what() << "\n";
        return 1;
    }
    return 0;
}

SearchFont finds a system font and embeds a subset. Use doc.GetFonts().GetStandard14Font(PdfStandard14FontType::Helvetica) for a non-embedded standard font.

How to extract text from a PDF#

C++
PdfMemDocument doc;
doc.Load("in.pdf");
auto &pages = doc.GetPages();
for (unsigned i = 0; i < pages.GetCount(); i++) {
    std::vector<PdfTextEntry> entries;
    pages.GetPageAt(i).ExtractTextTo(entries);
    for (const auto &e : entries)
        std::cout << e.Text << "  (x=" << e.X << ", y=" << e.Y << ")\n";
}

Each entry is a run of text with its position.

How to merge PDFs#

C++
PdfMemDocument out;
out.Load("a.pdf");
PdfMemDocument other;
other.Load("b.pdf");
out.GetPages().AppendDocumentPages(other);
out.Save("merged.pdf");

AppendDocumentPages(doc, pageIndex, pageCount) copies a range; RemovePageAt(index) deletes a page.

How to rotate pages#

C++
PdfMemDocument doc;
doc.Load("in.pdf");
auto &pages = doc.GetPages();
for (unsigned i = 0; i < pages.GetCount(); i++)
    pages.GetPageAt(i).SetRotation(90);
doc.Save("rotated.pdf");

How to fill a form field#

C++
PdfMemDocument doc;
doc.Load("form.pdf");
PdfAcroForm *form = doc.GetAcroForm();
if (form != nullptr) {
    for (unsigned i = 0; i < form->GetFieldCount(); i++) {
        PdfField &field = form->GetFieldAt(i);
        std::cout << field.GetFullName() << "\n";
        if (field.GetType() == PdfFieldType::TextBox && field.GetFullName() == "name")
            static_cast<PdfTextBox &>(field).SetText(PdfString("Jane Doe"));
    }
}
doc.Save("filled.pdf");

How to read metadata and encrypt a PDF#

C++
PdfMemDocument doc;
doc.Load("in.pdf", PdfLoadOptions::None, "password-if-any");
auto title = doc.GetMetadata().GetTitle();
if (title.has_value())
    std::cout << "Title: " << title->GetString() << "\n";

doc.SetEncrypted("user", "owner",
                 PdfPermissions::Print | PdfPermissions::Copy,
                 PdfEncryptionAlgorithm::AESV3R6);
doc.Save("encrypted.pdf");

Tips#