~ubuntu-branches/ubuntu/vivid/qpdfview/vivid

« back to all changes in this revision

Viewing changes to sources/tileitem.cpp

  • Committer: Package Import Robot
  • Author(s): Benjamin Eltzner
  • Date: 2014-10-22 21:49:15 UTC
  • mfrom: (1.2.15)
  • Revision ID: package-import@ubuntu.com-20141022214915-agqeoe318lzs2s4d
Tags: 0.4.12-1
* New upstream release.
* Fixed option to zoom to selection and implemented tiled rendering
  (Closes: #739554)
* Enable support for qt5 and poppler-qt5.
* Explicit dependence on hicolor-icon-theme.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright 2012-2014 Adam Reichold
 
4
 
 
5
This file is part of qpdfview.
 
6
 
 
7
qpdfview is free software: you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation, either version 2 of the License, or
 
10
(at your option) any later version.
 
11
 
 
12
qpdfview is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with qpdfview.  If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
*/
 
21
 
 
22
#include "tileitem.h"
 
23
 
 
24
#include <QPainter>
 
25
#include <QTimer>
 
26
 
 
27
#include "settings.h"
 
28
#include "rendertask.h"
 
29
#include "pageitem.h"
 
30
 
 
31
namespace qpdfview
 
32
{
 
33
 
 
34
Settings* TileItem::s_settings = 0;
 
35
 
 
36
QCache< TileItem::CacheKey, TileItem::CacheObject > TileItem::s_cache;
 
37
 
 
38
TileItem::TileItem(QObject* parent) : QObject(parent),
 
39
    m_rect(),
 
40
    m_cropRect(),
 
41
    m_pixmapError(false),
 
42
    m_pixmap(),
 
43
    m_obsoletePixmap(),
 
44
    m_renderTask(0)
 
45
{
 
46
    if(s_settings == 0)
 
47
    {
 
48
        s_settings = Settings::instance();
 
49
    }
 
50
 
 
51
    s_cache.setMaxCost(s_settings->pageItem().cacheSize());
 
52
 
 
53
    m_renderTask = new RenderTask(parentPage()->m_page, this);
 
54
 
 
55
    connect(m_renderTask, SIGNAL(finished()), SLOT(on_renderTask_finished()));
 
56
    connect(m_renderTask, SIGNAL(imageReady(RenderParam,QRect,bool,QImage,QRectF)), SLOT(on_renderTask_imageReady(RenderParam,QRect,bool,QImage,QRectF)));
 
57
}
 
58
 
 
59
TileItem::~TileItem()
 
60
{
 
61
    m_renderTask->cancel(true);
 
62
    m_renderTask->wait();
 
63
}
 
64
 
 
65
void TileItem::setCropRect(const QRectF& cropRect)
 
66
{
 
67
    if(!s_settings->pageItem().trimMargins())
 
68
    {
 
69
        return;
 
70
    }
 
71
 
 
72
    if(m_cropRect.isNull() && !cropRect.isNull())
 
73
    {
 
74
        m_cropRect = cropRect;
 
75
 
 
76
        parentPage()->updateCropRect();
 
77
    }
 
78
}
 
79
 
 
80
void TileItem::dropCachedPixmaps(PageItem* page)
 
81
{
 
82
    foreach(CacheKey key, s_cache.keys())
 
83
    {
 
84
        if(key.first == page)
 
85
        {
 
86
            s_cache.remove(key);
 
87
        }
 
88
    }
 
89
}
 
90
 
 
91
void TileItem::paint(QPainter* painter, const QPointF& topLeft)
 
92
{
 
93
    const QPixmap& pixmap = takePixmap();
 
94
 
 
95
    if(!pixmap.isNull())
 
96
    {
 
97
        // pixmap
 
98
 
 
99
        painter->drawPixmap(m_rect.topLeft() + topLeft, pixmap);
 
100
    }
 
101
    else if(!m_obsoletePixmap.isNull())
 
102
    {
 
103
        // obsolete pixmap
 
104
 
 
105
        painter->drawPixmap(QRectF(m_rect).translated(topLeft), m_obsoletePixmap, QRectF());
 
106
    }
 
107
    else
 
108
    {
 
109
        const qreal iconExtent = qMin(0.1 * m_rect.width(), 0.1 * m_rect.height());
 
110
        const QRect iconRect(topLeft.x() + m_rect.left() + 0.01 * m_rect.width(),
 
111
                             topLeft.y() + m_rect.top() + 0.01 * m_rect.height(),
 
112
                             iconExtent, iconExtent);
 
113
 
 
114
        if(!m_pixmapError)
 
115
        {
 
116
            // progress icon
 
117
 
 
118
            s_settings->pageItem().progressIcon().paint(painter, iconRect);
 
119
        }
 
120
        else
 
121
        {
 
122
            // error icon
 
123
 
 
124
            s_settings->pageItem().errorIcon().paint(painter, iconRect);
 
125
        }
 
126
    }
 
127
}
 
128
 
 
129
void TileItem::refresh(bool keepObsoletePixmaps)
 
130
{
 
131
    if(keepObsoletePixmaps && s_settings->pageItem().keepObsoletePixmaps())
 
132
    {
 
133
        CacheObject* object = s_cache.object(cacheKey());
 
134
 
 
135
        if(object != 0)
 
136
        {
 
137
            m_obsoletePixmap = object->first;
 
138
        }
 
139
    }
 
140
    else
 
141
    {
 
142
        m_obsoletePixmap = QPixmap();
 
143
    }
 
144
 
 
145
    if(!keepObsoletePixmaps)
 
146
    {
 
147
        m_cropRect = QRectF();
 
148
    }
 
149
 
 
150
    m_renderTask->cancel(true);
 
151
 
 
152
    m_pixmapError = false;
 
153
    m_pixmap = QPixmap();
 
154
}
 
155
 
 
156
int TileItem::startRender(bool prefetch)
 
157
{
 
158
    if(m_pixmapError || m_renderTask->isRunning() || (prefetch && s_cache.contains(cacheKey())))
 
159
    {
 
160
        return 0;
 
161
    }
 
162
 
 
163
    m_renderTask->start(parentPage()->m_renderParam,
 
164
                        m_rect, prefetch,
 
165
                        s_settings->pageItem().trimMargins(), s_settings->pageItem().paperColor());
 
166
 
 
167
    return 1;
 
168
}
 
169
 
 
170
void TileItem::cancelRender()
 
171
{
 
172
    m_renderTask->cancel();
 
173
 
 
174
    m_pixmap = QPixmap();
 
175
    m_obsoletePixmap = QPixmap();
 
176
}
 
177
 
 
178
void TileItem::deleteAfterRender()
 
179
{
 
180
    cancelRender();
 
181
 
 
182
    if(!m_renderTask->isRunning())
 
183
    {
 
184
        delete this;
 
185
    }
 
186
    else
 
187
    {
 
188
        QTimer::singleShot(0, this, SLOT(deleteAfterRender()));
 
189
    }
 
190
}
 
191
 
 
192
void TileItem::on_renderTask_finished()
 
193
{
 
194
    parentPage()->update();
 
195
}
 
196
 
 
197
void TileItem::on_renderTask_imageReady(const RenderParam& renderParam,
 
198
                                        const QRect& rect, bool prefetch,
 
199
                                        QImage image, QRectF cropRect)
 
200
{
 
201
    if(parentPage()->m_renderParam != renderParam || m_rect != rect)
 
202
    {
 
203
        return;
 
204
    }
 
205
 
 
206
    m_obsoletePixmap = QPixmap();
 
207
 
 
208
    if(image.isNull())
 
209
    {
 
210
        m_pixmapError = true;
 
211
 
 
212
        return;
 
213
    }
 
214
 
 
215
    if(prefetch && !m_renderTask->wasCanceledForcibly())
 
216
    {
 
217
        int cost = image.width() * image.height() * image.depth() / 8;
 
218
        s_cache.insert(cacheKey(), new CacheObject(QPixmap::fromImage(image), cropRect), cost);
 
219
 
 
220
        setCropRect(cropRect);
 
221
    }
 
222
    else if(!m_renderTask->wasCanceled())
 
223
    {
 
224
        m_pixmap = QPixmap::fromImage(image);
 
225
 
 
226
        setCropRect(cropRect);
 
227
    }
 
228
}
 
229
 
 
230
PageItem* TileItem::parentPage() const
 
231
{
 
232
    return qobject_cast< PageItem* >(parent());
 
233
}
 
234
 
 
235
TileItem::CacheKey TileItem::cacheKey() const
 
236
{
 
237
    PageItem* page = parentPage();
 
238
    QByteArray key;
 
239
 
 
240
    QDataStream(&key, QIODevice::WriteOnly)
 
241
            << page->m_renderParam.resolution.resolutionX
 
242
            << page->m_renderParam.resolution.resolutionY
 
243
            << page->m_renderParam.scaleFactor
 
244
            << page->m_renderParam.rotation
 
245
            << page->m_renderParam.invertColors
 
246
            << m_rect;
 
247
 
 
248
    return qMakePair(page, key);
 
249
}
 
250
 
 
251
QPixmap TileItem::takePixmap()
 
252
{
 
253
    CacheObject* object = s_cache.object(cacheKey());
 
254
 
 
255
    if(object != 0)
 
256
    {
 
257
        m_obsoletePixmap = QPixmap();
 
258
 
 
259
        setCropRect(object->second);
 
260
        return object->first;
 
261
    }
 
262
 
 
263
    QPixmap pixmap;
 
264
 
 
265
    if(!m_pixmap.isNull())
 
266
    {
 
267
        int cost = m_pixmap.width() * m_pixmap.height() * m_pixmap.depth() / 8;
 
268
        s_cache.insert(cacheKey(), new CacheObject(m_pixmap, m_cropRect), cost);
 
269
 
 
270
        pixmap = m_pixmap;
 
271
        m_pixmap = QPixmap();
 
272
    }
 
273
    else
 
274
    {
 
275
        startRender();
 
276
    }
 
277
 
 
278
    return pixmap;
 
279
}
 
280
 
 
281
} // qpdfview