OSDN Git Service

effectively revert 6157a323582fc3ec8fa6601a6cb9485624613748, 90110af1acb56c683116886b...
authorIvailo Monev <xakepa10@gmail.com>
Tue, 24 Aug 2021 01:00:48 +0000 (04:00 +0300)
committerIvailo Monev <xakepa10@gmail.com>
Tue, 24 Aug 2021 01:00:48 +0000 (04:00 +0300)
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
src/gui/effects/qgraphicseffect.cpp
src/gui/effects/qgraphicseffect.h
src/gui/effects/qgraphicseffect_p.h
src/gui/graphicsview/qgraphicsitem_p.h
src/gui/kernel/qwidget_p.h

index a540e2f..90b2443 100644 (file)
@@ -155,8 +155,21 @@ QRectF QGraphicsEffect::sourceBoundingRect(Qt::CoordinateSystem system) const
 }
 
 /*!
+    Returns a pointer to the item if this source is a QGraphicsItem; otherwise
+    returns 0.
+
+    \sa widget()
+*/
+const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const
+{
+    return d_func()->graphicsItem();
+}
+
+/*!
     Returns a pointer to the widget if this source is a QWidget; otherwise
     returns 0.
+
+    \sa graphicsItem()
 */
 const QWidget *QGraphicsEffectSource::widget() const
 {
@@ -164,6 +177,17 @@ const QWidget *QGraphicsEffectSource::widget() const
 }
 
 /*!
+    Returns a pointer to the style options (used when drawing the source) if
+    available; otherwise returns 0.
+
+    \sa graphicsItem(), widget()
+*/
+const QStyleOption *QGraphicsEffectSource::styleOption() const
+{
+    return d_func()->styleOption();
+}
+
+/*!
     Draws the source using the given \a painter.
 
     This function should only be called from QGraphicsEffect::draw().
@@ -222,6 +246,32 @@ void QGraphicsEffectSource::update()
 }
 
 /*!
+    Returns true if the source effectively is a pixmap, e.g., a
+    QGraphicsPixmapItem.
+
+    This function is useful for optimization purposes. For instance, there's no
+    point in drawing the source in device coordinates to avoid pixmap scaling
+    if this function returns true - the source pixmap will be scaled anyways.
+*/
+bool QGraphicsEffectSource::isPixmap() const
+{
+    return d_func()->isPixmap();
+}
+
+/*!
+    Returns true if the source effectively is a pixmap, e.g., a
+    QGraphicsPixmapItem.
+
+    This function is useful for optimization purposes. For instance, there's no
+    point in drawing the source in device coordinates to avoid pixmap scaling
+    if this function returns true - the source pixmap will be scaled anyways.
+*/
+bool QGraphicsEffect::sourceIsPixmap() const
+{
+    return source() ? source()->isPixmap() : false;
+}
+
+/*!
     Returns a pixmap with the source painted into it.
 
     The \a system specifies which coordinate system to be used for the source.
@@ -240,12 +290,33 @@ QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offse
 {
     Q_D(const QGraphicsEffectSource);
 
-    QPixmap pm = d->pixmap(system, &d->m_cachedOffset, mode);
-    d->m_cachedSystem = system;
-    d->m_cachedMode = mode;
+    // Shortcut, no cache for childless pixmap items...
+    const QGraphicsItem *item = graphicsItem();
+    if (system == Qt::LogicalCoordinates && mode == QGraphicsEffect::NoPad && item && isPixmap()) {
+        const QGraphicsPixmapItem *pixmapItem = static_cast<const QGraphicsPixmapItem *>(item);
+        if (offset)
+            *offset = pixmapItem->offset().toPoint();
+        return pixmapItem->pixmap();
+    }
 
-    d->invalidateCache();
-    d->m_cacheKey = QPixmapCache::insert(pm);
+    if (system == Qt::DeviceCoordinates && item
+        && !static_cast<const QGraphicsItemEffectSourcePrivate *>(d_func())->info) {
+        qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+        return QPixmap();
+    }
+
+    QPixmap pm;
+    if (item && d->m_cachedSystem == system && d->m_cachedMode == mode)
+        QPixmapCache::find(d->m_cacheKey, &pm);
+
+    if (pm.isNull()) {
+        pm = d->pixmap(system, &d->m_cachedOffset, mode);
+        d->m_cachedSystem = system;
+        d->m_cachedMode = mode;
+
+        d->invalidateCache();
+        d->m_cacheKey = QPixmapCache::insert(pm);
+    }
 
     if (offset)
         *offset = d->m_cachedOffset;
@@ -602,6 +673,15 @@ void QGraphicsColorizeEffect::draw(QPainter *painter)
     }
 
     QPoint offset;
+    if (sourceIsPixmap()) {
+        // No point in drawing in device coordinates (pixmap will be scaled anyways).
+        const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, NoPad);
+        if (!pixmap.isNull())
+            d->filter->draw(painter, offset, pixmap);
+
+        return;
+    }
+
     // Draw pixmap in deviceCoordinates to avoid pixmap scaling.
     const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
     if (pixmap.isNull())
@@ -1092,7 +1172,8 @@ void QGraphicsOpacityEffect::draw(QPainter *painter)
     }
 
     QPoint offset;
-    QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, QGraphicsEffect::NoPad);
+    Qt::CoordinateSystem system = sourceIsPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates;
+    QPixmap pixmap = sourcePixmap(system, &offset, QGraphicsEffect::NoPad);
     if (pixmap.isNull())
         return;
 
@@ -1103,13 +1184,19 @@ void QGraphicsOpacityEffect::draw(QPainter *painter)
         QPainter pixmapPainter(&pixmap);
         pixmapPainter.setRenderHints(painter->renderHints());
         pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
-        QTransform worldTransform = painter->worldTransform();
-        worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y());
-        pixmapPainter.setWorldTransform(worldTransform);
-        pixmapPainter.fillRect(sourceBoundingRect(), d->opacityMask);
+        if (system == Qt::DeviceCoordinates) {
+            QTransform worldTransform = painter->worldTransform();
+            worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y());
+            pixmapPainter.setWorldTransform(worldTransform);
+            pixmapPainter.fillRect(sourceBoundingRect(), d->opacityMask);
+        } else {
+            pixmapPainter.translate(-offset);
+            pixmapPainter.fillRect(pixmap.rect(), d->opacityMask);
+        }
     }
 
-    painter->setWorldTransform(QTransform());
+    if (system == Qt::DeviceCoordinates)
+        painter->setWorldTransform(QTransform());
 
     painter->drawPixmap(offset, pixmap);
     painter->restore();
index faa4f48..958af8d 100644 (file)
@@ -82,6 +82,7 @@ protected:
     virtual void sourceChanged(ChangeFlags flags);
     void updateBoundingRect();
 
+    bool sourceIsPixmap() const;
     QRectF sourceBoundingRect(Qt::CoordinateSystem system = Qt::LogicalCoordinates) const;
     void drawSource(QPainter *painter);
     QPixmap sourcePixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates,
index 57fe145..e976d8b 100644 (file)
@@ -49,8 +49,11 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject
     Q_OBJECT
 public:
     ~QGraphicsEffectSource();
+    const QGraphicsItem *graphicsItem() const;
     const QWidget *widget() const;
+    const QStyleOption *styleOption() const;
 
+    bool isPixmap() const;
     void draw(QPainter *painter);
     void update();
 
@@ -96,9 +99,12 @@ public:
     virtual void detach() = 0;
     virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0;
     virtual QRect deviceRect() const = 0;
+    virtual const QGraphicsItem *graphicsItem() const = 0;
     virtual const QWidget *widget() const = 0;
+    virtual const QStyleOption *styleOption() const = 0;
     virtual void draw(QPainter *p) = 0;
     virtual void update() = 0;
+    virtual bool isPixmap() const = 0;
     virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0,
                            QGraphicsEffect::PixmapPadMode mode = QGraphicsEffect::PadToTransparentBorder) const = 0;
     virtual void effectBoundingRectChanged() = 0;
index 0ab1302..552bb04 100644 (file)
@@ -637,7 +637,7 @@ public:
     { return item; }
 
     inline const QWidget *widget() const
-    { return 0; }
+    { return nullptr; }
 
     inline void update() {
         item->d_ptr->updateDueToGraphicsEffect = true;
index 8d1b746..e46aa08 100644 (file)
@@ -623,6 +623,9 @@ public:
     inline void detach()
     { m_widget->d_func()->graphicsEffect = 0; }
 
+    inline const QGraphicsItem *graphicsItem() const
+    { return nullptr; }
+
     inline const QWidget *widget() const
     { return m_widget; }
 
@@ -633,6 +636,9 @@ public:
         updateDueToGraphicsEffect = false;
     }
 
+    inline bool isPixmap() const
+    { return false; }
+
     inline void effectBoundingRectChanged()
     {
         // ### This function should take a rect parameter; then we can avoid
@@ -643,6 +649,9 @@ public:
             update();
     }
 
+    inline const QStyleOption *styleOption() const
+    { return nullptr; }
+
     inline QRect deviceRect() const
     { return m_widget->window()->rect(); }