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

0001 /*
0002     SPDX-FileCopyrightText: 2007 Albert Astals Cid <aacid@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "rendererthread.h"
0008 
0009 #include <QImage>
0010 
0011 #include "spectre_debug.h"
0012 
0013 #include "core/generator.h"
0014 #include "core/page.h"
0015 #include "core/utils.h"
0016 
0017 GSRendererThread *GSRendererThread::theRenderer = nullptr;
0018 
0019 GSRendererThread *GSRendererThread::getCreateRenderer()
0020 {
0021     if (!theRenderer) {
0022         theRenderer = new GSRendererThread();
0023     }
0024     return theRenderer;
0025 }
0026 
0027 GSRendererThread::GSRendererThread()
0028 {
0029     m_renderContext = spectre_render_context_new();
0030 }
0031 
0032 GSRendererThread::~GSRendererThread()
0033 {
0034     spectre_render_context_free(m_renderContext);
0035 }
0036 
0037 void GSRendererThread::addRequest(const GSRendererThreadRequest &req)
0038 {
0039     m_queueMutex.lock();
0040     m_queue.enqueue(req);
0041     m_queueMutex.unlock();
0042     m_semaphore.release();
0043 }
0044 
0045 void GSRendererThread::run()
0046 {
0047     while (true) {
0048         m_semaphore.acquire();
0049         {
0050             m_queueMutex.lock();
0051             GSRendererThreadRequest req = m_queue.dequeue();
0052             m_queueMutex.unlock();
0053 
0054             spectre_render_context_set_scale(m_renderContext, req.magnify, req.magnify);
0055             spectre_render_context_set_use_platform_fonts(m_renderContext, req.platformFonts);
0056             spectre_render_context_set_antialias_bits(m_renderContext, req.graphicsAAbits, req.textAAbits);
0057             // Do not use spectre_render_context_set_rotation makes some files not render correctly, e.g. bug210499.ps
0058             // so we basically do the rendering without any rotation and then rotate to the orientation as needed
0059             // spectre_render_context_set_rotation(m_renderContext, req.orientation);
0060 
0061             unsigned char *data = nullptr;
0062             int row_length = 0;
0063             int wantedWidth = req.request->width();
0064             int wantedHeight = req.request->height();
0065 
0066             if (req.orientation % 2) {
0067                 std::swap(wantedWidth, wantedHeight);
0068             }
0069 
0070             spectre_page_render(req.spectrePage, m_renderContext, &data, &row_length);
0071 
0072             // Qt needs the missing alpha of QImage::Format_RGB32 to be 0xff
0073             if (data && data[3] != 0xff) {
0074                 for (int i = 3; i < row_length * wantedHeight; i += 4) {
0075                     data[i] = 0xff;
0076                 }
0077             }
0078 
0079             QImage img;
0080             if (row_length == wantedWidth * 4) {
0081                 img = QImage(data, wantedWidth, wantedHeight, QImage::Format_RGB32);
0082             } else {
0083                 // In case this ends up beign very slow we can try with some memmove
0084                 QImage aux(data, row_length / 4, wantedHeight, QImage::Format_RGB32);
0085                 img = QImage(aux.copy(0, 0, wantedWidth, wantedHeight));
0086             }
0087 
0088             switch (req.orientation) {
0089             case Okular::Rotation90: {
0090                 QTransform m;
0091                 m.rotate(90);
0092                 img = img.transformed(m);
0093                 break;
0094             }
0095 
0096             case Okular::Rotation180: {
0097                 QTransform m;
0098                 m.rotate(180);
0099                 img = img.transformed(m);
0100                 break;
0101             }
0102             case Okular::Rotation270: {
0103                 QTransform m;
0104                 m.rotate(270);
0105                 img = img.transformed(m);
0106             }
0107             }
0108 
0109             QImage *image = new QImage(img.copy());
0110             free(data);
0111 
0112             if (image->width() != req.request->width() || image->height() != req.request->height()) {
0113                 qCWarning(OkularSpectreDebug).nospace() << "Generated image does not match wanted size: "
0114                                                         << "[" << image->width() << "x" << image->height() << "] vs requested "
0115                                                         << "[" << req.request->width() << "x" << req.request->height() << "]";
0116                 QImage aux = image->scaled(wantedWidth, wantedHeight);
0117                 delete image;
0118                 image = new QImage(aux);
0119             }
0120             Q_EMIT imageDone(image, req.request);
0121 
0122             spectre_page_free(req.spectrePage);
0123         }
0124     }
0125 }
0126 
0127 /* kate: replace-tabs on; indent-width 4; */