forked from qt-creator/qt-creator
QmlDesigner: Render item inside the bounding rect
We have to render an item inside the bounding rect, because if it is a component there might be child items outside its actual size. The way we calculate the bounding rectangle excludes children on the document level. We take clipping into account when calculating the bounding rect. When rendering the effect we do not have the instance. Therefore we fall back to the standard bounding rectangle. Change-Id: I7cd09d08d461d28c49a91fb891a5487185df0245 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -348,6 +348,14 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item)
|
||||
ServerNodeInstance instance = instanceForObject(item);
|
||||
const auto childInstances = instance.childItems();
|
||||
|
||||
// Setting layer enabled to false messes up the bounding rect.
|
||||
// Therefore we calculate it upfront.
|
||||
QRectF renderBoundingRect;
|
||||
if (instance.isValid())
|
||||
renderBoundingRect = instance.boundingRect();
|
||||
else
|
||||
renderBoundingRect = item->boundingRect();
|
||||
|
||||
// Hide immediate children that have instances and are QQuickItems so we get only
|
||||
// the parent item's content, as compositing is handled on creator side.
|
||||
for (const auto &childInstance : childInstances) {
|
||||
@@ -372,11 +380,15 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item)
|
||||
QSGRenderContext *rc = QQuickWindowPrivate::get(m_viewData.window.data())->context;
|
||||
QSGLayer *layer = rc->sceneGraphContext()->createLayer(rc);
|
||||
layer->setItem(pItem->itemNode());
|
||||
QSizeF itemSize = QSizeF(item->width(), item->height());
|
||||
layer->setRect(QRectF(0, itemSize.height(), itemSize.width(), -itemSize.height()));
|
||||
|
||||
layer->setRect(QRectF(renderBoundingRect.x(),
|
||||
renderBoundingRect.y() + renderBoundingRect.height(),
|
||||
renderBoundingRect.width(),
|
||||
-renderBoundingRect.height()));
|
||||
|
||||
const QSize minSize = rc->sceneGraphContext()->minimumFBOSize();
|
||||
layer->setSize(QSize(qMax(minSize.width(), int(itemSize.width())),
|
||||
qMax(minSize.height(), int(itemSize.height()))));
|
||||
layer->setSize(QSize(qMax(minSize.width(), int(renderBoundingRect.width())),
|
||||
qMax(minSize.height(), int(renderBoundingRect.height()))));
|
||||
layer->scheduleUpdate();
|
||||
|
||||
if (layer->updateTexture())
|
||||
|
@@ -28,6 +28,9 @@
|
||||
|
||||
#include <qmlprivategate.h>
|
||||
|
||||
#include <QtQuick/private/qquickitem_p.h>
|
||||
#include <QtQuick/private/qquickshadereffectsource_p.h>
|
||||
|
||||
#include <QQmlProperty>
|
||||
#include <QQmlExpression>
|
||||
#include <QQuickView>
|
||||
@@ -476,11 +479,12 @@ QImage QuickItemNodeInstance::renderImage() const
|
||||
}
|
||||
renderImage.setDevicePixelRatio(devicePixelRatio);
|
||||
#else
|
||||
if (s_unifiedRenderPath)
|
||||
if (s_unifiedRenderPath) {
|
||||
renderImage = nodeInstanceServer()->grabWindow();
|
||||
else
|
||||
renderImage = renderImage.copy(renderBoundingRect.toRect());
|
||||
} else {
|
||||
renderImage = nodeInstanceServer()->grabItem(quickItem());
|
||||
renderImage = renderImage.copy(renderBoundingRect.toRect());
|
||||
}
|
||||
|
||||
/* When grabbing an offscren window the device pixel ratio is 1 */
|
||||
renderImage.setDevicePixelRatio(1);
|
||||
@@ -613,6 +617,34 @@ static inline bool isRectangleSane(const QRectF &rect)
|
||||
return rect.isValid() && (rect.width() < 10000) && (rect.height() < 10000);
|
||||
}
|
||||
|
||||
static bool isEffectItem(QQuickItem *item)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
Q_UNUSED(item)
|
||||
return false;
|
||||
#else
|
||||
if (qobject_cast<QQuickShaderEffectSource *>(item))
|
||||
return true;
|
||||
|
||||
const auto propName = "source";
|
||||
|
||||
QQmlProperty prop(item, QString::fromLatin1(propName));
|
||||
if (!prop.isValid())
|
||||
return false;
|
||||
|
||||
QQuickShaderEffectSource *source = prop.read().value<QQuickShaderEffectSource *>();
|
||||
|
||||
if (source && source->sourceItem()) {
|
||||
QQuickItemPrivate *pItem = QQuickItemPrivate::get(source->sourceItem());
|
||||
|
||||
if (pItem && pItem->layer() && pItem->layer()->enabled() && pItem->layer()->effect())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
QRectF QuickItemNodeInstance::boundingRectWithStepChilds(QQuickItem *parentItem) const
|
||||
{
|
||||
QRectF boundingRect = parentItem->boundingRect();
|
||||
@@ -620,8 +652,9 @@ QRectF QuickItemNodeInstance::boundingRectWithStepChilds(QQuickItem *parentItem)
|
||||
boundingRect = boundingRect.united(QRectF(QPointF(0, 0), size()));
|
||||
|
||||
for (QQuickItem *childItem : parentItem->childItems()) {
|
||||
if (!nodeInstanceServer()->hasInstanceForObject(childItem)) {
|
||||
QRectF transformedRect = childItem->mapRectToItem(parentItem, boundingRectWithStepChilds(childItem));
|
||||
if (!nodeInstanceServer()->hasInstanceForObject(childItem) && !isEffectItem(childItem)) {
|
||||
QRectF transformedRect = childItem->mapRectToItem(parentItem,
|
||||
boundingRectWithStepChilds(childItem));
|
||||
if (isRectangleSane(transformedRect))
|
||||
boundingRect = boundingRect.united(transformedRect);
|
||||
}
|
||||
|
Reference in New Issue
Block a user