Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/gui/qt/widgets/native/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 9 kB image not shown  

Quelle  viewblockingrectangle.cpp   Sprache: C

 

/*****************************************************************************
 * Copyright (C) 2022 VLC authors and VideoLAN
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * ( at your option ) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


#include "viewblockingrectangle.hpp"

#include <QQuickWindow>
#include <QPainter>
#include <QPointer>
#include <QSGRectangleNode>
#include <QSGMaterial>
#include <QSGRenderNode>

class SoftwareRenderNode : public QSGRenderNode
{
public:
    void render(const RenderState *renderState) override
    {
        assert(m_window);
        const auto painter = static_cast<QPainter *>(m_window->rendererInterface()->getResource(m_window, QSGRendererInterface::PainterResource));
        assert(painter);

        painter->setCompositionMode(QPainter::CompositionMode_Source);

        const auto clipRegion = renderState->clipRegion();
        if (clipRegion && !clipRegion->isEmpty())
            painter->setClipRegion(*clipRegion, Qt::ReplaceClip);

        painter->setTransform(matrix()->toTransform());
        painter->setOpacity(inheritedOpacity());

        painter->fillRect(rect().toRect(), m_color);
    }

    RenderingFlags flags() const override
    {
        return BoundedRectRendering | DepthAwareRendering | OpaqueRendering;
    }

    QRectF rect() const override
    {
        return m_rect;
    }

    void setRect(const QRectF& rect)
    {
        if (m_rect != rect)
        {
            m_rect = rect;
            markDirty(DirtyGeometry);
        }
    }

    void setWindow(QQuickWindow* const window)
    {
        if (Q_LIKELY(m_window != window))
        {
            m_window = window;
            markDirty(DirtyForceUpdate);
        }
    }

    void setColor(const QColor& color)
    {
        if (m_color != color)
        {
            m_color = color;
            markDirty(DirtyMaterial);
        }
    }

private:
    QPointer<QQuickWindow> m_window = nullptr;
    QRectF m_rect;
    QColor m_color {Qt::transparent};
};

ViewBlockingRectangle::ViewBlockingRectangle(QQuickItem *parent)
    : QQuickItem(parent)
    , m_color(Qt::transparent)
{
    if (m_renderingEnabled || m_updateRenderPosition)
        setFlag(QQuickItem::ItemHasContents);
    connect(this, &ViewBlockingRectangle::colorChanged, this, &QQuickItem::update);
    connect(this, &ViewBlockingRectangle::windowChanged, this, [this] {
        if (window())
        {
            // The new window might use an appropriate graphics API:
            setFlag(QQuickItem::ItemHasContents);
            m_windowChanged = true;
        }
    });
}

QSGNode *ViewBlockingRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    QSGRectangleNode *rectangleNode = nullptr;
    SoftwareRenderNode *softwareRenderNode = nullptr;

    if (oldNode)
    {
        switch (oldNode->type())
        {
        case QSGNode::GeometryNodeType:
            assert(dynamic_cast<QSGRectangleNode*>(oldNode));
            rectangleNode = static_cast<QSGRectangleNode*>(oldNode);
            break;
        case QSGNode::RenderNodeType:
            // Can be `SoftwareRenderNode` or `MatrixChangeObserverNode`:
            softwareRenderNode = dynamic_cast<SoftwareRenderNode*>(oldNode);
            break;
        default:
            break;
        }
    }

    assert(window());
    const bool softwareMode = (window()->rendererInterface()->graphicsApi() == QSGRendererInterface::GraphicsApi::Software);

    if (m_renderingEnabled)
    {
        if (Q_UNLIKELY(oldNode && ((softwareMode && !softwareRenderNode)
                                   || (!softwareMode && !rectangleNode))))
        {
            delete oldNode;
            oldNode = nullptr;
        }
    }
    else
    {
        if (rectangleNode || softwareRenderNode || (!m_updateRenderPosition && oldNode))
        {
            // If `m_updateRenderPosition` is true, new node will be the observer node,
            // otherwise, we early return as a scene graph node is not necessary.
            // Currently we are not reparenting the observer node that could be reused
            // otherwise.
            delete oldNode;
            oldNode = nullptr;
        }

        if (!m_updateRenderPosition)
            return nullptr;
    }

    const auto createObserverNode = [this]() {
        const auto node = new MatrixChangeObserverNode([p = QPointer(this)](const QMatrix4x4& ;matrix) {
            if (Q_LIKELY(p))
            {
                p->m_renderPosition = {matrix.row(0)[3], // Viewport/scene X
                                       matrix.row(1)[3]}; // Viewport/scene y
                emit p->scenePositionHasChanged();
            }
        });
        node->setFlag(QSGNode::OwnedByParent);
        return node;
    };

    if (!oldNode)
    {
        MatrixChangeObserverNode *observerNode;

        if (m_updateRenderPosition)
        {
            observerNode = createObserverNode();

            // Initial position:
            m_renderPosition = mapToScene(QPointF(0,0));
        }
        else
        {
            observerNode = nullptr;
        }

        if (m_renderingEnabled)
        {
            if (softwareMode)
            {
                softwareRenderNode = new SoftwareRenderNode;
                softwareRenderNode->setWindow(window());
                if (observerNode)
                    softwareRenderNode->appendChildNode(observerNode);
            }
            else
            {
                rectangleNode = window()->createRectangleNode();
                assert(rectangleNode);
                if (observerNode)
                    rectangleNode->appendChildNode(observerNode);

                const auto material = rectangleNode->material();
                if (!material ||
                    material == reinterpret_cast<QSGMaterial*>(1) /* Qt may explicitly set the material pointer to 1 in OpenVG */)
                {
                    // Scene graph adaptation does not support shading
                    qmlDebug(this) << "ViewBlockingRectangle is being used under an incompatible scene graph adaptation.";
                    delete rectangleNode;
                    setFlag(QQuickItem::ItemHasContents, false);
                    return nullptr;
                }

                rectangleNode->material()->setFlag(QSGMaterial::Blending, false);
            }
        }
        else if (observerNode)
        {
            oldNode = observerNode;
        }
    }
    else if (m_renderingEnabled)
    {
        const auto observerNode = oldNode->childAtIndex(0);

        if (m_updateRenderPosition)
        {
            if (!observerNode)
            {
                oldNode->appendChildNode(createObserverNode());
            }
        }
        else
        {
            if (observerNode)
            {
                assert(dynamic_cast<MatrixChangeObserverNode*>(observerNode));
                observerNode->setFlag(QSGNode::OwnedByParent, false); // this may not be necessary
                delete observerNode;
            }
        }
    }

    const auto rect = boundingRect();

    m_renderSize = rect.size();

    if (m_renderingEnabled)
    {
        if (softwareMode)
        {
            softwareRenderNode->setRect(rect);
            softwareRenderNode->setColor(m_color);

            if (Q_UNLIKELY(m_windowChanged))
            {
                softwareRenderNode->setWindow(window());
                m_windowChanged = false;
            }

            return softwareRenderNode;
        }
        else
        {
            if (rectangleNode->rect() != rect)
                rectangleNode->setRect(rect);

            if (rectangleNode->color() != m_color)
            {
                rectangleNode->setColor(m_color);
                assert(rectangleNode->material());
                rectangleNode->material()->setFlag(QSGMaterial::Blending, false);
            }

            return rectangleNode;
        }
    }
    else
    {
        if (m_updateRenderPosition)
        {
            assert(oldNode);
            return oldNode; // observer node
        }
        else
        {
            setFlag(ItemHasContents, false);
            return nullptr;
        }
    }
}

QSizeF ViewBlockingRectangle::renderSize() const
{
    return m_renderSize;
}

QPointF ViewBlockingRectangle::renderPosition() const
{
    return m_renderPosition;
}

void ViewBlockingRectangle::setRenderingEnabled(bool enabled)
{
    if (m_renderingEnabled == enabled)
        return;

    m_renderingEnabled = enabled;

    if (enabled)
    {
        setFlag(ItemHasContents, true);
        if (isVisible())
            update();
    }
    else if (!m_updateRenderPosition)
    {
        setFlag(ItemHasContents, false);
    }

    emit renderingEnabledChanged();
}

void ViewBlockingRectangle::setUpdateRenderPosition(bool _update)
{
    if (m_updateRenderPosition == _update)
        return;

    m_updateRenderPosition = _update;

    if (_update)
    {
        setFlag(ItemHasContents, true);
        if (isVisible())
            update();
    }
    else if (!m_renderingEnabled)
    {
        setFlag(ItemHasContents, false);
    }
}

bool ViewBlockingRectangle::updateRenderPosition() const
{
    return m_updateRenderPosition;
}

void ViewBlockingRectangle::componentComplete()
{
    QQuickItem::componentComplete();

    if (isVisible())
    {
        m_renderSize = QSizeF(width(), height());

        if (m_updateRenderPosition)
        {
            m_renderPosition = mapToScene(QPointF(0.0, 0.0));
        }
    }
}


Messung
CHZG
831008589

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.