src/gui/painting/qpainter.cpp
changeset 18 2f34d5167611
parent 3 41300fa6a67c
child 25 e24348a560a6
equal deleted inserted replaced
3:41300fa6a67c 18:2f34d5167611
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     8 **
     8 **
   706                           || brushStyle == Qt::TexturePattern));
   706                           || brushStyle == Qt::TexturePattern));
   707 
   707 
   708         bool penTextureAlpha = false;
   708         bool penTextureAlpha = false;
   709         if (penBrush.style() == Qt::TexturePattern)
   709         if (penBrush.style() == Qt::TexturePattern)
   710             penTextureAlpha = qHasPixmapTexture(penBrush)
   710             penTextureAlpha = qHasPixmapTexture(penBrush)
   711                               ? penBrush.texture().hasAlpha()
   711                               ? (penBrush.texture().depth() > 1) && penBrush.texture().hasAlpha()
   712                               : penBrush.textureImage().hasAlphaChannel();
   712                               : penBrush.textureImage().hasAlphaChannel();
   713         bool brushTextureAlpha = false;
   713         bool brushTextureAlpha = false;
   714         if (s->brush.style() == Qt::TexturePattern)
   714         if (s->brush.style() == Qt::TexturePattern) {
   715             brushTextureAlpha = qHasPixmapTexture(s->brush)
   715             brushTextureAlpha = qHasPixmapTexture(s->brush)
   716                                 ? s->brush.texture().hasAlpha()
   716                                 ? (s->brush.texture().depth() > 1) && s->brush.texture().hasAlpha()
   717                                 : s->brush.textureImage().hasAlphaChannel();
   717                                 : s->brush.textureImage().hasAlphaChannel();
       
   718         }
   718         if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
   719         if (((penBrush.style() == Qt::TexturePattern && penTextureAlpha)
   719              || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
   720              || (s->brush.style() == Qt::TexturePattern && brushTextureAlpha))
   720             && !engine->hasFeature(QPaintEngine::MaskedBrush))
   721             && !engine->hasFeature(QPaintEngine::MaskedBrush))
   721             s->emulationSpecifier |= QPaintEngine::MaskedBrush;
   722             s->emulationSpecifier |= QPaintEngine::MaskedBrush;
   722         else
   723         else
  1327     implications for performance, and ensuring that every single
  1328     implications for performance, and ensuring that every single
  1328     operation is fast in combination with all the various combinations
  1329     operation is fast in combination with all the various combinations
  1329     of composition modes, brushes, clipping, transformation, etc, is
  1330     of composition modes, brushes, clipping, transformation, etc, is
  1330     close to an impossible task because of the number of
  1331     close to an impossible task because of the number of
  1331     permutations. As a compromise we have selected a subset of the
  1332     permutations. As a compromise we have selected a subset of the
  1332     QPainter API and backends, were performance is guaranteed to be as
  1333     QPainter API and backends, where performance is guaranteed to be as
  1333     good as we can sensibly get it for the given combination of
  1334     good as we can sensibly get it for the given combination of
  1334     hardware and software.
  1335     hardware and software.
  1335 
  1336 
  1336     The backends we focus on as high-performance engines are:
  1337     The backends we focus on as high-performance engines are:
  1337 
  1338 
  1371     0, 90, 180, 270 degree rotations.
  1372     0, 90, 180, 270 degree rotations.
  1372 
  1373 
  1373     \o \c drawPixmap() in combination with simple transformations and
  1374     \o \c drawPixmap() in combination with simple transformations and
  1374     opacity with non-smooth transformation mode
  1375     opacity with non-smooth transformation mode
  1375     (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
  1376     (\c QPainter::SmoothPixmapTransform not enabled as a render hint).
  1376 
       
  1377     \o Text drawing with regular font sizes with simple
       
  1378     transformations with solid colors using no or 8-bit antialiasing.
       
  1379 
  1377 
  1380     \o Rectangle fills with solid color, two-color linear gradients
  1378     \o Rectangle fills with solid color, two-color linear gradients
  1381     and simple transforms.
  1379     and simple transforms.
  1382 
  1380 
  1383     \o Rectangular clipping with simple transformations and intersect
  1381     \o Rectangular clipping with simple transformations and intersect
  1982 }
  1980 }
  1983 
  1981 
  1984 /*!
  1982 /*!
  1985     \since 4.6
  1983     \since 4.6
  1986 
  1984 
  1987     Flushes the painting pipeline and prepares for the user issuing
  1985     Flushes the painting pipeline and prepares for the user issuing commands
  1988     commands directly to the underlying graphics context. Must be
  1986     directly to the underlying graphics context. Must be followed by a call to
  1989     followed by a call to endNativePainting().
  1987     endNativePainting().
  1990 
  1988 
  1991     Here is an example that shows intermixing of painter commands
  1989     Note that only the states the underlying paint engine changes will be reset
  1992     and raw OpenGL commands:
  1990     to their respective default states. The states we reset may change from
       
  1991     release to release. The following states are currently reset in the OpenGL
       
  1992     2 engine:
       
  1993 
       
  1994     \list
       
  1995     \i blending is disabled
       
  1996     \i the depth, stencil and scissor tests are disabled
       
  1997     \i the active texture unit is reset to 0
       
  1998     \i the depth mask, depth function and the clear depth are reset to their
       
  1999     default values
       
  2000     \i the stencil mask, stencil operation and stencil function are reset to
       
  2001     their default values
       
  2002      \i the current color is reset to solid white
       
  2003     \endlist
       
  2004 
       
  2005     If, for example, the OpenGL polygon mode is changed by the user inside a
       
  2006     beginNativePaint()/endNativePainting() block, it will not be reset to the
       
  2007     default state by endNativePainting(). Here is an example that shows
       
  2008     intermixing of painter commands and raw OpenGL commands:
  1993 
  2009 
  1994     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
  2010     \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21
  1995 
  2011 
  1996     \sa endNativePainting()
  2012     \sa endNativePainting()
  1997 */
  2013 */
  2008 }
  2024 }
  2009 
  2025 
  2010 /*!
  2026 /*!
  2011     \since 4.6
  2027     \since 4.6
  2012 
  2028 
  2013     Restores the painter after manually issuing native painting commands.
  2029     Restores the painter after manually issuing native painting commands. Lets
  2014     Lets the painter restore any native state that it relies on before
  2030     the painter restore any native state that it relies on before calling any
  2015     calling any other painter commands.
  2031     other painter commands.
  2016 
  2032 
  2017     \sa beginNativePainting()
  2033     \sa beginNativePainting()
  2018 */
  2034 */
  2019 void QPainter::endNativePainting()
  2035 void QPainter::endNativePainting()
  2020 {
  2036 {
  7378 };
  7394 };
  7379 
  7395 
  7380 typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
  7396 typedef QList<QPaintDeviceRedirection> QPaintDeviceRedirectionList;
  7381 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
  7397 Q_GLOBAL_STATIC(QPaintDeviceRedirectionList, globalRedirections)
  7382 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
  7398 Q_GLOBAL_STATIC(QMutex, globalRedirectionsMutex)
       
  7399 Q_GLOBAL_STATIC(QAtomicInt, globalRedirectionAtomic)
  7383 
  7400 
  7384 /*!
  7401 /*!
  7385     \threadsafe
  7402     \threadsafe
       
  7403 
       
  7404     \obsolete
       
  7405 
       
  7406     Please use QWidget::render() instead.
  7386 
  7407 
  7387     Redirects all paint commands for the given paint \a device, to the
  7408     Redirects all paint commands for the given paint \a device, to the
  7388     \a replacement device. The optional point \a offset defines an
  7409     \a replacement device. The optional point \a offset defines an
  7389     offset within the source device.
  7410     offset within the source device.
  7390 
  7411 
  7391     The redirection will not be effective until the begin() function
  7412     The redirection will not be effective until the begin() function
  7392     has been called; make sure to call end() for the given \a
  7413     has been called; make sure to call end() for the given \a
  7393     device's painter (if any) before redirecting. Call
  7414     device's painter (if any) before redirecting. Call
  7394     restoreRedirected() to restore the previous redirection.
  7415     restoreRedirected() to restore the previous redirection.
  7395 
  7416 
  7396     In general, you'll probably find that calling
  7417     \warning Making use of redirections in the QPainter API implies
  7397     QPixmap::grabWidget() or QPixmap::grabWindow() is an easier
  7418     that QPainter::begin() and QPaintDevice destructors need to hold
  7398     solution.
  7419     a mutex for a short period. This can impact performance. Use of
       
  7420     QWidget::render is strongly encouraged.
  7399 
  7421 
  7400     \sa redirected(), restoreRedirected()
  7422     \sa redirected(), restoreRedirected()
  7401 */
  7423 */
  7402 void QPainter::setRedirected(const QPaintDevice *device,
  7424 void QPainter::setRedirected(const QPaintDevice *device,
  7403                              QPaintDevice *replacement,
  7425                              QPaintDevice *replacement,
  7425     QMutexLocker locker(globalRedirectionsMutex());
  7447     QMutexLocker locker(globalRedirectionsMutex());
  7426     QPaintDeviceRedirectionList *redirections = globalRedirections();
  7448     QPaintDeviceRedirectionList *redirections = globalRedirections();
  7427     Q_ASSERT(redirections != 0);
  7449     Q_ASSERT(redirections != 0);
  7428     *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
  7450     *redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
  7429                                              hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
  7451                                              hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
       
  7452     globalRedirectionAtomic()->ref();
  7430 }
  7453 }
  7431 
  7454 
  7432 /*!
  7455 /*!
  7433     \threadsafe
  7456     \threadsafe
       
  7457 
       
  7458     \obsolete
       
  7459 
       
  7460     Using QWidget::render() obsoletes the use of this function.
  7434 
  7461 
  7435     Restores the previous redirection for the given \a device after a
  7462     Restores the previous redirection for the given \a device after a
  7436     call to setRedirected().
  7463     call to setRedirected().
       
  7464 
       
  7465     \warning Making use of redirections in the QPainter API implies
       
  7466     that QPainter::begin() and QPaintDevice destructors need to hold
       
  7467     a mutex for a short period. This can impact performance. Use of
       
  7468     QWidget::render is strongly encouraged.
  7437 
  7469 
  7438     \sa redirected()
  7470     \sa redirected()
  7439  */
  7471  */
  7440 void QPainter::restoreRedirected(const QPaintDevice *device)
  7472 void QPainter::restoreRedirected(const QPaintDevice *device)
  7441 {
  7473 {
  7443     QMutexLocker locker(globalRedirectionsMutex());
  7475     QMutexLocker locker(globalRedirectionsMutex());
  7444     QPaintDeviceRedirectionList *redirections = globalRedirections();
  7476     QPaintDeviceRedirectionList *redirections = globalRedirections();
  7445     Q_ASSERT(redirections != 0);
  7477     Q_ASSERT(redirections != 0);
  7446     for (int i = redirections->size()-1; i >= 0; --i) {
  7478     for (int i = redirections->size()-1; i >= 0; --i) {
  7447         if (redirections->at(i) == device) {
  7479         if (redirections->at(i) == device) {
       
  7480             globalRedirectionAtomic()->deref();
  7448             const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
  7481             const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
  7449             redirections->removeAt(i);
  7482             redirections->removeAt(i);
  7450             // Restore the internal widget redirection, i.e. remove it from the global
  7483             // Restore the internal widget redirection, i.e. remove it from the global
  7451             // redirection list and put it back into QWidgetPrivate. The index is only set when
  7484             // redirection list and put it back into QWidgetPrivate. The index is only set when
  7452             // someone call QPainter::setRedirected in a widget's paint event and we internally
  7485             // someone call QPainter::setRedirected in a widget's paint event and we internally
  7464 }
  7497 }
  7465 
  7498 
  7466 /*!
  7499 /*!
  7467     \threadsafe
  7500     \threadsafe
  7468 
  7501 
       
  7502     \obsolete
       
  7503 
       
  7504     Using QWidget::render() obsoletes the use of this function.
       
  7505 
  7469     Returns the replacement for given \a device. The optional out
  7506     Returns the replacement for given \a device. The optional out
  7470     parameter \a offset returns the offset within the replaced device.
  7507     parameter \a offset returns the offset within the replaced device.
       
  7508 
       
  7509     \warning Making use of redirections in the QPainter API implies
       
  7510     that QPainter::begin() and QPaintDevice destructors need to hold
       
  7511     a mutex for a short period. This can impact performance. Use of
       
  7512     QWidget::render is strongly encouraged.
  7471 
  7513 
  7472     \sa setRedirected(), restoreRedirected()
  7514     \sa setRedirected(), restoreRedirected()
  7473 */
  7515 */
  7474 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
  7516 QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
  7475 {
  7517 {
  7478     if (device->devType() == QInternal::Widget) {
  7520     if (device->devType() == QInternal::Widget) {
  7479         const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
  7521         const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
  7480         if (widgetPrivate->redirectDev)
  7522         if (widgetPrivate->redirectDev)
  7481             return widgetPrivate->redirected(offset);
  7523             return widgetPrivate->redirected(offset);
  7482     }
  7524     }
       
  7525 
       
  7526     if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
       
  7527         return 0;
  7483 
  7528 
  7484     QMutexLocker locker(globalRedirectionsMutex());
  7529     QMutexLocker locker(globalRedirectionsMutex());
  7485     QPaintDeviceRedirectionList *redirections = globalRedirections();
  7530     QPaintDeviceRedirectionList *redirections = globalRedirections();
  7486     Q_ASSERT(redirections != 0);
  7531     Q_ASSERT(redirections != 0);
  7487     for (int i = redirections->size()-1; i >= 0; --i)
  7532     for (int i = redirections->size()-1; i >= 0; --i)
  7496 }
  7541 }
  7497 
  7542 
  7498 
  7543 
  7499 void qt_painter_removePaintDevice(QPaintDevice *dev)
  7544 void qt_painter_removePaintDevice(QPaintDevice *dev)
  7500 {
  7545 {
       
  7546     if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
       
  7547         return;
       
  7548 
  7501     QMutex *mutex = 0;
  7549     QMutex *mutex = 0;
  7502     QT_TRY {
  7550     QT_TRY {
  7503         mutex = globalRedirectionsMutex();
  7551         mutex = globalRedirectionsMutex();
  7504     } QT_CATCH(...) {
  7552     } QT_CATCH(...) {
  7505         // ignore the missing mutex, since we could be called from
  7553         // ignore the missing mutex, since we could be called from