15

I'm upgrading some Qt (C++ & QML) code from Qt4.8 to Qt5.1.

The Qt4.8 code is a trivial C++ "QML viewer" app subclassing a QDeclarativeView, and a bunch of QML.

It's been easy enough to change this to use Qt5/QtQuick2's QQuickView except for one thing:

The Qt4.8 app has a method for printing to PDF:

void MyQMLViewer::printToPDF(const QString& filename) const {
  QPrinter printer(QPrinter::HighResolution);
  printer.setOutputFormat(QPrinter::PdfFormat);
  printer.setPageSize(QPrinter::A3);
  printer.setOutputFileName(filename);
  printer.setOrientation(QPrinter::Landscape);
  QPainter painter(&printer);
  render(&painter);
}

There were a few "environment" changes needed for Qt5.1 to get a QPrinter (ie add QT += printsupport to the project .pro file and #include <QtPrintSupport>), but there seems to be a more fundamental problem that QQuickView doesn't provide anything which is obviously compatible with the QGraphicsView/QPainter/QPaintDevice world of QPrinter (specifically, QQuickView has no render method, and all the drawing/painting/rendering-related methods it does have seem very tied up with OpenGL).

Any suggestions for how to best obtain high-quality PDF output from a QQuickView ?

(Note that I am not simply looking to screenshot the view; with QDeclarativeView, the code above generates PDFs with much better resolution even than the app fullscreened on my largest monitor).

I see the "QDeclarativeItem and QDeclarativeView" section of the "Porting QML Applications to Qt 5" guide does mention the loss of QGraphicsView-specific functionality, but doesn't offer any solutions (although it does mention workrounds for the case of items with custom QPainter-based rendering being bought into the new regime).

Update with some additional background info: an example of a PDF printed from QDeclarativeView using the above code can be found here. There's a png of the same view on a decent size monitor here. (This is actually the last slide in a series of slides; it's actually a gallery of the previous slides which bounces each slide onto the screen; if I had the time I'd look into the feasibility of the gallery being the only thing and transforming each scattered slide into view for a Prezi-style presentation; suspect QDeclarative isn't really performant enough though, which is one reason for wanting to get onto QtQuick2+Qt5.2's new scene graph stuff). Anyway, If you zoom the PDF up to 100% you'll see the text is... well it's better than anything a sanely sized image file will manage I think, although the sloping text baselines perhaps look a little uneven. There is also an issue with opacity values not being represented in the PDF (so the drop shadows and "bubbles" come out solid); another one of my motivations for trying for a QtQuick2 version was actually to see if translucent elements were dealt with any better. I assume the PDF just contains rasterized (or maybe vector outlines) of all the elements as utilities like "pdftotext" can't extract anything from it. I don't know enough about PDF tools to know how to inspect the internal structure of the thing but I assume there's some hierarchy there and the QML element tree is all laid out using a similar structure of nested transforms to the QML. Just for comparison and the sort of richness I'm potentially working towards here's a poster I did with LaTeX/Beamerposter; I find Beamerposter's rigid block structure rather limiting (and fiddly) compared with the possibilities QML seems to offer though. BTW, another thing on my wishlist/todolist is a QML element which can render LaTeX source, math and all, just to get the best of both worlds.

Update: Recent Qt blog post on all the backend changes in Qt5.8 has a comment linking to this Qt issue to use the new possibility of QPainter-rendered QtQuick scenes to render PDFs.

Community
  • 1
  • 1
timday
  • 24,582
  • 12
  • 83
  • 135
  • 2
    Right, so you are not looking for http://stackoverflow.com/questions/16792634/how-to-printwith-the-printer-a-qml-object if I understood correctly? – László Papp Dec 29 '13 at 12:47
  • @LaszloPapp: Yes that's right. I'm actually interested in using QML as a combined presentation/poster system not unlike Latex/Beamer/Beamerposter (except Qt makes it very easy to add animations, interactive plugins etc). QML makes it easy to have individual slides as QML files, and also to assemble/layout all those slides onto a massive A0/A1 sized poster (which is itself another master QML file with the slides as elements). For posters with that much detail, you really need something like PDF; rasterizing to one massive image is completely impractical. – timday Dec 29 '13 at 12:58
  • OK, intereting and useful question, so I gave a +1. I guess it will boil down to the SceneGraph API, but I may be totally off. I do not have much experience with that. :-) – László Papp Dec 29 '13 at 13:00
  • 1
    Take a look at https://www.kdab.com/creating-pdf-qtquick-2-scene-slideviewer/ :) – mlvljr Dec 22 '16 at 23:00

1 Answers1

2

At the moment, there is no code in Qt that supports rendering of a scene graph to a pdf. The underlying data that is used to render Qt Quick 2 is held in the scene graph. As Laszlo suggests, you'd need to iterate the scene graph and generate PDF primitives. There's some impedance mismatch there, but it should be doable with some sweat. I think a proof of concept could be small enough to fit here, so I'll see how easy it could be :)

If you really want a PDF, you currently have no choice but to render it to a large image at 300dpi and wrap that in a PDF. The image doesn't have to be large if the poster has large areas of solid color. PDF can do do TIFF encoding and also JPEG encoding.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • See some updated background added to the question. My experience with PDFs which just wrap one huge 300dpi image is generally that printers choke on them; however using PDF (possibly with font embedding) allows large amounts of text to be encoded efficiently (unfortunately I suspect even QDeclarative's QML-to-PDF capabilities just rasterize the text elements, but I don't know enough about PDF files to be sure). – timday Dec 30 '13 at 21:30
  • 1
    The scene graph rendering nominally uses distance fields to render text, but this is only the rasterization aspect. The text primitives per se (in the form of paths) can be output to PDF directly - it will be bigger than if fonts were used, but should still work. – Kuba hasn't forgotten Monica Dec 30 '13 at 23:54
  • Also note that QML can be used instead of Qt Quick, and then you're free to do whatever you want. For all I know you can encode various PDF primitives as QML, just as you can QWidget-based UIs, or completely custom objects. QML is just a way of instantiating QObjects and running some javascript on them. Do you actually need Qt Quick 2? – Kuba hasn't forgotten Monica Dec 30 '13 at 23:56
  • Well I could stick with QDeclarative but get the impression it's now at worst deprecated in favour of QtQuick, and at best a dead end getting little attention compared with all the new shiny stuff going into QtQuick (you're aware that QDeclarativeView doesn't support any new QML elements needing "import QtQuick 2.0" QML content, right? Or work on iOS.). Also, since a fair amount of my interest in this is also related to custom C++ interactive elements in the QML (and the print to PDF is pretty incidental), I'd really like to be using stuff considered current in the Qt5+ world. – timday Dec 31 '13 at 09:53
  • What I'm saying is: if you need PDF composition in QML, use your own elements and some PDF library. Qt Quick is for UIs, after all. QML != Qt Quick. The latter builds on the former, the former can be used without the latter. I'm not suggesting to use Qt Quick 1 at all. – Kuba hasn't forgotten Monica Dec 31 '13 at 12:58
  • Hmmm, that sounds simple, but given the app views I want to capture as PDF make use of javascript and custom C++ components in their QML, seems like that could end up as a bit of an epic project. If QtDeclarative is a QML-to-QPainter/QGraphicsView engine, and QtQuick is a QML-to-OpenGL engine - or is it a QML-to-QSG engine? - what you're proposing amounts to creating a whole new QML-to-PDF engine, no? Maybe it'd be simpler than I think though... probably I need to look at the sources of these things - and QSG especially - closer... – timday Dec 31 '13 at 14:48
  • @timday: did you get any closer with this? I personally think that Quick could be a very interesting reporting solution: it already has tooling, it is easy to write and some interesting layout features. Being able to leverage all that would be very cool. – André Jan 29 '14 at 16:09
  • @Andre: No, too many projects, too little time. I need to get around to playing with QSG properly first. Related, you can find this story repeated a few places on KDE forums: As the node.js project founder said when he saw QML for the first time: "Wow, it's HTML5 done right." – timday Jan 30 '14 at 00:14