diff options
Diffstat (limited to 'src/quick/items/qquickimagebase.cpp')
-rw-r--r-- | src/quick/items/qquickimagebase.cpp | 159 |
1 files changed, 75 insertions, 84 deletions
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 750b71b25e..bcc685d64c 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQuick module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qquickimagebase_p.h" #include "qquickimagebase_p_p.h" @@ -51,24 +15,16 @@ QT_BEGIN_NAMESPACE +using namespace Qt::Literals::StringLiterals; + // This function gives derived classes the chance set the devicePixelRatio // if they're not happy with our implementation of it. bool QQuickImageBasePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio) { // QQuickImageProvider and SVG and PDF can generate a high resolution image when - // sourceSize is set (this function is only called if it's set). - // If sourceSize is not set then the provider default size will be used, as usual. - bool setDevicePixelRatio = false; - if (url.scheme() == QLatin1String("image")) { - setDevicePixelRatio = true; - } else { - QString stringUrl = url.path(QUrl::PrettyDecoded); - if (stringUrl.endsWith(QLatin1String("svg")) || - stringUrl.endsWith(QLatin1String("svgz")) || - stringUrl.endsWith(QLatin1String("pdf"))) { - setDevicePixelRatio = true; - } - } + // sourceSize is set. If sourceSize is not set then the provider default size will + // be used, as usual. + const bool setDevicePixelRatio = QQuickPixmap::isScalableImageFormat(url); if (setDevicePixelRatio) devicePixelRatio = targetDevicePixelRatio; @@ -76,6 +32,28 @@ bool QQuickImageBasePrivate::updateDevicePixelRatio(qreal targetDevicePixelRatio return setDevicePixelRatio; } +void QQuickImageBasePrivate::setStatus(QQuickImageBase::Status value) +{ + Q_Q(QQuickImageBase); + + if (status == value) + return; + + status = value; + emit q->statusChanged(status); +} + +void QQuickImageBasePrivate::setProgress(qreal value) +{ + Q_Q(QQuickImageBase); + + if (qFuzzyCompare(progress, value)) + return; + + progress = value; + emit q->progressChanged(progress); +} + QQuickImageBase::QQuickImageBase(QQuickItem *parent) : QQuickImplicitSizeItem(*(new QQuickImageBasePrivate), parent) { @@ -98,14 +76,12 @@ QQuickImageBase::Status QQuickImageBase::status() const return d->status; } - qreal QQuickImageBase::progress() const { Q_D(const QQuickImageBase); return d->progress; } - bool QQuickImageBase::asynchronous() const { Q_D(const QQuickImageBase); @@ -180,6 +156,7 @@ void QQuickImageBase::setSourceClipRect(const QRectF &r) return; d->sourceClipRect = r; + d->providerOptions.setSourceClipRect(r); emit sourceClipRectChanged(); if (isComponentComplete()) load(); @@ -217,10 +194,10 @@ QImage QQuickImageBase::image() const void QQuickImageBase::setMirror(bool mirror) { Q_D(QQuickImageBase); - if (mirror == d->mirror) + if (mirror == d->mirrorHorizontally) return; - d->mirror = mirror; + d->mirrorHorizontally = mirror; if (isComponentComplete()) update(); @@ -231,7 +208,27 @@ void QQuickImageBase::setMirror(bool mirror) bool QQuickImageBase::mirror() const { Q_D(const QQuickImageBase); - return d->mirror; + return d->mirrorHorizontally; +} + +void QQuickImageBase::setMirrorVertically(bool mirror) +{ + Q_D(QQuickImageBase); + if (mirror == d->mirrorVertically) + return; + + d->mirrorVertically = mirror; + + if (isComponentComplete()) + update(); + + emit mirrorVerticallyChanged(); +} + +bool QQuickImageBase::mirrorVertically() const +{ + Q_D(const QQuickImageBase); + return d->mirrorVertically; } void QQuickImageBase::setCurrentFrame(int frame) @@ -268,11 +265,8 @@ void QQuickImageBase::loadEmptyUrl() { Q_D(QQuickImageBase); d->pix.clear(this); - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } - d->status = Null; + d->setProgress(0); + d->status = Null; // do not emit statusChanged until after setImplicitSize setImplicitSize(0, 0); // also called in QQuickImageBase::pixmapChange, but not QQuickImage/QQuickBorderImage overrides pixmapChange(); // This calls update() in QQuickBorderImage and QQuickImage, not in QQuickImageBase... @@ -306,8 +300,10 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio()); d->devicePixelRatio = 1.0; bool updatedDevicePixelRatio = false; - if (d->sourcesize.isValid()) + if (d->sourcesize.isValid() + || (QQuickPixmap::isScalableImageFormat(d->url) && d->url.scheme() != "image"_L1)) { updatedDevicePixelRatio = d->updateDevicePixelRatio(targetDevicePixelRatio); + } if (!updatedDevicePixelRatio) { // (possible) local file: loadUrl and d->devicePixelRatio will be modified if @@ -317,23 +313,20 @@ void QQuickImageBase::loadPixmap(const QUrl &url, LoadPixmapOptions loadOptions) } } + d->status = Null; // reset status, no emit + d->pix.load(qmlEngine(this), loadUrl, d->sourceClipRect.toRect(), (loadOptions & HandleDPR) ? d->sourcesize * d->devicePixelRatio : QSize(), options, (loadOptions & UseProviderOptions) ? d->providerOptions : QQuickImageProviderOptions(), - d->currentFrame, d->frameCount); + d->currentFrame, d->frameCount, + d->devicePixelRatio); if (d->pix.isLoading()) { - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } - if (d->status != Loading) { - d->status = Loading; - emit statusChanged(d->status); - } + d->setProgress(0); + d->setStatus(Loading); static int thisRequestProgress = -1; static int thisRequestFinished = -1; @@ -372,19 +365,15 @@ void QQuickImageBase::requestFinished() qmlWarning(this) << d->pix.error(); d->pix.clear(this); d->status = Error; - if (d->progress != 0.0) { - d->progress = 0.0; - emit progressChanged(d->progress); - } + d->setProgress(0); } else { - d->status = Ready; - if (d->progress != 1.0) { - d->progress = 1.0; - emit progressChanged(d->progress); - } + d->status = Ready; // do not emit statusChanged until after setImplicitSize + d->setProgress(1); } + pixmapChange(); emit statusChanged(d->status); + if (sourceSize() != d->oldSourceSize) { d->oldSourceSize = sourceSize(); emit sourceSizeChanged(); @@ -408,10 +397,8 @@ void QQuickImageBase::requestFinished() void QQuickImageBase::requestProgress(qint64 received, qint64 total) { Q_D(QQuickImageBase); - if (d->status == Loading && total > 0) { - d->progress = qreal(received)/total; - emit progressChanged(d->progress); - } + if (d->status == Loading && total > 0) + d->setProgress(qreal(received) / total); } void QQuickImageBase::itemChange(ItemChange change, const ItemChangeData &value) @@ -419,10 +406,14 @@ void QQuickImageBase::itemChange(ItemChange change, const ItemChangeData &value) Q_D(QQuickImageBase); // If the screen DPI changed, reload image. if (change == ItemDevicePixelRatioHasChanged && value.realValue != d->devicePixelRatio) { + const auto oldDpr = d->devicePixelRatio; // ### how can we get here with !qmlEngine(this)? that implies // itemChange() on an item pending deletion, which seems strange. if (qmlEngine(this) && isComponentComplete() && d->url.isValid()) { load(); + // not changed when loading (sourceSize might not be set) + if (d->devicePixelRatio == oldDpr) + d->updateDevicePixelRatio(value.realValue); } } QQuickItem::itemChange(change, value); |