1 // Commit: 695a39410c8ce186a2ce78cef51093c55fc32643
2 /****************************************************************************
4 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5 ** All rights reserved.
6 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 ** This file is part of the QtDeclarative module of the Qt Toolkit.
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** No Commercial Usage
12 ** This file contains pre-release code and may not be distributed.
13 ** You may use this file in accordance with the terms and conditions
14 ** contained in the Technology Preview License Agreement accompanying
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
41 ****************************************************************************/
43 #include "qsgimage_p.h"
44 #include "qsgimage_p_p.h"
46 #include <private/qsgcontext_p.h>
47 #include <private/qsgadaptationlayer_p.h>
49 #include <QtGui/qpainter.h>
53 QSGImagePrivate::QSGImagePrivate()
54 : fillMode(QSGImage::Stretch)
57 , pixmapChanged(false)
61 QSGImage::QSGImage(QSGItem *parent)
62 : QSGImageBase(*(new QSGImagePrivate), parent)
66 QSGImage::QSGImage(QSGImagePrivate &dd, QSGItem *parent)
67 : QSGImageBase(dd, parent)
75 void QSGImagePrivate::setPixmap(const QPixmap &pixmap)
78 pix.setPixmap(pixmap);
80 q->setImplicitWidth(pix.width());
81 q->setImplicitHeight(pix.height());
82 status = pix.isNull() ? QSGImageBase::Null : QSGImageBase::Ready;
88 QSGImage::FillMode QSGImage::fillMode() const
94 void QSGImage::setFillMode(FillMode mode)
97 if (d->fillMode == mode)
101 updatePaintedGeometry();
102 emit fillModeChanged();
105 qreal QSGImage::paintedWidth() const
108 return d->paintedWidth;
111 qreal QSGImage::paintedHeight() const
114 return d->paintedHeight;
117 void QSGImage::updatePaintedGeometry()
121 if (d->fillMode == PreserveAspectFit) {
122 if (!d->pix.width() || !d->pix.height())
124 qreal w = widthValid() ? width() : d->pix.width();
125 qreal widthScale = w / qreal(d->pix.width());
126 qreal h = heightValid() ? height() : d->pix.height();
127 qreal heightScale = h / qreal(d->pix.height());
128 if (widthScale <= heightScale) {
130 d->paintedHeight = widthScale * qreal(d->pix.height());
131 } else if(heightScale < widthScale) {
132 d->paintedWidth = heightScale * qreal(d->pix.width());
133 d->paintedHeight = h;
135 if (widthValid() && !heightValid()) {
136 setImplicitHeight(d->paintedHeight);
138 if (heightValid() && !widthValid()) {
139 setImplicitWidth(d->paintedWidth);
141 } else if (d->fillMode == PreserveAspectCrop) {
142 if (!d->pix.width() || !d->pix.height())
144 qreal widthScale = width() / qreal(d->pix.width());
145 qreal heightScale = height() / qreal(d->pix.height());
146 if (widthScale < heightScale) {
147 widthScale = heightScale;
148 } else if(heightScale < widthScale) {
149 heightScale = widthScale;
152 d->paintedHeight = heightScale * qreal(d->pix.height());
153 d->paintedWidth = widthScale * qreal(d->pix.width());
155 d->paintedWidth = width();
156 d->paintedHeight = height();
158 emit paintedGeometryChanged();
161 void QSGImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
163 QSGImageBase::geometryChanged(newGeometry, oldGeometry);
164 updatePaintedGeometry();
167 QRectF QSGImage::boundingRect() const
170 return QRectF(0, 0, qMax(width(), d->paintedWidth), qMax(height(), d->paintedHeight));
173 QSGTexture *QSGImage::texture() const
176 QSGTexture *t = d->pix.texture();
177 t->setFiltering(QSGItemPrivate::get(this)->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
178 t->setMipmapFiltering(QSGTexture::None);
179 t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
180 t->setVerticalWrapMode(QSGTexture::ClampToEdge);
184 QSGNode *QSGImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
187 //XXX Support mirror property
189 if (!d->pix.texture() || width() <= 0 || height() <= 0) {
194 QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
196 d->pixmapChanged = true;
197 node = d->sceneGraphContext()->createImageNode();
198 node->setTexture(d->pix.texture());
201 if (d->pixmapChanged) {
202 // force update the texture in the node to trigger reconstruction of
203 // geometry and the likes when a atlas segment has changed.
204 QSGTexture *t = d->pix.texture();
207 d->pixmapChanged = false;
212 QSGTexture::WrapMode hWrap = QSGTexture::ClampToEdge;
213 QSGTexture::WrapMode vWrap = QSGTexture::ClampToEdge;
215 switch (d->fillMode) {
218 targetRect = QRectF(0, 0, width(), height());
219 sourceRect = d->pix.rect();
222 case PreserveAspectFit:
223 targetRect = QRectF((width() - d->paintedWidth) / 2., (height() - d->paintedHeight) / 2.,
224 d->paintedWidth, d->paintedHeight);
225 sourceRect = d->pix.rect();
228 case PreserveAspectCrop: {
229 targetRect = QRect(0, 0, width(), height());
230 qreal wscale = width() / qreal(d->pix.width());
231 qreal hscale = height() / qreal(d->pix.height());
233 if (wscale > hscale) {
234 int src = (hscale / wscale) * qreal(d->pix.height());
235 sourceRect = QRectF(0, (d->pix.height() - src) / 2, d->pix.width(), src);
237 int src = (wscale / hscale) * qreal(d->pix.width());
238 sourceRect = QRectF((d->pix.width() - src) / 2, 0, src, d->pix.height());
244 targetRect = QRectF(0, 0, width(), height());
245 sourceRect = QRectF(0, 0, width(), height());
246 hWrap = QSGTexture::Repeat;
247 vWrap = QSGTexture::Repeat;
250 case TileHorizontally:
251 targetRect = QRectF(0, 0, width(), height());
252 sourceRect = QRectF(0, 0, width(), d->pix.height());
253 hWrap = QSGTexture::Repeat;
257 targetRect = QRectF(0, 0, width(), height());
258 sourceRect = QRectF(0, 0, d->pix.width(), height());
259 vWrap = QSGTexture::Repeat;
264 QRectF nsrect(sourceRect.x() / d->pix.width(),
265 1 - sourceRect.y() / d->pix.height(),
266 sourceRect.width() / d->pix.width(),
267 -sourceRect.height() / d->pix.height());
269 node->setHorizontalWrapMode(hWrap);
270 node->setVerticalWrapMode(vWrap);
271 node->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
273 node->setTargetRect(targetRect);
274 node->setSourceRect(nsrect);
280 void QSGImage::pixmapChange()
284 updatePaintedGeometry();
285 d->pixmapChanged = true;