22
22
#include "rendertask.h"
24
25
#include <QThreadPool>
32
using namespace qpdfview;
41
void setCancellation(QAtomicInt& wasCanceled, bool force)
43
#if QT_VERSION > QT_VERSION_CHECK(5,0,0)
45
wasCanceled.storeRelease(force ? CanceledForcibly : CanceledNormally);
49
wasCanceled.fetchAndStoreRelease(force ? CanceledForcibly : CanceledNormally);
54
void resetCancellation(QAtomicInt& wasCanceled)
56
#if QT_VERSION > QT_VERSION_CHECK(5,0,0)
58
wasCanceled.storeRelease(NotCanceled);
62
wasCanceled.fetchAndStoreRelease(NotCanceled);
67
bool testCancellation(QAtomicInt& wasCanceled, bool prefetch)
69
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
72
wasCanceled.load() == CanceledForcibly :
73
wasCanceled.load() != NotCanceled;
78
wasCanceled.testAndSetRelaxed(CanceledForcibly, CanceledForcibly) :
79
!wasCanceled.testAndSetRelaxed(NotCanceled, NotCanceled);
84
int loadWasCanceled(const QAtomicInt& wasCanceled)
86
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
88
return wasCanceled.load();
97
qreal scaledResolutionX(const RenderParam& renderParam)
99
return renderParam.resolution.devicePixelRatio *
100
renderParam.resolution.resolutionX * renderParam.scaleFactor;
103
qreal scaledResolutionY(const RenderParam& renderParam)
105
return renderParam.resolution.devicePixelRatio *
106
renderParam.resolution.resolutionY * renderParam.scaleFactor;
109
bool columnHasPaperColor(int x, QRgb paperColor, const QImage& image)
111
const int height = image.height();
113
for(int y = 0; y < height; ++y)
115
if(paperColor != (image.pixel(x, y) | 0xff000000u))
124
bool rowHasPaperColor(int y, QRgb paperColor, const QImage& image)
126
const int width = image.width();
128
for(int x = 0; x < width; ++x)
130
if(paperColor != (image.pixel(x, y) | 0xff000000u))
139
QRectF trimMargins(QRgb paperColor, const QImage& image)
143
return QRectF(0.0, 0.0, 1.0, 1.0);
146
const int width = image.width();
147
const int height = image.height();
150
for(left = 0; left < width; ++left)
152
if(!columnHasPaperColor(left, paperColor, image))
157
left = qMin(left, width / 3);
160
for(right = width - 1; right >= left; --right)
162
if(!columnHasPaperColor(right, paperColor, image))
167
right = qMax(right, 2 * width / 3);
170
for(top = 0; top < height; ++top)
172
if(!rowHasPaperColor(top, paperColor, image))
177
top = qMin(top, height / 3);
180
for(bottom = height - 1; bottom >= top; --bottom)
182
if(!rowHasPaperColor(bottom, paperColor, image))
187
bottom = qMax(bottom, 2 * height / 3);
189
left = qMax(left - width / 100, 0);
190
top = qMax(top - height / 100, 0);
192
right = qMin(right + width / 100, width);
193
bottom = qMin(bottom + height / 100, height);
195
return QRectF(static_cast< qreal >(left) / width,
196
static_cast< qreal >(top) / height,
197
static_cast< qreal >(right - left) / width,
198
static_cast< qreal >(bottom - top) / height);
28
203
namespace qpdfview
31
RenderTask::RenderTask(QObject* parent) : QObject(parent), QRunnable(),
206
RenderTask::RenderTask(Model::Page* page, QObject* parent) : QObject(parent), QRunnable(),
32
207
m_isRunning(false),
37
m_devicePixelRatio(1.0),
39
m_rotation(RotateBy0),
40
m_invertColors(false),
208
m_wasCanceled(NotCanceled),
213
m_trimMargins(false),
43
216
setAutoDelete(false);
63
236
bool RenderTask::wasCanceled() const
238
return loadWasCanceled(m_wasCanceled) != NotCanceled;
241
bool RenderTask::wasCanceledNormally() const
243
return loadWasCanceled(m_wasCanceled) == CanceledNormally;
246
bool RenderTask::wasCanceledForcibly() const
248
return loadWasCanceled(m_wasCanceled) == CanceledForcibly;
68
251
void RenderTask::run()
70
if(m_wasCanceled && !m_prefetch)
85
resolutionX = m_resolutionX * m_scaleFactor;
86
resolutionY = m_resolutionY * m_scaleFactor;
90
resolutionX = m_resolutionY * m_scaleFactor;
91
resolutionY = m_resolutionX * m_scaleFactor;
253
#define CANCELLATION_POINT if(testCancellation(m_wasCanceled, m_prefetch)) { finish(); return; }
260
image = m_page->render(scaledResolutionX(m_renderParam), scaledResolutionY(m_renderParam),
261
m_renderParam.rotation, m_rect);
95
263
#if QT_VERSION >= QT_VERSION_CHECK(5,1,0)
97
QImage image = m_page->render(m_devicePixelRatio * resolutionX, m_devicePixelRatio * resolutionY, m_rotation);
99
image.setDevicePixelRatio(m_devicePixelRatio);
103
QImage image = m_page->render(resolutionX, resolutionY, m_rotation);
265
image.setDevicePixelRatio(m_renderParam.resolution.devicePixelRatio);
105
267
#endif // QT_VERSION
107
if(m_wasCanceled && !m_prefetch)
269
if(m_renderParam.invertColors)
116
273
image.invertPixels();
119
emit imageReady(m_resolutionX, m_resolutionY, m_devicePixelRatio, m_scaleFactor, m_rotation, m_invertColors, m_prefetch, image);
280
cropRect = trimMargins(m_paperColor.rgb(), image);
285
emit imageReady(m_renderParam,
291
#undef CANCELLATION_POINT
124
void RenderTask::start(Model::Page* page, int resolutionX, int resolutionY, qreal devicePixelRatio, qreal scaleFactor, Rotation rotation, bool invertColors, bool prefetch)
294
void RenderTask::start(const RenderParam& renderParam,
295
const QRect& rect, bool prefetch,
296
bool trimMargins, const QColor& paperColor)
128
m_resolutionX = resolutionX;
129
m_resolutionY = resolutionY;
130
m_devicePixelRatio = devicePixelRatio;
132
m_scaleFactor = scaleFactor;
133
m_rotation = rotation;
135
m_invertColors = invertColors;
298
m_renderParam = renderParam;
137
301
m_prefetch = prefetch;
303
m_trimMargins = trimMargins;
304
m_paperColor = paperColor;
140
307
m_isRunning = true;
141
308
m_mutex.unlock();
143
m_wasCanceled = false;
310
resetCancellation(m_wasCanceled);
145
QThreadPool::globalInstance()->start(this);
312
QThreadPool::globalInstance()->start(this, prefetch ? 0 : 1);
148
void RenderTask::cancel()
315
void RenderTask::cancel(bool force)
150
m_wasCanceled = true;
317
setCancellation(m_wasCanceled, force);
153
320
void RenderTask::finish()