File indexing completed on 2024-05-12 04:21:08

0001 /*
0002  * SPDX-FileCopyrightText: (C) 2021 Mikel Johnson <mikel5764@gmail.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "vectorimage.h"
0008 #include <QQuickWindow>
0009 
0010 VectorImage::VectorImage(QQuickItem *parent)
0011     : QQuickPaintedItem(parent)
0012     , m_devicePixelRatio(0)
0013     , m_status(Null)
0014 {
0015 }
0016 
0017 void VectorImage::setSourceClipRect(const QRectF &sourceClipRect)
0018 {
0019     if (m_sourceClipRect == sourceClipRect) {
0020         return;
0021     }
0022     m_sourceClipRect = sourceClipRect;
0023     Q_EMIT sourceClipRectChanged();
0024     update();
0025 }
0026 
0027 void VectorImage::setSourceSize(const QSize &sourceSize)
0028 {
0029     if (m_sourceSize == sourceSize) {
0030         return;
0031     }
0032     m_sourceSize = sourceSize;
0033     Q_EMIT sourceSizeChanged();
0034 }
0035 
0036 void VectorImage::setStatus(Status status)
0037 {
0038     if (m_status == status) {
0039         return;
0040     }
0041     m_status = status;
0042     Q_EMIT statusChanged(m_status);
0043 }
0044 
0045 void VectorImage::setSource(const QUrl &source)
0046 {
0047     if (m_source == source) {
0048         return;
0049     }
0050     m_source = source;
0051     Q_EMIT sourceChanged();
0052 
0053     if (m_source.isEmpty()) {
0054         setStatus(Null);
0055         m_viewBoxF = QRectF();
0056         setSourceSize(QSize());
0057         return;
0058     }
0059 
0060     setStatus(Loading);
0061 
0062     m_renderer = std::make_unique<QSvgRenderer>(m_source.toLocalFile());
0063 
0064     if (!m_renderer->isValid()) {
0065         setStatus(Error);
0066         m_viewBoxF = QRectF();
0067         setSourceSize(QSize());
0068         return;
0069     }
0070 
0071     m_renderer->setAspectRatioMode(Qt::KeepAspectRatio);
0072 
0073     setSourceSize(m_renderer->defaultSize());
0074 
0075     m_viewBoxF = m_renderer->viewBoxF();
0076 
0077     if (m_devicePixelRatio == 0) {
0078         m_devicePixelRatio = window()->effectiveDevicePixelRatio();
0079     }
0080     setStatus(Ready);
0081     update();
0082 }
0083 
0084 void VectorImage::itemChange(ItemChange change, const ItemChangeData &value)
0085 {
0086     if (change == ItemDevicePixelRatioHasChanged && m_devicePixelRatio != value.realValue) {
0087         m_devicePixelRatio = value.realValue;
0088         update();
0089     }
0090     QQuickItem::itemChange(change, value);
0091 }
0092 
0093 void VectorImage::paint(QPainter *painter)
0094 {
0095     if (m_status != Ready) {
0096         return;
0097     }
0098 
0099     auto scale_x = sourceSize().width() / width() / m_devicePixelRatio;
0100     auto zoom_x = sourceClipRect().width() / m_viewBoxF.width() * scale_x;
0101 
0102     auto scale_y = sourceSize().height() / height() / m_devicePixelRatio;
0103     auto zoom_y = sourceClipRect().height() / m_viewBoxF.height() * scale_y;
0104 
0105     QRectF clip(sourceClipRect().x() / zoom_x * scale_x + m_viewBoxF.x(),
0106                 sourceClipRect().y() / zoom_y * scale_y + m_viewBoxF.y(),
0107                 sourceSize().width() / zoom_x,
0108                 sourceSize().height() / zoom_y);
0109 
0110     m_renderer->setViewBox(clip);
0111     m_renderer->render(painter);
0112 
0113     return;
0114 }