Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTextDocument to PDF with watermarks and header/footer -> filesize too large?
Forum Update on Monday, May 27th 2025

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

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 5.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • the_T Offline
    the_T Offline
    the_
    wrote on last edited by
    #1

    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?

    -- No support in PM --

    1 Reply Last reply
    1
    • the_T Offline
      the_T Offline
      the_
      wrote on last edited by
      #2

      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

      -- No support in PM --

      mrjjM 1 Reply Last reply
      4
      • the_T the_

        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

        mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @the_
        Very good info :) thank you.

        the_T 1 Reply Last reply
        0
        • mrjjM mrjj

          @the_
          Very good info :) thank you.

          the_T Offline
          the_T Offline
          the_
          wrote on last edited by
          #4

          @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 :)

          -- No support in PM --

          mrjjM 1 Reply Last reply
          1
          • the_T the_

            @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 :)

            mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

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

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved