File indexing completed on 2024-05-12 04:01:31

0001 /*
0002     SPDX-FileCopyrightText: 2010-2016 Sune Vuorela <sune@vuorela.dk>
0003     SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #include <config-prison.h>
0008 
0009 #include "barcode.h"
0010 
0011 #include "abstractbarcode_p.h"
0012 #include "aztecbarcode_p.h"
0013 #include "code128barcode_p.h"
0014 #include "code39barcode_p.h"
0015 #include "code93barcode_p.h"
0016 #include "datamatrixbarcode_p.h"
0017 #include "pdf417barcode_p.h"
0018 #include "qrcodebarcode_p.h"
0019 #if HAVE_ZXING
0020 #include "zxingonedbarcode_p.h"
0021 #endif
0022 
0023 #include <QColor>
0024 #include <QPainter>
0025 #include <QVariant>
0026 
0027 using namespace Prison;
0028 
0029 std::optional<Barcode> Barcode::create(Prison::BarcodeType format)
0030 {
0031     std::unique_ptr<AbstractBarcodePrivate> d;
0032     switch (format) {
0033     case Prison::QRCode:
0034         d = std::make_unique<QRCodeBarcode>();
0035         break;
0036     case Prison::DataMatrix:
0037 #if HAVE_DMTX
0038         d = std::make_unique<DataMatrixBarcode>();
0039 #endif
0040         break;
0041     case Prison::Aztec:
0042         d = std::make_unique<AztecBarcode>();
0043         break;
0044     case Prison::Code39:
0045         d = std::make_unique<Code39Barcode>();
0046         break;
0047     case Prison::Code93:
0048         d = std::make_unique<Code93Barcode>();
0049         break;
0050     case Prison::Code128:
0051         d = std::make_unique<Code128Barcode>();
0052         break;
0053     case Prison::PDF417:
0054 #if HAVE_ZXING
0055         d = std::make_unique<Pdf417Barcode>();
0056 #endif
0057         break;
0058     case Prison::EAN13:
0059 #if HAVE_ZXING
0060         d = std::make_unique<ZXingOneDBarcode<ZXing::BarcodeFormat::EAN13>>();
0061 #endif
0062         break;
0063     }
0064 
0065     if (d) {
0066         d->m_format = format;
0067         return Barcode(std::move(d));
0068     }
0069     return std::nullopt;
0070 }
0071 
0072 Barcode::Barcode(std::unique_ptr<AbstractBarcodePrivate> &&dd)
0073     : d(std::move(dd))
0074 {
0075 }
0076 
0077 Barcode::Barcode(Barcode &&) = default;
0078 Barcode::~Barcode() = default;
0079 Barcode &Barcode::operator=(Barcode &&) = default;
0080 
0081 Prison::BarcodeType Barcode::format() const
0082 {
0083     return d->m_format;
0084 }
0085 
0086 QString Barcode::data() const
0087 {
0088     return d->m_data.userType() == QMetaType::QString ? d->m_data.toString() : QString();
0089 }
0090 
0091 QByteArray Barcode::byteArrayData() const
0092 {
0093     return d->m_data.userType() == QMetaType::QByteArray ? d->m_data.toByteArray() : QByteArray();
0094 }
0095 
0096 QImage Barcode::toImage(const QSizeF &size)
0097 {
0098     d->recompute();
0099     if (d->m_cache.isNull() || d->sizeTooSmall(size)) {
0100         return QImage();
0101     }
0102 
0103     // scale to the requested size, using only full integer factors to keep the code readable
0104     int scaleX = std::max<int>(1, size.width() / d->m_cache.width());
0105     int scaleY = std::max<int>(1, size.height() / d->m_cache.height());
0106     if (dimensions() == TwoDimensions) {
0107         scaleX = scaleY = std::min(scaleX, scaleY);
0108     }
0109 
0110     QImage out(d->m_cache.width() * scaleX, d->m_cache.height() * scaleY, d->m_cache.format());
0111     QPainter p(&out);
0112     p.setRenderHint(QPainter::SmoothPixmapTransform, false);
0113     p.drawImage(out.rect(), d->m_cache, d->m_cache.rect());
0114     return out;
0115 }
0116 
0117 void Barcode::setData(const QString &data)
0118 {
0119     if (d) {
0120         d->m_data = data;
0121         d->m_cache = QImage();
0122     }
0123 }
0124 
0125 void Barcode::setData(const QByteArray &data)
0126 {
0127     d->m_data = data;
0128     d->m_cache = QImage();
0129 }
0130 
0131 QSizeF Barcode::minimumSize() const
0132 {
0133     d->recompute();
0134     return d->m_cache.size();
0135 }
0136 
0137 QSizeF Barcode::preferredSize(qreal devicePixelRatio) const
0138 {
0139     d->recompute();
0140     return d->preferredSize(devicePixelRatio);
0141 }
0142 
0143 QColor Barcode::backgroundColor() const
0144 {
0145     return d->m_background;
0146 }
0147 
0148 QColor Barcode::foregroundColor() const
0149 {
0150     return d->m_foreground;
0151 }
0152 
0153 void Barcode::setBackgroundColor(const QColor &backgroundcolor)
0154 {
0155     if (backgroundcolor != backgroundColor()) {
0156         d->m_background = backgroundcolor;
0157         d->m_cache = QImage();
0158     }
0159 }
0160 
0161 void Barcode::setForegroundColor(const QColor &foregroundcolor)
0162 {
0163     if (foregroundcolor != foregroundColor()) {
0164         d->m_foreground = foregroundcolor;
0165         d->m_cache = QImage();
0166     }
0167 }
0168 
0169 Barcode::Dimensions Barcode::dimensions() const
0170 {
0171     return d->m_dimension;
0172 }