Hi,

I recently started using the poppler library with the Qt4 headers and
have found it easy to use and generally excellent. 
For example, see http://www.qtrac.eu/diffpdf.html

(1)

I'm now trying to develop a console app that will do 2-up, 4-up, and so
on printing, optionally ignoring each page's margins to maximize the use
of space.

But unfortunately, I'm getting blurred pages and don't know why.

I create a QPrinter in PDF mode and switch render hints _on_ for the
poppler document which I render to a QImage. I then create a QPainter on
the printer and switch its render hints _off_---so that it will just
paint the QImage pixel for pixel.

I've attached (the very rough first cut) of the source (since it is only
160 lines), in case anyone has the time/inclination to have a look, esp.
since I'm hoping I just did something silly that you'll spot in a
moment:-)

[Another problem with the program is that poppler seems to default to 72
dpi, but QPrinter depends on the actual printer driver, so in my case is
75 dpi.]

(2)

In the docs it makes clear that you get ownership of Poppler::Document
and Poppler::Page and so must delete them---that's fine, I use
std::tr1::shared_ptr to handle that. But when you do
Poppler::Page::textList() it isn't clear whether you get ownership of
the Poppler::TextBoxes or not? I've assumed that you don't, but I'd like
to know.

Thanks!

-- 
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
    C++, Python, Qt, PyQt - training and consultancy
        "Programming in Python 3" - ISBN 0137129297

/*
    Copyright (c) 2008 Qtrac Ltd. All rights reserved.
    This program or module is free software: you can redistribute it
    and/or modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version. This program is
    distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
    for more details.
*/

#include <tr1/memory>
#include <poppler-qt4.h>
#include <QCoreApplication>
#include <QPainter>
#include <QPrinter>
#include <QtDebug> // TODO replace with QTextStream etc.

typedef std::tr1::shared_ptr<Poppler::Document> PdfDocument;
typedef std::tr1::shared_ptr<Poppler::Page> PdfPage;

/*
    [ 1 | 2 ] landscape -2 paginate2up

    [ 1 | 2 ] portrait -4 paginate4up
    [ 3 | 4 ]

    [ 1 | 2 | 3 ] landscape -6 paginate6up
    [ 4 | 5 | 6 ]
*/

QRectF pageBoundary(PdfPage page, const double scale_factor)
{
    double x0 = -1.0;
    double x1 = -1.0;
    double y0 = -1.0;
    double y1 = -1.0;
    foreach (Poppler::TextBox *box, page->textList()) {
        QRectF boundary = box->boundingBox();
        double x = boundary.x() / scale_factor;
        double y = boundary.y() / scale_factor;
        double width = boundary.width() / scale_factor;
        double height = boundary.height() / scale_factor;
        x0 = x0 < 0.0 ? x : qMin(x, x0);
        x1 = x1 < 0.0 ? x + width : qMax(x + width, x1);
        y0 = y0 < 0.0 ? y : qMin(y, y0);
        y1 = y1 < 0.0 ? x + height : qMax(y + height, y1);
    }
    if (x0 < 0.0 || x1 <= 0.0 || y0 < 0.0 || y1 <= 0.0)
        return QRectF();
    QRectF rect(x0, y0, x1 - x0, y1 - y0);
    if (!rect.isNull()) {
        // I don't know why...
        const double factor = scale_factor * 13;
        rect.adjust(-factor, -factor, factor * 3, factor * 3);
    }
    return rect;
}


void paginate2up(QPrinter &printer, PdfDocument pdf, const int gap,
                 bool expand, bool border)
{
    const double SCALE_FACTOR = printer.resolution() / 72.0;
    const double PAGE_WIDTH = printer.pageRect().width() - gap;
    const double PAGE_HEIGHT = printer.pageRect().height();
    const double ONE_WIDTH = PAGE_WIDTH / 2;
    const double ONE_HEIGHT = PAGE_HEIGHT;
    const int XS[2] = {0, int(ONE_WIDTH + gap)};
    const int YS[2] = {0, 0};
    const int ROW_COUNT = 1;
    const int COLUMN_COUNT = 2;

qDebug() << "one-width =" << ONE_WIDTH << "one-height =" << ONE_HEIGHT
    << "res = " << printer.resolution() << "scale = " << SCALE_FACTOR;

    QPainter painter(&printer);
    painter.setRenderHints(QPainter::Antialiasing|
                           QPainter::TextAntialiasing, false);
    int row = 0;
    int column = 0;
    for (int i = 0; i <  pdf->numPages(); ++i) {
        PdfPage page(pdf->page(i));
        QSizeF size = page->pageSizeF();
        QRectF boundaryRect;
        if (expand) {
            boundaryRect = pageBoundary(page, SCALE_FACTOR);
            if (!boundaryRect.isNull())
                size = boundaryRect.size();
        }
        const double DPI = printer.resolution() *
                qMin(ONE_WIDTH / size.width(), ONE_HEIGHT / size.height());

qDebug() << "dpi =" << DPI << "x =" << XS[column] << "y =" << YS[row]
    << size << boundaryRect;

        QImage image = page->renderToImage(DPI, DPI);
        if (expand && !boundaryRect.isNull())
            image = image.copy(boundaryRect.toRect()
                               .adjusted(-1, -1, 1, 1));
        if (border)
            painter.drawRect(QRectF(XS[column], YS[row], image.width(),
                             image.height()).adjusted(-2, -2, 2, 2));
        painter.drawImage(XS[column], YS[row], image);

        ++column;
        if (column == COLUMN_COUNT) {
            column = 0;
            ++row;
            if (row == ROW_COUNT) {
                row = 0;
                printer.newPage();
            }
        }
    }
    painter.end();
    if (row || column)
        printer.newPage();
}


int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    // TODO command line arg parsing
    // -o --outfile # defaults to infile-2.pdf (or -4 or -6)
    // -p --pagesize <a4>|letter # size of the actual output pages
    // -g --gap <12pt> # gap between the laid out pages
    // -x --expand  # if set, laid out pages' margins are ignored
    // -b --border # draw a border around each page
    // <-2>|-4|-6 # number of pages to lay out per actual page
    // last arg is assumed to be infile (and is the only mandatory arg)
    QString filename(argv[1]);

    PdfDocument pdf(Poppler::Document::load(filename));
    if (!pdf) {
        qDebug() << "Failed to load" << filename;
        return 1;
    }
    else if (pdf->isLocked()) {
        qDebug() << "Cannot read a locked PDF";
        pdf.reset();
        return 1;
    }
    pdf->setRenderHint(Poppler::Document::Antialiasing);
    pdf->setRenderHint(Poppler::Document::TextAntialiasing);

    // TODO set from command line args
    QPrinter printer(QPrinter::ScreenResolution); // 72 DPI
    printer.setOutputFormat(QPrinter::PdfFormat);
    printer.setOutputFileName("test.pdf");
    printer.setOrientation(QPrinter::Landscape);
    printer.setPaperSize(QPrinter::A4);
    //printer.setPageMargins(24, 24, 24, 24, QPrinter::Point);
    paginate2up(printer, pdf, 12, true, true);

    return 0;
}


# TODO QtCore only
SOURCES     += main.cpp
LIBS        += -lpoppler-qt4
INCLUDEPATH += /usr/include/poppler/qt4
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to