aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2019-12-23 08:39:26 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-01-30 19:16:48 +0100
commitf7647d5adaaed4c651cb2e65c7ce66d7ef6639f1 (patch)
treea121b8cb94b63e5b871f5b329e621707114c0cdd
parent9cc4568de330e0075c960a5431ecd69a1f9a761d (diff)
Add Image.sourceClipRect property
Since we set sourceSize, we expect to use that coordinate system in sourceClipRect too. Therefore we use QImageReader::setScaledClipRect(), not setClipRect(). [ChangeLog][QtQuick][Image] Image now has a sourceClipRect property to render a clipped image from a region of the sourceSize. Change-Id: If08277df772c2ab1063dd88572e49de41b97bca4 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r--src/quick/items/qquickimage.cpp54
-rw-r--r--src/quick/items/qquickimage_p.h1
-rw-r--r--src/quick/items/qquickimagebase.cpp25
-rw-r--r--src/quick/items/qquickimagebase_p.h5
-rw-r--r--src/quick/items/qquickimagebase_p_p.h1
-rw-r--r--tests/manual/tableview/imagetiling/imageTiling.qml90
-rw-r--r--tests/manual/tableview/imagetiling/map.pdfbin0 -> 31904 bytes
-rw-r--r--tests/manual/tableview/imagetiling/map.pngbin0 -> 21101 bytes
-rw-r--r--tests/manual/tableview/imagetiling/map.svgzbin0 -> 27956 bytes
9 files changed, 172 insertions, 4 deletions
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index fccacdcce8..1882ec8997 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -427,10 +427,10 @@ qreal QQuickImage::paintedHeight() const
/*!
\qmlproperty QSize QtQuick::Image::sourceSize
- This property holds the actual width and height of the loaded image.
+ This property holds the scaled width and height of the full-frame image.
Unlike the \l {Item::}{width} and \l {Item::}{height} properties, which scale
- the painting of the image, this property sets the actual number of pixels
+ the painting of the image, this property sets the maximum number of pixels
stored for the loaded image so that large images do not use more
memory than necessary. For example, this ensures the image in memory is no
larger than 1024x1024 pixels, regardless of the Image's \l {Item::}{width} and
@@ -455,7 +455,7 @@ qreal QQuickImage::paintedHeight() const
other dimension is set in proportion to preserve the source image's aspect ratio.
(The \l fillMode is independent of this.)
- If both the sourceSize.width and sourceSize.height are set the image will be scaled
+ If both the sourceSize.width and sourceSize.height are set, the image will be scaled
down to fit within the specified size (unless PreserveAspectCrop or PreserveAspectFit
are used, then it will be scaled to match the optimal size for cropping/fitting),
maintaining the image's aspect ratio. The actual
@@ -470,6 +470,9 @@ qreal QQuickImage::paintedHeight() const
be no greater than this property specifies. For some formats (currently only JPEG),
the whole image will never actually be loaded into memory.
+ If the \l sourceClipRect property is also set, \c sourceSize determines the scale,
+ but it will be clipped to the size of the clip rectangle.
+
sourceSize can be cleared to the natural size of the image
by setting sourceSize to \c undefined.
@@ -478,6 +481,51 @@ qreal QQuickImage::paintedHeight() const
*/
/*!
+ \qmlproperty rect QtQuick::Image::sourceClipRect
+ \since 5.15
+
+ This property, if set, holds the rectangular region of the source image to
+ be loaded.
+
+ The \c sourceClipRect works together with the \l sourceSize property to
+ conserve system resources when only a portion of an image needs to be
+ loaded.
+
+ \code
+ Rectangle {
+ width: ...
+ height: ...
+
+ Image {
+ anchors.fill: parent
+ source: "reallyBigImage.svg"
+ sourceSize.width: 1024
+ sourceSize.height: 1024
+ sourceClipRect: Qt.rect(100, 100, 512, 512)
+ }
+ }
+ \endcode
+
+ In the above example, we conceptually scale the SVG graphic to 1024x1024
+ first, and then cut out a region of interest that is 512x512 pixels from a
+ location 100 pixels from the top and left edges. Thus \c sourceSize
+ determines the scale, but the actual output image is 512x512 pixels.
+
+ Some image formats are able to conserve CPU time by rendering only the
+ specified region. Others will need to load the entire image first and then
+ clip it to the specified region.
+
+ This property can be cleared to reload the entire image by setting
+ \c sourceClipRect to \c undefined.
+
+ \note \e {Changing this property dynamically causes the image source to be reloaded,
+ potentially even from the network, if it is not in the disk cache.}
+
+ \note Sub-pixel clipping is not supported: the given rectangle will be
+ passed to \l QImageReader::setScaledClipRect().
+*/
+
+/*!
\qmlproperty url QtQuick::Image::source
Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index f7e652cdcc..e22a94c5af 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -68,6 +68,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImage : public QQuickImageBase
Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged)
Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION 3)
Q_PROPERTY(bool autoTransform READ autoTransform WRITE setAutoTransform NOTIFY autoTransformChanged REVISION 5)
+ Q_PROPERTY(QRectF sourceClipRect READ sourceClipRect WRITE setSourceClipRect RESET resetSourceClipRect NOTIFY sourceClipRectChanged REVISION 15)
QML_NAMED_ELEMENT(Image)
public:
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 20454fb919..2118f67387 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -167,6 +167,29 @@ void QQuickImageBase::resetSourceSize()
setSourceSize(QSize());
}
+QRectF QQuickImageBase::sourceClipRect() const
+{
+ Q_D(const QQuickImageBase);
+ return d->sourceClipRect;
+}
+
+void QQuickImageBase::setSourceClipRect(const QRectF &r)
+{
+ Q_D(QQuickImageBase);
+ if (d->sourceClipRect == r)
+ return;
+
+ d->sourceClipRect = r;
+ emit sourceClipRectChanged();
+ if (isComponentComplete())
+ load();
+}
+
+void QQuickImageBase::resetSourceClipRect()
+{
+ setSourceClipRect(QRect());
+}
+
bool QQuickImageBase::cache() const
{
Q_D(const QQuickImageBase);
@@ -295,7 +318,7 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions)
d->pix.load(qmlEngine(this),
loadUrl,
- QRect(),
+ d->sourceClipRect.toRect(),
(loadOptions & HandleDPR) ? d->sourcesize * d->devicePixelRatio : QSize(),
options,
(loadOptions & UseProviderOptions) ? d->providerOptions : QQuickImageProviderOptions(),
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 9308230bfa..238b31b2e5 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -107,6 +107,10 @@ public:
QSize sourceSize() const;
void resetSourceSize();
+ QRectF sourceClipRect() const;
+ void setSourceClipRect(const QRectF &r);
+ void resetSourceClipRect();
+
virtual void setMirror(bool mirror);
bool mirror() const;
@@ -134,6 +138,7 @@ Q_SIGNALS:
void mirrorChanged();
Q_REVISION(14) void currentFrameChanged();
Q_REVISION(14) void frameCountChanged();
+ Q_REVISION(15) void sourceClipRectChanged();
protected:
void loadEmptyUrl();
diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h
index 88e18ba32e..00a9295ef0 100644
--- a/src/quick/items/qquickimagebase_p_p.h
+++ b/src/quick/items/qquickimagebase_p_p.h
@@ -86,6 +86,7 @@ public:
QSize sourcesize;
QSize oldSourceSize;
qreal devicePixelRatio;
+ QRectF sourceClipRect;
QQuickImageProviderOptions providerOptions;
int currentFrame;
int frameCount;
diff --git a/tests/manual/tableview/imagetiling/imageTiling.qml b/tests/manual/tableview/imagetiling/imageTiling.qml
new file mode 100644
index 0000000000..5c9cdb9888
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/imageTiling.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the manual tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.15
+import Qt.labs.qmlmodels 1.0
+
+TableView {
+ id: root
+ width: 1024
+ height: 200
+ property int tileSize: 1024 / 8
+ rowSpacing: 1; columnSpacing: 1
+ model: TableModel {
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ TableModelColumn {}
+ columns: [0, 1, 2, 3, 4, 5, 6, 7]
+ rows: [0, 1, 2, 3]
+ }
+ delegate: Image {
+ id: image
+// source: "map.png" // unscaled because png doesn't support QImageIOHandler::ScaledClipRect
+// source: "map.svgz" // tiles offset incorrectly: see QTBUG-81044
+ source: "map.pdf" // ok if the qtpdf plugin is installed
+ fillMode: Image.Pad
+ sourceSize.width: 1024
+ sourceClipRect: Qt.rect(model.column * tileSize, model.row * tileSize, tileSize, tileSize)
+ cache: true
+ asynchronous: true
+ Text {
+ text: image.sourceClipRect.width + "x" + image.sourceClipRect.height +
+ " " + image.sourceClipRect.x + "," + image.sourceClipRect.y +
+ "\nfrom " + image.sourceSize.toString() + // inconsistency: if we don't set sourceSize, it ends up being sourceClipRect.size
+ "\nimplicit " + image.implicitWidth + "x" + image.implicitHeight
+ }
+ }
+ columnWidthProvider: function (c) { return tileSize } // workaround for QTBUG-81045
+ rowHeightProvider: function (r) { return tileSize }
+}
diff --git a/tests/manual/tableview/imagetiling/map.pdf b/tests/manual/tableview/imagetiling/map.pdf
new file mode 100644
index 0000000000..31e7b5225e
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/map.pdf
Binary files differ
diff --git a/tests/manual/tableview/imagetiling/map.png b/tests/manual/tableview/imagetiling/map.png
new file mode 100644
index 0000000000..23a8342818
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/map.png
Binary files differ
diff --git a/tests/manual/tableview/imagetiling/map.svgz b/tests/manual/tableview/imagetiling/map.svgz
new file mode 100644
index 0000000000..64d509c106
--- /dev/null
+++ b/tests/manual/tableview/imagetiling/map.svgz
Binary files differ