| 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') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | #include <config.h> | |||
| 2 | #include "ev-pixbuf-cache.h" | |||
| 3 | #include "ev-job-scheduler.h" | |||
| 4 | #include "ev-view-private.h" | |||
| 5 | ||||
| 6 | typedef enum { | |||
| 7 | SCROLL_DIRECTION_DOWN, | |||
| 8 | SCROLL_DIRECTION_UP | |||
| 9 | } ScrollDirection; | |||
| 10 | ||||
| 11 | typedef 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 | ||||
| 41 | struct _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 | ||||
| 68 | struct _EvPixbufCacheClass | |||
| 69 | { | |||
| 70 | GObjectClass parent_class; | |||
| 71 | ||||
| 72 | void (* job_finished) (EvPixbufCache *pixbuf_cache); | |||
| 73 | }; | |||
| 74 | ||||
| 75 | ||||
| 76 | enum | |||
| 77 | { | |||
| 78 | JOB_FINISHED, | |||
| 79 | N_SIGNALS, | |||
| 80 | }; | |||
| 81 | ||||
| 82 | static guint signals[N_SIGNALS] = {0, }; | |||
| 83 | ||||
| 84 | static void ev_pixbuf_cache_finalize (GObject *object); | |||
| 85 | static void ev_pixbuf_cache_dispose (GObject *object); | |||
| 86 | static void job_finished_cb (EvJob *job, | |||
| 87 | EvPixbufCache *pixbuf_cache); | |||
| 88 | static CacheJobInfo *find_job_cache (EvPixbufCache *pixbuf_cache, | |||
| 89 | int page); | |||
| 90 | static 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 | ||||
| 106 | G_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 GType 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_pointer ( &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_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (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 | ||||
| 108 | static void | |||
| 109 | ev_pixbuf_cache_init (EvPixbufCache *pixbuf_cache) | |||
| 110 | { | |||
| 111 | pixbuf_cache->start_page = -1; | |||
| 112 | pixbuf_cache->end_page = -1; | |||
| 113 | } | |||
| 114 | ||||
| 115 | static void | |||
| 116 | ev_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 | ||||
| 136 | static void | |||
| 137 | ev_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 | ||||
| 164 | static void | |||
| 165 | end_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 | ||||
| 176 | static void | |||
| 177 | dispose_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 | ||||
| 206 | static void | |||
| 207 | ev_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 | ||||
| 227 | EvPixbufCache * | |||
| 228 | ev_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 | ||||
| 244 | void | |||
| 245 | ev_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 | ||||
| 256 | static int | |||
| 257 | get_device_scale (EvPixbufCache *pixbuf_cache) | |||
| 258 | { | |||
| 259 | return ctk_widget_get_scale_factor (pixbuf_cache->view); | |||
| 260 | } | |||
| 261 | ||||
| 262 | static void | |||
| 263 | set_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 | ||||
| 269 | static void | |||
| 270 | copy_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 | ||||
| 314 | static void | |||
| 315 | job_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 | */ | |||
| 337 | static void | |||
| 338 | check_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 | */ | |||
| 368 | static void | |||
| 369 | move_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 | ||||
| 423 | static gsize | |||
| 424 | ev_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 | ||||
| 437 | static gint | |||
| 438 | ev_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 | ||||
| 492 | static void | |||
| 493 | ev_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); | |||
| 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 && | |||
| 512 | pixbuf_cache->end_page == end_page && | |||
| 513 | pixbuf_cache->preload_cache_size == new_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
| |||
| 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++) { | |||
| 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++) { | |||
| 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
| |||
| 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) { | |||
| 565 | g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->job_list_len, | |||
| 566 | pixbuf_cache->job_list); | |||
| 567 | } | |||
| 568 | if (pixbuf_cache->prev_job) { | |||
| 569 | g_slice_free1 (sizeof (CacheJobInfo) * pixbuf_cache->preload_cache_size, | |||
| 570 | pixbuf_cache->prev_job); | |||
| 571 | } | |||
| 572 | if (pixbuf_cache->next_job) { | |||
| 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; | |||
| 583 | ||||
| 584 | pixbuf_cache->start_page = start_page; | |||
| 585 | pixbuf_cache->end_page = end_page; | |||
| 586 | } | |||
| 587 | ||||
| 588 | static CacheJobInfo * | |||
| 589 | find_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 | ||||
| 620 | static void | |||
| 621 | ev_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++) { | |||
| 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++) { | |||
| 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 | ||||
| 636 | static void | |||
| 637 | get_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 | ||||
| 654 | static void | |||
| 655 | add_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 | ||||
| 697 | static void | |||
| 698 | add_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) | |||
| ||||
| 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 | ||||
| 739 | static void | |||
| 740 | add_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 | ||||
| 758 | static void | |||
| 759 | add_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++) { | |||
| 768 | job_info = (pixbuf_cache->next_job + i); | |||
| 769 | page = pixbuf_cache->end_page + 1 + i; | |||
| 770 | ||||
| 771 | add_job_if_needed (pixbuf_cache, job_info, | |||
| 772 | page, rotation, scale, | |||
| 773 | EV_JOB_PRIORITY_LOW); | |||
| 774 | } | |||
| 775 | } | |||
| 776 | ||||
| 777 | static void | |||
| 778 | ev_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++) { | |||
| 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) { | |||
| 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); | |||
| 800 | add_prev_jobs_if_needed (pixbuf_cache, rotation, scale); | |||
| 801 | } | |||
| 802 | } | |||
| 803 | ||||
| 804 | static ScrollDirection | |||
| 805 | ev_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 | ||||
| 824 | void | |||
| 825 | ev_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); | |||
| ||||
| 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); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| 848 | ||||
| 849 | /* Next, we update the target selection for our pages */ | |||
| 850 | ev_pixbuf_cache_set_selection_list (pixbuf_cache, 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); | |||
| 855 | } | |||
| 856 | ||||
| 857 | void | |||
| 858 | ev_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 | ||||
| 889 | cairo_surface_t * | |||
| 890 | ev_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 | ||||
| 912 | static gboolean | |||
| 913 | new_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 | ||||
| 923 | static gboolean | |||
| 924 | new_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 | ||||
| 934 | static void | |||
| 935 | clear_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 | ||||
| 948 | static void | |||
| 949 | clear_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 | */ | |||
| 964 | void | |||
| 965 | ev_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 | ||||
| 983 | void | |||
| 984 | ev_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 | ||||
| 1022 | cairo_surface_t * | |||
| 1023 | ev_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 | ||||
| 1092 | cairo_region_t * | |||
| 1093 | ev_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 | ||||
| 1149 | static void | |||
| 1150 | update_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 | ||||
| 1158 | static void | |||
| 1159 | clear_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 | */ | |||
| 1179 | void | |||
| 1180 | ev_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); | |||
| 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; }))))) | |||
| 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 | ||||
| 1265 | GList * | |||
| 1266 | ev_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 | ||||
| 1331 | void | |||
| 1332 | ev_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 |