Get rid of remaining QWidget dependencies in QPainter.

This commit is contained in:
Samuel Rødal 2011-05-04 10:02:42 +02:00
parent 862263b0ab
commit 8d5df33f9c
6 changed files with 57 additions and 130 deletions

View File

@ -5559,7 +5559,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
if (!sharedPainter)
paintEngine->d_func()->systemRect = QRect();
else
paintEngine->d_func()->currentClipWidget = 0;
paintEngine->d_func()->currentClipDevice = 0;
paintEngine->d_func()->systemClip = QRegion();
}
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
@ -12516,6 +12516,27 @@ void QWidget::init(QPainter *painter) const
painter->d_func()->state->font = f;
}
QPaintDevice *QWidget::redirected(QPoint *offset) const
{
return d_func()->redirected(offset);
}
QPainter *QWidget::sharedPainter() const
{
// Someone sent a paint event directly to the widget
if (!d_func()->redirectDev)
return 0;
QPainter *sp = d_func()->sharedPainter();
if (!sp || !sp->isActive())
return 0;
if (sp->paintEngine()->paintDevice() != d_func()->redirectDev)
return 0;
return sp;
}
/*!
\fn void QWidget::setMask(const QRegion &region)
\overload

View File

@ -703,6 +703,8 @@ protected:
int metric(PaintDeviceMetric) const;
void init(QPainter *painter) const;
QPaintDevice *redirected(QPoint *offset) const;
QPainter *sharedPainter() const;
virtual void inputMethodEvent(QInputMethodEvent *);
public:

View File

@ -67,10 +67,20 @@ int QPaintDevice::metric(PaintDeviceMetric) const
}
#endif
void QPaintDevice::init(QPainter *painter) const
void QPaintDevice::init(QPainter *) const
{
}
QPaintDevice *QPaintDevice::redirected(QPoint *) const
{
return 0;
}
QPainter *QPaintDevice::sharedPainter() const
{
return 0;
}
Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, QPaintDevice::PaintDeviceMetric metric)
{
return device->metric(metric);

View File

@ -106,6 +106,8 @@ protected:
QPaintDevice();
virtual int metric(PaintDeviceMetric metric) const;
virtual void init(QPainter *painter) const;
virtual QPaintDevice *redirected(QPoint *offset) const;
virtual QPainter *sharedPainter() const;
ushort painters; // refcount
@ -113,6 +115,7 @@ private:
Q_DISABLE_COPY(QPaintDevice)
friend class QPainter;
friend class QPainterPrivate;
friend class QFontEngineMac;
friend class QX11PaintEngine;
friend Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, PaintDeviceMetric metric);

View File

@ -66,7 +66,7 @@ class QPaintEnginePrivate
{
Q_DECLARE_PUBLIC(QPaintEngine)
public:
QPaintEnginePrivate() : pdev(0), q_ptr(0), currentClipWidget(0), hasSystemTransform(0),
QPaintEnginePrivate() : pdev(0), q_ptr(0), currentClipDevice(0), hasSystemTransform(0),
hasSystemViewport(0) {}
virtual ~QPaintEnginePrivate() { }
QPaintDevice *pdev;
@ -75,7 +75,7 @@ public:
QRect systemRect;
QRegion systemViewport;
QTransform systemTransform;
QWidget *currentClipWidget;
QPaintDevice *currentClipDevice;
uint hasSystemTransform : 1;
uint hasSystemViewport : 1;

View File

@ -67,7 +67,6 @@
#include <private/qemulationpaintengine_p.h>
#include <private/qpainterpath_p.h>
#include <private/qtextengine_p.h>
#include <private/qwidget_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qmath_p.h>
#include <private/qstatictext_p.h>
@ -247,34 +246,10 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
Q_ASSERT(q);
Q_ASSERT(pdev);
if (pdev->devType() != QInternal::Widget)
QPainter *sp = pdev->sharedPainter();
if (!sp)
return false;
QWidget *widget = static_cast<QWidget *>(pdev);
Q_ASSERT(widget);
// Someone either called QPainter::setRedirected in the widget's paint event
// right before this painter was created (or begin was called) or
// sent a paint event directly to the widget.
if (!widget->d_func()->redirectDev)
return false;
QPainter *sp = widget->d_func()->sharedPainter();
if (!sp || !sp->isActive())
return false;
if (sp->paintEngine()->paintDevice() != widget->d_func()->redirectDev)
return false;
// Check if we're attempting to paint outside a paint event.
if (!sp->d_ptr->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
&& !widget->testAttribute(Qt::WA_PaintOutsidePaintEvent)
&& !widget->testAttribute(Qt::WA_WState_InPaintEvent)) {
qWarning("QPainter::begin: Widget painting can only begin as a result of a paintEvent");
return false;
}
// Save the current state of the shared painter and assign
// the current d_ptr to the shared painter's d_ptr.
sp->save();
@ -298,14 +273,14 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
Q_ASSERT(q->d_ptr->state);
// Now initialize the painter with correct widget properties.
q->initFrom(widget);
q->initFrom(pdev);
QPoint offset;
widget->d_func()->redirected(&offset);
pdev->redirected(&offset);
offset += q->d_ptr->engine->coordinateOffset();
// Update system rect.
q->d_ptr->state->ww = q->d_ptr->state->vw = widget->width();
q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
q->d_ptr->state->ww = q->d_ptr->state->vw = pdev->width();
q->d_ptr->state->wh = q->d_ptr->state->vh = pdev->height();
// Update matrix.
if (q->d_ptr->state->WxF) {
@ -319,13 +294,13 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
q->d_ptr->updateMatrix();
QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
if (enginePrivate->currentClipWidget == widget) {
if (enginePrivate->currentClipDevice == pdev) {
enginePrivate->systemStateChanged();
return true;
}
// Update system transform and clip.
enginePrivate->currentClipWidget = widget;
enginePrivate->currentClipDevice = pdev;
enginePrivate->setSystemTransform(q->d_ptr->state->matrix);
return true;
}
@ -1536,8 +1511,8 @@ QPainter::~QPainter()
QPaintDevice *QPainter::device() const
{
Q_D(const QPainter);
if (isActive() && d->engine->d_func()->currentClipWidget)
return d->engine->d_func()->currentClipWidget;
if (isActive() && d->engine->d_func()->currentClipDevice)
return d->engine->d_func()->currentClipDevice;
return d->original_device;
}
@ -1745,22 +1720,9 @@ bool QPainter::begin(QPaintDevice *pd)
d->helper_device = pd;
d->original_device = pd;
QPaintDevice *rpd = 0;
QPoint redirectionOffset;
// We know for sure that redirection is broken when the widget is inside
// its paint event, so it's safe to use our hard-coded redirection. However,
// there IS one particular case we still need to support, and that's
// when people call QPainter::setRedirected in the widget's paint event right
// before any painter is created (or QPainter::begin is called). In that
// particular case our hard-coded redirection is restored and the redirection
// is retrieved from QPainter::redirected (as before).
if (pd->devType() == QInternal::Widget)
rpd = static_cast<QWidget *>(pd)->d_func()->redirected(&redirectionOffset);
if (!rpd)
rpd = redirected(pd, &redirectionOffset);
QPaintDevice *rpd = pd->redirected(&redirectionOffset);
if (rpd)
pd = rpd;
@ -1803,6 +1765,8 @@ bool QPainter::begin(QPaintDevice *pd)
d->engine->state = d->state;
switch (pd->devType()) {
#if 0
// is this needed any more??
case QInternal::Widget:
{
const QWidget *widget = static_cast<const QWidget *>(pd);
@ -1810,13 +1774,6 @@ bool QPainter::begin(QPaintDevice *pd)
const bool paintOutsidePaintEvent = widget->testAttribute(Qt::WA_PaintOutsidePaintEvent);
const bool inPaintEvent = widget->testAttribute(Qt::WA_WState_InPaintEvent);
if(!d->engine->hasFeature(QPaintEngine::PaintOutsidePaintEvent)
&& !paintOutsidePaintEvent && !inPaintEvent) {
qWarning("QPainter::begin: Widget painting can only begin as a "
"result of a paintEvent");
qt_cleanup_painter_state(d);
return false;
}
// Adjust offset for alien widgets painting outside the paint event.
if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
@ -1826,6 +1783,7 @@ bool QPainter::begin(QPaintDevice *pd)
}
break;
}
#endif
case QInternal::Pixmap:
{
QPixmap *pm = static_cast<QPixmap *>(pd);
@ -1886,8 +1844,7 @@ bool QPainter::begin(QPaintDevice *pd)
// Copy painter properties from original paint device,
// required for QPixmap::grabWidget()
if (d->original_device->devType() == QInternal::Widget) {
QWidget *widget = static_cast<QWidget *>(d->original_device);
initFrom(widget);
initFrom(d->original_device);
} else {
d->state->layoutDirection = Qt::LayoutDirectionAuto;
// make sure we have a font compatible with the paintdevice
@ -7462,29 +7419,7 @@ void QPainter::setRedirected(const QPaintDevice *device,
{
Q_ASSERT(device != 0);
bool hadInternalWidgetRedirection = false;
if (device->devType() == QInternal::Widget) {
const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
// This is the case when the widget is in a paint event.
if (widgetPrivate->redirectDev) {
// Remove internal redirection and put it back into the global redirection list.
QPoint oldOffset;
QPaintDevice *oldReplacement = widgetPrivate->redirected(&oldOffset);
const_cast<QWidgetPrivate *>(widgetPrivate)->restoreRedirected();
setRedirected(device, oldReplacement, oldOffset);
hadInternalWidgetRedirection = true;
}
}
QPoint roffset;
QPaintDevice *rdev = redirected(replacement, &roffset);
QMutexLocker locker(globalRedirectionsMutex());
QPaintDeviceRedirectionList *redirections = globalRedirections();
Q_ASSERT(redirections != 0);
*redirections += QPaintDeviceRedirection(device, rdev ? rdev : replacement, offset + roffset,
hadInternalWidgetRedirection ? redirections->size() - 1 : -1);
globalRedirectionAtomic()->ref();
qWarning() << "QPainter::setRedirected(): ignoring call to deprecated function, use QWidget::render() instead";
}
/*!
@ -7506,29 +7441,7 @@ void QPainter::setRedirected(const QPaintDevice *device,
*/
void QPainter::restoreRedirected(const QPaintDevice *device)
{
Q_ASSERT(device != 0);
QMutexLocker locker(globalRedirectionsMutex());
QPaintDeviceRedirectionList *redirections = globalRedirections();
Q_ASSERT(redirections != 0);
for (int i = redirections->size()-1; i >= 0; --i) {
if (redirections->at(i) == device) {
globalRedirectionAtomic()->deref();
const int internalWidgetRedirectionIndex = redirections->at(i).internalWidgetRedirectionIndex;
redirections->removeAt(i);
// Restore the internal widget redirection, i.e. remove it from the global
// redirection list and put it back into QWidgetPrivate. The index is only set when
// someone call QPainter::setRedirected in a widget's paint event and we internally
// have a redirection set (typically set in QWidgetPrivate::drawWidget).
if (internalWidgetRedirectionIndex >= 0) {
Q_ASSERT(internalWidgetRedirectionIndex < redirections->size());
const QPaintDeviceRedirection &redirectionDevice = redirections->at(internalWidgetRedirectionIndex);
QWidget *widget = static_cast<QWidget *>(const_cast<QPaintDevice *>(device));
widget->d_func()->setRedirected(redirectionDevice.replacement, redirectionDevice.offset);
redirections->removeAt(internalWidgetRedirectionIndex);
}
return;
}
}
qWarning() << "QPainter::restoreRedirected(): ignoring call to deprecated function, use QWidget::render() instead";
}
/*!
@ -7550,28 +7463,6 @@ void QPainter::restoreRedirected(const QPaintDevice *device)
*/
QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
{
Q_ASSERT(device != 0);
if (device->devType() == QInternal::Widget) {
const QWidgetPrivate *widgetPrivate = static_cast<const QWidget *>(device)->d_func();
if (widgetPrivate->redirectDev)
return widgetPrivate->redirected(offset);
}
if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return 0;
QMutexLocker locker(globalRedirectionsMutex());
QPaintDeviceRedirectionList *redirections = globalRedirections();
Q_ASSERT(redirections != 0);
for (int i = redirections->size()-1; i >= 0; --i)
if (redirections->at(i) == device) {
if (offset)
*offset = redirections->at(i).offset;
return redirections->at(i).replacement;
}
if (offset)
*offset = QPoint(0, 0);
return 0;
}