aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Ionascu <stanislav.ionascu@nokia.com>2010-07-19 16:10:05 +0300
committerSergiy Dubovik <sergiy.dubovik@nokia.com>2010-07-21 13:14:04 +0300
commit0cc8bab7a60adcac984559da8660efa16e605875 (patch)
treeb5ec1c273d60842b2f12917f348a3489754181b6
parent0e733e08291da0a1adcd5edbf0620331f4f16aa6 (diff)
Changes: Make MImageWidget draw the QImage instead of transforming it into QPixmap.
RevBy: Sergiy Details: QPixmap::fromImage is a very slow operation on X11, so use QImage for drawing instead of transforming it on each set into QPixmap. Also do not calculate source and draw rectangles on each draw contents call. Because it will be recalculated on each draw pass. Some major refactoring involved such as separating draw, source rectangle calculations in their own functions. Refactored border draw code into own function, added caching of style parameters.
-rw-r--r--src/corelib/widgets/mimagewidget.cpp45
-rw-r--r--src/corelib/widgets/mimagewidget_p.h7
-rw-r--r--src/views/mimagewidgetview.cpp244
-rw-r--r--src/views/mimagewidgetview.h3
-rw-r--r--src/views/mimagewidgetview_p.h64
5 files changed, 256 insertions, 107 deletions
diff --git a/src/corelib/widgets/mimagewidget.cpp b/src/corelib/widgets/mimagewidget.cpp
index 9ef6edb5..7ea7eb95 100644
--- a/src/corelib/widgets/mimagewidget.cpp
+++ b/src/corelib/widgets/mimagewidget.cpp
@@ -50,6 +50,7 @@ void MImageWidgetPrivate::cleanUp()
MTheme::releasePixmap(pixmap);
pixmap = 0;
}
+ image = QImage();
}
QSizeF MImageWidgetPrivate::imageDataSize() const
@@ -57,11 +58,15 @@ QSizeF MImageWidgetPrivate::imageDataSize() const
Q_Q(const MImageWidget);
QSizeF imageSize = QSizeF(0, 0);
- if (pixmap != 0 && !pixmap->isNull()) {
- if (q->model()->crop().isEmpty())
- imageSize = pixmap->size();
- else
+ if ((pixmap != 0 && !pixmap->isNull()) || (!image.isNull())) {
+ if (q->model()->crop().isEmpty()) {
+ if (image.isNull())
+ imageSize = pixmap->size();
+ else
+ imageSize = image.size();
+ } else {
imageSize = q->model()->crop().size();
+ }
}
return imageSize;
@@ -72,8 +77,12 @@ MImageWidgetPrivate &MImageWidgetPrivate::operator=(const MImageWidgetPrivate &o
cleanUp();
if (other.pixmap != 0) {
- if (other.deletePixmap)
- pixmap = new QPixmap(*(other.pixmap));
+ if (other.deletePixmap) {
+ if (other.pixmap)
+ pixmap = new QPixmap(*(other.pixmap));
+ else
+ image = other.image;
+ }
else
setImageName(other.imageName, other.pixmap->size());
}
@@ -130,7 +139,8 @@ MImageWidget::MImageWidget(const QImage *image, QGraphicsItem *parent) :
MWidgetController(new MImageWidgetPrivate(), new MImageWidgetModel(), parent)
{
Q_D(MImageWidget);
- d->pixmap = new QPixmap(QPixmap::fromImage(*image));
+ d->pixmap = NULL;
+ d->image = *image;
}
MImageWidget::MImageWidget(const QPixmap *pixmap, QGraphicsItem *parent) :
@@ -180,6 +190,8 @@ QSize MImageWidget::imageSize() const
Q_D(const MImageWidget);
if (d->pixmap != 0)
return d->pixmap->size();
+ else
+ return d->image.size();
return QSize();
}
@@ -217,7 +229,8 @@ void MImageWidget::zoomFactor(qreal *fx, qreal *fy) const
Q_D(const MImageWidget);
QSizeF imageSize = d->imageDataSize();
- if (imageSize.isEmpty()) return;
+ if (imageSize.isEmpty())
+ return;
// if factor not equals 0, calculate it with imageSize, targetSize and widgetSize
QSizeF buffer;
@@ -267,7 +280,8 @@ void MImageWidget::zoomOut()
void MImageWidget::setAspectRatioMode(Qt::AspectRatioMode mode)
{
- if (model()->aspectRatioMode() == mode) return;
+ if (model()->aspectRatioMode() == mode)
+ return;
model()->setAspectRatioMode(mode);
}
@@ -279,10 +293,13 @@ Qt::AspectRatioMode MImageWidget::aspectRatioMode() const
void MImageWidget::setCrop(const QRectF &rect)
{
Q_D(MImageWidget);
- if (d->pixmap == 0) return;
- if (rect.size().width() < 0 || rect.size().height() < 0) return;
+ if (d->pixmap == 0 && d->image.isNull())
+ return;
- QSizeF imageSize = d->pixmap->size();
+ if (rect.size().width() < 0 || rect.size().height() < 0)
+ return;
+
+ QSizeF imageSize = this->imageSize();
// protect the crop section size not beyond the image size
QRectF r;
@@ -330,8 +347,8 @@ void MImageWidget::setImage(const QImage &image)
Q_D(MImageWidget);
d->cleanUp();
- d->pixmap = new QPixmap(QPixmap::fromImage(image));
- d->deletePixmap = true;
+ d->image = image;
+ d->deletePixmap = false;
model()->setCrop(QRect());
diff --git a/src/corelib/widgets/mimagewidget_p.h b/src/corelib/widgets/mimagewidget_p.h
index 4b3bc3bc..aed5b174 100644
--- a/src/corelib/widgets/mimagewidget_p.h
+++ b/src/corelib/widgets/mimagewidget_p.h
@@ -40,10 +40,11 @@ public:
void deepCopy(const MImageWidget &);
- const QPixmap *pixmap;
- QString imageName;
+ const QPixmap *pixmap;
+ QString imageName;
+ QImage image;
- bool deletePixmap;
+ bool deletePixmap;
};
#endif
diff --git a/src/views/mimagewidgetview.cpp b/src/views/mimagewidgetview.cpp
index 4ba442e6..b780ced1 100644
--- a/src/views/mimagewidgetview.cpp
+++ b/src/views/mimagewidgetview.cpp
@@ -18,6 +18,7 @@
****************************************************************************/
#include "mimagewidgetview.h"
+#include "mimagewidgetview_p.h"
#include <QPixmap>
@@ -26,17 +27,15 @@
#include "mviewcreator.h"
#include "private/mwidgetview_p.h"
-class MImageWidgetViewPrivate : public MWidgetViewPrivate
-{
-public:
- MImageWidgetViewPrivate();
- ~MImageWidgetViewPrivate();
-
- MImageWidget *controller;
-};
-
MImageWidgetViewPrivate::MImageWidgetViewPrivate()
- : controller(0)
+ : controller(NULL),
+ cachedPixmapSize(0, 0),
+ borderOpacity(1.0),
+ brush(Qt::transparent),
+ leftBorder(0.0),
+ topBorder(0.0),
+ rightBorder(0.0),
+ bottomBorder(0.0)
{
}
@@ -44,45 +43,53 @@ MImageWidgetViewPrivate::~MImageWidgetViewPrivate()
{
}
-MImageWidgetView::MImageWidgetView(MImageWidget *controller) :
- MWidgetView(* new MImageWidgetViewPrivate, controller)
+void MImageWidgetViewPrivate::calculateDrawRect(const QSizeF &imageSize)
{
- Q_D(MImageWidgetView);
- d->controller = controller;
-}
+ Q_Q(MImageWidgetView);
-MImageWidgetView::MImageWidgetView(MImageWidgetViewPrivate &dd, MImageWidget *controller) :
- MWidgetView(dd, controller)
-{
- Q_D(MImageWidgetView);
- d->controller = controller;
-}
+ // no image, return
+ if (imageSize.isEmpty())
+ return;
-MImageWidgetView::~MImageWidgetView()
-{
-}
+ // get target size, bounded by widget size
+ QSizeF widgetSize = q->size();
+ QSizeF targetSize = widgetSize;
+ QSizeF t;
-void MImageWidgetView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
-{
- Q_UNUSED(option);
+ // get the image display size
+ qreal fx, fy;
+ controller->zoomFactor(&fx, &fy);
- Q_D(const MImageWidgetView);
+ t.setWidth(imageSize.width()*fx);
+ t.setHeight(imageSize.height()*fy);
- // no image, return
- QSizeF imageSize = d->controller->d_func()->imageDataSize();
- if (imageSize.isEmpty()) return;
+ // limited by target size
+ t = targetSize.boundedTo(t);
+
+ // calculate the rectangle of draw
+ qreal dx = (widgetSize.width() - t.width()) / 2.0;
+ qreal dy = (widgetSize.height() - t.height()) / 2.0;
- // the source image section size will be used finally
+ // calculate draw rect
+ drawRect.setRect(dx, dy, t.width(), t.height());
+}
+
+QSizeF MImageWidgetViewPrivate::calculateSourceSize(const QSizeF &imageSize)
+{
QSizeF sourceSize = imageSize;
+ QSizeF targetSize = controller->size();
+
+ // protection codes
+ if (sourceSize.width() < 1.0)
+ sourceSize.setWidth(1.0);
+ if (sourceSize.height() < 1.0)
+ sourceSize.setHeight(1.0);
- // get target size, bounded by widget size
- QSizeF widgetSize = size();
- QSizeF targetSize = widgetSize;
QSizeF t;
// get the image display size
qreal fx, fy;
- d->controller->zoomFactor(&fx, &fy);
+ controller->zoomFactor(&fx, &fy);
t.setWidth(imageSize.width()*fx);
t.setHeight(imageSize.height()*fy);
@@ -98,57 +105,55 @@ void MImageWidgetView::drawContents(QPainter *painter, const QStyleOptionGraphic
sourceSize.setHeight(qRound(value * targetSize.height() / t.height()));
}
- // limited by target size
- t = targetSize.boundedTo(t);
-
- // protection codes
- if (sourceSize.width() < 1.0)
- sourceSize.setWidth(1.0);
- if (sourceSize.height() < 1.0)
- sourceSize.setHeight(1.0);
-
- // get values from controller
- const QPixmap *pixmap = d->controller->pixmap();
+ return sourceSize;
+}
- qreal leftBorder = style()->borderLeft();
- qreal topBorder = style()->borderTop();
- qreal rightBorder = style()->borderRight();
- qreal bottomBorder = style()->borderBottom();
+void MImageWidgetViewPrivate::calculateSourceRect(const QSizeF &imageSize)
+{
+ QPointF topLeft = controller->crop().topLeft();
+ QSizeF originalSize = controller->imageSize();
+ QSizeF sourceSize = calculateSourceSize(imageSize);
- qreal w = leftBorder + rightBorder;
- qreal h = topBorder + bottomBorder;
+ if (topLeft == QPointF(-1.0, -1.0)) {
+ // calculate default crop section
+ qreal dx = (originalSize.width() - sourceSize.width()) / 2.0;
+ qreal dy = (originalSize.height() - sourceSize.height()) / 2.0;
- // calculate if need draw border
- // notice: no border on the cropped edge
- QSizeF originSize = pixmap->size();
+ sourceRect = QRectF(dx, dy, sourceSize.width(), sourceSize.height());
+ } else {
+ // calculate crop section by given topLeft corner
+ qreal dx = topLeft.x();
+ qreal dy = topLeft.y();
- if (originSize.width() > sourceSize.width())
- w = 0;
+ sourceRect = QRectF(dx, dy, qMin(dx + sourceSize.width(), originalSize.width()),
+ qMin(dy + sourceSize.height(), originalSize.height()));
+ }
+}
- if (originSize.height() > sourceSize.height())
- h = 0;
+void MImageWidgetViewPrivate::checkPixmapSize()
+{
+ Q_Q(MImageWidgetView);
- // calculate the rectangle of draw
- qreal dx = (widgetSize.width() - t.width()) / 2.0;
- qreal dy = (widgetSize.height() - t.height()) / 2.0;
+ const QPixmap *pixmap = controller->pixmap();
+ if (pixmap->size() != cachedPixmapSize) {
+ cachedPixmapSize = pixmap->size();
+ q->updateGeometry();
+ }
+}
- // calculate draw rect
- QRectF drawRect, sourceRect, border;
- drawRect.setRect(dx, dy, t.width(), t.height());
+void MImageWidgetViewPrivate::drawBorders(QPainter *painter, const QRectF &drawRect) const
+{
+ qreal w = leftBorder + rightBorder;
+ qreal h = topBorder + bottomBorder;
- // draw borders outside of target
- // if both borders equals 0, do not draw border
if (w > 0 || h > 0) {
-
- QColor borderColor = style()->borderColor();
- qreal borderOpacity = style()->borderOpacity();
- QBrush brush(borderColor);
+ QRectF border;
qreal oldOpacity = painter->opacity();
painter->setOpacity(borderOpacity);
- dx = drawRect.x() - leftBorder;
- dy = drawRect.y() - topBorder;
+ qreal dx = drawRect.x() - leftBorder;
+ qreal dy = drawRect.y() - topBorder;
if (w > 0 && h == 0) {
// only have horizontal border
@@ -165,7 +170,6 @@ void MImageWidgetView::drawContents(QPainter *painter, const QStyleOptionGraphic
border = QRectF(drawRect.x(), drawRect.y() + drawRect.height(), drawRect.width(), bottomBorder);
painter->fillRect(border, brush);
} else {
-
// draw top border
border = QRectF(dx, dy, drawRect.width() + w, topBorder);
painter->fillRect(border, brush);
@@ -185,27 +189,56 @@ void MImageWidgetView::drawContents(QPainter *painter, const QStyleOptionGraphic
painter->setOpacity(oldOpacity);
}
- // draw image
- QPointF topLeft = d->controller->crop().topLeft();
+}
- if (topLeft == QPointF(-1.0, -1.0)) {
+void MImageWidgetViewPrivate::applyStyle()
+{
+ Q_Q(MImageWidgetView);
- // calculate default crop section
- dx = (originSize.width() - sourceSize.width()) / 2.0;
- dy = (originSize.height() - sourceSize.height()) / 2.0;
+ borderOpacity = q->style()->borderOpacity();
+ brush.setColor(q->style()->borderColor());
- sourceRect = QRectF(dx, dy, sourceSize.width(), sourceSize.height());
- } else {
+ leftBorder = q->style()->borderLeft();
+ topBorder = q->style()->borderTop();
+ rightBorder = q->style()->borderRight();
+ bottomBorder = q->style()->borderBottom();
+}
- // calculate crop section by given topLeft corner
- dx = topLeft.x();
- dy = topLeft.y();
+MImageWidgetView::MImageWidgetView(MImageWidget *controller) :
+ MWidgetView(* new MImageWidgetViewPrivate, controller)
+{
+ Q_D(MImageWidgetView);
+ d->controller = controller;
+}
- sourceRect = QRectF(dx, dy, qMin(dx + sourceSize.width(), originSize.width()),
- qMin(dy + sourceSize.height(), originSize.height()));
- }
+MImageWidgetView::MImageWidgetView(MImageWidgetViewPrivate &dd, MImageWidget *controller) :
+ MWidgetView(dd, controller)
+{
+ Q_D(MImageWidgetView);
+ d->controller = controller;
+}
- painter->drawPixmap(drawRect, *pixmap, sourceRect);
+MImageWidgetView::~MImageWidgetView()
+{
+}
+
+void MImageWidgetView::drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const
+{
+ Q_UNUSED(option);
+
+ Q_D(const MImageWidgetView);
+
+ const QPixmap *pixmap = d->controller->pixmap();
+
+ d->drawBorders(painter, d->drawRect);
+
+ if (pixmap) {
+ const_cast<MImageWidgetViewPrivate*>(d)->checkPixmapSize();
+ painter->drawPixmap(d->drawRect, *pixmap, d->sourceRect);
+ } else {
+ QImage image = d->controller->d_func()->image;
+ painter->drawImage(d->drawRect, image, d->sourceRect);
+ }
}
void MImageWidgetView::resizeEvent(QGraphicsSceneResizeEvent *event)
@@ -214,6 +247,37 @@ void MImageWidgetView::resizeEvent(QGraphicsSceneResizeEvent *event)
update();
}
+void MImageWidgetView::setGeometry(const QRectF &rect)
+{
+ Q_D(MImageWidgetView);
+ MWidgetView::setGeometry(rect);
+
+ QSizeF imageSize = d->controller->d_func()->imageDataSize();
+ d->calculateDrawRect(imageSize);
+ d->calculateSourceRect(imageSize);
+}
+
+void MImageWidgetView::applyStyle()
+{
+ Q_D(MImageWidgetView);
+ MWidgetView::applyStyle();
+
+ d->applyStyle();
+}
+
+void MImageWidgetView::updateData(const QList<const char *> &modifications)
+{
+ MWidgetView::updateData(modifications);
+
+ const char *member;
+ for (int i = 0; i < modifications.count(); i++) {
+ member = modifications[i];
+ if (member == MImageWidgetModel::ZoomFactorX || member == MImageWidgetModel::ZoomFactorY || member == MImageWidgetModel::Crop) {
+ updateGeometry();
+ }
+ }
+}
+
QSizeF MImageWidgetView::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
Q_D(const MImageWidgetView);
diff --git a/src/views/mimagewidgetview.h b/src/views/mimagewidgetview.h
index 0f1d0040..fd4c80e0 100644
--- a/src/views/mimagewidgetview.h
+++ b/src/views/mimagewidgetview.h
@@ -72,6 +72,9 @@ protected:
//! \reimp
virtual void drawContents(QPainter *painter, const QStyleOptionGraphicsItem *option) const;
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+ virtual void setGeometry(const QRectF &rect);
+ virtual void applyStyle();
+ virtual void updateData(const QList<const char *> &modifications);
//! \reimp_end
//! \internal
diff --git a/src/views/mimagewidgetview_p.h b/src/views/mimagewidgetview_p.h
new file mode 100644
index 00000000..569643b4
--- /dev/null
+++ b/src/views/mimagewidgetview_p.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (directui@nokia.com)
+**
+** This file is part of libmeegotouch.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at directui@nokia.com.
+**
+** This library is free software; you can redistribute it and/or
+** modify it 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.
+**
+****************************************************************************/
+
+#ifndef MIMAGEWIDGETVIEW_P_H
+#define MIMAGEWIDGETVIEW_P_H
+
+#include "private/mwidgetview_p.h"
+
+class MImageWidget;
+
+class MImageWidgetViewPrivate : public MWidgetViewPrivate
+{
+public:
+ MImageWidgetViewPrivate();
+ ~MImageWidgetViewPrivate();
+
+ void calculateDrawRect(const QSizeF &imageSize);
+ QSizeF calculateSourceSize(const QSizeF &imageSize);
+ void calculateSourceRect(const QSizeF &imageSize);
+
+ void checkPixmapSize();
+
+ void drawBorders(QPainter *painter, const QRectF &drawRect) const;
+
+ void applyStyle();
+
+
+ QRectF drawRect;
+ QRectF sourceRect;
+
+private:
+ Q_DECLARE_PUBLIC(MImageWidgetView)
+ MImageWidget *controller;
+
+ QSize cachedPixmapSize;
+
+ //border related
+ qreal borderOpacity;
+ QBrush brush;
+
+ qreal leftBorder;
+ qreal topBorder;
+ qreal rightBorder;
+ qreal bottomBorder;
+};
+
+
+#endif // MIMAGEWIDGETVIEW_P_H