Bug Summary

File:libview/ev-pixbuf-cache.c
Warning:line 708, column 6
Access to field 'job' results in a dereference of a null pointer (loaded from variable 'job_info')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ev-pixbuf-cache.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/libview -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D LECTORDATADIR="/usr/share/lector" -D G_LOG_DOMAIN="LectorView" -D CAFELOCALEDIR="/usr/share/locale" -D LECTOR_COMPILATION -I .. -I ../libdocument -I .. -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/cail-3.0 -I /usr/include/ctk-3.0/unix-print -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/libview -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-18-122410-54188-1 -x c ev-pixbuf-cache.c
1#include <config.h>
2#include "ev-pixbuf-cache.h"
3#include "ev-job-scheduler.h"
4#include "ev-view-private.h"
5
6typedef enum {
7 SCROLL_DIRECTION_DOWN,
8 SCROLL_DIRECTION_UP
9} ScrollDirection;
10
11typedef struct _CacheJobInfo
12{
13 EvJob *job;
14 gboolean page_ready;
15
16 /* Region of the page that needs to be drawn */
17 cairo_region_t *region;
18
19 /* Data we get from rendering */
20 cairo_surface_t *surface;
21
22 /* Device scale factor of target widget */
23 int device_scale;
24
25 /* Selection data.
26 * Selection_points are the coordinates encapsulated in selection.
27 * target_points is the target selection size. */
28 EvRectangle target_points;
29 EvSelectionStyle selection_style;
30 gboolean points_set;
31
32 cairo_surface_t *selection;
33 gdouble selection_scale;
34 EvRectangle selection_points;
35
36 cairo_region_t *selection_region;
37 gdouble selection_region_scale;
38 EvRectangle selection_region_points;
39} CacheJobInfo;
40
41struct _EvPixbufCache
42{
43 GObject parent;
44
45 /* We keep a link to our containing view just for style information. */
46 CtkWidget *view;
47 EvDocument *document;
48 EvDocumentModel *model;
49 int start_page;
50 int end_page;
51 ScrollDirection scroll_direction;
52 gboolean inverted_colors;
53
54 gsize max_size;
55
56 /* preload_cache_size is the number of pages prior to the current
57 * visible area that we cache. It's normally 1, but could be 2 in the
58 * case of twin pages.
59 */
60 int preload_cache_size;
61 guint job_list_len;
62
63 CacheJobInfo *prev_job;
64 CacheJobInfo *job_list;
65 CacheJobInfo *next_job;
66};
67
68struct _EvPixbufCacheClass
69{
70 GObjectClass parent_class;
71
72 void (* job_finished) (EvPixbufCache *pixbuf_cache);
73};
74
75
76enum
77{
78 JOB_FINISHED,
79 N_SIGNALS,
80};
81
82static guint signals[N_SIGNALS] = {0, };
83
84static void ev_pixbuf_cache_finalize (GObject *object);
85static void ev_pixbuf_cache_dispose (GObject *object);
86static void job_finished_cb (EvJob *job,
87 EvPixbufCache *pixbuf_cache);
88static CacheJobInfo *find_job_cache (EvPixbufCache *pixbuf_cache,
89 int page);
90static gboolean new_selection_surface_needed(EvPixbufCache *pixbuf_cache,
91 CacheJobInfo *job_info,
92 gint page,
93 gfloat scale);
94
95
96/* These are used for iterating through the prev and next arrays */
97#define FIRST_VISIBLE_PREV(pixbuf_cache)((((0) > (pixbuf_cache->preload_cache_size - pixbuf_cache
->start_page)) ? (0) : (pixbuf_cache->preload_cache_size
- pixbuf_cache->start_page)))
\
98 (MAX (0, pixbuf_cache->preload_cache_size - pixbuf_cache->start_page)(((0) > (pixbuf_cache->preload_cache_size - pixbuf_cache
->start_page)) ? (0) : (pixbuf_cache->preload_cache_size
- pixbuf_cache->start_page))
)
99#define VISIBLE_NEXT_LEN(pixbuf_cache)((((pixbuf_cache->preload_cache_size) < (ev_document_get_n_pages
(pixbuf_cache->document) - (1 + pixbuf_cache->end_page
))) ? (pixbuf_cache->preload_cache_size) : (ev_document_get_n_pages
(pixbuf_cache->document) - (1 + pixbuf_cache->end_page
))))
\
100 (MIN(pixbuf_cache->preload_cache_size, ev_document_get_n_pages (pixbuf_cache->document) - (1 + pixbuf_cache->end_page))(((pixbuf_cache->preload_cache_size) < (ev_document_get_n_pages
(pixbuf_cache->document) - (1 + pixbuf_cache->end_page
))) ? (pixbuf_cache->preload_cache_size) : (ev_document_get_n_pages
(pixbuf_cache->document) - (1 + pixbuf_cache->end_page
)))
)
101#define PAGE_CACHE_LEN(pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
\
102 (pixbuf_cache->start_page>=0?((pixbuf_cache->end_page - pixbuf_cache->start_page) + 1):0)
103
104#define MAX_PRELOADED_PAGES3 3
105
106G_DEFINE_TYPE (EvPixbufCache, ev_pixbuf_cache, G_TYPE_OBJECT)static void ev_pixbuf_cache_init (EvPixbufCache *self); static
void ev_pixbuf_cache_class_init (EvPixbufCacheClass *klass);
static GType ev_pixbuf_cache_get_type_once (void); static gpointer
ev_pixbuf_cache_parent_class = ((void*)0); static gint EvPixbufCache_private_offset
; static void ev_pixbuf_cache_class_intern_init (gpointer klass
) { ev_pixbuf_cache_parent_class = g_type_class_peek_parent (
klass); if (EvPixbufCache_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EvPixbufCache_private_offset); ev_pixbuf_cache_class_init
((EvPixbufCacheClass*) klass); } __attribute__ ((__unused__)
) static inline gpointer ev_pixbuf_cache_get_instance_private
(EvPixbufCache *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EvPixbufCache_private_offset)))); } GType ev_pixbuf_cache_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = ev_pixbuf_cache_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType ev_pixbuf_cache_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("EvPixbufCache"
), sizeof (EvPixbufCacheClass), (GClassInitFunc)(void (*)(void
)) ev_pixbuf_cache_class_intern_init, sizeof (EvPixbufCache),
(GInstanceInitFunc)(void (*)(void)) ev_pixbuf_cache_init, (GTypeFlags
) 0); { {{};} } return g_define_type_id; }
107
108static void
109ev_pixbuf_cache_init (EvPixbufCache *pixbuf_cache)
110{
111 pixbuf_cache->start_page = -1;
112 pixbuf_cache->end_page = -1;
113}
114
115static void
116ev_pixbuf_cache_class_init (EvPixbufCacheClass *class)
117{
118 GObjectClass *object_class;
119
120 object_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
121
122 object_class->finalize = ev_pixbuf_cache_finalize;
123 object_class->dispose = ev_pixbuf_cache_dispose;
124
125 signals[JOB_FINISHED] =
126 g_signal_new ("job-finished",
127 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
128 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
129 G_STRUCT_OFFSET (EvPixbufCacheClass, job_finished)((glong) __builtin_offsetof(EvPixbufCacheClass, job_finished)
)
,
130 NULL((void*)0), NULL((void*)0),
131 g_cclosure_marshal_VOID__POINTER,
132 G_TYPE_NONE((GType) ((1) << (2))), 1,
133 G_TYPE_POINTER((GType) ((17) << (2))));
134}
135
136static void
137ev_pixbuf_cache_finalize (GObject *object)
138{
139 EvPixbufCache *pixbuf_cache;
140
141 pixbuf_cache = EV_PIXBUF_CACHE (object)((((EvPixbufCache*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ev_pixbuf_cache_get_type ()))))))
;
142
143 if (pixbuf_cache->job_list) {
144 g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->job_list_len,
145 pixbuf_cache->job_list);
146 pixbuf_cache->job_list = NULL((void*)0);
147 }
148 if (pixbuf_cache->prev_job) {
149 g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->preload_cache_size,
150 pixbuf_cache->prev_job);
151 pixbuf_cache->prev_job = NULL((void*)0);
152 }
153 if (pixbuf_cache->next_job) {
154 g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->preload_cache_size,
155 pixbuf_cache->next_job);
156 pixbuf_cache->next_job = NULL((void*)0);
157 }
158
159 g_object_unref (pixbuf_cache->model);
160
161 G_OBJECT_CLASS (ev_pixbuf_cache_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ev_pixbuf_cache_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
162}
163
164static void
165end_job (CacheJobInfo *job_info,
166 gpointer data)
167{
168 g_signal_handlers_disconnect_by_func (job_info->job,g_signal_handlers_disconnect_matched ((job_info->job), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (job_finished_cb))), (data))
169 G_CALLBACK (job_finished_cb),g_signal_handlers_disconnect_matched ((job_info->job), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (job_finished_cb))), (data))
170 data)g_signal_handlers_disconnect_matched ((job_info->job), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (job_finished_cb))), (data))
;
171 ev_job_cancel (job_info->job);
172 g_object_unref (job_info->job);
173 job_info->job = NULL((void*)0);
174}
175
176static void
177dispose_cache_job_info (CacheJobInfo *job_info,
178 gpointer data)
179{
180 if (job_info == NULL((void*)0))
181 return;
182
183 if (job_info->job)
184 end_job (job_info, data);
185
186 if (job_info->surface) {
187 cairo_surface_destroy (job_info->surface);
188 job_info->surface = NULL((void*)0);
189 }
190 if (job_info->region) {
191 cairo_region_destroy (job_info->region);
192 job_info->region = NULL((void*)0);
193 }
194 if (job_info->selection) {
195 cairo_surface_destroy (job_info->selection);
196 job_info->selection = NULL((void*)0);
197 }
198 if (job_info->selection_region) {
199 cairo_region_destroy (job_info->selection_region);
200 job_info->selection_region = NULL((void*)0);
201 }
202
203 job_info->points_set = FALSE(0);
204}
205
206static void
207ev_pixbuf_cache_dispose (GObject *object)
208{
209 EvPixbufCache *pixbuf_cache;
210 int i;
211
212 pixbuf_cache = EV_PIXBUF_CACHE (object)((((EvPixbufCache*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ev_pixbuf_cache_get_type ()))))))
;
213
214 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
215 dispose_cache_job_info (pixbuf_cache->prev_job + i, pixbuf_cache);
216 dispose_cache_job_info (pixbuf_cache->next_job + i, pixbuf_cache);
217 }
218
219 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
220 dispose_cache_job_info (pixbuf_cache->job_list + i, pixbuf_cache);
221 }
222
223 G_OBJECT_CLASS (ev_pixbuf_cache_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ev_pixbuf_cache_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
224}
225
226
227EvPixbufCache *
228ev_pixbuf_cache_new (CtkWidget *view,
229 EvDocumentModel *model,
230 gsize max_size)
231{
232 EvPixbufCache *pixbuf_cache;
233
234 pixbuf_cache = (EvPixbufCache *) g_object_new (EV_TYPE_PIXBUF_CACHE(ev_pixbuf_cache_get_type ()), NULL((void*)0));
235 /* This is a backlink, so we don't ref this */
236 pixbuf_cache->view = view;
237 pixbuf_cache->model = g_object_ref (model)((__typeof__ (model)) (g_object_ref) (model));
238 pixbuf_cache->document = ev_document_model_get_document (model);
239 pixbuf_cache->max_size = max_size;
240
241 return pixbuf_cache;
242}
243
244void
245ev_pixbuf_cache_set_max_size (EvPixbufCache *pixbuf_cache,
246 gsize max_size)
247{
248 if (pixbuf_cache->max_size == max_size)
249 return;
250
251 if (pixbuf_cache->max_size > max_size)
252 ev_pixbuf_cache_clear (pixbuf_cache);
253 pixbuf_cache->max_size = max_size;
254}
255
256static int
257get_device_scale (EvPixbufCache *pixbuf_cache)
258{
259 return ctk_widget_get_scale_factor (pixbuf_cache->view);
260}
261
262static void
263set_device_scale_on_surface (cairo_surface_t *surface,
264 int device_scale)
265{
266 cairo_surface_set_device_scale (surface, device_scale, device_scale);
267}
268
269static void
270copy_job_to_job_info (EvJobRender *job_render,
271 CacheJobInfo *job_info,
272 EvPixbufCache *pixbuf_cache)
273{
274 if (job_info->surface) {
275 cairo_surface_destroy (job_info->surface);
276 }
277 job_info->surface = cairo_surface_reference (job_render->surface);
278 set_device_scale_on_surface (job_info->surface, job_info->device_scale);
279 if (pixbuf_cache->inverted_colors) {
280 ev_document_misc_invert_surface (job_info->surface);
281 }
282
283 job_info->points_set = FALSE(0);
284 if (job_render->include_selection) {
285 if (job_info->selection) {
286 cairo_surface_destroy (job_info->selection);
287 job_info->selection = NULL((void*)0);
288 }
289 if (job_info->selection_region) {
290 cairo_region_destroy (job_info->selection_region);
291 job_info->selection_region = NULL((void*)0);
292 }
293
294 job_info->selection_points = job_render->selection_points;
295 job_info->selection = cairo_surface_reference (job_render->selection);
296 if (job_info->selection)
297 set_device_scale_on_surface (job_info->selection, job_info->device_scale);
298 job_info->selection_scale = job_render->scale * job_info->device_scale;
299 g_assert (job_info->selection_points.x1 >= 0)do { if (job_info->selection_points.x1 >= 0) ; else g_assertion_message_expr
("LectorView", "ev-pixbuf-cache.c", 299, ((const char*) (__func__
)), "job_info->selection_points.x1 >= 0"); } while (0)
;
300
301 job_info->selection_region_points = job_render->selection_points;
302 job_info->selection_region = cairo_region_reference (job_render->selection_region);
303 job_info->selection_region_scale = job_render->scale;
304
305 job_info->points_set = TRUE(!(0));
306 }
307
308 if (job_info->job)
309 end_job (job_info, pixbuf_cache);
310
311 job_info->page_ready = TRUE(!(0));
312}
313
314static void
315job_finished_cb (EvJob *job,
316 EvPixbufCache *pixbuf_cache)
317{
318 CacheJobInfo *job_info;
319 EvJobRender *job_render = EV_JOB_RENDER (job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job)), ((ev_job_render_get_type()))))))
;
320
321 /* If the job is outside of our interest, we silently discard it */
322 if ((job_render->page < (pixbuf_cache->start_page - pixbuf_cache->preload_cache_size)) ||
323 (job_render->page > (pixbuf_cache->end_page + pixbuf_cache->preload_cache_size))) {
324 g_object_unref (job);
325 return;
326 }
327
328 job_info = find_job_cache (pixbuf_cache, job_render->page);
329
330 copy_job_to_job_info (job_render, job_info, pixbuf_cache);
331 g_signal_emit (pixbuf_cache, signals[JOB_FINISHED], 0, job_info->region);
332}
333
334/* This checks a job to see if the job would generate the right sized pixbuf
335 * given a scale. If it won't, it removes the job and clears it to NULL.
336 */
337static void
338check_job_size_and_unref (EvPixbufCache *pixbuf_cache,
339 CacheJobInfo *job_info,
340 gfloat scale)
341{
342 gint width, height;
343 gint device_scale;
344
345 g_assert (job_info)do { if (job_info) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 345, ((const char*) (__func__)), "job_info"
); } while (0)
;
346
347 if (job_info->job == NULL((void*)0))
348 return;
349
350 device_scale = get_device_scale (pixbuf_cache);
351 if (job_info->device_scale == device_scale) {
352 _get_page_size_for_scale_and_rotation (job_info->job->document,
353 EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->page,
354 scale,
355 EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->rotation,
356 &width, &height);
357 if (width * device_scale == EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->target_width &&
358 height * device_scale == EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->target_height)
359 return;
360 }
361
362 end_job (job_info, pixbuf_cache);
363}
364
365/* Do all function that copies a job from an older cache to it's position in the
366 * new cache. It clears the old job if it doesn't have a place.
367 */
368static void
369move_one_job (CacheJobInfo *job_info,
370 EvPixbufCache *pixbuf_cache,
371 int page,
372 CacheJobInfo *new_job_list,
373 CacheJobInfo *new_prev_job,
374 CacheJobInfo *new_next_job,
375 int new_preload_cache_size,
376 int start_page,
377 int end_page,
378 gint priority)
379{
380 CacheJobInfo *target_page = NULL((void*)0);
381 int page_offset;
382 gint new_priority;
383
384 if (page < (start_page - new_preload_cache_size) ||
385 page > (end_page + new_preload_cache_size)) {
386 dispose_cache_job_info (job_info, pixbuf_cache);
387 return;
388 }
389
390 /* find the target page to copy it over to. */
391 if (page < start_page) {
392 page_offset = (page - (start_page - new_preload_cache_size));
393
394 g_assert (page_offset >= 0 &&do { if (page_offset >= 0 && page_offset < new_preload_cache_size
) ; else g_assertion_message_expr ("LectorView", "ev-pixbuf-cache.c"
, 395, ((const char*) (__func__)), "page_offset >= 0 && page_offset < new_preload_cache_size"
); } while (0)
395 page_offset < new_preload_cache_size)do { if (page_offset >= 0 && page_offset < new_preload_cache_size
) ; else g_assertion_message_expr ("LectorView", "ev-pixbuf-cache.c"
, 395, ((const char*) (__func__)), "page_offset >= 0 && page_offset < new_preload_cache_size"
); } while (0)
;
396 target_page = new_prev_job + page_offset;
397 new_priority = EV_JOB_PRIORITY_LOW;
398 } else if (page > end_page) {
399 page_offset = (page - (end_page + 1));
400
401 g_assert (page_offset >= 0 &&do { if (page_offset >= 0 && page_offset < new_preload_cache_size
) ; else g_assertion_message_expr ("LectorView", "ev-pixbuf-cache.c"
, 402, ((const char*) (__func__)), "page_offset >= 0 && page_offset < new_preload_cache_size"
); } while (0)
402 page_offset < new_preload_cache_size)do { if (page_offset >= 0 && page_offset < new_preload_cache_size
) ; else g_assertion_message_expr ("LectorView", "ev-pixbuf-cache.c"
, 402, ((const char*) (__func__)), "page_offset >= 0 && page_offset < new_preload_cache_size"
); } while (0)
;
403 target_page = new_next_job + page_offset;
404 new_priority = EV_JOB_PRIORITY_LOW;
405 } else {
406 page_offset = page - start_page;
407 g_assert (page_offset >= 0 &&do { if (page_offset >= 0 && page_offset <= ((end_page
- start_page) + 1)) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 408, ((const char*) (__func__)), "page_offset >= 0 && page_offset <= ((end_page - start_page) + 1)"
); } while (0)
408 page_offset <= ((end_page - start_page) + 1))do { if (page_offset >= 0 && page_offset <= ((end_page
- start_page) + 1)) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 408, ((const char*) (__func__)), "page_offset >= 0 && page_offset <= ((end_page - start_page) + 1)"
); } while (0)
;
409 new_priority = EV_JOB_PRIORITY_URGENT;
410 target_page = new_job_list + page_offset;
411 }
412
413 *target_page = *job_info;
414 job_info->job = NULL((void*)0);
415 job_info->region = NULL((void*)0);
416 job_info->surface = NULL((void*)0);
417
418 if (new_priority != priority && target_page->job) {
419 ev_job_scheduler_update_job (target_page->job, new_priority);
420 }
421}
422
423static gsize
424ev_pixbuf_cache_get_page_size (EvPixbufCache *pixbuf_cache,
425 gint page_index,
426 gdouble scale,
427 gint rotation)
428{
429 gint width, height;
430
431 _get_page_size_for_scale_and_rotation (pixbuf_cache->document,
432 page_index, scale, rotation,
433 &width, &height);
434 return height * cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, width);
435}
436
437static gint
438ev_pixbuf_cache_get_preload_size (EvPixbufCache *pixbuf_cache,
439 gint start_page,
440 gint end_page,
441 gdouble scale,
442 gint rotation)
443{
444 gsize range_size = 0;
445 gint new_preload_cache_size = 0;
446 gint i;
447 guint n_pages = ev_document_get_n_pages (pixbuf_cache->document);
448
449 /* Get the size of the current range */
450 for (i = start_page; i <= end_page; i++) {
451 range_size += ev_pixbuf_cache_get_page_size (pixbuf_cache, i, scale, rotation);
452 }
453
454 if (range_size >= pixbuf_cache->max_size)
455 return new_preload_cache_size;
456
457 i = 1;
458 while (((start_page - i > 0) || (end_page + i < n_pages)) &&
459 new_preload_cache_size < MAX_PRELOADED_PAGES3) {
460 gsize page_size;
461 gboolean updated = FALSE(0);
462
463 if (end_page + i < n_pages) {
464 page_size = ev_pixbuf_cache_get_page_size (pixbuf_cache, end_page + i,
465 scale, rotation);
466 if (page_size + range_size <= pixbuf_cache->max_size) {
467 range_size += page_size;
468 new_preload_cache_size++;
469 updated = TRUE(!(0));
470 } else {
471 break;
472 }
473 }
474
475 if (start_page - i > 0) {
476 page_size = ev_pixbuf_cache_get_page_size (pixbuf_cache, start_page - i,
477 scale, rotation);
478 if (page_size + range_size <= pixbuf_cache->max_size) {
479 range_size += page_size;
480 if (!updated)
481 new_preload_cache_size++;
482 } else {
483 break;
484 }
485 }
486 i++;
487 }
488
489 return new_preload_cache_size;
490}
491
492static void
493ev_pixbuf_cache_update_range (EvPixbufCache *pixbuf_cache,
494 gint start_page,
495 gint end_page,
496 guint rotation,
497 gdouble scale)
498{
499 CacheJobInfo *new_job_list;
500 CacheJobInfo *new_prev_job = NULL((void*)0);
501 CacheJobInfo *new_next_job = NULL((void*)0);
18
'new_next_job' initialized to a null pointer value
502 gint new_preload_cache_size;
503 guint new_job_list_len;
504 int i, page;
505
506 new_preload_cache_size = ev_pixbuf_cache_get_preload_size (pixbuf_cache,
507 start_page,
508 end_page,
509 scale,
510 rotation);
511 if (pixbuf_cache->start_page == start_page &&
19
Assuming 'start_page' is equal to field 'start_page'
22
Taking false branch
512 pixbuf_cache->end_page == end_page &&
20
Assuming 'end_page' is equal to field 'end_page'
513 pixbuf_cache->preload_cache_size == new_preload_cache_size)
21
Assuming 'new_preload_cache_size' is not equal to field 'preload_cache_size'
514 return;
515
516 new_job_list_len = (end_page - start_page) + 1;
517 new_job_list = g_slice_alloc0 (sizeof (CacheJobInfo) * new_job_list_len);
518 if (new_preload_cache_size
22.1
'new_preload_cache_size' is <= 0
> 0) {
23
Taking false branch
519 new_prev_job = g_slice_alloc0 (sizeof (CacheJobInfo) * new_preload_cache_size);
520 new_next_job = g_slice_alloc0 (sizeof (CacheJobInfo) * new_preload_cache_size);
521 }
522
523 /* We go through each job in the old cache and either clear it or move
524 * it to a new location. */
525
526 /* Start with the prev cache. */
527 page = pixbuf_cache->start_page - pixbuf_cache->preload_cache_size;
528 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
24
Assuming 'i' is >= field 'preload_cache_size'
25
Loop condition is false. Execution continues on line 541
529 if (page < 0) {
530 dispose_cache_job_info (pixbuf_cache->prev_job + i, pixbuf_cache);
531 } else {
532 move_one_job (pixbuf_cache->prev_job + i,
533 pixbuf_cache, page,
534 new_job_list, new_prev_job, new_next_job,
535 new_preload_cache_size,
536 start_page, end_page, EV_JOB_PRIORITY_LOW);
537 }
538 page ++;
539 }
540
541 page = pixbuf_cache->start_page;
542 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
&& page >= 0; i++) {
26
Assuming field 'start_page' is < 0
27
'?' condition is false
543 move_one_job (pixbuf_cache->job_list + i,
544 pixbuf_cache, page,
545 new_job_list, new_prev_job, new_next_job,
546 new_preload_cache_size,
547 start_page, end_page, EV_JOB_PRIORITY_URGENT);
548 page ++;
549 }
550
551 for (i = 0; i
27.1
'i' is >= field 'preload_cache_size'
< pixbuf_cache->preload_cache_size; i++) {
28
Loop condition is false. Execution continues on line 564
552 if (page >= ev_document_get_n_pages (pixbuf_cache->document)) {
553 dispose_cache_job_info (pixbuf_cache->next_job + i, pixbuf_cache);
554 } else {
555 move_one_job (pixbuf_cache->next_job + i,
556 pixbuf_cache, page,
557 new_job_list, new_prev_job, new_next_job,
558 new_preload_cache_size,
559 start_page, end_page, EV_JOB_PRIORITY_LOW);
560 }
561 page ++;
562 }
563
564 if (pixbuf_cache->job_list) {
29
Assuming field 'job_list' is null
30
Taking false branch
565 g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->job_list_len,
566 pixbuf_cache->job_list);
567 }
568 if (pixbuf_cache->prev_job) {
31
Assuming field 'prev_job' is null
32
Taking false branch
569 g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->preload_cache_size,
570 pixbuf_cache->prev_job);
571 }
572 if (pixbuf_cache->next_job) {
33
Assuming field 'next_job' is null
34
Taking false branch
573 g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->preload_cache_size,
574 pixbuf_cache->next_job);
575 }
576
577 pixbuf_cache->preload_cache_size = new_preload_cache_size;
578 pixbuf_cache->job_list_len = new_job_list_len;
579
580 pixbuf_cache->job_list = new_job_list;
581 pixbuf_cache->prev_job = new_prev_job;
582 pixbuf_cache->next_job = new_next_job;
35
Null pointer value stored to field 'next_job'
583
584 pixbuf_cache->start_page = start_page;
585 pixbuf_cache->end_page = end_page;
586}
587
588static CacheJobInfo *
589find_job_cache (EvPixbufCache *pixbuf_cache,
590 int page)
591{
592 int page_offset;
593
594 if (page < (pixbuf_cache->start_page - pixbuf_cache->preload_cache_size) ||
595 page > (pixbuf_cache->end_page + pixbuf_cache->preload_cache_size))
596 return NULL((void*)0);
597
598 if (page < pixbuf_cache->start_page) {
599 page_offset = (page - (pixbuf_cache->start_page - pixbuf_cache->preload_cache_size));
600
601 g_assert (page_offset >= 0 &&do { if (page_offset >= 0 && page_offset < pixbuf_cache
->preload_cache_size) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 602, ((const char*) (__func__)), "page_offset >= 0 && page_offset < pixbuf_cache->preload_cache_size"
); } while (0)
602 page_offset < pixbuf_cache->preload_cache_size)do { if (page_offset >= 0 && page_offset < pixbuf_cache
->preload_cache_size) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 602, ((const char*) (__func__)), "page_offset >= 0 && page_offset < pixbuf_cache->preload_cache_size"
); } while (0)
;
603 return pixbuf_cache->prev_job + page_offset;
604 }
605
606 if (page > pixbuf_cache->end_page) {
607 page_offset = (page - (pixbuf_cache->end_page + 1));
608
609 g_assert (page_offset >= 0 &&do { if (page_offset >= 0 && page_offset < pixbuf_cache
->preload_cache_size) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 610, ((const char*) (__func__)), "page_offset >= 0 && page_offset < pixbuf_cache->preload_cache_size"
); } while (0)
610 page_offset < pixbuf_cache->preload_cache_size)do { if (page_offset >= 0 && page_offset < pixbuf_cache
->preload_cache_size) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 610, ((const char*) (__func__)), "page_offset >= 0 && page_offset < pixbuf_cache->preload_cache_size"
); } while (0)
;
611 return pixbuf_cache->next_job + page_offset;
612 }
613
614 page_offset = page - pixbuf_cache->start_page;
615 g_assert (page_offset >= 0 &&do { if (page_offset >= 0 && page_offset <= (pixbuf_cache
->start_page>=0?((pixbuf_cache->end_page - pixbuf_cache
->start_page) + 1):0)) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 616, ((const char*) (__func__)), "page_offset >= 0 && page_offset <= PAGE_CACHE_LEN(pixbuf_cache)"
); } while (0)
616 page_offset <= PAGE_CACHE_LEN(pixbuf_cache))do { if (page_offset >= 0 && page_offset <= (pixbuf_cache
->start_page>=0?((pixbuf_cache->end_page - pixbuf_cache
->start_page) + 1):0)) ; else g_assertion_message_expr ("LectorView"
, "ev-pixbuf-cache.c", 616, ((const char*) (__func__)), "page_offset >= 0 && page_offset <= PAGE_CACHE_LEN(pixbuf_cache)"
); } while (0)
;
617 return pixbuf_cache->job_list + page_offset;
618}
619
620static void
621ev_pixbuf_cache_clear_job_sizes (EvPixbufCache *pixbuf_cache,
622 gfloat scale)
623{
624 int i;
625
626 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
38
'?' condition is true
39
Assuming the condition is false
40
Loop condition is false. Execution continues on line 630
627 check_job_size_and_unref (pixbuf_cache, pixbuf_cache->job_list + i, scale);
628 }
629
630 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
41
Loop condition is false. Execution continues on line 630
631 check_job_size_and_unref (pixbuf_cache, pixbuf_cache->prev_job + i, scale);
632 check_job_size_and_unref (pixbuf_cache, pixbuf_cache->next_job + i, scale);
633 }
634}
635
636static void
637get_selection_colors (EvView *view, CdkColor *text, CdkColor *base)
638{
639 CdkRGBA fg, bg;
640
641 _ev_view_get_selection_colors (view, &bg, &fg);
642
643 text->pixel = 0;
644 text->red = CLAMP ((guint) (fg.red * 65535), 0, 65535)((((guint) (fg.red * 65535)) > (65535)) ? (65535) : ((((guint
) (fg.red * 65535)) < (0)) ? (0) : ((guint) (fg.red * 65535
))))
;
645 text->green = CLAMP ((guint) (fg.green * 65535), 0, 65535)((((guint) (fg.green * 65535)) > (65535)) ? (65535) : ((((
guint) (fg.green * 65535)) < (0)) ? (0) : ((guint) (fg.green
* 65535))))
;
646 text->blue = CLAMP ((guint) (fg.blue * 65535), 0, 65535)((((guint) (fg.blue * 65535)) > (65535)) ? (65535) : ((((guint
) (fg.blue * 65535)) < (0)) ? (0) : ((guint) (fg.blue * 65535
))))
;
647
648 base->pixel = 0;
649 base->red = CLAMP ((guint) (bg.red * 65535), 0, 65535)((((guint) (bg.red * 65535)) > (65535)) ? (65535) : ((((guint
) (bg.red * 65535)) < (0)) ? (0) : ((guint) (bg.red * 65535
))))
;
650 base->green = CLAMP ((guint) (bg.green * 65535), 0, 65535)((((guint) (bg.green * 65535)) > (65535)) ? (65535) : ((((
guint) (bg.green * 65535)) < (0)) ? (0) : ((guint) (bg.green
* 65535))))
;
651 base->blue = CLAMP ((guint) (bg.blue * 65535), 0, 65535)((((guint) (bg.blue * 65535)) > (65535)) ? (65535) : ((((guint
) (bg.blue * 65535)) < (0)) ? (0) : ((guint) (bg.blue * 65535
))))
;
652}
653
654static void
655add_job (EvPixbufCache *pixbuf_cache,
656 CacheJobInfo *job_info,
657 cairo_region_t *region,
658 gint width,
659 gint height,
660 gint page,
661 gint rotation,
662 gfloat scale,
663 EvJobPriority priority)
664{
665 job_info->device_scale = get_device_scale (pixbuf_cache);
666 job_info->page_ready = FALSE(0);
667
668 if (job_info->region)
669 cairo_region_destroy (job_info->region);
670 job_info->region = region ? cairo_region_reference (region) : NULL((void*)0);
671
672 if (job_info->job)
673 end_job (job_info, pixbuf_cache);
674
675 job_info->job = ev_job_render_new (pixbuf_cache->document,
676 page, rotation,
677 scale * job_info->device_scale,
678 width * job_info->device_scale,
679 height * job_info->device_scale);
680
681 if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
682 CdkColor text, base;
683
684 get_selection_colors (EV_VIEW (pixbuf_cache->view)((((EvView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pixbuf_cache->view)), ((ev_view_get_type ()))))))
, &text, &base);
685 ev_job_render_set_selection_info (EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
,
686 &(job_info->target_points),
687 job_info->selection_style,
688 &text, &base);
689 }
690
691 g_signal_connect (job_info->job, "finished",g_signal_connect_data ((job_info->job), ("finished"), (((GCallback
) (job_finished_cb))), (pixbuf_cache), ((void*)0), (GConnectFlags
) 0)
692 G_CALLBACK (job_finished_cb),g_signal_connect_data ((job_info->job), ("finished"), (((GCallback
) (job_finished_cb))), (pixbuf_cache), ((void*)0), (GConnectFlags
) 0)
693 pixbuf_cache)g_signal_connect_data ((job_info->job), ("finished"), (((GCallback
) (job_finished_cb))), (pixbuf_cache), ((void*)0), (GConnectFlags
) 0)
;
694 ev_job_scheduler_push_job (job_info->job, priority);
695}
696
697static void
698add_job_if_needed (EvPixbufCache *pixbuf_cache,
699 CacheJobInfo *job_info,
700 gint page,
701 gint rotation,
702 gfloat scale,
703 EvJobPriority priority)
704{
705 gint device_scale = get_device_scale (pixbuf_cache);
706 gint width, height;
707
708 if (job_info->job)
65
Access to field 'job' results in a dereference of a null pointer (loaded from variable 'job_info')
709 return;
710
711 _get_page_size_for_scale_and_rotation (pixbuf_cache->document,
712 page, scale, rotation,
713 &width, &height);
714
715 if (job_info->surface &&
716 job_info->device_scale == device_scale &&
717 cairo_image_surface_get_width (job_info->surface) == width * device_scale &&
718 cairo_image_surface_get_height (job_info->surface) == height * device_scale)
719 return;
720
721 /* Free old surfaces for non visible pages */
722 if (priority == EV_JOB_PRIORITY_LOW) {
723 if (job_info->surface) {
724 cairo_surface_destroy (job_info->surface);
725 job_info->surface = NULL((void*)0);
726 }
727
728 if (job_info->selection) {
729 cairo_surface_destroy (job_info->selection);
730 job_info->selection = NULL((void*)0);
731 }
732 }
733
734 add_job (pixbuf_cache, job_info, NULL((void*)0),
735 width, height, page, rotation, scale,
736 priority);
737}
738
739static void
740add_prev_jobs_if_needed (EvPixbufCache *pixbuf_cache,
741 gint rotation,
742 gfloat scale)
743{
744 CacheJobInfo *job_info;
745 int page;
746 int i;
747
748 for (i = pixbuf_cache->preload_cache_size - 1; i >= FIRST_VISIBLE_PREV(pixbuf_cache)((((0) > (pixbuf_cache->preload_cache_size - pixbuf_cache
->start_page)) ? (0) : (pixbuf_cache->preload_cache_size
- pixbuf_cache->start_page)))
; i--) {
749 job_info = (pixbuf_cache->prev_job + i);
750 page = pixbuf_cache->start_page - pixbuf_cache->preload_cache_size + i;
751
752 add_job_if_needed (pixbuf_cache, job_info,
753 page, rotation, scale,
754 EV_JOB_PRIORITY_LOW);
755 }
756}
757
758static void
759add_next_jobs_if_needed (EvPixbufCache *pixbuf_cache,
760 gint rotation,
761 gfloat scale)
762{
763 CacheJobInfo *job_info;
764 int page;
765 int i;
766
767 for (i = 0; i < VISIBLE_NEXT_LEN(pixbuf_cache)((((pixbuf_cache->preload_cache_size) < (ev_document_get_n_pages
(pixbuf_cache->document) - (1 + pixbuf_cache->end_page
))) ? (pixbuf_cache->preload_cache_size) : (ev_document_get_n_pages
(pixbuf_cache->document) - (1 + pixbuf_cache->end_page
))))
; i++) {
58
Assuming the condition is false
59
'?' condition is false
60
Assuming the condition is true
61
Loop condition is true. Entering loop body
768 job_info = (pixbuf_cache->next_job + i);
62
Null pointer value stored to 'job_info'
769 page = pixbuf_cache->end_page + 1 + i;
770
771 add_job_if_needed (pixbuf_cache, job_info,
63
Passing null pointer value via 2nd parameter 'job_info'
64
Calling 'add_job_if_needed'
772 page, rotation, scale,
773 EV_JOB_PRIORITY_LOW);
774 }
775}
776
777static void
778ev_pixbuf_cache_add_jobs_if_needed (EvPixbufCache *pixbuf_cache,
779 gint rotation,
780 gfloat scale)
781{
782 CacheJobInfo *job_info;
783 int page;
784 int i;
785
786 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
53
'?' condition is true
54
Loop condition is false. Execution continues on line 795
787 job_info = (pixbuf_cache->job_list + i);
788 page = pixbuf_cache->start_page + i;
789
790 add_job_if_needed (pixbuf_cache, job_info,
791 page, rotation, scale,
792 EV_JOB_PRIORITY_URGENT);
793 }
794
795 if (pixbuf_cache->scroll_direction == SCROLL_DIRECTION_UP) {
55
Assuming field 'scroll_direction' is not equal to SCROLL_DIRECTION_UP
56
Taking false branch
796 add_prev_jobs_if_needed (pixbuf_cache, rotation, scale);
797 add_next_jobs_if_needed (pixbuf_cache, rotation, scale);
798 } else {
799 add_next_jobs_if_needed (pixbuf_cache, rotation, scale);
57
Calling 'add_next_jobs_if_needed'
800 add_prev_jobs_if_needed (pixbuf_cache, rotation, scale);
801 }
802}
803
804static ScrollDirection
805ev_pixbuf_cache_get_scroll_direction (EvPixbufCache *pixbuf_cache,
806 gint start_page,
807 gint end_page)
808{
809 if (start_page < pixbuf_cache->start_page)
810 return SCROLL_DIRECTION_UP;
811
812 if (end_page > pixbuf_cache->end_page)
813 return SCROLL_DIRECTION_DOWN;
814
815 if (start_page > pixbuf_cache->start_page)
816 return SCROLL_DIRECTION_DOWN;
817
818 if (end_page < pixbuf_cache->end_page)
819 return SCROLL_DIRECTION_UP;
820
821 return pixbuf_cache->scroll_direction;
822}
823
824void
825ev_pixbuf_cache_set_page_range (EvPixbufCache *pixbuf_cache,
826 gint start_page,
827 gint end_page,
828 GList *selection_list)
829{
830 gdouble scale = ev_document_model_get_scale (pixbuf_cache->model);
831 gint rotation = ev_document_model_get_rotation (pixbuf_cache->model);
832
833 g_return_if_fail (EV_IS_PIXBUF_CACHE (pixbuf_cache))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf_cache)); GType __t = ((ev_pixbuf_cache_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("LectorView"
, ((const char*) (__func__)), "EV_IS_PIXBUF_CACHE (pixbuf_cache)"
); return; } } while (0)
;
1
Taking false branch
2
Assuming field 'g_class' is null
3
Assuming the condition is true
4
Taking true branch
834
835 g_return_if_fail (start_page >= 0 && start_page < ev_document_get_n_pages (pixbuf_cache->document))do { if ((start_page >= 0 && start_page < ev_document_get_n_pages
(pixbuf_cache->document))) { } else { g_return_if_fail_warning
("LectorView", ((const char*) (__func__)), "start_page >= 0 && start_page < ev_document_get_n_pages (pixbuf_cache->document)"
); return; } } while (0)
;
5
Loop condition is false. Exiting loop
6
Assuming 'start_page' is >= 0
7
Assuming the condition is true
8
Taking true branch
836 g_return_if_fail (end_page >= 0 && end_page < ev_document_get_n_pages (pixbuf_cache->document))do { if ((end_page >= 0 && end_page < ev_document_get_n_pages
(pixbuf_cache->document))) { } else { g_return_if_fail_warning
("LectorView", ((const char*) (__func__)), "end_page >= 0 && end_page < ev_document_get_n_pages (pixbuf_cache->document)"
); return; } } while (0)
;
9
Loop condition is false. Exiting loop
10
Assuming 'end_page' is >= 0
11
Assuming the condition is true
12
Taking true branch
13
Loop condition is false. Exiting loop
837 g_return_if_fail (end_page >= start_page)do { if ((end_page >= start_page)) { } else { g_return_if_fail_warning
("LectorView", ((const char*) (__func__)), "end_page >= start_page"
); return; } } while (0)
;
14
Assuming 'end_page' is >= 'start_page'
15
Taking true branch
16
Loop condition is false. Exiting loop
838
839 pixbuf_cache->scroll_direction = ev_pixbuf_cache_get_scroll_direction (pixbuf_cache, start_page, end_page);
840
841 /* First, resize the page_range as needed. We cull old pages
842 * mercilessly. */
843 ev_pixbuf_cache_update_range (pixbuf_cache, start_page, end_page, rotation, scale);
17
Calling 'ev_pixbuf_cache_update_range'
36
Returning from 'ev_pixbuf_cache_update_range'
844
845 /* Then, we update the current jobs to see if any of them are the wrong
846 * size, we remove them if we need to. */
847 ev_pixbuf_cache_clear_job_sizes (pixbuf_cache, scale);
37
Calling 'ev_pixbuf_cache_clear_job_sizes'
42
Returning from 'ev_pixbuf_cache_clear_job_sizes'
848
849 /* Next, we update the target selection for our pages */
850 ev_pixbuf_cache_set_selection_list (pixbuf_cache, selection_list);
43
Calling 'ev_pixbuf_cache_set_selection_list'
51
Returning from 'ev_pixbuf_cache_set_selection_list'
851
852 /* Finally, we add the new jobs for all the sizes that don't have a
853 * pixbuf */
854 ev_pixbuf_cache_add_jobs_if_needed (pixbuf_cache, rotation, scale);
52
Calling 'ev_pixbuf_cache_add_jobs_if_needed'
855}
856
857void
858ev_pixbuf_cache_set_inverted_colors (EvPixbufCache *pixbuf_cache,
859 gboolean inverted_colors)
860{
861 gint i;
862
863 if (pixbuf_cache->inverted_colors == inverted_colors)
864 return;
865
866 pixbuf_cache->inverted_colors = inverted_colors;
867
868 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
869 CacheJobInfo *job_info;
870
871 job_info = pixbuf_cache->prev_job + i;
872 if (job_info && job_info->surface)
873 ev_document_misc_invert_surface (job_info->surface);
874
875 job_info = pixbuf_cache->next_job + i;
876 if (job_info && job_info->surface)
877 ev_document_misc_invert_surface (job_info->surface);
878 }
879
880 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
881 CacheJobInfo *job_info;
882
883 job_info = pixbuf_cache->job_list + i;
884 if (job_info && job_info->surface)
885 ev_document_misc_invert_surface (job_info->surface);
886 }
887}
888
889cairo_surface_t *
890ev_pixbuf_cache_get_surface (EvPixbufCache *pixbuf_cache,
891 gint page)
892{
893 CacheJobInfo *job_info;
894
895 job_info = find_job_cache (pixbuf_cache, page);
896 if (job_info == NULL((void*)0))
897 return NULL((void*)0);
898
899 if (job_info->page_ready)
900 return job_info->surface;
901
902 /* We don't need to wait for the idle to handle the callback */
903 if (job_info->job &&
904 EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->page_ready) {
905 copy_job_to_job_info (EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
, job_info, pixbuf_cache);
906 g_signal_emit (pixbuf_cache, signals[JOB_FINISHED], 0, job_info->region);
907 }
908
909 return job_info->surface;
910}
911
912static gboolean
913new_selection_surface_needed (EvPixbufCache *pixbuf_cache,
914 CacheJobInfo *job_info,
915 gint page,
916 gfloat scale)
917{
918 if (job_info->selection)
919 return job_info->selection_scale != scale;
920 return job_info->points_set;
921}
922
923static gboolean
924new_selection_region_needed (EvPixbufCache *pixbuf_cache,
925 CacheJobInfo *job_info,
926 gint page,
927 gfloat scale)
928{
929 if (job_info->selection_region)
930 return job_info->selection_region_scale != scale;
931 return job_info->points_set;
932}
933
934static void
935clear_selection_surface_if_needed (EvPixbufCache *pixbuf_cache,
936 CacheJobInfo *job_info,
937 gint page,
938 gfloat scale)
939{
940 if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
941 if (job_info->selection)
942 cairo_surface_destroy (job_info->selection);
943 job_info->selection = NULL((void*)0);
944 job_info->selection_points.x1 = -1;
945 }
946}
947
948static void
949clear_selection_region_if_needed (EvPixbufCache *pixbuf_cache,
950 CacheJobInfo *job_info,
951 gint page,
952 gfloat scale)
953{
954 if (new_selection_region_needed (pixbuf_cache, job_info, page, scale)) {
955 if (job_info->selection_region)
956 cairo_region_destroy (job_info->selection_region);
957 job_info->selection_region = NULL((void*)0);
958 job_info->selection_region_points.x1 = -1;
959 }
960}
961
962/* Clears the cache of jobs and pixbufs.
963 */
964void
965ev_pixbuf_cache_clear (EvPixbufCache *pixbuf_cache)
966{
967 int i;
968
969 if (!pixbuf_cache->job_list)
970 return;
971
972 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
973 dispose_cache_job_info (pixbuf_cache->prev_job + i, pixbuf_cache);
974 dispose_cache_job_info (pixbuf_cache->next_job + i, pixbuf_cache);
975 }
976
977 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
978 dispose_cache_job_info (pixbuf_cache->job_list + i, pixbuf_cache);
979 }
980}
981
982
983void
984ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache)
985{
986 gint i;
987
988 if (!pixbuf_cache->job_list)
989 return;
990
991 /* FIXME: doesn't update running jobs. */
992 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
993 CacheJobInfo *job_info;
994
995 job_info = pixbuf_cache->prev_job + i;
996 if (job_info->selection) {
997 cairo_surface_destroy (job_info->selection);
998 job_info->selection = NULL((void*)0);
999 job_info->selection_points.x1 = -1;
1000 }
1001
1002 job_info = pixbuf_cache->next_job + i;
1003 if (job_info->selection) {
1004 cairo_surface_destroy (job_info->selection);
1005 job_info->selection = NULL((void*)0);
1006 job_info->selection_points.x1 = -1;
1007 }
1008 }
1009
1010 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
1011 CacheJobInfo *job_info;
1012
1013 job_info = pixbuf_cache->job_list + i;
1014 if (job_info->selection) {
1015 cairo_surface_destroy (job_info->selection);
1016 job_info->selection = NULL((void*)0);
1017 job_info->selection_points.x1 = -1;
1018 }
1019 }
1020}
1021
1022cairo_surface_t *
1023ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
1024 gint page,
1025 gfloat scale)
1026{
1027 CacheJobInfo *job_info;
1028
1029 /* the document does not implement the selection interface */
1030 if (!EV_IS_SELECTION (pixbuf_cache->document)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(pixbuf_cache->document)); GType __t = ((ev_selection_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
1031 return NULL((void*)0);
1032
1033 job_info = find_job_cache (pixbuf_cache, page);
1034 if (job_info == NULL((void*)0))
1035 return NULL((void*)0);
1036
1037 /* No selection on this page */
1038 if (!job_info->points_set)
1039 return NULL((void*)0);
1040
1041 /* If we have a running job, we just return what we have under the
1042 * assumption that it'll be updated later and we can scale it as need
1043 * be */
1044 if (job_info->job && EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->include_selection)
1045 return job_info->selection;
1046
1047 /* Now, lets see if we need to resize the image. If we do, we clear the
1048 * old one. */
1049 clear_selection_surface_if_needed (pixbuf_cache, job_info, page, scale);
1050
1051 /* Finally, we see if the two scales are the same, and get a new pixbuf
1052 * if needed. We do this synchronously for now. At some point, we
1053 * _should_ be able to get rid of the doc_mutex, so the synchronicity
1054 * doesn't kill us. Rendering a few glyphs should really be fast.
1055 */
1056 if (ev_rect_cmp (&(job_info->target_points), &(job_info->selection_points))) {
1057 EvRectangle *old_points;
1058 CdkColor text, base;
1059 EvRenderContext *rc;
1060 EvPage *ev_page;
1061
1062 /* we need to get a new selection pixbuf */
1063 ev_document_doc_mutex_lock ();
1064 if (job_info->selection_points.x1 < 0) {
1065 g_assert (job_info->selection == NULL)do { if (job_info->selection == ((void*)0)) ; else g_assertion_message_expr
("LectorView", "ev-pixbuf-cache.c", 1065, ((const char*) (__func__
)), "job_info->selection == NULL"); } while (0)
;
1066 old_points = NULL((void*)0);
1067 } else {
1068 old_points = &(job_info->selection_points);
1069 }
1070
1071 ev_page = ev_document_get_page (pixbuf_cache->document, page);
1072 rc = ev_render_context_new (ev_page, 0, scale * job_info->device_scale);
1073 g_object_unref (ev_page);
1074
1075 get_selection_colors (EV_VIEW (pixbuf_cache->view)((((EvView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pixbuf_cache->view)), ((ev_view_get_type ()))))))
, &text, &base);
1076 ev_selection_render_selection (EV_SELECTION (pixbuf_cache->document)((((EvSelection*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pixbuf_cache->document)), ((ev_selection_get_type ())
)))))
,
1077 rc, &(job_info->selection),
1078 &(job_info->target_points),
1079 old_points,
1080 job_info->selection_style,
1081 &text, &base);
1082 if (job_info->selection)
1083 set_device_scale_on_surface (job_info->selection, job_info->device_scale);
1084 job_info->selection_points = job_info->target_points;
1085 job_info->selection_scale = scale * job_info->device_scale;
1086 g_object_unref (rc);
1087 ev_document_doc_mutex_unlock ();
1088 }
1089 return job_info->selection;
1090}
1091
1092cairo_region_t *
1093ev_pixbuf_cache_get_selection_region (EvPixbufCache *pixbuf_cache,
1094 gint page,
1095 gfloat scale)
1096{
1097 CacheJobInfo *job_info;
1098
1099 /* the document does not implement the selection interface */
1100 if (!EV_IS_SELECTION (pixbuf_cache->document)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(pixbuf_cache->document)); GType __t = ((ev_selection_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
1101 return NULL((void*)0);
1102
1103 job_info = find_job_cache (pixbuf_cache, page);
1104 if (job_info == NULL((void*)0))
1105 return NULL((void*)0);
1106
1107 /* No selection on this page */
1108 if (!job_info->points_set)
1109 return NULL((void*)0);
1110
1111 /* If we have a running job, we just return what we have under the
1112 * assumption that it'll be updated later and we can scale it as need
1113 * be */
1114 if (job_info->job && EV_JOB_RENDER (job_info->job)((((EvJobRender*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((job_info->job)), ((ev_job_render_get_type()))))))
->include_selection)
1115 return job_info->selection_region && !cairo_region_is_empty(job_info->selection_region) ?
1116 job_info->selection_region : NULL((void*)0);
1117
1118 /* Now, lets see if we need to resize the region. If we do, we clear the
1119 * old one. */
1120 clear_selection_region_if_needed (pixbuf_cache, job_info, page, scale);
1121
1122 /* Finally, we see if the two scales are the same, and get a new region
1123 * if needed.
1124 */
1125 if (ev_rect_cmp (&(job_info->target_points), &(job_info->selection_region_points))) {
1126 EvRenderContext *rc;
1127 EvPage *ev_page;
1128
1129 ev_document_doc_mutex_lock ();
1130 ev_page = ev_document_get_page (pixbuf_cache->document, page);
1131 rc = ev_render_context_new (ev_page, 0, scale);
1132 g_object_unref (ev_page);
1133
1134 if (job_info->selection_region)
1135 cairo_region_destroy (job_info->selection_region);
1136 job_info->selection_region =
1137 ev_selection_get_selection_region (EV_SELECTION (pixbuf_cache->document)((((EvSelection*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pixbuf_cache->document)), ((ev_selection_get_type ())
)))))
,
1138 rc, job_info->selection_style,
1139 &(job_info->target_points));
1140 job_info->selection_region_points = job_info->target_points;
1141 job_info->selection_region_scale = scale;
1142 g_object_unref (rc);
1143 ev_document_doc_mutex_unlock ();
1144 }
1145 return job_info->selection_region && !cairo_region_is_empty(job_info->selection_region) ?
1146 job_info->selection_region : NULL((void*)0);
1147}
1148
1149static void
1150update_job_selection (CacheJobInfo *job_info,
1151 EvViewSelection *selection)
1152{
1153 job_info->points_set = TRUE(!(0));
1154 job_info->target_points = selection->rect;
1155 job_info->selection_style = selection->style;
1156}
1157
1158static void
1159clear_job_selection (CacheJobInfo *job_info)
1160{
1161 job_info->points_set = FALSE(0);
1162 job_info->selection_points.x1 = -1;
1163
1164 if (job_info->selection) {
1165 cairo_surface_destroy (job_info->selection);
1166 job_info->selection = NULL((void*)0);
1167 }
1168
1169 if (job_info->selection_region) {
1170 cairo_region_destroy (job_info->selection_region);
1171 job_info->selection_region = NULL((void*)0);
1172 }
1173}
1174
1175/* This function will reset the selection on pages that no longer have them, and
1176 * will update the target_selection on those that need it. It will _not_ free
1177 * the previous selection_list -- that's up to caller to do.
1178 */
1179void
1180ev_pixbuf_cache_set_selection_list (EvPixbufCache *pixbuf_cache,
1181 GList *selection_list)
1182{
1183 EvViewSelection *selection;
1184 GList *list = selection_list;
1185 int page;
1186 int i;
1187
1188 g_return_if_fail (EV_IS_PIXBUF_CACHE (pixbuf_cache))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf_cache)); GType __t = ((ev_pixbuf_cache_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("LectorView"
, ((const char*) (__func__)), "EV_IS_PIXBUF_CACHE (pixbuf_cache)"
); return; } } while (0)
;
44
Taking false branch
45
Assuming the condition is true
46
Taking true branch
47
Loop condition is false. Exiting loop
1189
1190 if (!EV_IS_SELECTION (pixbuf_cache->document)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(pixbuf_cache->document)); GType __t = ((ev_selection_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
48
Assuming '__inst' is null
49
Taking true branch
50
Taking true branch
1191 return;
1192
1193 if (pixbuf_cache->start_page == -1 || pixbuf_cache->end_page == -1)
1194 return;
1195
1196 /* We check each area to see what needs updating, and what needs freeing; */
1197 page = pixbuf_cache->start_page - pixbuf_cache->preload_cache_size;
1198 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
1199 if (page < 0) {
1200 page ++;
1201 continue;
1202 }
1203
1204 selection = NULL((void*)0);
1205 while (list) {
1206 if (((EvViewSelection *)list->data)->page == page) {
1207 selection = list->data;
1208 break;
1209 } else if (((EvViewSelection *)list->data)->page > page)
1210 break;
1211 list = list->next;
1212 }
1213
1214 if (selection)
1215 update_job_selection (pixbuf_cache->prev_job + i, selection);
1216 else
1217 clear_job_selection (pixbuf_cache->prev_job + i);
1218 page ++;
1219 }
1220
1221 page = pixbuf_cache->start_page;
1222 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
1223 selection = NULL((void*)0);
1224 while (list) {
1225 if (((EvViewSelection *)list->data)->page == page) {
1226 selection = list->data;
1227 break;
1228 } else if (((EvViewSelection *)list->data)->page > page)
1229 break;
1230 list = list->next;
1231 }
1232
1233 if (selection)
1234 update_job_selection (pixbuf_cache->job_list + i, selection);
1235 else
1236 clear_job_selection (pixbuf_cache->job_list + i);
1237 page ++;
1238 }
1239
1240 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
1241 if (page >= ev_document_get_n_pages (pixbuf_cache->document))
1242 break;
1243
1244 selection = NULL((void*)0);
1245 while (list) {
1246 if (((EvViewSelection *)list->data)->page == page) {
1247 selection = list->data;
1248 break;
1249 } else if (((EvViewSelection *)list->data)->page > page)
1250 break;
1251 list = list->next;
1252 }
1253
1254 if (selection)
1255 update_job_selection (pixbuf_cache->next_job + i, selection);
1256 else
1257 clear_job_selection (pixbuf_cache->next_job + i);
1258 page ++;
1259 }
1260}
1261
1262
1263/* Returns what the pixbuf cache thinks is */
1264
1265GList *
1266ev_pixbuf_cache_get_selection_list (EvPixbufCache *pixbuf_cache)
1267{
1268 EvViewSelection *selection;
1269 GList *retval = NULL((void*)0);
1270 int page;
1271 int i;
1272
1273 g_return_val_if_fail (EV_IS_PIXBUF_CACHE (pixbuf_cache), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((pixbuf_cache)); GType __t = ((ev_pixbuf_cache_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("LectorView"
, ((const char*) (__func__)), "EV_IS_PIXBUF_CACHE (pixbuf_cache)"
); return (((void*)0)); } } while (0)
;
1274
1275 if (pixbuf_cache->start_page == -1 || pixbuf_cache->end_page == -1)
1276 return NULL((void*)0);
1277
1278 /* We check each area to see what needs updating, and what needs freeing; */
1279 page = pixbuf_cache->start_page - pixbuf_cache->preload_cache_size;
1280 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
1281 if (page < 0) {
1282 page ++;
1283 continue;
1284 }
1285
1286 if (pixbuf_cache->prev_job[i].selection_points.x1 != -1) {
1287 selection = g_slice_new0 (EvViewSelection)((EvViewSelection*) g_slice_alloc0 (sizeof (EvViewSelection))
)
;
1288 selection->page = page;
1289 selection->rect = pixbuf_cache->prev_job[i].selection_points;
1290 if (pixbuf_cache->prev_job[i].selection_region)
1291 selection->covered_region = cairo_region_reference (pixbuf_cache->prev_job[i].selection_region);
1292 retval = g_list_prepend (retval, selection);
1293 }
1294
1295 page ++;
1296 }
1297
1298 page = pixbuf_cache->start_page;
1299 for (i = 0; i < PAGE_CACHE_LEN (pixbuf_cache)(pixbuf_cache->start_page>=0?((pixbuf_cache->end_page
- pixbuf_cache->start_page) + 1):0)
; i++) {
1300 if (pixbuf_cache->job_list[i].selection_points.x1 != -1) {
1301 selection = g_slice_new0 (EvViewSelection)((EvViewSelection*) g_slice_alloc0 (sizeof (EvViewSelection))
)
;
1302 selection->page = page;
1303 selection->rect = pixbuf_cache->job_list[i].selection_points;
1304 if (pixbuf_cache->job_list[i].selection_region)
1305 selection->covered_region = cairo_region_reference (pixbuf_cache->job_list[i].selection_region);
1306 retval = g_list_prepend (retval, selection);
1307 }
1308
1309 page ++;
1310 }
1311
1312 for (i = 0; i < pixbuf_cache->preload_cache_size; i++) {
1313 if (page >= ev_document_get_n_pages (pixbuf_cache->document))
1314 break;
1315
1316 if (pixbuf_cache->next_job[i].selection_points.x1 != -1) {
1317 selection = g_slice_new0 (EvViewSelection)((EvViewSelection*) g_slice_alloc0 (sizeof (EvViewSelection))
)
;
1318 selection->page = page;
1319 selection->rect = pixbuf_cache->next_job[i].selection_points;
1320 if (pixbuf_cache->next_job[i].selection_region)
1321 selection->covered_region = cairo_region_reference (pixbuf_cache->next_job[i].selection_region);
1322 retval = g_list_prepend (retval, selection);
1323 }
1324
1325 page ++;
1326 }
1327
1328 return g_list_reverse (retval);
1329}
1330
1331void
1332ev_pixbuf_cache_reload_page (EvPixbufCache *pixbuf_cache,
1333 cairo_region_t *region,
1334 gint page,
1335 gint rotation,
1336 gdouble scale)
1337{
1338 CacheJobInfo *job_info;
1339 gint width, height;
1340
1341 job_info = find_job_cache (pixbuf_cache, page);
1342 if (job_info == NULL((void*)0))
1343 return;
1344
1345 _get_page_size_for_scale_and_rotation (pixbuf_cache->document,
1346 page, scale, rotation,
1347 &width, &height);
1348 add_job (pixbuf_cache, job_info, region,
1349 width, height, page, rotation, scale,
1350 EV_JOB_PRIORITY_URGENT);
1351}
1352
1353