File indexing completed on 2024-05-19 04:35:22
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; */