On Tue, Feb 1, 2011 at 8:04 PM,  <[email protected]> wrote:
> Hello,
>
>
>
> Why can we not support rounded corners in Image element with clipping on. I
> realize it’s a performance hit, but if the image doesn’t change width and
> height the impact to animations could be minimal. It would be useful for
> some layouts we would like to achieve.

Currently you can achieve this creating a C++ element with a
QGraphicsEffect applied.
There is an element in qt-components called MaskedItem that does what
you want, but it's a little borderline (attached is the source code).

Br,
Adriano
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation ([email protected])
**
** This file is part of the Qt Components project on Qt Labs.
**
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions contained
** in the Technology Preview License Agreement accompanying this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at [email protected].
**
****************************************************************************/

#ifndef MDECLARATIVEMASKEDITEM_H
#define MDECLARATIVEMASKEDITEM_H

#include <QDeclarativeItem>

class MaskEffect;
class QDeclarativeComponent;


class MDeclarativeMaskedItem : public QDeclarativeItem
{
    Q_OBJECT

    Q_PROPERTY(QDeclarativeComponent *mask READ mask WRITE setMask NOTIFY maskChanged)

public:
    MDeclarativeMaskedItem(QDeclarativeItem *parent = 0);
    virtual ~MDeclarativeMaskedItem();

    QDeclarativeComponent *mask() const;
    void setMask(QDeclarativeComponent *component);

signals:
    void maskChanged();

private:
    MaskEffect *m_effect;
    QDeclarativeComponent *m_maskComponent;
};

#endif //MDECLARATIVEMASKEDITEM_H
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation ([email protected])
**
** This file is part of the Qt Components project on Qt Labs.
**
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions contained
** in the Technology Preview License Agreement accompanying this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at [email protected].
**
****************************************************************************/

#include "mdeclarativemaskeditem.h"

#include <QEvent>
#include <QPainter>
#include <QScopedPointer>
#include <QGraphicsEffect>
#include <QDeclarativeComponent>


class MaskEffect : public QGraphicsEffect
{
    Q_OBJECT

public:
    MaskEffect(QObject *parent = 0);

    void setMask(QDeclarativeItem *mask);

protected:
    void draw(QPainter *painter);

private:
    QPixmap m_buffer;
    QScopedPointer<QDeclarativeItem> m_item;
};


MaskEffect::MaskEffect(QObject *parent)
    : QGraphicsEffect(parent)
{

}

void MaskEffect::setMask(QDeclarativeItem *mask)
{
    if (!m_item.isNull()) {
        disconnect(m_item.data(), SIGNAL(widthChanged()), this, SLOT(update()));
        disconnect(m_item.data(), SIGNAL(heightChanged()), this, SLOT(update()));
    }

    m_item.reset(mask);
    update();

    if (!m_item.isNull()) {
        connect(m_item.data(), SIGNAL(widthChanged()), this, SLOT(update()));
        connect(m_item.data(), SIGNAL(heightChanged()), this, SLOT(update()));
    }
}

void MaskEffect::draw(QPainter *painter)
{
    if (m_item.isNull()) {
        drawSource(painter);
        return;
    }

    QPoint offset;
    const QPixmap &pixmap = sourcePixmap(Qt::LogicalCoordinates,
                                         &offset, QGraphicsEffect::NoPad);

    if (pixmap.isNull())
        return;

    if (pixmap.size() != m_buffer.size())
        m_buffer = pixmap;

    QPainter p(&m_buffer);

    // clear buffer and set mask
    p.setCompositionMode(QPainter::CompositionMode_Source);
    p.fillRect(0, 0, m_buffer.width(), m_buffer.height(), Qt::transparent);
    m_item->paint(&p, 0, 0);

    // compose pixmap with mask in buffer
    p.setCompositionMode(QPainter::CompositionMode_SourceIn);
    p.drawPixmap(0, 0, pixmap);

    // draw composed buffer
    painter->drawPixmap(offset, m_buffer);
}


/*!
  \qmlclass MaskedItem MDeclarativeMaskedItem
  \brief The MaskedItem element allows you to compose an Item with an alpha mask.
  \inherits Item

  The MaskedItem element reveals portion of your picture or item by composing this
  item with a mask element. The mask element will be used as an alpha mask.

  \section1 Usage Example

  The following example shows how to apply an alpha mask in a rectangle.

  \qml
  MaskedItem {
      width: 100
      height: 100

      mask: Image {
          source: "mask.png"
      }

      Rectangle {
          anchors.fill: parent
          color: "red"
      }
  }
  \endqml

  \section1 Performance Issues

  Internally MaskedItem needs to cache their children in a pixmap in
  order to compose the final result with the mask. So, some cautions are
  needed while using this item:

  1. MaskedItem is clipped by default. It's recommended to not set clip
  to false, since this may lead to high memory consumption depending on
  the children geometries; behind the scenes, a pixmap with the size of
  the final bounding rect is needed. So clipping guarantees that this
  final bounding rect will not be greater than the element itself.

  2. Avoid resizing the MaskedItem element in animations. When the element
  is resized a new pixmap is created according to the new size, and this
  will have performance impact. You can resize the children though, if clip
  is not changed.

  3. Try to minimize children updates (like child resize, move, ...), this
  will reduce cache repaints. You can change mask item size with no additional
  cost though.

  \section1 Limitations

  1. Currently just the mask element contents is used to create the alpha mask.
  So do not place any children inside its declaration, as they will not be used.
*/

MDeclarativeMaskedItem::MDeclarativeMaskedItem(QDeclarativeItem *parent)
    : QDeclarativeItem(parent),
      m_maskComponent(0)
{
    // XXX: this is a workaround to avoid a bug in
    // QGraphicsEffect that keeps dirty regions on
    // an item with no contents
    setFlag(QGraphicsItem::ItemHasNoContents, false);

    setFlag(QGraphicsItem::ItemClipsChildrenToShape);

    m_effect = new MaskEffect();
    setGraphicsEffect(m_effect);
}

MDeclarativeMaskedItem::~MDeclarativeMaskedItem()
{

}

/*!
  \qmlproperty Component MaskedItem::mask

  The mask item defines the image of the masking effect applied over the
  children. Only the root item of the mask component will be painted to
  create the mask.
*/

QDeclarativeComponent *MDeclarativeMaskedItem::mask() const
{
    return m_maskComponent;
}

void MDeclarativeMaskedItem::setMask(QDeclarativeComponent *component)
{
    if (m_maskComponent == component)
        return;

    QDeclarativeItem *mask = 0;

    if (component) {
        QObject *object = component->create(component->creationContext());
        mask = qobject_cast<QDeclarativeItem *>(object);

        if (!mask)
            qWarning("MaskedItem: Unable to create mask element.");
        else if (!mask->childItems().isEmpty())
            qWarning("MaskedItem: Mask element has children. Due to current limitation, they won't be painted.");
    }

    m_effect->setMask(mask);
    m_maskComponent = component;

    emit maskChanged();
}

#include "mdeclarativemaskeditem.moc"
_______________________________________________
Qt-qml mailing list
[email protected]
http://lists.qt.nokia.com/mailman/listinfo/qt-qml

Reply via email to