]> www.fi.muni.cz Git - evince.git/blob - backend/ev-page-cache.c
Cr 31 13:27:50 2005 Jonathan Blandford <jrb@redhat.com>
[evince.git] / backend / ev-page-cache.c
1 #include "ev-page-cache.h"
2 #include "ev-job-queue.h"
3
4 typedef struct _EvPageCacheInfo
5 {
6         gint width;
7         gint height;
8 }
9 EvPageCacheInfo;
10
11
12 struct _EvPageCache
13 {
14         GObject parent;
15
16         gint current_page;
17         int n_pages;
18         char *title;
19         char **page_labels;
20
21         gboolean uniform;
22         gint uniform_width;
23         gint uniform_height;
24
25         EvPageCacheInfo *size_cache;
26 };
27
28 struct _EvPageCacheClass
29 {
30         GObjectClass parent_class;
31
32         void (* page_changed) (EvPageCache *page_cache, gint page);
33 };
34
35 enum
36 {
37         PAGE_CHANGED,
38         N_SIGNALS,
39 };
40
41 static guint signals[N_SIGNALS] = {0, };
42
43 static void ev_page_cache_init       (EvPageCache      *page_cache);
44 static void ev_page_cache_class_init (EvPageCacheClass *page_cache);
45 static void ev_page_cache_finalize   (GObject *object);
46
47 G_DEFINE_TYPE (EvPageCache, ev_page_cache, G_TYPE_OBJECT)
48
49 static void
50 ev_page_cache_init (EvPageCache *page_cache)
51 {
52         page_cache->current_page = 0;
53 }
54
55 static void
56 ev_page_cache_class_init (EvPageCacheClass *class)
57 {
58         GObjectClass *object_class;
59
60         object_class = G_OBJECT_CLASS (class);
61
62         object_class->finalize = ev_page_cache_finalize;
63
64         signals [PAGE_CHANGED] =
65                 g_signal_new ("page-changed",
66                               EV_TYPE_PAGE_CACHE,
67                               G_SIGNAL_RUN_LAST,
68                               G_STRUCT_OFFSET (EvPageCacheClass, page_changed),
69                               NULL, NULL,
70                               g_cclosure_marshal_VOID__INT,
71                               G_TYPE_NONE, 1,
72                               G_TYPE_INT);
73
74 }
75
76 static void
77 ev_page_cache_finalize (GObject *object)
78 {
79         EvPageCache *page_cache;
80
81         page_cache = EV_PAGE_CACHE (object);
82
83         g_free (page_cache->title);
84         g_free (page_cache->size_cache);
85 }
86
87 EvPageCache *
88 _ev_page_cache_new (EvDocument *document)
89 {
90         EvPageCache *page_cache;
91         EvPageCacheInfo *info;
92         gint i;
93
94         page_cache = (EvPageCache *) g_object_new (EV_TYPE_PAGE_CACHE, NULL);
95
96         g_mutex_lock (EV_DOC_MUTEX);
97
98         /* We read page information out of the document */
99
100         /* Assume all pages are the same size until proven otherwise */
101         page_cache->uniform = TRUE;
102         page_cache->n_pages = ev_document_get_n_pages (document);
103         page_cache->title = ev_document_get_title (document);
104         page_cache->page_labels = g_new0 (char *, page_cache->n_pages);
105
106         ev_document_set_scale (document, 1.0);
107         for (i = 0; i < page_cache->n_pages; i++) {
108                 gint page_width = 0;
109                 gint page_height = 0;
110
111                 ev_document_get_page_size (document, i, &page_width, &page_height);
112                 page_cache->page_labels[i] = ev_document_get_page_label (document, i);
113
114                 if (i == 0) {
115                         page_cache->uniform_width = page_width;
116                         page_cache->uniform_height = page_height;
117                 } else if (page_cache->uniform &&
118                            (page_cache->uniform_width != page_width ||
119                             page_cache->uniform_height != page_height)) {
120                         /* It's a different page size.  Backfill the array. */
121                         int j;
122
123                         page_cache->size_cache = g_new0 (EvPageCacheInfo, page_cache->n_pages);
124
125                         for (j = 1; j < i; j++) {
126                                 info = &(page_cache->size_cache [j - 1]);
127                                 info->width = page_width;
128                                 info->height = page_height;
129                         }
130                         page_cache->uniform = FALSE;
131
132                 }
133
134                 if (! page_cache->uniform) {
135                         info = &(page_cache->size_cache [i - 1]);
136
137                         info->width = page_width;
138                         info->height = page_height;
139                 }
140         }
141
142         /* make some sanity check assertions */
143         g_assert (page_cache->n_pages > 0);
144         if (! page_cache->uniform)
145                 g_assert (page_cache->size_cache != NULL);
146         if (page_cache->uniform)
147                 g_assert (page_cache->uniform_width > 0 && page_cache->uniform_height > 0);
148
149         g_mutex_unlock (EV_DOC_MUTEX);
150
151         return page_cache;
152 }
153
154 gint
155 ev_page_cache_get_n_pages (EvPageCache *page_cache)
156 {
157         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
158
159         return page_cache->n_pages;
160 }
161
162 gint
163 ev_page_cache_get_current_page (EvPageCache *page_cache)
164 {
165         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), 0);
166
167         return page_cache->current_page;
168 }
169
170 void
171 ev_page_cache_set_current_page (EvPageCache *page_cache,
172                                 int          page)
173 {
174         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
175         g_return_if_fail (page >= 0 || page < page_cache->n_pages);
176
177         if (page == page_cache->current_page)
178                 return;
179
180         page_cache->current_page = page;
181         g_signal_emit (page_cache, signals[PAGE_CHANGED], 0, page);
182 }
183
184 void
185 ev_page_cache_set_link (EvPageCache *page_cache,
186                         EvLink      *link)
187 {
188         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
189         g_return_if_fail (EV_IS_LINK (link));
190
191         ev_page_cache_set_current_page (page_cache, ev_link_get_page (link));
192 }
193
194 char *
195 ev_page_cache_get_title (EvPageCache *page_cache)
196 {
197         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), NULL);
198
199         return page_cache->title;
200 }
201
202 void
203 ev_page_cache_get_size (EvPageCache *page_cache,
204                         gint         page,
205                         gfloat       scale,
206                         gint        *width,
207                         gint        *height)
208 {
209         g_return_if_fail (EV_IS_PAGE_CACHE (page_cache));
210         g_return_if_fail (page >= 0 && page < page_cache->n_pages);
211
212         if (page_cache->uniform) {
213                 if (width)
214                         *width = page_cache->uniform_width;
215                 if (height)
216                         *height = page_cache->uniform_height;
217         } else {
218                 EvPageCacheInfo *info;
219
220                 info = &(page_cache->size_cache [page]);
221                 
222                 if (width)
223                         *width = info->width;
224                 if (height)
225                         *height = info->height;
226         }
227
228         if (width)
229                 *width = (*width) * scale;
230         if (width)
231                 *height = (*height) * scale;
232
233 }
234 gchar *
235 ev_page_cache_get_page_label (EvPageCache *page_cache,
236                               gint         page)
237 {
238         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), NULL);
239         g_return_val_if_fail (page >= 0 && page < page_cache->n_pages, NULL);
240
241         if (page_cache->page_labels[page] == NULL)
242                 return g_strdup_printf ("%d", page + 1);
243
244         return g_strdup (page_cache->page_labels[page]);
245 }
246
247
248 gboolean
249 ev_page_cache_next_page (EvPageCache *page_cache)
250 {
251         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
252
253         if (page_cache->current_page > page_cache->n_pages)
254                 return FALSE;
255
256         ev_page_cache_set_current_page (page_cache, page_cache->current_page + 1);
257         return TRUE;
258
259 }
260
261 gboolean
262 ev_page_cache_prev_page (EvPageCache *page_cache)
263 {
264         g_return_val_if_fail (EV_IS_PAGE_CACHE (page_cache), FALSE);
265
266         if (page_cache->current_page <= 0)
267                 return FALSE;
268
269         ev_page_cache_set_current_page (page_cache, page_cache->current_page - 1);
270         return TRUE;
271 }
272