]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/xps/xps-zip.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / xps / xps-zip.c
1 #include "mupdf/xps.h"
2
3 static void xps_init_document(xps_document *doc);
4
5 xps_part *
6 xps_new_part(xps_document *doc, char *name, unsigned char *data, int size)
7 {
8         xps_part *part;
9
10         part = fz_malloc_struct(doc->ctx, xps_part);
11         fz_try(doc->ctx)
12         {
13                 part->name = fz_strdup(doc->ctx, name);
14                 part->data = data;
15                 part->size = size;
16         }
17         fz_catch(doc->ctx)
18         {
19                 fz_free(doc->ctx, part->name);
20                 fz_free(doc->ctx, part->data);
21                 fz_free(doc->ctx, part);
22                 fz_rethrow(doc->ctx);
23         }
24
25         return part;
26 }
27
28 void
29 xps_free_part(xps_document *doc, xps_part *part)
30 {
31         fz_free(doc->ctx, part->name);
32         fz_free(doc->ctx, part->data);
33         fz_free(doc->ctx, part);
34 }
35
36 /*
37  * Read and interleave split parts from a ZIP file.
38  */
39 xps_part *
40 xps_read_part(xps_document *doc, char *partname)
41 {
42         fz_context *ctx = doc->ctx;
43         fz_archive *zip = doc->zip;
44         fz_buffer *buf, *tmp;
45         char path[2048];
46         unsigned char *data;
47         int size;
48         int count;
49         char *name;
50         int seen_last;
51
52         name = partname;
53         if (name[0] == '/')
54                 name ++;
55
56         /* All in one piece */
57         if (fz_has_archive_entry(ctx, zip, name))
58         {
59                 buf = fz_read_archive_entry(ctx, zip, name);
60         }
61
62         /* Assemble all the pieces */
63         else
64         {
65                 buf = fz_new_buffer(ctx, 512);
66                 seen_last = 0;
67                 for (count = 0; !seen_last; ++count)
68                 {
69                         sprintf(path, "%s/[%d].piece", name, count);
70                         if (fz_has_archive_entry(ctx, zip, path))
71                         {
72                                 tmp = fz_read_archive_entry(ctx, zip, path);
73                                 fz_buffer_cat(ctx, buf, tmp);
74                                 fz_drop_buffer(ctx, tmp);
75                         }
76                         else
77                         {
78                                 sprintf(path, "%s/[%d].last.piece", name, count);
79                                 if (fz_has_archive_entry(ctx, zip, path))
80                                 {
81                                         tmp = fz_read_archive_entry(ctx, zip, path);
82                                         fz_buffer_cat(ctx, buf, tmp);
83                                         fz_drop_buffer(ctx, tmp);
84                                         seen_last = 1;
85                                 }
86                                 else
87                                 {
88                                         fz_drop_buffer(ctx, buf);
89                                         fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find all pieces for part '%s'", partname);
90                                 }
91                         }
92                 }
93         }
94
95         fz_write_buffer_byte(ctx, buf, 0); /* zero-terminate */
96
97         /* take over the data */
98         data = buf->data;
99         /* size doesn't include the added zero-terminator */
100         size = buf->len - 1;
101         fz_free(ctx, buf);
102
103         return xps_new_part(doc, partname, data, size);
104 }
105
106 int
107 xps_has_part(xps_document *doc, char *name)
108 {
109         char buf[2048];
110         if (name[0] == '/')
111                 name++;
112         if (fz_has_archive_entry(doc->ctx, doc->zip, name))
113                 return 1;
114         sprintf(buf, "%s/[0].piece", name);
115         if (fz_has_archive_entry(doc->ctx, doc->zip, buf))
116                 return 1;
117         sprintf(buf, "%s/[0].last.piece", name);
118         if (fz_has_archive_entry(doc->ctx, doc->zip, buf))
119                 return 1;
120         return 0;
121 }
122
123 static xps_document *
124 xps_open_document_with_directory(fz_context *ctx, const char *directory)
125 {
126         xps_document *doc;
127
128         doc = fz_malloc_struct(ctx, xps_document);
129         xps_init_document(doc);
130         doc->ctx = ctx;
131         doc->zip = fz_open_directory(ctx, directory);
132
133         fz_try(ctx)
134         {
135                 xps_read_page_list(doc);
136         }
137         fz_catch(ctx)
138         {
139                 xps_close_document(doc);
140                 fz_rethrow(ctx);
141         }
142
143         return doc;
144 }
145
146 xps_document *
147 xps_open_document_with_stream(fz_context *ctx, fz_stream *file)
148 {
149         xps_document *doc;
150
151         doc = fz_malloc_struct(ctx, xps_document);
152         xps_init_document(doc);
153         doc->ctx = ctx;
154
155         fz_try(ctx)
156         {
157                 doc->zip = fz_open_archive_with_stream(ctx, file);
158                 xps_read_page_list(doc);
159         }
160         fz_catch(ctx)
161         {
162                 xps_close_document(doc);
163                 fz_rethrow(ctx);
164         }
165
166         return doc;
167 }
168
169 xps_document *
170 xps_open_document(fz_context *ctx, const char *filename)
171 {
172         char buf[2048];
173         fz_stream *file;
174         char *p;
175         xps_document *doc;
176
177         if (strstr(filename, "/_rels/.rels") || strstr(filename, "\\_rels\\.rels"))
178         {
179                 fz_strlcpy(buf, filename, sizeof buf);
180                 p = strstr(buf, "/_rels/.rels");
181                 if (!p)
182                         p = strstr(buf, "\\_rels\\.rels");
183                 *p = 0;
184                 return xps_open_document_with_directory(ctx, buf);
185         }
186
187         file = fz_open_file(ctx, filename);
188         if (!file)
189                 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
190
191         fz_try(ctx)
192         {
193                 doc = xps_open_document_with_stream(ctx, file);
194         }
195         fz_always(ctx)
196         {
197                 fz_close(file);
198         }
199         fz_catch(ctx)
200         {
201                 fz_rethrow_message(ctx, "cannot load document '%s'", filename);
202         }
203         return doc;
204 }
205
206 void
207 xps_close_document(xps_document *doc)
208 {
209         xps_font_cache *font, *next;
210
211         if (!doc)
212                 return;
213
214         if (doc->zip)
215                 fz_close_archive(doc->ctx, doc->zip);
216
217         font = doc->font_table;
218         while (font)
219         {
220                 next = font->next;
221                 fz_drop_font(doc->ctx, font->font);
222                 fz_free(doc->ctx, font->name);
223                 fz_free(doc->ctx, font);
224                 font = next;
225         }
226
227         xps_free_page_list(doc);
228
229         fz_free(doc->ctx, doc->start_part);
230         fz_free(doc->ctx, doc);
231 }
232
233 static int
234 xps_meta(xps_document *doc, int key, void *ptr, int size)
235 {
236         switch (key)
237         {
238         case FZ_META_FORMAT_INFO:
239                 sprintf((char *)ptr, "XPS");
240                 return FZ_META_OK;
241         default:
242                 return FZ_META_UNKNOWN_KEY;
243         }
244 }
245
246 static void
247 xps_rebind(xps_document *doc, fz_context *ctx)
248 {
249         doc->ctx = ctx;
250         fz_rebind_archive(doc->zip, ctx);
251         fz_rebind_device(doc->dev, ctx);
252 }
253
254 static void
255 xps_init_document(xps_document *doc)
256 {
257         doc->super.close = (fz_document_close_fn *)xps_close_document;
258         doc->super.load_outline = (fz_document_load_outline_fn *)xps_load_outline;
259         doc->super.count_pages = (fz_document_count_pages_fn *)xps_count_pages;
260         doc->super.load_page = (fz_document_load_page_fn *)xps_load_page;
261         doc->super.load_links = (fz_document_load_links_fn *)xps_load_links;
262         doc->super.bound_page = (fz_document_bound_page_fn *)xps_bound_page;
263         doc->super.run_page_contents = (fz_document_run_page_contents_fn *)xps_run_page;
264         doc->super.free_page = (fz_document_free_page_fn *)xps_free_page;
265         doc->super.meta = (fz_document_meta_fn *)xps_meta;
266         doc->super.rebind = (fz_document_rebind_fn *)xps_rebind;
267 }