Multi-threaded text layout and printing

Published Thursday September 27th, 2007
7 Comments on Multi-threaded text layout and printing
Posted in Painting, Qt, Threads

I just integrated a series of changes that adds support for doing multi-threaded text layout and printing. So it is now safe to use QFont and QFontMetrics outside the GUI thread. This means QPainter::drawText() works too (when painting on QImage, QPrinter, and QPicture). We’ve also done changes to QTextDocument that allow it to be cloned and passed off to a thread, so that all the layouting and printing happens without blocking the GUI.

For those interested, you can checkout tonight’s 4.4 snapshot. In tools/assistant/mainwindow.cpp, you’ll see code like this:

void PrintThread::start(QTextDocument *document)
{
    _document = document->clone();
    _document->moveToThread(this);
    QThread::start();
}

void PrintThread::run()
{
    _document->print(printer());
    delete _document;
    _document = 0;
}

void MainWindow::on_actionFilePrint_triggered()
{
    if (!QFontDatabase::supportsThreadedFontRendering()) {
        QPrinter printer(QPrinter::HighResolution);
        printer.setFullPage(true);

        QPrintDialog dlg(&printer, this);
        if (dlg.exec() == QDialog::Accepted) {
            qApp->setOverrideCursor(Qt::WaitCursor);
            tabs->currentBrowser()->document()->print(&printer);
            qApp->restoreOverrideCursor();
        }
        return;
    }

    PrintThread *thread = new PrintThread(this);

    QPrintDialog dlg(thread->printer(), this);
    if (dlg.exec() == QDialog::Accepted) {
        connect(thread, SIGNAL(finished()), SLOT(printingFinished()));
        connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

        qApp->setOverrideCursor(Qt::BusyCursor);
        thread->start(tabs->currentBrowser()->document());
    } else {
        delete thread;
    }
}

void MainWindow::printingFinished()
{
    qApp->restoreOverrideCursor();
}

The Thread Support in Qt documentation has also been updated to show what is supported (Note, at the time of writing, the snapshot documentation has not been updated, check back later if you don’t have a 4.4 snapshot after 27 Sep 2007).

And just to be clear, painting onto a QPixmap or a QWidget outside the GUI is not supported at all. We are looking at ways of making the GL paint engine safe for painting on to FrameBufferObjects and/or Pbuffers, which may or may not make it into 4.4.

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Painting, Qt, Threads

7 comments

Marc says:

This is great! I just wonder what QFontDatabase::supportsThreadedFontRendering() is supposed to do. It’s not in 4.3.,, and if it’s going to be in 4.4, that means that there are platforms or configurations in which it is false. Which are these?

brad says:

QFontDatabase::supportsThreadedFontRendering() is necessary on X11 systems that don’t have FontConfig. All of the fonts are bitmap fonts that reside on the X server (we don’t get direct access to the font). Due to Xlib limitations, we can’t ask for the bitmaps outside the GUI thread either, so we basically have to say that text rendering on such system doesn’t work outside the GUI thread. We made this a run-time check since Qt/X11 allows people to turn off FontConfig (export QT_X11_NO_FONTCONFIG=1).

Kevin Kofler says:

Why would one want to use the ancient deprecated X11 font system anyway? FontConfig is the way to go.

Will Stokes says:

This is truely outstanding. Wrt not being able ot multithread painting onto a QPixmap, an easy workaround would simply be to paint onto a QImage and let your GUI thread convert QImage’s to QPixmap’s or splace QImages’s onto the widget directly, correct? In other words, what can’t be accomplished now?! ๐Ÿ™‚

brad says:

Sometimes it’s not a matter of choice. We support AIX, HP-UX, HP-UXi, IRIX, and Solaris as well. Most of these don’t have FontConfig installed (newer Solaris installations do, thankfully :D).

Marius says:

Great news! But when you clone QTextDocument and pass it to another thread, what happens with userData() objects?

Romain says:

“painting onto a QPixmap […] outside the GUI is not supported at all”

Huh ? Is that something specific to QTextDocument ? or is it a change in 4.4 ? I’ve never heard of drawing on a QPixmap not being supported outside the GUI thread.

Commenting closed.

Get started today with Qt Download now