From 53807e58770f27d46ca8ecaa33a3d5f7b6925517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Mon, 17 Aug 2009 15:45:43 +0200 Subject: Fixed text rendering on GL ES 2 implementations. Some GL ES 2 implementations seem to have problems with glCopyTexSubImage2D(), so we fall back and read the old font texture into system memory and re-upload the new font texture. Also, the precision used for texture coordinates in the fragment programs wasn't high enough, which could lead to rendering artifacts. Reviewed-by: Samuel --- .../gl2paintengineex/qglengineshadersource_p.h | 6 ++-- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 37 ++++++++++++++++------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index b0b91ae..c80d6e1 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -73,8 +73,8 @@ static const char* const qglslMainVertexShader = "\ }"; static const char* const qglslMainWithTexCoordsVertexShader = "\ - attribute lowp vec2 textureCoordArray; \ - varying lowp vec2 textureCoords; \ + attribute mediump vec2 textureCoordArray; \ + varying mediump vec2 textureCoords; \ uniform highp float depth;\ void setPosition();\ void main(void) \ @@ -284,7 +284,7 @@ static const char* const qglslSolidBrushSrcFragmentShader = "\ }"; static const char* const qglslImageSrcFragmentShader = "\ - varying highp vec2 textureCoords; \ + varying mediump vec2 textureCoords; \ uniform sampler2D imageTexture; \ lowp vec4 srcPixel() { \ return texture2D(imageTexture, textureCoords); \ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 5e1e892..34f7e7a 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -75,6 +75,7 @@ #include #include #include +#include #include "qglgradientcache_p.h" #include "qglengineshadermanager_p.h" @@ -175,7 +176,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) m_height = height; QVarLengthArray data(width * height); - for (int i = 0; i < width * height; ++i) + for (int i = 0; i < data.size(); ++i) data[i] = 0; if (m_type == QFontEngineGlyphCache::Raster_RGBMask) @@ -200,13 +201,18 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); - GLuint colorBuffer; - glGenRenderbuffers(1, &colorBuffer); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, colorBuffer); - glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA, oldWidth, oldHeight); - glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_RENDERBUFFER_EXT, colorBuffer); - glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); + GLuint tmp_texture; + glGenTextures(1, &tmp_texture); + glBindTexture(GL_TEXTURE_2D, tmp_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, tmp_texture, 0); glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, oldTexture); @@ -237,11 +243,24 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); glBindTexture(GL_TEXTURE_2D, m_texture); + +#ifdef QT_OPENGL_ES_2 + QDataBuffer buffer(4*oldWidth*oldHeight); + glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); + + // do an in-place conversion from GL_RGBA to GL_ALPHA + for (int i=0; id_ptr->current_fbo); -- cgit v0.12 From 85edfcbde9f1d2f77a05edb8d01361c76234f47c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 17 Aug 2009 15:41:51 +0200 Subject: Merge QGV delta from kinetic-declarativeui into master. New flag: QGraphicsItem::ItemNegativeZStacksBehindParent, which makes it easy to toggle stack-behind based on the value of Z alone. Add interface initializations to QGV classes. Add a simple internal focus policy to QGraphicsItem to allow derived items to be focusable without allowing clickfocus. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 15 +++++++++++++++ src/gui/graphicsview/qgraphicsitem.h | 8 +++++--- src/gui/graphicsview/qgraphicsitem_p.h | 10 ++++++---- src/gui/graphicsview/qgraphicslayout.h | 2 ++ src/gui/graphicsview/qgraphicslayoutitem.h | 2 ++ src/gui/graphicsview/qgraphicsscene.cpp | 7 ++++--- src/gui/graphicsview/qgraphicsscene_p.h | 1 + src/gui/graphicsview/qgraphicswidget.cpp | 4 +++- src/gui/graphicsview/qgraphicswidget.h | 1 + tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 26 ++++++++++++++++++++++++++ 10 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 6d75db3..37d969b 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -328,6 +328,10 @@ used for Asian languages. This flag was introduced in Qt 4.6. + \value ItemNegativeZStacksBehindParent The item automatically stacks behind + it's parent if it's z-value is negative. This flag enables setZValue() to + toggle ItemStacksBehindParent. + \value ItemAutoDetectsFocusProxy The item will assign any child that gains input focus as its focus proxy. See also focusProxy(). This flag was introduced in Qt 4.6. @@ -1566,6 +1570,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); } + if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) { + // Update stack-behind. + setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0)); + } + if (d_ptr->scene) { d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, @@ -3719,6 +3728,9 @@ void QGraphicsItem::setZValue(qreal z) itemChange(ItemZValueHasChanged, newZVariant); + if (d_ptr->flags & ItemNegativeZStacksBehindParent) + setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0)); + if (d_ptr->isObject) emit static_cast(this)->zChanged(); } @@ -10103,6 +10115,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemAcceptsInputMethod: str = "ItemAcceptsInputMethod"; break; + case QGraphicsItem::ItemNegativeZStacksBehindParent: + str = "ItemNegativeZStacksBehindParent"; + break; case QGraphicsItem::ItemAutoDetectsFocusProxy: str = "ItemAutoDetectsFocusProxy"; break; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 3acf265..b5e6ed5 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -101,7 +101,8 @@ public: ItemHasNoContents = 0x400, ItemSendsGeometryChanges = 0x800, ItemAcceptsInputMethod = 0x1000, - ItemAutoDetectsFocusProxy = 0x2000 + ItemAutoDetectsFocusProxy = 0x2000, + ItemNegativeZStacksBehindParent = 0x4000 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) @@ -452,6 +453,7 @@ private: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags) +Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem") inline void QGraphicsItem::setPos(qreal ax, qreal ay) { setPos(QPointF(ax, ay)); } @@ -504,9 +506,9 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem Q_OBJECT Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false) Q_PROPERTY(QString id READ objectName WRITE setObjectName) - Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged) + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) - Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) Q_PROPERTY(QPointF pos READ pos WRITE setPos) Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged) Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c654d4f..43d690f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -95,7 +95,7 @@ public: void purge(); }; -class Q_AUTOTEST_EXPORT QGraphicsItemPrivate +class Q_GUI_EXPORT QGraphicsItemPrivate { Q_DECLARE_PUBLIC(QGraphicsItem) public: @@ -165,6 +165,7 @@ public: acceptedTouchBeginEvent(0), filtersDescendantEvents(0), sceneTransformTranslateOnly(0), + mouseSetsFocus(1), globalStackingOrder(-1), q_ptr(0) { @@ -201,7 +202,7 @@ public: virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; static bool movableAncestorIsSelected(const QGraphicsItem *item); - void setPosHelper(const QPointF &pos); + virtual void setPosHelper(const QPointF &pos); void setTransformHelper(const QTransform &transform); void appendGraphicsTransform(QGraphicsTransform *t); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); @@ -452,7 +453,7 @@ public: // New 32 bits quint32 fullUpdatePending : 1; - quint32 flags : 14; + quint32 flags : 15; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; @@ -465,7 +466,8 @@ public: quint32 acceptedTouchBeginEvent : 1; quint32 filtersDescendantEvents : 1; quint32 sceneTransformTranslateOnly : 1; - quint32 unused : 5; // feel free to use + quint32 mouseSetsFocus : 1; + quint32 unused : 3; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h index d7e087b..1a21e53 100644 --- a/src/gui/graphicsview/qgraphicslayout.h +++ b/src/gui/graphicsview/qgraphicslayout.h @@ -85,6 +85,8 @@ private: friend class QGraphicsWidget; }; +Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout") + #endif QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h index 44c1c0f..f315404 100644 --- a/src/gui/graphicsview/qgraphicslayoutitem.h +++ b/src/gui/graphicsview/qgraphicslayoutitem.h @@ -121,6 +121,8 @@ private: friend class QGraphicsLayout; }; +Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem") + inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah) { setMinimumSize(QSizeF(aw, ah)); } inline void QGraphicsLayoutItem::setPreferredSize(qreal aw, qreal ah) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 2178850..21ea72f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1079,7 +1079,7 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou // Set focus on the topmost enabled item that can take focus. bool setFocus = false; foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { + if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { setFocus = true; if (item != q->focusItem()) @@ -3802,7 +3802,8 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent) bool hasSetFocus = false; foreach (QGraphicsItem *item, wheelCandidates) { - if (!hasSetFocus && item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { + if (!hasSetFocus && item->isEnabled() + && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { if (item->isWidget() && static_cast(item)->focusPolicy() == Qt::WheelFocus) { hasSetFocus = true; if (item != focusItem()) @@ -5298,7 +5299,7 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve // Set focus on the topmost enabled item that can take focus. bool setFocus = false; foreach (QGraphicsItem *item, cachedItemsUnderMouse) { - if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { + if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { setFocus = true; if (item != q->focusItem()) diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 836522d..685f534 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -59,6 +59,7 @@ #include "qgraphicssceneevent.h" #include "qgraphicsview.h" +#include "qgraphicsview_p.h" #include "qgraphicsitem_p.h" #include diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 64881b5..4b41f1f 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -258,7 +258,7 @@ QGraphicsWidget::~QGraphicsWidget() //we check if we have a layout previously if (d->layout) { - delete d->layout; + QGraphicsLayout *temp = d->layout; foreach (QGraphicsItem * item, childItems()) { // In case of a custom layout which doesn't remove and delete items, we ensure that // the parent layout item does not point to the deleted layout. This code is here to @@ -269,6 +269,8 @@ QGraphicsWidget::~QGraphicsWidget() widget->setParentLayoutItem(0); } } + d->layout = 0; + delete temp; } // Remove this graphics widget from widgetStyles diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index 62b353a..57015f9 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -69,6 +69,7 @@ class QGraphicsWidgetPrivate; class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem { Q_OBJECT + Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem) Q_PROPERTY(QPalette palette READ palette WRITE setPalette) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index a623b50..10f0e42 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -281,6 +281,7 @@ private slots: void subFocus(); void reverseCreateAutoFocusProxy(); void focusProxyDeletion(); + void negativeZStacksBehindParent(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -7558,5 +7559,30 @@ void tst_QGraphicsItem::focusProxyDeletion() delete scene; // don't crash } +void tst_QGraphicsItem::negativeZStacksBehindParent() +{ + QGraphicsRectItem rect; + QCOMPARE(rect.zValue(), qreal(0.0)); + QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent)); + QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); + rect.setZValue(-1); + QCOMPARE(rect.zValue(), qreal(-1.0)); + QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); + rect.setZValue(0); + rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent); + QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent); + QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); + rect.setZValue(-1); + QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); + rect.setZValue(0); + QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent)); + rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false); + rect.setZValue(-1); + rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true); + QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); + rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false); + QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 55e3c88a002de2a99e144df82ad7ac375a7c51aa Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Mon, 17 Aug 2009 16:07:21 +0200 Subject: Doc - some clean ups to QSortFilterProxyModel's documentation Reviewed-By: TrustMe --- src/gui/itemviews/qsortfilterproxymodel.cpp | 171 +++++++++++++--------------- 1 file changed, 82 insertions(+), 89 deletions(-) diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 8444a5b..aef59b5 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -1278,82 +1278,76 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved( /*! \since 4.1 \class QSortFilterProxyModel - \brief The QSortFilterProxyModel class provides support for sorting and filtering data passed - between another model and a view. + \brief The QSortFilterProxyModel class provides support for sorting and + filtering data passed between another model and a view. \ingroup model-view - QSortFilterProxyModel can be used for sorting items, filtering - out items, or both. The model transforms the structure of a - source model by mapping the model indexes it supplies to new - indexes, corresponding to different locations, for views to use. - This approach allows a given source model to be restructured as - far as views are concerned without requiring any transformations - on the underlying data, and without duplicating the data in + QSortFilterProxyModel can be used for sorting items, filtering out items, + or both. The model transforms the structure of a source model by mapping + the model indexes it supplies to new indexes, corresponding to different + locations, for views to use. This approach allows a given source model to + be restructured as far as views are concerned without requiring any + transformations on the underlying data, and without duplicating the data in memory. - Let's assume that we want to sort and filter the items provided - by a custom model. The code to set up the model and the view, \e - without sorting and filtering, would look like this: + Let's assume that we want to sort and filter the items provided by a custom + model. The code to set up the model and the view, \e without sorting and + filtering, would look like this: \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 1 - To add sorting and filtering support to \c MyItemModel, we need - to create a QSortFilterProxyModel, call setSourceModel() with the - \c MyItemModel as argument, and install the QSortFilterProxyModel - on the view: + To add sorting and filtering support to \c MyItemModel, we need to create + a QSortFilterProxyModel, call setSourceModel() with the \c MyItemModel as + argument, and install the QSortFilterProxyModel on the view: \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 0 \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 2 - At this point, neither sorting nor filtering is enabled; the - original data is displayed in the view. Any changes made through - the QSortFilterProxyModel are applied to the original model. + At this point, neither sorting nor filtering is enabled; the original data + is displayed in the view. Any changes made through the + QSortFilterProxyModel are applied to the original model. - The QSortFilterProxyModel acts as a wrapper for the original - model. If you need to convert source \l{QModelIndex}es to - sorted/filtered model indexes or vice versa, use mapToSource(), - mapFromSource(), mapSelectionToSource(), and - mapSelectionFromSource(). + The QSortFilterProxyModel acts as a wrapper for the original model. If you + need to convert source \l{QModelIndex}es to sorted/filtered model indexes + or vice versa, use mapToSource(), mapFromSource(), mapSelectionToSource(), + and mapSelectionFromSource(). - \note By default, the model does not dynamically re-sort and re-filter - data whenever the original model changes. This behavior can be - changed by setting the \l{QSortFilterProxyModel::dynamicSortFilter} - {dynamicSortFilter} property. + \note By default, the model does not dynamically re-sort and re-filter data + whenever the original model changes. This behavior can be changed by + setting the \l{QSortFilterProxyModel::dynamicSortFilter}{dynamicSortFilter} + property. - The \l{itemviews/basicsortfiltermodel}{Basic Sort/Filter Model} - and \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} - examples illustrate how to use QSortFilterProxyModel to perform - basic sorting and filtering and how to subclass it to implement - custom behavior. + The \l{itemviews/basicsortfiltermodel}{Basic Sort/Filter Model} and + \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} examples + illustrate how to use QSortFilterProxyModel to perform basic sorting and + filtering and how to subclass it to implement custom behavior. \section1 Sorting QTableView and QTreeView have a - \l{QTreeView::sortingEnabled}{sortingEnabled} property that - controls whether the user can sort the view by clicking the - view's horizontal header. For example: + \l{QTreeView::sortingEnabled}{sortingEnabled} property that controls + whether the user can sort the view by clicking the view's horizontal + header. For example: \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 3 - When this feature is on (the default is off), clicking on a - header section sorts the items according to that column. By - clicking repeatedly, the user can alternate between ascending and - descending order. + When this feature is on (the default is off), clicking on a header section + sorts the items according to that column. By clicking repeatedly, the user + can alternate between ascending and descending order. \image qsortfilterproxymodel-sorting.png A sorted QTreeView - Behind the scene, the view calls the sort() virtual function on - the model to reorder the data in the model. To make your data - sortable, you can either implement sort() in your model, or you - use a QSortFilterProxyModel to wrap your model -- - QSortFilterProxyModel provides a generic sort() reimplementation - that operates on the sortRole() (Qt::DisplayRole by default) of - the items and that understands several data types, including \c - int, QString, and QDateTime. For hierarchical models, sorting is - applied recursively to all child items. String comparisons are - case sensitive by default; this can be changed by setting the - \l{QSortFilterProxyModel::}{sortCaseSensitivity} property. + Behind the scene, the view calls the sort() virtual function on the model + to reorder the data in the model. To make your data sortable, you can + either implement sort() in your model, or use a QSortFilterProxyModel to + wrap your model -- QSortFilterProxyModel provides a generic sort() + reimplementation that operates on the sortRole() (Qt::DisplayRole by + default) of the items and that understands several data types, including + \c int, QString, and QDateTime. For hierarchical models, sorting is applied + recursively to all child items. String comparisons are case sensitive by + default; this can be changed by setting the \l{QSortFilterProxyModel::} + {sortCaseSensitivity} property. Custom sorting behavior is achieved by subclassing QSortFilterProxyModel and reimplementing lessThan(), which is @@ -1365,43 +1359,42 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved( \l{itemviews/customsortfiltermodel}{Custom Sort/Filter Model} example.) - An alternative approach to sorting is to disable sorting on the - view and to impose a certain order to the user. This is done by - explicitly calling sort() with the desired column and order as - arguments on the QSortFilterProxyModel (or on the original model - if it implements sort()). For example: + An alternative approach to sorting is to disable sorting on the view and to + impose a certain order to the user. This is done by explicitly calling + sort() with the desired column and order as arguments on the + QSortFilterProxyModel (or on the original model if it implements sort()). + For example: \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 4 - QSortFilterProxyModel can be sorted by column -1, in which case it - returns to the sort order of the underlying source model. + QSortFilterProxyModel can be sorted by column -1, in which case it returns + to the sort order of the underlying source model. \section1 Filtering - In addition to sorting, QSortFilterProxyModel can be used to hide - items that don't match a certain filter. The filter is specified - using a QRegExp object and is applied to the filterRole() - (Qt::DisplayRole by default) of each item, for a given column. - The QRegExp object can be used to match a regular expression, a - wildcard pattern, or a fixed string. For example: + In addition to sorting, QSortFilterProxyModel can be used to hide items + that do not match a certain filter. The filter is specified using a QRegExp + object and is applied to the filterRole() (Qt::DisplayRole by default) of + each item, for a given column. The QRegExp object can be used to match a + regular expression, a wildcard pattern, or a fixed string. For example: \snippet doc/src/snippets/qsortfilterproxymodel-details/main.cpp 5 - For hierarchical models, the filter is applied recursively to all - children. If a parent item doesn't match the filter, none of its - children will be shown. + For hierarchical models, the filter is applied recursively to all children. + If a parent item doesn't match the filter, none of its children will be + shown. - A common use case is to let the user specify the filter regexp, - wildcard pattern, or fixed string in a QLineEdit and to connect - the \l{QLineEdit::textChanged()}{textChanged()} signal to - setFilterRegExp(), setFilterWildcard(), or setFilterFixedString() - to reapply the filter. + A common use case is to let the user specify the filter regexp, wildcard + pattern, or fixed string in a QLineEdit and to connect the + \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegExp(), + setFilterWildcard(), or setFilterFixedString() to reapply the filter. Custom filtering behavior can be achieved by reimplementing the filterAcceptsRow() and filterAcceptsColumn() functions. For - example, the following implementation ignores the - \l{QSortFilterProxyModel::filterKeyColumn}{filterKeyColumn} - property and performs filtering on columns 0, 1, and 2: + example (from the \l{itemviews/customsortfiltermodel} + {Custom Sort/Filter Model} example), the following implementation ignores + the \l{QSortFilterProxyModel::filterKeyColumn}{filterKeyColumn} property + and performs filtering on columns 0, 1, and 2: \snippet examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 3 @@ -1411,24 +1404,24 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsRemoved( If you are working with large amounts of filtering and have to invoke invalidateFilter() repeatedly, using reset() may be more efficient, - depending on the implementation of your model. However, note that reset() - returns the proxy model to its original state, losing selection - information, and will cause the proxy model to be repopulated. + depending on the implementation of your model. However, reset() returns the + proxy model to its original state, losing selection information, and will + cause the proxy model to be repopulated. \section1 Subclassing - \bold{Note:} Some general guidelines for subclassing models are - available in the \l{Model Subclassing Reference}. - Since QAbstractProxyModel and its subclasses are derived from - QAbstractItemModel, much of the same advice about subclassing normal - models also applies to proxy models. In addition, it is worth noting - that many of the default implementations of functions in this class - are written so that they call the equivalent functions in the relevant - source model. This simple proxying mechanism may need to be overridden - for source models with more complex behavior; for example, if the - source model provides a custom hasChildren() implementation, you - should also provide one in the proxy model. + QAbstractItemModel, much of the same advice about subclassing normal models + also applies to proxy models. In addition, it is worth noting that many of + the default implementations of functions in this class are written so that + they call the equivalent functions in the relevant source model. This + simple proxying mechanism may need to be overridden for source models with + more complex behavior; for example, if the source model provides a custom + hasChildren() implementation, you should also provide one in the proxy + model. + + \note Some general guidelines for subclassing models are available in the + \l{Model Subclassing Reference}. \sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming}, {Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example} -- cgit v0.12 From b31244b59396abea08254cb649eb1f59b2f8ed55 Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Mon, 17 Aug 2009 16:12:55 +0200 Subject: Doc - mentioned that if no QRegExp is set, or an empty string is set, everything in the source model will be accepted. Task: 251308 Reviewed-By: Olivier Goffart --- src/gui/itemviews/qsortfilterproxymodel.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index aef59b5..d173efe 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -1984,9 +1984,11 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const \brief the QRegExp used to filter the contents of the source model Setting this property overwrites the current - \l{QSortFilterProxyModel::filterCaseSensitivity} - {filterCaseSensitivity}. By default, the QRegExp is an empty - string matching all contents. + \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}. + By default, the QRegExp is an empty string matching all contents. + + If no QRegExp or an empty string is set, everything in the source model + will be accepted. \sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString() */ -- cgit v0.12 From ac9f56b31dacc35dd2007caee69a9cf521ed8410 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Mon, 17 Aug 2009 16:12:12 +0200 Subject: Add support for the orientation of tiff images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The orientation tag was ignored for tiff images. The tag is now used to rotate the image before providing it to the user. The orientation of indexed an mono images is done completely manually. The orientation of other type is done in conjunction to the mirroring already performed by libtiff. Task-number: 258526 Reviewed-by: Samuel Rødal --- src/plugins/imageformats/tiff/qtiffhandler.cpp | 107 ++++++++++++++++++++- .../tiff_oriented/indexed_orientation_1.tiff | Bin 0 -> 7740 bytes .../tiff_oriented/indexed_orientation_2.tiff | Bin 0 -> 9570 bytes .../tiff_oriented/indexed_orientation_3.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_4.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_5.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_6.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_7.tiff | Bin 0 -> 11392 bytes .../tiff_oriented/indexed_orientation_8.tiff | Bin 0 -> 11392 bytes .../images/tiff_oriented/mono_orientation_1.tiff | Bin 0 -> 2382 bytes .../images/tiff_oriented/mono_orientation_2.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_3.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_4.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_5.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_6.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_7.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/mono_orientation_8.tiff | Bin 0 -> 1608 bytes .../images/tiff_oriented/original_indexed.tiff | Bin 0 -> 5922 bytes .../images/tiff_oriented/original_mono.tiff | Bin 0 -> 786 bytes .../images/tiff_oriented/original_rgb.tiff | Bin 0 -> 12608 bytes .../images/tiff_oriented/rgb_orientation_1.tiff | Bin 0 -> 15560 bytes .../images/tiff_oriented/rgb_orientation_2.tiff | Bin 0 -> 17972 bytes .../images/tiff_oriented/rgb_orientation_3.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_4.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_5.tiff | Bin 0 -> 17648 bytes .../images/tiff_oriented/rgb_orientation_6.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_7.tiff | Bin 0 -> 17324 bytes .../images/tiff_oriented/rgb_orientation_8.tiff | Bin 0 -> 17324 bytes tests/auto/qimagereader/tst_qimagereader.cpp | 45 +++++++++ 29 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff create mode 100644 tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index ec8a483..59edaf4 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -98,6 +98,43 @@ void qtiffUnmapProc(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/) { } +// for 32 bits images +inline void rotate_right_mirror_horizontal(QImage *const image)// rotate right->mirrored horizontal +{ + const int height = image->height(); + const int width = image->width(); + QImage generated(/* width = */ height, /* height = */ width, image->format()); + const uint32 *originalPixel = reinterpret_cast(image->bits()); + uint32 *const generatedPixels = reinterpret_cast(generated.bits()); + for (int row=0; row < height; ++row) { + for (int col=0; col < width; ++col) { + int idx = col * height + row; + generatedPixels[idx] = *originalPixel; + ++originalPixel; + } + } + *image = generated; +} + +inline void rotate_right_mirror_vertical(QImage *const image) // rotate right->mirrored vertical +{ + const int height = image->height(); + const int width = image->width(); + QImage generated(/* width = */ height, /* height = */ width, image->format()); + const int lastCol = width - 1; + const int lastRow = height - 1; + const uint32 *pixel = reinterpret_cast(image->bits()); + uint32 *const generatedBits = reinterpret_cast(generated.bits()); + for (int row=0; row < height; ++row) { + for (int col=0; col < width; ++col) { + int idx = (lastCol - col) * height + (lastRow - row); + generatedBits[idx] = *pixel; + ++pixel; + } + } + *image = generated; +} + QTiffHandler::QTiffHandler() : QImageIOHandler() { compression = NoCompression; @@ -223,7 +260,8 @@ bool QTiffHandler::read(QImage *image) if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32) *image = QImage(width, height, QImage::Format_ARGB32); if (!image->isNull()) { - if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), ORIENTATION_TOPLEFT, 0)) { + const int stopOnError = 1; + if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast(image->bits()), ORIENTATION_TOPLEFT, stopOnError)) { for (uint32 y=0; yscanLine(y), width); } else { @@ -262,6 +300,73 @@ bool QTiffHandler::read(QImage *image) } } + // rotate the image if the orientation is defined in the file + uint16 orientationTag; + if (TIFFGetField(tiff, TIFFTAG_ORIENTATION, &orientationTag)) { + if (image->format() == QImage::Format_ARGB32) { + // TIFFReadRGBAImageOriented() flip the image but does not rotate them + switch (orientationTag) { + case 5: + rotate_right_mirror_horizontal(image); + break; + case 6: + rotate_right_mirror_vertical(image); + break; + case 7: + rotate_right_mirror_horizontal(image); + break; + case 8: + rotate_right_mirror_vertical(image); + break; + } + } else { + switch (orientationTag) { + case 1: // default orientation + break; + case 2: // mirror horizontal + *image = image->mirrored(true, false); + break; + case 3: // mirror both + *image = image->mirrored(true, true); + break; + case 4: // mirror vertical + *image = image->mirrored(false, true); + break; + case 5: // rotate right mirror horizontal + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + *image = image->mirrored(true, false); + break; + } + case 6: // rotate right + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + break; + } + case 7: // rotate right, mirror vertical + { + QMatrix transformation; + transformation.rotate(90); + *image = image->transformed(transformation); + *image = image->mirrored(false, true); + break; + } + case 8: // rotate left + { + QMatrix transformation; + transformation.rotate(270); + *image = image->transformed(transformation); + break; + } + } + } + } + + TIFFClose(tiff); return true; } diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff new file mode 100644 index 0000000..3fcb8a9 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_1.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff new file mode 100644 index 0000000..6f3e9d5 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_2.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff new file mode 100644 index 0000000..aab9cf2 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_3.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff new file mode 100644 index 0000000..aad96ff Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_4.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff new file mode 100644 index 0000000..05d23dc Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_5.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff new file mode 100644 index 0000000..9ffe7fc Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_6.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff new file mode 100644 index 0000000..eeeb019 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_7.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff new file mode 100644 index 0000000..87cf2fd Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/indexed_orientation_8.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff new file mode 100644 index 0000000..3b589b2 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_1.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff new file mode 100644 index 0000000..9a66223 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_2.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff new file mode 100644 index 0000000..eed2423 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_3.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff new file mode 100644 index 0000000..055480e Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_4.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff new file mode 100644 index 0000000..b4d0974 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_5.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff new file mode 100644 index 0000000..3b1e02a Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_6.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff new file mode 100644 index 0000000..b752c74 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_7.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff new file mode 100644 index 0000000..e228d05 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/mono_orientation_8.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff b/tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff new file mode 100644 index 0000000..7507e52 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/original_indexed.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff b/tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff new file mode 100644 index 0000000..8ff9db8 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/original_mono.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff b/tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff new file mode 100644 index 0000000..321ea3e Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/original_rgb.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff new file mode 100644 index 0000000..2756a82 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_1.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff new file mode 100644 index 0000000..ae9af09 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_2.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff new file mode 100644 index 0000000..a2f4325 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_3.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff new file mode 100644 index 0000000..f35bfc4 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_4.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff new file mode 100644 index 0000000..70e5478 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_5.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff new file mode 100644 index 0000000..b2635fe Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_6.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff new file mode 100644 index 0000000..1fb0cd9 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_7.tiff differ diff --git a/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff new file mode 100644 index 0000000..666b1b4 Binary files /dev/null and b/tests/auto/qimagereader/images/tiff_oriented/rgb_orientation_8.tiff differ diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index dad771b..ba3d83e 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -149,6 +149,9 @@ private slots: void tiffCompression_data(); void tiffCompression(); void tiffEndianness(); + + void tiffOrientation_data(); + void tiffOrientation(); #endif void autoDetectImageFormat(); @@ -1308,6 +1311,48 @@ void tst_QImageReader::tiffEndianness() QCOMPARE(littleEndian, bigEndian); } +void tst_QImageReader::tiffOrientation_data() +{ + QTest::addColumn("expected"); + QTest::addColumn("oriented"); + QTest::newRow("Indexed TIFF, orientation1") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_1.tiff"; + QTest::newRow("Indexed TIFF, orientation2") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_2.tiff"; + QTest::newRow("Indexed TIFF, orientation3") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_3.tiff"; + QTest::newRow("Indexed TIFF, orientation4") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_4.tiff"; + QTest::newRow("Indexed TIFF, orientation5") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_5.tiff"; + QTest::newRow("Indexed TIFF, orientation6") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_6.tiff"; + QTest::newRow("Indexed TIFF, orientation7") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_7.tiff"; + QTest::newRow("Indexed TIFF, orientation8") << "tiff_oriented/original_indexed.tiff" << "tiff_oriented/indexed_orientation_8.tiff"; + + QTest::newRow("Mono TIFF, orientation1") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_1.tiff"; + QTest::newRow("Mono TIFF, orientation2") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_2.tiff"; + QTest::newRow("Mono TIFF, orientation3") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_3.tiff"; + QTest::newRow("Mono TIFF, orientation4") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_4.tiff"; + QTest::newRow("Mono TIFF, orientation5") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_5.tiff"; + QTest::newRow("Mono TIFF, orientation6") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_6.tiff"; + QTest::newRow("Mono TIFF, orientation7") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_7.tiff"; + QTest::newRow("Mono TIFF, orientation8") << "tiff_oriented/original_mono.tiff" << "tiff_oriented/mono_orientation_8.tiff"; + + QTest::newRow("RGB TIFF, orientation1") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_1.tiff"; + QTest::newRow("RGB TIFF, orientation2") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_2.tiff"; + QTest::newRow("RGB TIFF, orientation3") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_3.tiff"; + QTest::newRow("RGB TIFF, orientation4") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_4.tiff"; + QTest::newRow("RGB TIFF, orientation5") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_5.tiff"; + QTest::newRow("RGB TIFF, orientation6") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_6.tiff"; + QTest::newRow("RGB TIFF, orientation7") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_7.tiff"; + QTest::newRow("RGB TIFF, orientation8") << "tiff_oriented/original_rgb.tiff" << "tiff_oriented/rgb_orientation_8.tiff"; +} + +void tst_QImageReader::tiffOrientation() +{ + QFETCH(QString, expected); + QFETCH(QString, oriented); + + QImage expectedImage(prefix + expected); + QImage orientedImage(prefix + oriented); + QCOMPARE(expectedImage, orientedImage); +} + #endif void tst_QImageReader::dotsPerMeter_data() -- cgit v0.12 From 351f8f97fbb2996827f8345cf4dc26afe4208cea Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Fri, 14 Aug 2009 17:45:30 +0200 Subject: Initialize QSvgTinyDocument::m_widthPercent and m_heightPercent. Reviewed-by: Trond --- src/svg/qsvgtinydocument.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index 5ab2608..614494f 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -61,10 +61,12 @@ QT_BEGIN_NAMESPACE QSvgTinyDocument::QSvgTinyDocument() - : QSvgStructureNode(0), - m_animated(false), - m_animationDuration(0), - m_fps(30) + : QSvgStructureNode(0) + , m_widthPercent(false) + , m_heightPercent(false) + , m_animated(false) + , m_animationDuration(0) + , m_fps(30) { } -- cgit v0.12 From 994ca2d739830ea30334d1aca080813d7db4498c Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 17 Aug 2009 11:37:39 +0200 Subject: Removed unused member variable from QGLFramebufferObjectPrivate. Reviewed-by: Samuel --- src/opengl/qglframebufferobject.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index f48c18d..b93cee8 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -275,7 +275,6 @@ public: GLenum target; QSize size; QGLFramebufferObjectFormat format; - int samples; uint valid : 1; uint bound : 1; QGLFramebufferObject::Attachment fbo_attachment; @@ -368,7 +367,6 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At valid = checkFramebufferStatus(); color_buffer = 0; - samples = 0; } else { GLint maxSamples; glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples); -- cgit v0.12 From d490ce3d1f2ec3937f3dd272821d139fcd8de506 Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 17 Aug 2009 15:18:20 +0200 Subject: Implemented faster image transformation in the raster engine. Task-number: 245650 Reviewed-by: Gunnar --- src/gui/painting/qblendfunctions.cpp | 633 +++++++++++++++++++++++++++++++ src/gui/painting/qdrawhelper_p.h | 9 + src/gui/painting/qpaintengine_raster.cpp | 35 +- 3 files changed, 664 insertions(+), 13 deletions(-) diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 1121c0e..e447301 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -793,8 +793,351 @@ void qt_scale_image_argb32_on_argb32(uchar *destPixels, int dbpl, } } +struct QTransformImageVertex +{ + qreal x, y, u, v; // destination coordinates (x, y) and source coordinates (u, v) +}; + +template +void qt_transform_image_rasterize(DestT *destPixels, int dbpl, + const SrcT *srcPixels, int sbpl, + const QTransformImageVertex &topLeft, const QTransformImageVertex &bottomLeft, + const QTransformImageVertex &topRight, const QTransformImageVertex &bottomRight, + const QRect &sourceRect, + const QRect &clip, + qreal topY, qreal bottomY, + int dudx, int dvdx, int dudy, int dvdy, int u0, int v0, + Blender blender) +{ + int fromY = qMax(qRound(topY), clip.top()); + int toY = qMin(qRound(bottomY), clip.top() + clip.height()); + if (fromY >= toY) + return; + + qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y); + qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y); + int dx_l = int(leftSlope * 0x10000); + int dx_r = int(rightSlope * 0x10000); + int x_l = int((topLeft.x + (0.5 + fromY - topLeft.y) * leftSlope + 0.5) * 0x10000); + int x_r = int((topRight.x + (0.5 + fromY - topRight.y) * rightSlope + 0.5) * 0x10000); + + int fromX, toX, x1, x2, u, v, i, ii; + DestT *line; + for (int y = fromY; y < toY; ++y) { + line = reinterpret_cast(reinterpret_cast(destPixels) + y * dbpl); + + fromX = qMax(x_l >> 16, clip.left()); + toX = qMin(x_r >> 16, clip.left() + clip.width()); + if (fromX < toX) { + // Because of rounding, we can get source coordinates outside the source image. + // Clamp these coordinates to the source rect to avoid segmentation fault and + // garbage on the screen. + + // Find the first pixel on the current scan line where the source coordinates are within the source rect. + x1 = fromX; + u = x1 * dudx + y * dudy + u0; + v = x1 * dvdx + y * dvdy + v0; + for (; x1 < toX; ++x1) { + int uu = u >> 16; + int vv = v >> 16; + if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() + && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { + break; + } + u += dudx; + v += dvdx; + } + + // Find the last pixel on the current scan line where the source coordinates are within the source rect. + x2 = toX; + u = (x2 - 1) * dudx + y * dudy + u0; + v = (x2 - 1) * dvdx + y * dvdy + v0; + for (; x2 > x1; --x2) { + int uu = u >> 16; + int vv = v >> 16; + if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width() + && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) { + break; + } + u -= dudx; + v -= dvdx; + } + + // Set up values at the beginning of the scan line. + u = fromX * dudx + y * dudy + u0; + v = fromX * dvdx + y * dvdy + v0; + line += fromX; + + // Beginning of the scan line, with per-pixel checks. + i = x1 - fromX; + while (i) { + int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); + int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); + blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + vv * sbpl)[uu]); + u += dudx; + v += dvdx; + ++line; + --i; + } + + // Middle of the scan line, without checks. + // Manual loop unrolling. + i = x2 - x1; + ii = i >> 3; + while (ii) { + blender.write(&line[0], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[1], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[2], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[3], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[4], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[5], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[6], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + blender.write(&line[7], reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; + line += 8; + --ii; + } + switch (i & 7) { + case 7: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 6: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 5: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 4: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 3: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 2: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + case 1: blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + (v >> 16) * sbpl)[u >> 16]); u += dudx; v += dvdx; ++line; + } + + // End of the scan line, with per-pixel checks. + i = toX - x2; + while (i) { + int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1); + int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1); + blender.write(line, reinterpret_cast(reinterpret_cast(srcPixels) + vv * sbpl)[uu]); + u += dudx; + v += dvdx; + ++line; + --i; + } + } + x_l += dx_l; + x_r += dx_r; + } +} + +template +void qt_transform_image(DestT *destPixels, int dbpl, + const SrcT *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + Blender blender) +{ + enum Corner + { + TopLeft, + TopRight, + BottomRight, + BottomLeft + }; + + // map source rectangle to destination. + QTransformImageVertex v[4]; + v[TopLeft].u = v[BottomLeft].u = sourceRect.left(); + v[TopLeft].v = v[TopRight].v = sourceRect.top(); + v[TopRight].u = v[BottomRight].u = sourceRect.right(); + v[BottomLeft].v = v[BottomRight].v = sourceRect.bottom(); + targetRectTransform.map(targetRect.left(), targetRect.top(), &v[TopLeft].x, &v[TopLeft].y); + targetRectTransform.map(targetRect.right(), targetRect.top(), &v[TopRight].x, &v[TopRight].y); + targetRectTransform.map(targetRect.left(), targetRect.bottom(), &v[BottomLeft].x, &v[BottomLeft].y); + targetRectTransform.map(targetRect.right(), targetRect.bottom(), &v[BottomRight].x, &v[BottomRight].y); + + // find topmost vertex. + int topmost = 0; + for (int i = 1; i < 4; ++i) { + if (v[i].y < v[topmost].y) + topmost = i; + } + // rearrange array such that topmost vertex is at index 0. + switch (topmost) { + case 1: + { + QTransformImageVertex t = v[0]; + for (int i = 0; i < 3; ++i) + v[i] = v[i+1]; + v[3] = t; + } + break; + case 2: + qSwap(v[0], v[2]); + qSwap(v[1], v[3]); + break; + case 3: + { + QTransformImageVertex t = v[3]; + for (int i = 3; i > 0; --i) + v[i] = v[i-1]; + v[0] = t; + } + break; + } + + // if necessary, swap vertex 1 and 3 such that 1 is to the left of 3. + qreal dx1 = v[1].x - v[0].x; + qreal dy1 = v[1].y - v[0].y; + qreal dx2 = v[3].x - v[0].x; + qreal dy2 = v[3].y - v[0].y; + if (dx1 * dy2 - dx2 * dy1 > 0) + qSwap(v[1], v[3]); + + QTransformImageVertex u = {v[1].x - v[0].x, v[1].y - v[0].y, v[1].u - v[0].u, v[1].v - v[0].v}; + QTransformImageVertex w = {v[2].x - v[0].x, v[2].y - v[0].y, v[2].u - v[0].u, v[2].v - v[0].v}; + + qreal det = u.x * w.y - u.y * w.x; + if (det == 0) + return; + + qreal invDet = 1.0 / det; + qreal m11, m12, m21, m22, mdx, mdy; + + m11 = (u.u * w.y - u.y * w.u) * invDet; + m12 = (u.x * w.u - u.u * w.x) * invDet; + m21 = (u.v * w.y - u.y * w.v) * invDet; + m22 = (u.x * w.v - u.v * w.x) * invDet; + mdx = v[0].u - m11 * v[0].x - m12 * v[0].y; + mdy = v[0].v - m21 * v[0].x - m22 * v[0].y; + + int dudx = int(m11 * 0x10000); + int dvdx = int(m21 * 0x10000); + int dudy = int(m12 * 0x10000); + int dvdy = int(m22 * 0x10000); + int u0 = qCeil((0.5 * m11 + 0.5 * m12 + mdx) * 0x10000) - 1; + int v0 = qCeil((0.5 * m21 + 0.5 * m22 + mdy) * 0x10000) - 1; + + int x1 = qFloor(sourceRect.left()); + int y1 = qFloor(sourceRect.top()); + int x2 = qCeil(sourceRect.right()); + int y2 = qCeil(sourceRect.bottom()); + QRect sourceRectI(x1, y1, x2 - x1, y2 - y1); + + // rasterize trapezoids. + if (v[1].y < v[3].y) { + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[0], v[3], sourceRectI, clip, v[1].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[3].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + } else { + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[0], v[3], sourceRectI, clip, v[0].y, v[3].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[0], v[1], v[3], v[2], sourceRectI, clip, v[3].y, v[1].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + qt_transform_image_rasterize(destPixels, dbpl, srcPixels, sbpl, v[1], v[2], v[3], v[2], sourceRectI, clip, v[1].y, v[2].y, dudx, dvdx, dudy, dvdy, u0, v0, blender); + } +} + +void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_RGB16_on_RGB16_NoAlpha noAlpha; + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_RGB16_on_RGB16_ConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + +void qt_transform_image_argb24_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_ARGB24_on_RGB16_SourceAlpha noAlpha; + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} +void qt_transform_image_argb32_on_rgb16(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_ARGB32_on_RGB16_SourceAlpha noAlpha; + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_ARGB32_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + + +void qt_transform_image_rgb32_on_rgb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_RGB32_on_RGB32_NoAlpha noAlpha; + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, noAlpha); + } else { + Blend_RGB32_on_RGB32_ConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + +void qt_transform_image_argb32_on_argb32(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + const QTransform &targetRectTransform, + int const_alpha) +{ + if (const_alpha == 256) { + Blend_ARGB32_on_ARGB32_SourceAlpha sourceAlpha; + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, sourceAlpha); + } else { + Blend_ARGB32_on_ARGB32_SourceAndConstAlpha constAlpha(const_alpha); + qt_transform_image(reinterpret_cast(destPixels), dbpl, + reinterpret_cast(srcPixels), sbpl, + targetRect, sourceRect, clip, targetRectTransform, constAlpha); + } +} + SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = { { // Format_Invalid 0, // Format_Invalid, @@ -1378,5 +1721,295 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] = } }; +SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats] = { + { // Format_Invalid + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_Mono + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_MonoLSB + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_Indexed8 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB32 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + qt_transform_image_rgb32_on_rgb32, // Format_RGB32, + 0, // Format_ARGB32, + qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB32 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB32_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + qt_transform_image_rgb32_on_rgb32, // Format_RGB32, + 0, // Format_ARGB32, + qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB16 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + qt_transform_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied, + qt_transform_image_rgb16_on_rgb16, // Format_RGB16, + qt_transform_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB8565_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB666 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB6666_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB555 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB8555_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB888 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_RGB444 + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + }, + { // Format_ARGB4444_Premultiplied + 0, // Format_Invalid, + 0, // Format_Mono, + 0, // Format_MonoLSB, + 0, // Format_Indexed8, + 0, // Format_RGB32, + 0, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied, + 0, // Format_RGB16, + 0, // Format_ARGB8565_Premultiplied, + 0, // Format_RGB666, + 0, // Format_ARGB6666_Premultiplied, + 0, // Format_RGB555, + 0, // Format_ARGB8555_Premultiplied, + 0, // Format_RGB888, + 0, // Format_RGB444, + 0 // Format_ARGB4444_Premultiplied, + } +}; QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 18c3358..83d2671 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -146,6 +146,14 @@ typedef void (*SrcOverScaleFunc)(uchar *destPixels, int dbpl, const QRect &clipRect, int const_alpha); +typedef void (*SrcOverTransformFunc)(uchar *destPixels, int dbpl, + const uchar *src, int spbl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clipRect, + const QTransform &targetRectTransform, + int const_alpha); + struct DrawHelper { ProcessSpans blendColor; @@ -158,6 +166,7 @@ struct DrawHelper { extern SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats]; extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats]; +extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats]; extern DrawHelper qDrawHelper[QImage::NImageFormats]; diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index d00329b..8b83f02 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2495,10 +2495,7 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) const QClipData *clip = d->clip(); QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); - // ### TODO: remove this eventually... - static bool NO_BLEND_FUNC = !qgetenv("QT_NO_BLEND_FUNCTIONS").isNull(); - - if (s->flags.fast_images && !NO_BLEND_FUNC) { + if (s->flags.fast_images) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { if (!clip) { @@ -2511,6 +2508,8 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) } } + + d->image_filler.clip = clip; d->image_filler.initTexture(&img, s->intOpacity, QTextureData::Plain, img.rect()); if (!d->image_filler.blend) @@ -2562,14 +2561,24 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { if (s->flags.fast_images) { - SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()]; - if (func && (!clip || clip->hasRectClip)) { - func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), - img.bits(), img.bytesPerLine(), - qt_mapRect_non_normalizing(r, s->matrix), sr, - !clip ? d->deviceRect : clip->clipRect, - s->intOpacity); - return; + if (s->matrix.type() > QTransform::TxScale) { + SrcOverTransformFunc func = qTransformFunctions[d->rasterBuffer->format][img.format()]; + if (func && (!clip || clip->hasRectClip)) { + func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), img.bits(), + img.bytesPerLine(), r, sr, !clip ? d->deviceRect : clip->clipRect, + s->matrix, s->intOpacity); + return; + } + } else { + SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()]; + if (func && (!clip || clip->hasRectClip)) { + func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(), + img.bits(), img.bytesPerLine(), + qt_mapRect_non_normalizing(r, s->matrix), sr, + !clip ? d->deviceRect : clip->clipRect, + s->intOpacity); + return; + } } } @@ -4056,7 +4065,7 @@ void QRasterPaintEnginePrivate::recalculateFastImages() s->flags.fast_images = !(s->renderHints & QPainter::SmoothPixmapTransform) && rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver - && s->matrix.type() <= QTransform::TxScale; + && s->matrix.type() <= QTransform::TxShear; } -- cgit v0.12