2 #include "ev-page-cache.h"
3 #include "ev-document-thumbnails.h"
8 #define THUMBNAIL_WIDTH 100
10 typedef struct _EvPageThumbsInfo
24 gboolean dual_even_left;
26 double* height_to_page;
27 double* dual_height_to_page;
31 /* Thumbnail dimensions */
32 gboolean thumbs_uniform;
33 gint thumbs_uniform_width;
34 gint thumbs_uniform_height;
35 gint thumbs_max_width;
36 gint thumbs_max_height;
37 EvPageThumbsInfo *thumbs_size_cache;
40 struct _EvPageCacheClass
42 GObjectClass parent_class;
44 void (* page_changed) (EvPageCache *page_cache, gint page);
45 void (* history_changed) (EvPageCache *page_cache, gint page);
55 static guint signals[N_SIGNALS] = {0, };
57 static void ev_page_cache_init (EvPageCache *page_cache);
58 static void ev_page_cache_class_init (EvPageCacheClass *page_cache);
59 static void ev_page_cache_finalize (GObject *object);
61 G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
64 ev_page_cache_init (EvPageCache *page_cache)
66 page_cache->current_page = -1;
70 ev_page_cache_class_init (EvPageCacheClass *class)
72 GObjectClass *object_class;
74 object_class = G_OBJECT_CLASS (class);
76 object_class->finalize = ev_page_cache_finalize;
78 signals [PAGE_CHANGED] =
79 g_signal_new ("page-changed",
82 G_STRUCT_OFFSET (EvPageCacheClass, page_changed),
84 g_cclosure_marshal_VOID__INT,
88 signals [HISTORY_CHANGED] =
89 g_signal_new ("history-changed",
92 G_STRUCT_OFFSET (EvPageCacheClass, history_changed),
94 g_cclosure_marshal_VOID__INT,
101 ev_page_cache_finalize (GObject *object)
103 EvPageCache *page_cache = EV_PAGE_CACHE (object);
105 page_cache->document = NULL;
107 if (page_cache->thumbs_size_cache) {
108 g_free (page_cache->thumbs_size_cache);
109 page_cache->thumbs_size_cache = NULL;
112 if (page_cache->height_to_page) {
113 g_free (page_cache->height_to_page);
114 page_cache->height_to_page = NULL;
117 if (page_cache->dual_height_to_page) {
118 g_free (page_cache->dual_height_to_page);
119 page_cache->dual_height_to_page = NULL;
122 G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object);
126 build_height_to_page (EvPageCache *page_cache)
128 gboolean swap, uniform, dual_even_left;
130 double uniform_height, page_height, next_page_height;
132 gdouble u_width, u_height;
135 swap = (page_cache->rotation == 90 ||
136 page_cache->rotation == 270);
138 uniform = ev_document_is_page_size_uniform (page_cache->document);
139 n_pages = ev_document_get_n_pages (page_cache->document);
140 dual_even_left = (n_pages > 2);
142 g_free (page_cache->height_to_page);
143 g_free (page_cache->dual_height_to_page);
145 page_cache->height_to_page = g_new0 (double, n_pages + 1);
146 page_cache->dual_height_to_page = g_new0 (double, n_pages + 2);
149 ev_document_get_page_size (page_cache->document, 0, &u_width, &u_height);
152 for (i = 0; i <= n_pages; i++) {
154 uniform_height = swap ? u_width : u_height;
155 page_cache->height_to_page[i] = i * uniform_height;
160 ev_document_get_page_size (page_cache->document, i, &w, &h);
161 page_height = swap ? w : h;
165 page_cache->height_to_page[i] = saved_height;
166 saved_height += page_height;
170 if (dual_even_left && !uniform) {
173 ev_document_get_page_size (page_cache->document, 0, &w, &h);
174 saved_height = swap ? w : h;
179 for (i = dual_even_left; i < n_pages + 2; i += 2) {
181 uniform_height = swap ? u_width : u_height;
182 page_cache->dual_height_to_page[i] = ((i + dual_even_left) / 2) * uniform_height;
183 if (i + 1 < n_pages + 2)
184 page_cache->dual_height_to_page[i + 1] = ((i + dual_even_left) / 2) * uniform_height;
186 if (i + 1 < n_pages) {
189 ev_document_get_page_size (page_cache->document, i + 1, &w, &h);
190 next_page_height = swap ? w : h;
192 next_page_height = 0;
198 ev_document_get_page_size (page_cache->document, i, &w, &h);
199 page_height = swap ? w : h;
204 if (i + 1 < n_pages + 2) {
205 page_cache->dual_height_to_page[i] = saved_height;
206 page_cache->dual_height_to_page[i + 1] = saved_height;
207 saved_height += MAX(page_height, next_page_height);
209 page_cache->dual_height_to_page[i] = saved_height;
216 ev_page_cache_new (EvDocument *document)
218 EvPageCache *page_cache;
219 EvPageThumbsInfo *thumb_info;
220 EvRenderContext *rc = NULL;
223 page_cache = (EvPageCache *) g_object_new (EV_TYPE_PAGE_CACHE, NULL);
224 page_cache->document = document;
226 n_pages = ev_document_get_n_pages (document);
228 build_height_to_page (page_cache);
230 if (!EV_IS_DOCUMENT_THUMBNAILS (document)) {
232 ev_page_cache_set_current_page (page_cache, 0);
236 /* Assume all pages are the same size until proven otherwise */
237 page_cache->thumbs_uniform = TRUE;
239 for (i = 0; i < n_pages; i++) {
241 gdouble page_width, page_height;
242 gint thumb_width = 0;
243 gint thumb_height = 0;
245 page = ev_document_get_page (document, i);
247 ev_document_get_page_size (document, i, &page_width, &page_height);
250 rc = ev_render_context_new (page, 0, (gdouble)THUMBNAIL_WIDTH / page_width);
252 ev_render_context_set_page (rc, page);
253 ev_render_context_set_scale (rc, (gdouble)THUMBNAIL_WIDTH / page_width);
256 ev_document_thumbnails_get_dimensions (EV_DOCUMENT_THUMBNAILS (document),
257 rc, &thumb_width, &thumb_height);
259 if (thumb_width > page_cache->thumbs_max_width) {
260 page_cache->thumbs_max_width = thumb_width;
263 if (thumb_height > page_cache->thumbs_max_height) {
264 page_cache->thumbs_max_height = thumb_height;
268 page_cache->thumbs_uniform_width = thumb_width;
269 page_cache->thumbs_uniform_height = thumb_height;
270 } else if (page_cache->thumbs_uniform &&
271 (page_cache->thumbs_uniform_width != thumb_width ||
272 page_cache->thumbs_uniform_height != thumb_height)) {
273 /* It's a different thumbnail size. Backfill the array. */
276 page_cache->thumbs_size_cache = g_new0 (EvPageThumbsInfo, n_pages);
278 for (j = 0; j < i; j++) {
279 thumb_info = &(page_cache->thumbs_size_cache[j]);
280 thumb_info->width = page_cache->thumbs_uniform_width;
281 thumb_info->height = page_cache->thumbs_uniform_height;
283 page_cache->thumbs_uniform = FALSE;
286 if (! page_cache->thumbs_uniform) {
287 thumb_info = &(page_cache->thumbs_size_cache[i]);
289 thumb_info->width = thumb_width;
290 thumb_info->height = thumb_height;
293 g_object_unref (page);
301 ev_page_cache_set_current_page (page_cache, 0);
307 ev_page_cache_check_dimensions (EvPageCache *page_cache)
309 gdouble document_width, document_height;
311 ev_document_get_max_page_size (page_cache->document,
312 &document_width, &document_height);
314 return (document_width > 0 && document_height > 0);
318 ev_page_cache_get_current_page (EvPageCache *page_cache)
320 g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
322 return page_cache->current_page;
326 ev_page_cache_set_current_page (EvPageCache *page_cache,
329 g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
331 if (page == page_cache->current_page)
334 page_cache->current_page = page;
335 g_signal_emit (page_cache, signals[PAGE_CHANGED], 0, page);
339 ev_page_cache_set_current_page_history (EvPageCache *page_cache,
342 if (abs (page - page_cache->current_page) > 1)
343 g_signal_emit (page_cache, signals [HISTORY_CHANGED], 0, page);
345 ev_page_cache_set_current_page (page_cache, page);
349 ev_page_cache_set_page_label (EvPageCache *page_cache,
350 const gchar *page_label)
354 g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
356 if (ev_document_find_page_by_label (page_cache->document, page_label, &page)) {
357 ev_page_cache_set_current_page (page_cache, page);
365 ev_page_cache_get_size (EvPageCache *page_cache,
374 g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
376 ev_document_get_page_size (page_cache->document, page, &w, &h);
381 if (rotation == 0 || rotation == 180) {
382 if (width) *width = (int)w;
383 if (height) *height = (int)h;
385 if (width) *width = (int)h;
386 if (height) *height = (int)w;
391 ev_page_cache_get_max_width (EvPageCache *page_cache,
398 g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
403 ev_document_get_max_page_size (page_cache->document, &w, &h);
404 *width = (rotation == 0 || rotation == 180) ? w * scale : h * scale;
408 ev_page_cache_get_max_height (EvPageCache *page_cache,
415 g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
420 ev_document_get_max_page_size (page_cache->document, &w, &h);
421 *height = (rotation == 0 || rotation == 180) ? h * scale : w * scale;
425 ev_page_cache_get_height_to_page (EvPageCache *page_cache,
432 g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
433 g_return_if_fail (page >= 0);
435 if (page_cache->rotation != rotation) {
436 page_cache->rotation = rotation;
437 build_height_to_page (page_cache);
441 *height = page_cache->height_to_page[page] * scale;
444 *dual_height = page_cache->dual_height_to_page[page] * scale;
448 ev_page_cache_get_thumbnail_size (EvPageCache *page_cache,
456 g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
458 if (page_cache->thumbs_uniform) {
459 w = page_cache->thumbs_uniform_width;
460 h = page_cache->thumbs_uniform_height;
462 EvPageThumbsInfo *info;
464 info = &(page_cache->thumbs_size_cache [page]);
470 if (rotation == 0 || rotation == 180) {
471 if (width) *width = w;
472 if (height) *height = h;
474 if (width) *width = h;
475 if (height) *height = w;
480 ev_page_cache_get_dual_even_left (EvPageCache *page_cache)
482 g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
484 return (ev_document_get_n_pages (page_cache->document) > 2);
487 #define PAGE_CACHE_STRING "ev-page-cache"
490 ev_page_cache_get (EvDocument *document)
492 EvPageCache *page_cache;
494 g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
496 page_cache = g_object_get_data (G_OBJECT (document), PAGE_CACHE_STRING);
497 if (page_cache == NULL) {
498 page_cache = ev_page_cache_new (document);
499 g_object_set_data_full (G_OBJECT (document), PAGE_CACHE_STRING, page_cache, g_object_unref);