Handling PDF and QtPDF Build Instructions: Difference between pages

From Qt Wiki
(Difference between pages)
Jump to navigation Jump to search
 
(remove broken link to marketplace)
 
Line 1: Line 1:
{{Ambox|text=TODO: Tips for implementing a custom interactive viewer, using Qt and the PDF parsing and rendering libraries mentioned above}}
QtPdf binaries are available from the Qt installer; but here's how to build it yourself.
{{LangSwitch}}
__TOC__
[[Category:Developing_with_Qt]]
This page discusses various available options for working with [http://en.wikipedia.org/wiki/Portable_Document_Format Portable Document Format (PDF)] [en.wikipedia.org] documents in your Qt application. Please also read the general considerations outlined on the [[Handling_Document_Formats | Handling Document Formats]] page.


== Reading / Writing ==
==Building the 5.15 version==


=== Using QPrinter ===
*sources for QtPdf module are hosted within QtWebEngine repository. Let's clone and initialize the git repository:


For <span style="color:#800080">  creating</span> PDF documents from scratch, you can use Qt's built-in print support which also allows "printing" to PDF files. To do so you can set up a {{DocLink|QPrinter}} instance like this: <code>QPrinter printer(QPrinter::HighResolution);
<pre>
printer.setOutputFormat(QPrinter::PdfFormat);
$ git clone https://code.qt.io/qt/qtwebengine.git
printer.setOutputFileName("path/to/file.pdf");</code> Since QPrinter inherits {{DocLink|QPaintDevice}}, anything that supports outputting graphical content to a QPaintDevice (or has convenience API for printing with QPrinter) can thus be used for generating PDFs:
$ cd qtwebengine
$ git checkout 5.15
$ git submodule update --init --recursive
$ cd ..
</pre>


* '''''manual QPainter painting'''''
*fortunately build of QtWebEngine itself is not necessary for QtPdf build; therefore let's configure shadow build with:
The most basic (but not necessarily simplest) way of creating PDF documents with QPrinter is by manually painting the document's content with Qt's {{DocLink|QtDesigner-ArthurPlugin-Example||Arthur paint system}}.
Just pass the QPrinter object as a reference to the constructor of {{DocLink|PaintSystem.html||QPainter}} (or, alternatively, to {{DocLink|QPainter|begin|QPainter::begin()}} for an already existing QPainter) and then perform any painting operations with that QPainter instance like you usually would (with intermittent calls to {{DocLink|QPrinter|newPage|QPrinter::newPage()}} whenever you want to move on to the next PDF page).


* '''''Scribe'''''
<pre>
For a more high-level API for creating structured rich-text documents, use Qt's Scribe framework (see [[Handling Document Formats]]), which is based on a cursor interface that mimics the behavior of a cursor in a text editor. You can export the whole document with {{DocLink|QTextDocument|print|QTextDocument::print()}}, or a part of it with {{DocLink|QTextEdit|print|QTextEdit::print()}} (see [[Exporting a document to PDF]] for more details).
$ mkdir build
$ cd build
$ qmake ../qtwebengine -- -no-build-qtwebengine-core
</pre>


* '''''Graphics View'''''
*you should see configuration summary after previous step:
Qt's {{DocLink|GraphicsView||Graphics View framework}} can be a more suitable alternative for creating PDF documents with content that is mainly based on arbitrarily positioned and transformed 2D graphical items rather than continuous flowed rich text.
To export the content of a graphics scene or view (or a part of it) to PDF, you need to manually initialize a QPainter configured to paint on a PDF-creating QPrinter (as described above), and pass it to {{DocLink|QGraphicsScene|render|QGraphicsScene::render()}} or {{DocLink|QGraphicsView|render|QGraphicsView::render()}}.


=== Using third-party libraries ===
<pre>
Configure summary:


If you need more control over the output when <span style="color:#800080">creating</span> PDF documents, or you need to <span style="color:#800080">parse</span> existing PDF documents (anything from extracting specific information to assembling a full in-memory document object tree) and maybe even <span style="color:#800080">modify</span> their structure or content before writing them back to disk, refer to third-party PDF reading/writing libraries:
Qt WebEngine Build Tools:
  Use System Ninja ....................... yes
  Use System Gn .......................... no
  Jumbo Build Merge Limit ................ 8
  Developer build ........................ no
  QtWebEngine required system libraries:
    fontconfig ........................... yes
    dbus ................................. yes
    nss .................................. yes
    khr .................................. yes
    glibc ................................ yes
  QtWebEngine required system libraries for qpa-xcb:
    x11 .................................. yes
    libdrm ............................... yes
    xcomposite ........................... yes
    xcursor .............................. yes
    xi ................................... yes
    xtst ................................. yes
  Optional system libraries used:
    re2 .................................. yes
    icu .................................. no
    libwebp, libwebpmux and libwebpdemux . yes
    opus ................................. yes
    ffmpeg ............................... no
    libvpx ............................... yes
    snappy ............................... yes
    glib ................................. yes
    zlib ................................. yes
    minizip .............................. yes
    libevent ............................. yes
    jsoncpp .............................. yes
    protobuf ............................. yes
    libxml2 and libxslt .................. yes
    lcms2 ................................ yes
    png .................................. yes
    JPEG ................................. yes
    harfbuzz ............................. yes
    freetype ............................. yes
    xkbcommon ............................ yes
Qt PDF:
  Support V8 ............................. no
  Support XFA ............................ no
  Support XFA-BMP ........................ no
  Support XFA-GIF ........................ no
  Support XFA-PNG ........................ no
  Support XFA-TIFF ....................... no
Qt PDF Widgets:
  Support Qt PDF Widgets ................. yes


{| class="wikitable"
Note: QtWebEngine build is disabled by user.
|
! style="text-align:left;"| API
! style="text-align:left; color:#800080"| parsing
! style="text-align:left; color:#800080"| modifying
! style="text-align:left; color:#800080"| creating
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| style="text-align:left;"| [http://freedesktop.org/wiki/Software/poppler '''poppler-qt4'''] [freedesktop.org]
| C+''/Qt
| yes
| ?
| ?
| Win, Mac?, Linux, …
| GPL v2+ <span style="color:Navy">  [strong copyleft] </span>
|-
| style="text-align:left;"| [http://pdfhummus.com/ '''Hummus'''] [pdfhummus.com]
| C++
| yes
| yes
| yes
| Win, Mac, Linux
| Apache 2.0 <span style="color:Navy"> [permissive] </span>
|-
| style="text-align:left;"| [http://podofo.sourceforge.net '''PoDoFo'''] [podofo.sourceforge.net]
| C++
| yes
| yes
| yes
| Win, Mac, Linux
| LGPL <span style="color:Navy"> [weak copyleft] </span>
|}


=== Using batch conversion tools ===
Note: The following modules are not being compiled in this configuration:
    webenginecore
    webengine
    webenginewidgets


If all else fails, there is always the option of using an existing tool to automatically convert between PDF files and a more manageable format, and let your Qt application read/write that format instead. The conversion tool could be bundled with your application or specified as a prerequisite, and controlled via [http://doc.qt.io/qt-5/qprocess.html QProcess]. Some possibilities are:
Qt is now configured for building. Just run 'make'.
Once everything is built, you must run 'make install'.
Qt will be installed into '/usr'.
</pre>


*QtPdf build will use '''gn''' and '''ninja''' to build Pdfium which is required for the QtPdf module.  Let's perform the build:


{| class="wikitable"
<pre>
|
$ NINJAJOBS=-j4 make -j4 && make install
! style="text-align:left;"| executable names
</pre>
! style="text-align:left;"| .pdf to:
! style="text-align:left;"| … to .pdf
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| style="text-align:left;"| [http://freedesktop.org/wiki/Software/poppler/ '''poppler-utils '''] [freedesktop.org]
| pdftotext, pdftocairo, pdftohtml
| .txt .svg .html …
| -
| Win, Mac?, Linux, …
| GPL v2+ <span style="color:Navy">  [strong copyleft] </span>
|-
| style="text-align:left;"| [http://inkscape.org/ '''Inkscape'''] [inkscape.org]
| inkscape
| .svg …
| .svg …
| Win, Mac, Linux, …
| GPL v2 <span style="color:Navy"> [strong copyleft] </span>
|}


== Rendering ==
==Building the 6.3 version==


=== Using QtPDF ===
*sources for QtPdf module are hosted within QtWebEngine repository. Let's clone and initialize the git repository:


The QtPDF module is a wrapper around PDFium which supports rendering, navigating pages, bookmarks, links, document metadata, search, text selection and copying to the clipboard.  It includes an image plugin so that most image-viewing applications can view PDF files too (however most of those do not have multi-frame image support, so they will only render the first page).  At this point, more of the feature set is complete for Qt Quick applications than for widget-based ones; but both are possible.  It was introduced as a Qt Labs module in [http://blog.qt.io/blog/2017/01/30/new-qtpdf-qtlabs-module/ this blog post].  Since then, Qt Quick support has been added; and now the source code lives in the qtwebengine repository.  It is supported on all platforms that support Qt WebEngine, plus iOS.  You can build it using [[QtPDF Build Instructions|these instructions]].  Binary builds are also provided via Marketplace:  https://marketplace.qt.io/products/qtpdf  It's available under GPL, LGPL and commercial licenses.
<pre>
$ git clone https://code.qt.io/qt/qtwebengine.git
$ cd qtwebengine
$ git checkout 6.3
$ git submodule update --init --recursive
$ cd ..
</pre>


=== Using third-party libraries/tools ===
* Install html5lib:


For rendering pages or elements from existing PDF documents to image files or in-memory pixmaps (useful e.g. for thumbnail generation or implementing custom viewers), third-party libraries can be used:
pip3 install html5lib


*configure shadow build with:


{| class="wikitable"
<pre>
|
$ mkdir build
! style="text-align:left;"| API
$ cd build
! style="text-align:left;"| can render
$ qt-configure-module ../qtwebengine -- -DFEATURE_qtwebengine_build=OFF
! style="text-align:left;"| output to
</pre>
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://freedesktop.org/wiki/Software/poppler '''poppler-qt4'''] [freedesktop.org]
| C++/Qt
| pages, …?
| QImage
| Win, Mac?, Linux, …
| GPL v2 <span style="color:Navy"> [strong copyleft] </span>
|-
| [http://freedesktop.org/wiki/Software/poppler '''poppler-qt5'''] [freedesktop.org]
| C++/Qt
| pages, …?
| QImage
| Win, Mac?, Linux, …
| GPL v2 <span style="color:Navy"> [strong copyleft] </span>
|-
| [http://mupdf.com '''muPDF'''] [mupdf.com]
| C
| pages
| RGBA byte array
| Win, Mac, Linux, …
| GPL v3+ <span style="color:Navy"> [strong copyleft]; </span> or commercial
|}


Alternatively, the task can be delegated to existing command-line tools:
*build the pdf


{| class="wikitable"
<pre>
|
$ cmake --build . --parallel
! style="text-align:left;"| executable names
</pre>
! style="text-align:left;"| can render
! style="text-align:left;"| output to
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://freedesktop.org/wiki/Software/poppler '''poppler-utils'''] [freedesktop.org]
| pdftocairo, pdftoppm, pdfimages
| pages, image elements
| .png .jpg .svg .ppm …
| Win, Mac?, Linux, …
| GPL v2+ <span style="color:Navy"> [strong copyleft] </span>
|-
| [http://mupdf.com '''muPDF'''] [mupdf.com]
| pdfdraw
| pages
| .png, .ppm, .pgm, .pam, .pbm
| Win, Mac, Linux, …
| GPL v3+ <span style="color:Navy"> [strong copyleft]; </span> or commercial
|}


== Interactive Viewing ==
Since QtPdf comes with Qml and Widget APIs examples using those can be found in examples/pdf and examples/pdfwidgets.
=== Using QtPDF ===


The [[QtPDF_Build_Instructions|QtPDF module]] includes example PDF viewers which can be adapted and incorporated into Qt Quick or widget-based applications.
'''In case of any issues please open bug report for PDF component in https://bugreports.qt.io/<nowiki/>.'''


=== Calling an external viewer application ===
==Historical repository==


If your application merely needs to let the user view/read certain PDF documents on demand, displaying them within the UI of the application itself might not be necessary, and delegating the task to an existing viewer application can be a viable option.
The older version in the [https://code.qt.io/cgit/qt-labs/qtpdf.git/ Qt Labs QtPDF repository] still exists, but development now continues in the [https://code.qt.io/cgit/qt/qtwebengine.git/tree/src/pdf qtwebengine repository]. This was prompted mainly by the upstream Chromium switch of build system from gyp to gn: it was some work to get qtwebengine building with that. Chromium (and thus Qt WebEngine) includes PDFium already; so it was easier to build QtPDF from there than to fix the build in the other repository.
 
Many users have already chosen and installed a stand-alone PDF viewer according to their personal preferences, so simply letting the operating system open the PDF file with whatever it considers the default viewer for such files, might be the easiest (and potentially most user-friendly) choice.
To do so, simply pass the PDF file's URL to [http://doc.qt.io/qt-4.8/qdesktopservices.html#openUrl QDesktopServices::openUrl]. If you're downloading the file from the Internet, store it on disk using [http://doc.qt.io/qt-5/qtemporaryfile.html QTemporaryFile] first, since not all viewers can handle remote URLs.
 
=== Using a third-party Qt widget ===
 
The following widgets provide native PDF viewing for Qt applications:
 
{| class="wikitable"
|
! style="text-align:left;"| class name
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://www.glyphandcog.com/XpdfWidgetQt.html '''XpdfWidget/Qt'''] [glyphandcog.com]  
| XpdfWidget
| Win, Mac, Linux, …
| commercial
|}
 
=== Embedding a third-party ActiveX control ===
 
If you are exclusively targeting the Windows platform, you can embed an existing ActiveX component for viewing PDFs in your Qt applications by instantiating it as a [http://doc.qt.io/qt-5/qaxwidget.html QAxWidget] (see [http://doc.qt.io/qt-4.8/activeqt.html Qt's ActiveX Framework]).
 
The following PDF viewers provide such an ActiveX control:
 
{| class="wikitable"
|
! style="text-align:left;"| DLL file
! style="text-align:left;"| ActiveX control name
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://get.adobe.com/reader/ '''Adobe Reader'''] [get.adobe.com]
| Acropdf.dll
| AxAcroPDFLib.AxAcroPDF
| Win, Mac, Linux, …
| <span style="color:Navy"> freeware </span> ''(for commercial redistribution see [http://www.adobe.com/products/reader/distribution.html here]) [adobe.com])''
|}
 
In the case of the Adobe Reader control, opening a PDF file is done with:
<code>dynamicCall("LoadFile(const QString)", pathToFile)</code>
 
=== Embedding a third-party browser plugin ===
 
A more cross-platform technology for embedding reusable components is the [http://en.wikipedia.org/wiki/NPAPI NPAPI] [en.wikipedia.org] browser plugin architecture- which Qt's WebKit-based browser framework [http://doc.qt.io/qt-5/qtwebkitwidgets-index.html happens to support]. You'll need to set up a simple HTML page containing appropriate embed>…</embed> tags, and let a [http://doc.qt.io/qt-5/qwebview.html QWebView] display it (with [http://doc.qt.io/qt-4.8/qwebsettings.html#WebAttribute-enum QWebSettings::PluginsEnabled].
 
The following applications provide a reusable NPAPI plugin for viewing PDF:
 
{| class="wikitable"
|
! style="text-align:left;"| plugin name
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://get.adobe.com/reader/ '''Adobe Reader'''] [get.adobe.com]
| nppdf
| Win, Mac, (Linux)¹, …
| <span style="color:Navy"> freeware </span>''(for commercial redistribution see [http://www.adobe.com/products/reader/distribution.html here] [adobe.com])''
|}
 
<small>  ¹''While in theory it should work on all Desktop platforms, application developers have "reported problems":/forums/viewthread/14055 in trying to get it to work with Qt Webkit on Linux. '' </small>
 
As an alternative to using QWebView for running the plugin, it is possible to use a third-party solution that allows embedding NPAPI plugins in a Qt application without the overhead of a full web browser instance:
 
{| class="wikitable"
|
! style="text-align:left;"| component type
! style="text-align:left;"| has special convenience API for
! style="text-align:left;"| platforms
! style="text-align:left;"| license
|-
| [http://www.devmachines.com/products/qtitanmultimedia-overview.html '''QtitanMultimedia'''] [devmachines.com]
| QWidget
| Adobe Reader, …
| Win, Linux
| <span style="color:Navy"> commercial </span>
|}
 
== See Also ==
 
* [[Handling Document Formats]]
* [[Handling HTML]]
* [[Handling Microsoft Excel file format]]

Latest revision as of 23:58, 28 June 2024

QtPdf binaries are available from the Qt installer; but here's how to build it yourself.

Building the 5.15 version

  • sources for QtPdf module are hosted within QtWebEngine repository. Let's clone and initialize the git repository:
$ git clone https://code.qt.io/qt/qtwebengine.git
$ cd qtwebengine
$ git checkout 5.15
$ git submodule update --init --recursive
$ cd ..
  • fortunately build of QtWebEngine itself is not necessary for QtPdf build; therefore let's configure shadow build with:
$ mkdir build
$ cd build
$ qmake ../qtwebengine -- -no-build-qtwebengine-core
  • you should see configuration summary after previous step:
Configure summary: 

Qt WebEngine Build Tools:
  Use System Ninja ....................... yes
  Use System Gn .......................... no
  Jumbo Build Merge Limit ................ 8
  Developer build ........................ no
  QtWebEngine required system libraries:
    fontconfig ........................... yes
    dbus ................................. yes
    nss .................................. yes
    khr .................................. yes
    glibc ................................ yes
  QtWebEngine required system libraries for qpa-xcb:
    x11 .................................. yes
    libdrm ............................... yes
    xcomposite ........................... yes
    xcursor .............................. yes
    xi ................................... yes
    xtst ................................. yes
  Optional system libraries used:
    re2 .................................. yes
    icu .................................. no
    libwebp, libwebpmux and libwebpdemux . yes
    opus ................................. yes
    ffmpeg ............................... no
    libvpx ............................... yes
    snappy ............................... yes
    glib ................................. yes
    zlib ................................. yes
    minizip .............................. yes
    libevent ............................. yes
    jsoncpp .............................. yes
    protobuf ............................. yes
    libxml2 and libxslt .................. yes
    lcms2 ................................ yes
    png .................................. yes
    JPEG ................................. yes
    harfbuzz ............................. yes
    freetype ............................. yes
    xkbcommon ............................ yes
Qt PDF:
  Support V8 ............................. no
  Support XFA ............................ no
  Support XFA-BMP ........................ no
  Support XFA-GIF ........................ no
  Support XFA-PNG ........................ no
  Support XFA-TIFF ....................... no
Qt PDF Widgets:
  Support Qt PDF Widgets ................. yes

Note: QtWebEngine build is disabled by user.

Note: The following modules are not being compiled in this configuration:
    webenginecore
    webengine
    webenginewidgets

Qt is now configured for building. Just run 'make'. 
Once everything is built, you must run 'make install'. 
Qt will be installed into '/usr'.
  • QtPdf build will use gn and ninja to build Pdfium which is required for the QtPdf module. Let's perform the build:
$ NINJAJOBS=-j4 make -j4 && make install

Building the 6.3 version

  • sources for QtPdf module are hosted within QtWebEngine repository. Let's clone and initialize the git repository:
$ git clone https://code.qt.io/qt/qtwebengine.git
$ cd qtwebengine
$ git checkout 6.3
$ git submodule update --init --recursive
$ cd ..
  • Install html5lib:
pip3 install html5lib
  • configure shadow build with:
$ mkdir build
$ cd build
$ qt-configure-module ../qtwebengine -- -DFEATURE_qtwebengine_build=OFF
  • build the pdf
$ cmake --build . --parallel

Since QtPdf comes with Qml and Widget APIs examples using those can be found in examples/pdf and examples/pdfwidgets.

In case of any issues please open bug report for PDF component in https://bugreports.qt.io/.

Historical repository

The older version in the Qt Labs QtPDF repository still exists, but development now continues in the qtwebengine repository. This was prompted mainly by the upstream Chromium switch of build system from gyp to gn: it was some work to get qtwebengine building with that. Chromium (and thus Qt WebEngine) includes PDFium already; so it was easier to build QtPDF from there than to fix the build in the other repository.