QTextDocument to PDF with watermarks and header/footer -> filesize too large?



  • Hi all

    I try to create a PDF from a QTextDocument that contains long QTextTable (resulting in a PDF with 100+ pages).

    When I just print the QTextDocument with QTextDocument::print(QPagedPaintDevice *printer) a PDF with for example 134 pages has about 1MB, which I think is not too bad.

    But when I try to put a footer and a watermark to each page, it results in a PDF that has about 30MB.
    Code used to generate the pages:

    void MyProject::paintPage(QPrinter &printer, int pageNumber, int pageCount, QPainter* painter, QTextDocument* doc, const QRectF& textRect, qreal footerHeight) {
        //qDebug() << "Printing page" << pageNumber;
        const QSizeF pageSize = printer.paperRect().size();
        //qDebug() << "pageSize=" << pageSize;
        QFont foo;
        foo.setPointSize(50);
        const double bm = mmToPixels(printer, 10);
        const QRectF borderRect(bm, bm, pageSize.width() - 2 * bm, pageSize.height() - 2 * bm);
    //    painter->drawRect(borderRect);
        float wa = -qRadiansToDegrees(atan2(borderRect.height(),borderRect.width()));
        paintWatermark(*painter," - - D R A F T - - ",borderRect.width()/2,borderRect.height()/2,wa,foo);
        painter->save();
        painter->setRenderHint(QPainter::TextAntialiasing,true);
        painter->setRenderHint(QPainter::HighQualityAntialiasing,false);
        qDebug() << painter->renderHints();
    
        // textPageRect is the rectangle in the coordinate system of the QTextDocument, in pixels,
        // and starting at (0,0) for the first page. Second page is at y=doc->pageSize().height().
        const QRectF textPageRect(0, pageNumber * doc->pageSize().height(), doc->pageSize().width(), doc->pageSize().height());
        // Clip the drawing so that the text of the other pages doesn't appear in the margins
        painter->setClipRect(textRect);
        // Translate so that 0,0 is now the page corner
        painter->translate(0, -textPageRect.top());
        // Translate so that 0,0 is the text rect corner
        painter->translate(textRect.left(), textRect.top());
        doc->drawContents(painter);
    
    
        painter->restore();
    
        // Footer: page number or "end"
        QRectF footerRect = textRect;
        footerRect.setTop(textRect.bottom());
        footerRect.setHeight(footerHeight);
    
        painter->drawLine(footerRect.left(),footerRect.top(),footerRect.right(),footerRect.top());
        painter->drawText(footerRect, Qt::AlignVCenter | Qt::AlignRight, QObject::tr("Page %1/%2").arg(pageNumber+1).arg(pageCount));
    }
    
    void MyProject::printDocument(QPrinter &printer, QTextDocument* doc, QWidget* parentWidget)
    {
        QPainter painter( &printer );
    
        QSizeF pageSize = printer.pageRect().size(); // page size in pixels
        // Calculate the rectangle where to lay out the text
        double tm = mmToPixels(printer, 12);
        qreal footerHeight = painter.fontMetrics().height();
        QRectF textRect(tm, tm, pageSize.width() - 2 * tm, pageSize.height() - 2 * tm - footerHeight);
        //qDebug() << "textRect=" << textRect;
        doc->setPageSize(textRect.size());
    
        const int pageCount = doc->pageCount();
        QProgressDialog dialog( QObject::tr( "Printing" ), QObject::tr( "Cancel" ), 0, pageCount, parentWidget );
        dialog.setWindowModality( Qt::ApplicationModal );
    
        bool firstPage = true;
    
        for (int pageIndex = 0; pageIndex < pageCount; ++pageIndex) {
            dialog.setValue( pageIndex);
            dialog.setLabelText(tr("Page %1 / %2").arg(pageIndex).arg(pageCount));
            if (dialog.wasCanceled())
                 break;
    
            if (!firstPage)
                printer.newPage();
    
            paintPage( printer, pageIndex, pageCount, &painter, doc, textRect, footerHeight );
            firstPage = false;
        }
    
    }
    
    void MyProject::paintWatermark(QPainter &p, QString wm, int x, int y, float a, QFont font) {
        p.save();
        p.setFont(font);
        font.setWeight(QFont::Bold);
        p.translate(x,y);
        p.rotate(a);
        p.setPen(Qt::lightGray);
        p.setOpacity(0.3);
        p.drawText(-p.fontMetrics().width(wm)/2,p.fontMetrics().height()/2,wm);
    //    p.resetTransform();
    //    p.setOpacity(1);
        p.restore();
    
    }
    
    /*
    the printer is defined as
    QPrinter p;
    p.setOutputFileName("/tmp/test.pdf");
    p.setOutputFormat(QPrinter::PdfFormat);
    p.setPageSize(QPrinter::A4);
    p.setOrientation(QPrinter::Portrait);
    p.setResolution(96);
    printDocument(p,&doc,this);
    */
    

    What am I doing wrong here?



  • I think i just solved the problem myself.

    adding a clipping rect to QTextDocument::drawContents() makes the resulting PDF much smaller (1.1MB for 134 pages)

    sorry for the noise


  • Qt Champions 2016

    @the_
    Very good info :) thank you.



  • @mrjj

    Seems that drawContents() always draws the full QTextDocument to the given painter if you miss the second parameter. So in my case it was drawing 134 times 134 pages to the PDF :)


  • Qt Champions 2016

    @the_
    Oh, that's pretty good to know. It can get very huge otherwise ;)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.