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