comparison mupdf-source/source/reflow/reflow-doc.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 // Copyright (C) 2004-2021 Artifex Software, Inc.
2 //
3 // This file is part of MuPDF.
4 //
5 // MuPDF is free software: you can redistribute it and/or modify it under the
6 // terms of the GNU Affero General Public License as published by the Free
7 // Software Foundation, either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17 //
18 // Alternative licensing terms are available from the licensor.
19 // For commercial licensing, see <https://www.artifex.com/> or contact
20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21 // CA 94129, USA, for further information.
22
23 #include "mupdf/fitz.h"
24
25 #if FZ_ENABLE_HTML_ENGINE
26
27 #include <assert.h>
28 #include <limits.h>
29 #include <string.h>
30
31 #define DEF_WIDTH 612
32 #define DEF_HEIGHT 792
33 #define DEF_FONTSIZE 12
34
35 typedef struct
36 {
37 fz_document base;
38
39 fz_document *underdoc;
40 fz_stext_options opts;
41 float w;
42 float h;
43 float em;
44 } reflow_document;
45
46 typedef struct {
47 fz_page base;
48
49 fz_document *html_doc;
50 fz_page *html_page;
51 } reflow_page;
52
53 static void
54 reflow_drop_document_imp(fz_context *ctx, fz_document *doc_)
55 {
56 reflow_document *doc = (reflow_document*)doc_;
57 fz_defer_reap_start(ctx);
58
59 fz_drop_document(ctx, doc->underdoc);
60 fz_defer_reap_end(ctx);
61 }
62
63 static fz_colorspace *
64 reflow_document_output_intent(fz_context *ctx, fz_document *doc_)
65 {
66 reflow_document *doc = (reflow_document*)doc_;
67 return fz_document_output_intent(ctx, doc->underdoc);
68 }
69
70 static int
71 reflow_needs_password(fz_context *ctx, fz_document *doc_)
72 {
73 reflow_document *doc = (reflow_document*)doc_;
74 return fz_needs_password(ctx, doc->underdoc);
75 }
76
77 static int
78 reflow_authenticate_password(fz_context *ctx, fz_document *doc_, const char *password)
79 {
80 reflow_document *doc = (reflow_document*)doc_;
81 return fz_authenticate_password(ctx, doc->underdoc, password);
82 }
83
84 static int
85 reflow_has_permission(fz_context *ctx, fz_document *doc_, fz_permission permission)
86 {
87 reflow_document *doc = (reflow_document*)doc_;
88 return fz_has_permission(ctx, doc->underdoc, permission);
89 }
90
91 /* FIXME: Need to translate page targets somehow. */
92 static fz_outline *
93 reflow_load_outline(fz_context *ctx, fz_document *doc_)
94 {
95 reflow_document *doc = (reflow_document*)doc_;
96 return fz_load_outline(ctx, doc->underdoc);
97 }
98
99 /* FIXME: Need to translate page targets somehow. */
100 static fz_outline_iterator *
101 reflow_outline_iterator(fz_context *ctx, fz_document *doc_)
102 {
103 reflow_document *doc = (reflow_document*)doc_;
104 return fz_new_outline_iterator(ctx, doc->underdoc);
105 }
106
107 static fz_link_dest
108 reflow_resolve_link_dest(fz_context *ctx, fz_document *doc_, const char *uri)
109 {
110 reflow_document *doc = (reflow_document*)doc_;
111 return fz_resolve_link_dest(ctx, doc->underdoc, uri);
112 }
113
114 static int
115 reflow_count_pages(fz_context *ctx, fz_document *doc_, int chapter)
116 {
117 reflow_document *doc = (reflow_document*)doc_;
118 return fz_count_chapter_pages(ctx, doc->underdoc, chapter);
119 }
120
121 static fz_rect
122 reflow_bound_page(fz_context *ctx, fz_page *page_, fz_box_type box)
123 {
124 reflow_page *page = (reflow_page *)page_;
125
126 return fz_bound_page(ctx, page->html_page);
127 }
128
129 static void
130 reflow_drop_page(fz_context *ctx, fz_page *page_)
131 {
132 reflow_page *page = (reflow_page *)page_;
133
134 fz_drop_page(ctx, page->html_page);
135 fz_drop_document(ctx, page->html_doc);
136 }
137
138 static void
139 reflow_run_page_contents(fz_context *ctx, fz_page *page_, fz_device *dev, fz_matrix transform, fz_cookie *cookie)
140 {
141 reflow_page *page = (reflow_page *)page_;
142
143 fz_run_page_contents(ctx, page->html_page, dev, transform, cookie);
144 }
145
146 static void
147 reflow_run_page_annots(fz_context *ctx, fz_page *page_, fz_device *dev, fz_matrix transform, fz_cookie *cookie)
148 {
149 reflow_page *page = (reflow_page *)page_;
150
151 fz_run_page_annots(ctx, page->html_page, dev, transform, cookie);
152 }
153
154 static void
155 reflow_run_page_widgets(fz_context *ctx, fz_page *page_, fz_device *dev, fz_matrix transform, fz_cookie *cookie)
156 {
157 reflow_page *page = (reflow_page *)page_;
158
159 fz_run_page_widgets(ctx, page->html_page, dev, transform, cookie);
160 }
161
162 static fz_page *
163 reflow_load_page(fz_context *ctx, fz_document *doc_, int chapter, int pagenum)
164 {
165 reflow_document *doc = (reflow_document*)doc_;
166 fz_buffer *buf = NULL;
167 fz_stext_page *text = NULL;
168 fz_stext_options default_opts = { FZ_STEXT_PRESERVE_IMAGES | FZ_STEXT_DEHYPHENATE };
169 reflow_page *page = NULL;
170 fz_stream *stm = NULL;
171 fz_output *out = NULL;
172
173 page = fz_new_derived_page(ctx, reflow_page, doc_);
174 page->base.bound_page = reflow_bound_page;
175 page->base.drop_page = reflow_drop_page;
176 page->base.run_page_contents = reflow_run_page_contents;
177 page->base.run_page_annots = reflow_run_page_annots;
178 page->base.run_page_widgets = reflow_run_page_widgets;
179
180 fz_var(buf);
181 fz_var(out);
182 fz_var(text);
183 fz_var(stm);
184
185 fz_try(ctx)
186 {
187 buf = fz_new_buffer(ctx, 8192);
188 out = fz_new_output_with_buffer(ctx, buf);
189 fz_print_stext_header_as_xhtml(ctx, out);
190
191 text = fz_new_stext_page_from_chapter_page_number(ctx, doc->underdoc, chapter, pagenum, &default_opts);
192 fz_print_stext_page_as_xhtml(ctx, out, text, pagenum+1); /* pagenum is not right w.r.t chapter. */
193 fz_drop_stext_page(ctx, text);
194 text = NULL;
195
196 fz_print_stext_trailer_as_xhtml(ctx, out);
197 fz_close_output(ctx, out);
198 fz_terminate_buffer(ctx, buf);
199
200 stm = fz_open_buffer(ctx, buf);
201 page->html_doc = fz_open_document_with_stream(ctx, "application/xhtml+xml", stm);
202 fz_layout_document(ctx, page->html_doc, doc->w, 0, doc->em);
203 page->html_page = fz_load_chapter_page(ctx, page->html_doc, 0, 0);
204 }
205 fz_always(ctx)
206 {
207 fz_drop_stext_page(ctx, text);
208 fz_drop_output(ctx, out);
209 fz_drop_stream(ctx, stm);
210 fz_drop_buffer(ctx, buf);
211 }
212 fz_catch(ctx)
213 {
214 fz_drop_page(ctx, &page->base);
215 fz_rethrow(ctx);
216 }
217
218 return &page->base;
219 }
220
221 static int reflow_lookup_metadata(fz_context *ctx, fz_document *doc_, const char *key, char *buf, size_t size)
222 {
223 reflow_document *doc = (reflow_document*)doc_;
224 return fz_lookup_metadata(ctx, doc->underdoc, key, buf, size);
225 }
226
227 static void *reflow_layout_page(fz_context *ctx, fz_page *page_, void *state)
228 {
229 reflow_page *page = (reflow_page *) page_;
230 reflow_document *doc = (reflow_document *) page->base.doc;
231 fz_layout_document(ctx, page->html_doc, doc->w, 0, doc->em);
232 return NULL;
233 }
234
235 static void reflow_layout(fz_context *ctx, fz_document *doc_, float w, float h, float em)
236 {
237 reflow_document *doc = (reflow_document*)doc_;
238 if (doc->w == w && doc->h == h && doc->em == em)
239 return;
240 doc->w = w;
241 doc->h = h;
242 doc->em = em;
243
244 (void) fz_process_opened_pages(ctx, (fz_document *) doc, reflow_layout_page, NULL);
245 }
246
247 fz_document *
248 fz_open_reflowed_document(fz_context *ctx, fz_document *underdoc, const fz_stext_options *opts)
249 {
250 reflow_document *doc = fz_new_derived_document(ctx, reflow_document);
251
252 doc->base.drop_document = reflow_drop_document_imp;
253 doc->base.get_output_intent = reflow_document_output_intent;
254 doc->base.needs_password = reflow_needs_password;
255 doc->base.authenticate_password = reflow_authenticate_password;
256 doc->base.has_permission = reflow_has_permission;
257 doc->base.load_outline = reflow_load_outline;
258 doc->base.outline_iterator = reflow_outline_iterator;
259 doc->base.resolve_link_dest = reflow_resolve_link_dest;
260 doc->base.count_pages = reflow_count_pages;
261 doc->base.load_page = reflow_load_page;
262 doc->base.lookup_metadata = reflow_lookup_metadata;
263 doc->base.layout = reflow_layout;
264
265 doc->underdoc = fz_keep_document(ctx, underdoc);
266 doc->opts = *opts;
267
268 doc->w = DEF_WIDTH;
269 doc->h = DEF_HEIGHT;
270 doc->em = DEF_FONTSIZE;
271
272 return &doc->base;
273 }
274
275 #else
276
277 fz_document *
278 fz_open_reflowed_document(fz_context *ctx, fz_document *underdoc, const fz_stext_options *opts)
279 {
280 fz_throw(ctx, FZ_ERROR_UNSUPPORTED, "reflowed documents require html engine");
281 }
282
283 #endif