diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-08-10 00:25:29 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-08-10 00:25:29 (GMT) |
commit | 4cbb70502828d0cac808e891f3b9e586c9c9b0c1 (patch) | |
tree | bdaadfde810d450f94085f7bfe28008d900893de /src/declarative/fx/qfximage.cpp | |
parent | b1f10dc22091f80fba651e32e824175f25956313 (diff) | |
parent | c4235f6f90613f1a877da067354b912ef0004259 (diff) | |
download | Qt-4cbb70502828d0cac808e891f3b9e586c9c9b0c1.zip Qt-4cbb70502828d0cac808e891f3b9e586c9c9b0c1.tar.gz Qt-4cbb70502828d0cac808e891f3b9e586c9c9b0c1.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Diffstat (limited to 'src/declarative/fx/qfximage.cpp')
-rw-r--r-- | src/declarative/fx/qfximage.cpp | 437 |
1 files changed, 82 insertions, 355 deletions
diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 26e2727..0cb7988 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -41,11 +41,6 @@ #include "qfximage.h" #include "qfximage_p.h" -#include <private/qfxperf_p.h> -#include <QNetworkRequest> -#include <QNetworkReply> -#include <QFile> -#include <QtDeclarative/qmlengine.h> #include <QKeyEvent> #include <QPainter> @@ -60,13 +55,10 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Image,QFxImage) \brief The Image element allows you to add bitmaps to a scene. \inherits Item - The Image element supports untransformed, stretched, tiled, and grid-scaled images. + The Image element supports untransformed, stretched and tiled. For an explanation of stretching and tiling, see the fillMode property description. - For an explanation of grid-scaling see the scaleGrid property description - or the QFxScaleGrid class description. - Examples: \table \row @@ -86,16 +78,6 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Image,QFxImage) } \endqml \row - \o \image declarative-qtlogo4.png - \o Grid-scaled (only with fillMode: Stretch) - \qml - Image { scaleGrid.left: 20; scaleGrid.right: 10 - scaleGrid.top: 14; scaleGrid.bottom: 14 - width: 160; height: 160 - source: "pics/qtlogo.png" - } - \endqml - \row \o \image declarative-qtlogo3.png \o fillMode: Tile \qml @@ -144,33 +126,26 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Image,QFxImage) */ QFxImage::QFxImage(QFxItem *parent) - : QFxItem(*(new QFxImagePrivate), parent) + : QFxImageBase(*(new QFxImagePrivate), parent) { setFlag(QGraphicsItem::ItemHasNoContents, false); } QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent) - : QFxItem(dd, parent) + : QFxImageBase(dd, parent) { setFlag(QGraphicsItem::ItemHasNoContents, false); } QFxImage::~QFxImage() { - Q_D(QFxImage); - if (d->sciReply) - d->sciReply->deleteLater(); - if (!d->url.isEmpty()) - QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); } /*! - \property QFxImage::image + \property QFxImage::pixmap \brief the image displayed in this item. - This property contains the image currently being displayed by this item, + This property contains the pixmap currently being displayed by this item, which may be empty if nothing is currently displayed. Setting the source property overrides any setting of this property. */ @@ -194,37 +169,6 @@ void QFxImage::setPixmap(const QPixmap &pix) } /*! - \qmlproperty int Image::scaleGrid.left - \qmlproperty int Image::scaleGrid.right - \qmlproperty int Image::scaleGrid.top - \qmlproperty int Image::scaleGrid.bottom - - \target ImagexmlpropertiesscaleGrid - - A scale grid uses 4 grid lines (2 horizontal and 2 vertical) to break an image into 9 sections, as shown below: - - \image declarative-scalegrid.png - - When the image is scaled: - \list - \i the corners (sections 1, 3, 7, and 9) are not scaled at all - \i the middle (section 5) is scaled both horizontally and vertically - \i sections 2 and 8 are scaled horizontally - \i sections 4 and 6 are scaled vertically - \endlist - - Each scale grid property (left, right, top, and bottom) specifies an offset from the respective side. For example, \c scaleGrid.bottom="10" sets the bottom scale grid line 10 pixels up from the bottom of the image. - - A scale grid can also be specified using a - \l {Image::source}{.sci file}. -*/ -QFxScaleGrid *QFxImage::scaleGrid() -{ - Q_D(QFxImage); - return d->getScaleGrid(); -} - -/*! \qmlproperty FillMode Image::fillMode Set this property to define what happens when the image set for the item is smaller @@ -239,10 +183,6 @@ QFxScaleGrid *QFxImage::scaleGrid() \endlist \image declarative-image_fillMode.gif - - Only fillMode: Stretch can be used with scaleGrid. Other settings - will cause a run-time warning. - \sa examples/declarative/aspectratio */ QFxImage::FillMode QFxImage::fillMode() const @@ -261,105 +201,6 @@ void QFxImage::setFillMode(FillMode mode) emit fillModeChanged(); } -void QFxImage::componentComplete() -{ - QFxItem::componentComplete(); -} - -/*! - \property QFxImage::scaleGrid - \brief the 3x3 grid used to scale an image, excluding the corners. -*/ - -void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) -{ - Q_D(QFxImage); - if (d->pix.isNull()) - return; - - bool oldAA = p->testRenderHint(QPainter::Antialiasing); - bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); - if (d->smooth) - p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); - - QPixmap pix = d->pix; - - if (!d->scaleGrid || d->scaleGrid->isNull()) { - if (width() != pix.width() || height() != pix.height()) { - if (d->fillMode >= Tile) { - p->save(); - p->setClipRect(0, 0, width(), height(), Qt::IntersectClip); - - if (d->fillMode == Tile) { - const int pw = pix.width(); - const int ph = pix.height(); - int yy = 0; - - while(yy < height()) { - int xx = 0; - while(xx < width()) { - p->drawPixmap(xx, yy, pix); - xx += pw; - } - yy += ph; - } - } else if (d->fillMode == TileVertically) { - const int ph = pix.height(); - int yy = 0; - - while(yy < height()) { - p->drawPixmap(QRect(0, yy, width(), ph), pix); - yy += ph; - } - } else { - const int pw = pix.width(); - int xx = 0; - - while(xx < width()) { - p->drawPixmap(QRect(xx, 0, pw, height()), pix); - xx += pw; - } - } - - p->restore(); - } else { - qreal widthScale = width() / qreal(pix.width()); - qreal heightScale = height() / qreal(pix.height()); - - QTransform scale; - - if (d->fillMode == PreserveAspect) { - if (widthScale < heightScale) { - heightScale = widthScale; - scale.translate(0, (height() - heightScale * pix.height()) / 2); - } else if(heightScale < widthScale) { - widthScale = heightScale; - scale.translate((width() - widthScale * pix.width()) / 2, 0); - } - } - - scale.scale(widthScale, heightScale); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawPixmap(0, 0, pix); - p->setWorldTransform(old); - } - } else { - p->drawPixmap(0, 0, pix); - } - } else { - QMargins margins(d->scaleGrid->top(), d->scaleGrid->left(), d->scaleGrid->bottom(), d->scaleGrid->right()); - QTileRules rules((Qt::TileRule)d->scaleGrid->horizontalTileRule(), - (Qt::TileRule)d->scaleGrid->verticalTileRule()); - qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, pix, pix.rect(), margins, rules); - } - - if (d->smooth) { - p->setRenderHint(QPainter::Antialiasing, oldAA); - p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); - } -} - /*! \qmlproperty enum Image::status @@ -374,12 +215,6 @@ void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) \sa progress */ -QFxImage::Status QFxImage::status() const -{ - Q_D(const QFxImage); - return d->status; -} - /*! \qmlproperty real Image::progress @@ -389,215 +224,107 @@ QFxImage::Status QFxImage::status() const \sa status */ -qreal QFxImage::progress() const -{ - Q_D(const QFxImage); - return d->progress; -} - /*! - \qmlproperty url Image::source - - Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. + \qmlproperty bool Image::smooth - It can also handle .sci files, which are a Qml-specific format. A .sci file uses a simple text-based format that specifies - \list - \i the grid lines describing a \l {Image::scaleGrid.left}{scale grid}. - \i an image file. - \endlist - - The following .sci file sets grid line offsets of 10 on each side for the image \c picture.png: - \code - gridLeft: 10 - gridTop: 10 - gridBottom: 10 - gridRight: 10 - imageFile: picture.png - \endcode + Set this property if you want the image to be smoothly filtered when scaled or + transformed. Smooth filtering gives better visual quality, but is slower. If + the image is displayed at its natural size, this property has no visual or + performance effect. - The URL may be absolute, or relative to the URL of the component. + \note Generally scaling artifacts are only visible if the image is stationary on + the screen. A common pattern when animating an image is to disable smooth + filtering at the beginning of the animation and reenable it at the conclusion. */ /*! - \property QFxImage::source - \brief the url of the image to be displayed in this item. + \qmlproperty url Image::source - The content specified can be of any image type loadable by QImage. Alternatively, - you can specify an sci format file, which specifies both an image and it's scale grid. + Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt. + + The URL may be absolute, or relative to the URL of the component. */ -QUrl QFxImage::source() const -{ - Q_D(const QFxImage); - return d->url; -} -void QFxImage::setSource(const QUrl &url) +void QFxImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { -#ifdef Q_ENABLE_PERFORMANCE_LOG - QFxPerfTimer<QFxPerf::PixmapLoad> perf; -#endif Q_D(QFxImage); - //equality is fairly expensive, so we bypass for simple, common case - if ((d->url.isEmpty() == url.isEmpty()) && url == d->url) + if (d->pix.isNull()) return; - if (d->sciReply) { - d->sciReply->deleteLater(); - d->sciReply = 0; - } + bool oldAA = p->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + if (d->smooth) + p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); - if (!d->url.isEmpty()) - QFxPixmap::cancelGet(d->url, this); - if (!d->sciurl.isEmpty()) - QFxPixmap::cancelGet(d->sciurl, this); - - d->url = url; - d->sciurl = QUrl(); - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } + QPixmap pix = d->pix; - if (url.isEmpty()) { - d->pix = QPixmap(); - d->status = Null; - d->progress = 1.0; - setImplicitWidth(0); - setImplicitHeight(0); - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } else { - d->status = Loading; - if (d->url.path().endsWith(QLatin1String(".sci"))) { -#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - if (d->url.scheme() == QLatin1String("file")) { - QFile file(d->url.toLocalFile()); - file.open(QIODevice::ReadOnly); - setGridScaledImage(QFxGridScaledImage(&file)); - } else -#endif - { - QNetworkRequest req(d->url); - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->sciReply, SIGNAL(finished()), - this, SLOT(sciRequestFinished())); - } - } else { - d->reply = QFxPixmap::get(qmlEngine(this), d->url, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); + if (width() != pix.width() || height() != pix.height()) { + if (d->fillMode >= Tile) { + p->save(); + p->setClipRect(0, 0, width(), height(), Qt::IntersectClip); + + if (d->fillMode == Tile) { + const int pw = pix.width(); + const int ph = pix.height(); + int yy = 0; + + while(yy < height()) { + int xx = 0; + while(xx < width()) { + p->drawPixmap(xx, yy, pix); + xx += pw; + } + yy += ph; + } + } else if (d->fillMode == TileVertically) { + const int ph = pix.height(); + int yy = 0; + + while(yy < height()) { + p->drawPixmap(QRect(0, yy, width(), ph), pix); + yy += ph; + } } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); + const int pw = pix.width(); + int xx = 0; + + while(xx < width()) { + p->drawPixmap(QRect(xx, 0, pw, height()), pix); + xx += pw; + } } - } - } - emit statusChanged(d->status); -} + p->restore(); + } else { + qreal widthScale = width() / qreal(pix.width()); + qreal heightScale = height() / qreal(pix.height()); + + QTransform scale; + + if (d->fillMode == PreserveAspect) { + if (widthScale < heightScale) { + heightScale = widthScale; + scale.translate(0, (height() - heightScale * pix.height()) / 2); + } else if(heightScale < widthScale) { + widthScale = heightScale; + scale.translate((width() - widthScale * pix.width()) / 2, 0); + } + } -void QFxImage::requestFinished() -{ - Q_D(QFxImage); - if (d->url.path().endsWith(QLatin1String(".sci"))) { - QFxPixmap::find(d->sciurl, &d->pix); - } else { - if (d->reply) { - //###disconnect really needed? - disconnect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - if (d->reply->error() != QNetworkReply::NoError) - d->status = Error; + scale.scale(widthScale, heightScale); + QTransform old = p->transform(); + p->setWorldTransform(scale * old); + p->drawPixmap(0, 0, pix); + p->setWorldTransform(old); } - QFxPixmap::find(d->url, &d->pix); - } - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); -} - -void QFxImage::sciRequestFinished() -{ - Q_D(QFxImage); - if (d->sciReply->error() != QNetworkReply::NoError) { - d->status = Error; - d->sciReply->deleteLater(); - d->sciReply = 0; - emit statusChanged(d->status); } else { - QFxGridScaledImage sci(d->sciReply); - d->sciReply->deleteLater(); - d->sciReply = 0; - setGridScaledImage(sci); + p->drawPixmap(0, 0, pix); } -} - -void QFxImage::requestProgress(qint64 received, qint64 total) -{ - Q_D(QFxImage); - if (d->status == Loading && total > 0) { - d->progress = qreal(received)/total; - emit progressChanged(d->progress); - } -} -void QFxImage::setGridScaledImage(const QFxGridScaledImage& sci) -{ - Q_D(QFxImage); - if (!sci.isValid()) { - d->status = Error; - emit statusChanged(d->status); - } else { - QFxScaleGrid *sg = scaleGrid(); - sg->setTop(sci.gridTop()); - sg->setBottom(sci.gridBottom()); - sg->setLeft(sci.gridLeft()); - sg->setRight(sci.gridRight()); - sg->setHorizontalTileRule(sci.horizontalTileRule()); - sg->setVerticalTileRule(sci.verticalTileRule()); - - d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->reply = QFxPixmap::get(qmlEngine(this), d->sciurl, &d->pix); - if (d->reply) { - connect(d->reply, SIGNAL(finished()), this, SLOT(requestFinished())); - connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); - } else { - //### should be unified with requestFinished - setImplicitWidth(d->pix.width()); - setImplicitHeight(d->pix.height()); - - if (d->status == Loading) - d->status = Ready; - d->progress = 1.0; - emit statusChanged(d->status); - emit sourceChanged(d->url); - emit progressChanged(1.0); - update(); - } + if (d->smooth) { + p->setRenderHint(QPainter::Antialiasing, oldAA); + p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); } } - QT_END_NAMESPACE |