]> www.fi.muni.cz Git - evince.git/blob - libview/ev-page-cache.c
Move ev_page_cache_check_dimensions() to EvDocument
[evince.git] / libview / ev-page-cache.c
1 #include <config.h>
2 #include "ev-page-cache.h"
3 #include "ev-document-thumbnails.h"
4 #include "ev-page.h"
5 #include <stdlib.h>
6 #include <string.h>
7
8 struct _EvPageCache
9 {
10         GObject parent;
11
12         EvDocument *document;
13
14         gint current_page;
15
16         gboolean dual_even_left;
17
18         double* height_to_page;
19         double* dual_height_to_page;
20
21         int rotation;
22 };
23
24 struct _EvPageCacheClass
25 {
26         GObjectClass parent_class;
27
28         void (* page_changed) (EvPageCache *page_cache, gint page);
29         void (* history_changed) (EvPageCache *page_cache, gint page);
30 };
31
32 enum
33 {
34         PAGE_CHANGED,
35         HISTORY_CHANGED,
36         N_SIGNALS,
37 };
38
39 static guint signals[N_SIGNALS] = {0, };
40
41 static void ev_page_cache_init       (EvPageCache      *page_cache);
42 static void ev_page_cache_class_init (EvPageCacheClass *page_cache);
43 static void ev_page_cache_finalize   (GObject *object);
44
45 G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
46
47 static void
48 ev_page_cache_init (EvPageCache *page_cache)
49 {
50         page_cache->current_page = -1;
51 }
52
53 static void
54 ev_page_cache_class_init (EvPageCacheClass *class)
55 {
56         GObjectClass *object_class;
57
58         object_class = G_OBJECT_CLASS (class);
59
60         object_class->finalize = ev_page_cache_finalize;
61
62         signals [PAGE_CHANGED] =
63                 g_signal_new ("page-changed",
64                               EV_TYPE_PAGE_CACHE,
65                               G_SIGNAL_RUN_LAST,
66                               G_STRUCT_OFFSET (EvPageCacheClass, page_changed),
67                               NULL, NULL,
68                               g_cclosure_marshal_VOID__INT,
69                               G_TYPE_NONE, 1,
70                               G_TYPE_INT);
71
72         signals [HISTORY_CHANGED] =
73                 g_signal_new ("history-changed",
74                               EV_TYPE_PAGE_CACHE,
75                               G_SIGNAL_RUN_LAST,
76                               G_STRUCT_OFFSET (EvPageCacheClass, history_changed),
77                               NULL, NULL,
78                               g_cclosure_marshal_VOID__INT,
79                               G_TYPE_NONE, 1,
80                               G_TYPE_INT);
81
82 }
83
84 static void
85 ev_page_cache_finalize (GObject *object)
86 {
87         EvPageCache *page_cache = EV_PAGE_CACHE (object);
88
89         page_cache->document = NULL;
90
91         if (page_cache->height_to_page) {
92                 g_free (page_cache->height_to_page);
93                 page_cache->height_to_page = NULL;
94         }
95
96         if (page_cache->dual_height_to_page) {
97                 g_free (page_cache->dual_height_to_page);
98                 page_cache->dual_height_to_page = NULL;
99         }
100
101         G_OBJECT_CLASS (ev_page_cache_parent_class)->finalize (object);
102 }
103
104 static void
105 build_height_to_page (EvPageCache *page_cache)
106 {
107         gboolean swap, uniform, dual_even_left;
108         int i;
109         double uniform_height, page_height, next_page_height;
110         double saved_height;
111         gdouble u_width, u_height;
112         gint n_pages;
113
114         swap = (page_cache->rotation == 90 ||
115                 page_cache->rotation == 270);
116
117         uniform = ev_document_is_page_size_uniform (page_cache->document);
118         n_pages = ev_document_get_n_pages (page_cache->document);
119         dual_even_left = (n_pages > 2);
120
121         g_free (page_cache->height_to_page);
122         g_free (page_cache->dual_height_to_page);
123
124         page_cache->height_to_page = g_new0 (double, n_pages + 1);
125         page_cache->dual_height_to_page = g_new0 (double, n_pages + 2);
126
127         if (uniform)
128                 ev_document_get_page_size (page_cache->document, 0, &u_width, &u_height);
129
130         saved_height = 0;
131         for (i = 0; i <= n_pages; i++) {
132                 if (uniform) {
133                         uniform_height = swap ? u_width : u_height;
134                         page_cache->height_to_page[i] = i * uniform_height;
135                 } else {
136                         if (i < n_pages) {
137                                 gdouble w, h;
138
139                                 ev_document_get_page_size (page_cache->document, i, &w, &h);
140                                 page_height = swap ? w : h;
141                         } else {
142                                 page_height = 0;
143                         }
144                         page_cache->height_to_page[i] = saved_height;
145                         saved_height += page_height;
146                 }
147         }
148
149         if (dual_even_left && !uniform) {
150                 gdouble w, h;
151
152                 ev_document_get_page_size (page_cache->document, 0, &w, &h);
153                 saved_height = swap ? w : h;
154         } else {
155                 saved_height = 0;
156         }
157
158         for (i = dual_even_left; i < n_pages + 2; i += 2) {
159                 if (uniform) {
160                         uniform_height = swap ? u_width : u_height;
161                         page_cache->dual_height_to_page[i] = ((i + dual_even_left) / 2) * uniform_height;
162                         if (i + 1 < n_pages + 2)
163                                 page_cache->dual_height_to_page[i + 1] = ((i + dual_even_left) / 2) * uniform_height;
164                 } else {
165                         if (i + 1 < n_pages) {
166                                 gdouble w, h;
167
168                                 ev_document_get_page_size (page_cache->document, i + 1, &w, &h);
169                                 next_page_height = swap ? w : h;
170                         } else {
171                                 next_page_height = 0;
172                         }
173
174                         if (i < n_pages) {
175                                 gdouble w, h;
176
177                                 ev_document_get_page_size (page_cache->document, i, &w, &h);
178                                 page_height = swap ? w : h;
179                         } else {
180                                 page_height = 0;
181                         }
182
183                         if (i + 1 < n_pages + 2) {
184                                 page_cache->dual_height_to_page[i] = saved_height;
185                                 page_cache->dual_height_to_page[i + 1] = saved_height;
186                                 saved_height += MAX(page_height, next_page_height);
187                         } else {
188                                 page_cache->dual_height_to_page[i] = saved_height;
189                         }
190                 }
191         }
192 }
193
194 static EvPageCache *
195 ev_page_cache_new (EvDocument *document)
196 {
197         EvPageCache *page_cache;
198
199         page_cache = (EvPageCache *) g_object_new (EV_TYPE_PAGE_CACHE, NULL);
200         page_cache->document = document;
201
202         build_height_to_page (page_cache);
203
204         if (ev_document_get_n_pages (page_cache->document) > 0)
205                 ev_page_cache_set_current_page (page_cache, 0);
206
207         return page_cache;
208 }
209
210 gint
211 ev_page_cache_get_current_page (EvPageCache *page_cache)
212 {
213         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
214
215         return page_cache->current_page;
216 }
217
218 void
219 ev_page_cache_set_current_page (EvPageCache *page_cache,
220                                 int          page)
221 {
222         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
223
224         if (page == page_cache->current_page)
225                 return;
226
227         page_cache->current_page = page;
228         g_signal_emit (page_cache, signals[PAGE_CHANGED], 0, page);
229 }
230
231 void
232 ev_page_cache_set_current_page_history (EvPageCache *page_cache,
233                                         int          page)
234 {
235         if (abs (page - page_cache->current_page) > 1)
236                 g_signal_emit (page_cache, signals [HISTORY_CHANGED], 0, page);
237         
238         ev_page_cache_set_current_page (page_cache, page);
239 }
240
241 gboolean
242 ev_page_cache_set_page_label (EvPageCache *page_cache,
243                               const gchar *page_label)
244 {
245         gint page;
246
247         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
248
249         if (ev_document_find_page_by_label (page_cache->document, page_label, &page)) {
250                 ev_page_cache_set_current_page (page_cache, page);
251                 return TRUE;
252         }
253
254         return FALSE;
255 }
256
257 void
258 ev_page_cache_get_size (EvPageCache  *page_cache,
259                         gint          page,
260                         gint          rotation,
261                         gfloat        scale,
262                         gint         *width,
263                         gint         *height)
264 {
265         double w, h;
266
267         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
268
269         ev_document_get_page_size (page_cache->document, page, &w, &h);
270
271         w = w * scale + 0.5;
272         h = h * scale + 0.5;
273
274         if (rotation == 0 || rotation == 180) {
275                 if (width) *width = (int)w;
276                 if (height) *height = (int)h;
277         } else {
278                 if (width) *width = (int)h;
279                 if (height) *height = (int)w;
280         }
281 }
282
283 void
284 ev_page_cache_get_max_width (EvPageCache   *page_cache,
285                              gint           rotation,
286                              gfloat         scale,
287                              gint          *width)
288 {
289         double w, h;
290
291         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
292
293         if (!width)
294                 return;
295
296         ev_document_get_max_page_size (page_cache->document, &w, &h);
297         *width = (rotation == 0 || rotation == 180) ? w * scale : h * scale;
298 }
299
300 void
301 ev_page_cache_get_max_height (EvPageCache   *page_cache,
302                               gint           rotation,
303                               gfloat         scale,
304                               gint          *height)
305 {
306         double w, h;
307
308         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
309
310         if (!height)
311                 return;
312
313         ev_document_get_max_page_size (page_cache->document, &w, &h);
314         *height = (rotation == 0 || rotation == 180) ? h * scale : w * scale;
315 }
316
317 void
318 ev_page_cache_get_height_to_page (EvPageCache   *page_cache,
319                                   gint           page,
320                                   gint           rotation,
321                                   gfloat         scale,
322                                   gint          *height,
323                                   gint          *dual_height)
324 {
325         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
326         g_return_if_fail (page >= 0);
327
328         if (page_cache->rotation != rotation) {
329                 page_cache->rotation = rotation;
330                 build_height_to_page (page_cache);
331         }
332
333         if (height)
334                 *height = page_cache->height_to_page[page] * scale;
335
336         if (dual_height)
337                 *dual_height = page_cache->dual_height_to_page[page] * scale;
338 }
339
340 gboolean
341 ev_page_cache_get_dual_even_left (EvPageCache *page_cache)
342 {
343         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
344
345         return (ev_document_get_n_pages (page_cache->document) > 2);
346 }
347
348 #define PAGE_CACHE_STRING "ev-page-cache"
349
350 EvPageCache *
351 ev_page_cache_get (EvDocument *document)
352 {
353         EvPageCache *page_cache;
354
355         g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
356
357         page_cache = g_object_get_data (G_OBJECT (document), PAGE_CACHE_STRING);
358         if (page_cache == NULL) {
359                 page_cache = ev_page_cache_new (document);
360                 g_object_set_data_full (G_OBJECT (document), PAGE_CACHE_STRING, page_cache, g_object_unref);
361         }
362
363         return page_cache;
364 }