File indexing completed on 2024-05-12 16:06:43

0001 /*
0002     SPDX-FileCopyrightText: 2005 Albert Astals Cid <aacid@kde.org>
0003     SPDX-FileCopyrightText: 2006-2007 Pino Toscano <pino@kde.org>
0004     SPDX-FileCopyrightText: 2006-2007 Tobias Koenig <tokoe@kde.org>
0005 
0006     Work sponsored by the LiMux project of the city of Munich:
0007     SPDX-FileCopyrightText: 2017 Klarälvdalens Datakonsult AB a KDAB Group company <info@kdab.com>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #include "generator_kimgio.h"
0013 
0014 #include <QBuffer>
0015 #include <QFile>
0016 #include <QImageReader>
0017 #include <QMimeDatabase>
0018 #include <QMimeType>
0019 #include <QPainter>
0020 #include <QPrinter>
0021 
0022 #include <KAboutData>
0023 #include <KActionCollection>
0024 #include <KLocalizedString>
0025 #include <QAction>
0026 #include <QIcon>
0027 
0028 #ifdef WITH_KEXIV
0029 #include <kexiv2/kexiv2.h>
0030 #endif
0031 
0032 #include <core/page.h>
0033 
0034 OKULAR_EXPORT_PLUGIN(KIMGIOGenerator, "libokularGenerator_kimgio.json")
0035 
0036 KIMGIOGenerator::KIMGIOGenerator(QObject *parent, const QVariantList &args)
0037     : Generator(parent, args)
0038 {
0039     setFeature(ReadRawData);
0040     setFeature(Threaded);
0041     setFeature(TiledRendering);
0042     setFeature(PrintNative);
0043     setFeature(PrintToFile);
0044     setFeature(SwapBackingFile);
0045 }
0046 
0047 KIMGIOGenerator::~KIMGIOGenerator()
0048 {
0049 }
0050 
0051 bool KIMGIOGenerator::loadDocument(const QString &fileName, QVector<Okular::Page *> &pagesVector)
0052 {
0053     QFile f(fileName);
0054     if (!f.open(QFile::ReadOnly)) {
0055         Q_EMIT error(i18n("Unable to load document: %1", f.errorString()), -1);
0056         return false;
0057     }
0058     return loadDocumentInternal(f.readAll(), fileName, pagesVector);
0059 }
0060 
0061 bool KIMGIOGenerator::loadDocumentFromData(const QByteArray &fileData, QVector<Okular::Page *> &pagesVector)
0062 {
0063     return loadDocumentInternal(fileData, QString(), pagesVector);
0064 }
0065 
0066 bool KIMGIOGenerator::loadDocumentInternal(const QByteArray &fileData, const QString &fileName, QVector<Okular::Page *> &pagesVector)
0067 {
0068     QBuffer buffer;
0069     buffer.setData(fileData);
0070     buffer.open(QIODevice::ReadOnly);
0071 
0072     QImageReader reader(&buffer, QImageReader::imageFormat(&buffer));
0073     reader.setAutoDetectImageFormat(true);
0074     if (!reader.read(&m_img)) {
0075         if (!m_img.isNull()) {
0076             Q_EMIT warning(i18n("This document appears malformed. Here is a best approximation of the document's intended appearance."), -1);
0077         } else {
0078             Q_EMIT error(i18n("Unable to load document: %1", reader.errorString()), -1);
0079             return false;
0080         }
0081     }
0082     QMimeDatabase db;
0083     auto mime = db.mimeTypeForFileNameAndData(fileName, fileData);
0084     docInfo.set(Okular::DocumentInfo::MimeType, mime.name());
0085 
0086 #ifdef WITH_KEXIV
0087     // Apply transformations dictated by Exif metadata
0088     KExiv2Iface::KExiv2 exifMetadata;
0089     if (exifMetadata.loadFromData(fileData)) {
0090         exifMetadata.rotateExifQImage(m_img, exifMetadata.getImageOrientation());
0091     }
0092 #endif
0093 
0094     pagesVector.resize(1);
0095 
0096     Okular::Page *page = new Okular::Page(0, m_img.width(), m_img.height(), Okular::Rotation0);
0097     pagesVector[0] = page;
0098 
0099     return true;
0100 }
0101 
0102 KIMGIOGenerator::SwapBackingFileResult KIMGIOGenerator::swapBackingFile(QString const & /*newFileName*/, QVector<Okular::Page *> & /*newPagesVector*/)
0103 {
0104     // NOP: We don't actually need to do anything because all data has already
0105     // been loaded in RAM
0106     return SwapBackingFileNoOp;
0107 }
0108 
0109 bool KIMGIOGenerator::doCloseDocument()
0110 {
0111     m_img = QImage();
0112 
0113     return true;
0114 }
0115 
0116 QImage KIMGIOGenerator::image(Okular::PixmapRequest *request)
0117 {
0118     // perform a smooth scaled generation
0119     if (request->isTile()) {
0120         const QRect srcRect = request->normalizedRect().geometry(m_img.width(), m_img.height());
0121         const QRect destRect = request->normalizedRect().geometry(request->width(), request->height());
0122 
0123         QImage destImg(destRect.size(), QImage::Format_RGB32);
0124         destImg.fill(Qt::white);
0125 
0126         QPainter p(&destImg);
0127         p.setRenderHint(QPainter::SmoothPixmapTransform);
0128         p.drawImage(destImg.rect(), m_img, srcRect);
0129 
0130         return destImg;
0131     } else {
0132         int width = request->width();
0133         int height = request->height();
0134         if (request->page()->rotation() % 2 == 1) {
0135             qSwap(width, height);
0136         }
0137 
0138         return m_img.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
0139     }
0140 }
0141 
0142 Okular::Document::PrintError KIMGIOGenerator::print(QPrinter &printer)
0143 {
0144     QPainter p(&printer);
0145 
0146     QImage image(m_img);
0147 
0148     if ((image.width() > printer.width()) || (image.height() > printer.height())) {
0149         image = image.scaled(printer.width(), printer.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
0150     }
0151 
0152     p.drawImage(0, 0, image);
0153 
0154     return Okular::Document::NoPrintError;
0155 }
0156 
0157 Okular::DocumentInfo KIMGIOGenerator::generateDocumentInfo(const QSet<Okular::DocumentInfo::Key> &keys) const
0158 {
0159     Q_UNUSED(keys);
0160 
0161     return docInfo;
0162 }
0163 
0164 #include "generator_kimgio.moc"