/src/mupdf/source/fitz/context.c
Line | Count | Source (jump to first uncovered line) |
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 | | #include "context-imp.h" |
26 | | |
27 | | #include <assert.h> |
28 | | #include <string.h> |
29 | | #include <stdio.h> |
30 | | #include <time.h> |
31 | | |
32 | | struct fz_style_context |
33 | | { |
34 | | int refs; |
35 | | char *user_css; |
36 | | int use_document_css; |
37 | | }; |
38 | | |
39 | | static void fz_new_style_context(fz_context *ctx) |
40 | 14.8k | { |
41 | 14.8k | if (ctx) |
42 | 14.8k | { |
43 | 14.8k | ctx->style = fz_malloc_struct(ctx, fz_style_context); |
44 | 14.8k | ctx->style->refs = 1; |
45 | 14.8k | ctx->style->user_css = NULL; |
46 | 14.8k | ctx->style->use_document_css = 1; |
47 | 14.8k | } |
48 | 14.8k | } |
49 | | |
50 | | static fz_style_context *fz_keep_style_context(fz_context *ctx) |
51 | 0 | { |
52 | 0 | if (!ctx) |
53 | 0 | return NULL; |
54 | 0 | return fz_keep_imp(ctx, ctx->style, &ctx->style->refs); |
55 | 0 | } |
56 | | |
57 | | static void fz_drop_style_context(fz_context *ctx) |
58 | 14.8k | { |
59 | 14.8k | if (!ctx) |
60 | 0 | return; |
61 | 14.8k | if (fz_drop_imp(ctx, ctx->style, &ctx->style->refs)) |
62 | 14.8k | { |
63 | 14.8k | fz_free(ctx, ctx->style->user_css); |
64 | 14.8k | fz_free(ctx, ctx->style); |
65 | 14.8k | } |
66 | 14.8k | } |
67 | | |
68 | | void fz_set_use_document_css(fz_context *ctx, int use) |
69 | 0 | { |
70 | 0 | ctx->style->use_document_css = use; |
71 | 0 | } |
72 | | |
73 | | int fz_use_document_css(fz_context *ctx) |
74 | 0 | { |
75 | 0 | return ctx->style->use_document_css; |
76 | 0 | } |
77 | | |
78 | | void fz_set_user_css(fz_context *ctx, const char *user_css) |
79 | 0 | { |
80 | 0 | fz_free(ctx, ctx->style->user_css); |
81 | 0 | ctx->style->user_css = user_css ? fz_strdup(ctx, user_css) : NULL; |
82 | 0 | } |
83 | | |
84 | | const char *fz_user_css(fz_context *ctx) |
85 | 0 | { |
86 | 0 | return ctx->style->user_css; |
87 | 0 | } |
88 | | |
89 | | static void fz_new_tuning_context(fz_context *ctx) |
90 | 14.8k | { |
91 | 14.8k | if (ctx) |
92 | 14.8k | { |
93 | 14.8k | ctx->tuning = fz_malloc_struct(ctx, fz_tuning_context); |
94 | 14.8k | ctx->tuning->refs = 1; |
95 | 14.8k | ctx->tuning->image_decode = fz_default_image_decode; |
96 | 14.8k | ctx->tuning->image_scale = fz_default_image_scale; |
97 | 14.8k | } |
98 | 14.8k | } |
99 | | |
100 | | static fz_tuning_context *fz_keep_tuning_context(fz_context *ctx) |
101 | 0 | { |
102 | 0 | if (!ctx) |
103 | 0 | return NULL; |
104 | 0 | return fz_keep_imp(ctx, ctx->tuning, &ctx->tuning->refs); |
105 | 0 | } |
106 | | |
107 | | static void fz_drop_tuning_context(fz_context *ctx) |
108 | 14.8k | { |
109 | 14.8k | if (!ctx) |
110 | 0 | return; |
111 | 14.8k | if (fz_drop_imp(ctx, ctx->tuning, &ctx->tuning->refs)) |
112 | 14.8k | { |
113 | 14.8k | fz_free(ctx, ctx->tuning); |
114 | 14.8k | } |
115 | 14.8k | } |
116 | | |
117 | | void fz_tune_image_decode(fz_context *ctx, fz_tune_image_decode_fn *image_decode, void *arg) |
118 | 0 | { |
119 | 0 | ctx->tuning->image_decode = image_decode ? image_decode : fz_default_image_decode; |
120 | 0 | ctx->tuning->image_decode_arg = arg; |
121 | 0 | } |
122 | | |
123 | | void fz_tune_image_scale(fz_context *ctx, fz_tune_image_scale_fn *image_scale, void *arg) |
124 | 0 | { |
125 | 0 | ctx->tuning->image_scale = image_scale ? image_scale : fz_default_image_scale; |
126 | 0 | ctx->tuning->image_scale_arg = arg; |
127 | 0 | } |
128 | | |
129 | | static void fz_init_random_context(fz_context *ctx) |
130 | 14.8k | { |
131 | 14.8k | if (!ctx) |
132 | 0 | return; |
133 | | |
134 | 14.8k | ctx->seed48[0] = 0; |
135 | 14.8k | ctx->seed48[1] = 0; |
136 | 14.8k | ctx->seed48[2] = 0; |
137 | 14.8k | ctx->seed48[3] = 0xe66d; |
138 | 14.8k | ctx->seed48[4] = 0xdeec; |
139 | 14.8k | ctx->seed48[5] = 0x5; |
140 | 14.8k | ctx->seed48[6] = 0xb; |
141 | | |
142 | 14.8k | fz_srand48(ctx, (uint32_t)time(NULL)); |
143 | 14.8k | } |
144 | | |
145 | | void |
146 | | fz_drop_context(fz_context *ctx) |
147 | 14.8k | { |
148 | 14.8k | if (!ctx) |
149 | 0 | return; |
150 | | |
151 | | /* Other finalisation calls go here (in reverse order) */ |
152 | 14.8k | fz_drop_document_handler_context(ctx); |
153 | 14.8k | fz_drop_glyph_cache_context(ctx); |
154 | 14.8k | fz_drop_store_context(ctx); |
155 | 14.8k | fz_drop_style_context(ctx); |
156 | 14.8k | fz_drop_tuning_context(ctx); |
157 | 14.8k | fz_drop_colorspace_context(ctx); |
158 | 14.8k | fz_drop_font_context(ctx); |
159 | | |
160 | 14.8k | fz_flush_warnings(ctx); |
161 | | |
162 | 14.8k | assert(ctx->error.top == ctx->error.stack_base); |
163 | | |
164 | | /* Free the context itself */ |
165 | 14.8k | ctx->alloc.free(ctx->alloc.user, ctx); |
166 | 14.8k | } |
167 | | |
168 | | static void |
169 | | fz_init_error_context(fz_context *ctx) |
170 | 14.8k | { |
171 | 14.8k | #define ALIGN(addr, align) ((((intptr_t)(addr)) + (align-1)) & ~(align-1)) |
172 | 14.8k | ctx->error.stack_base = (fz_error_stack_slot *)ALIGN(ctx->error.stack, FZ_JMPBUF_ALIGN); |
173 | 14.8k | ctx->error.top = ctx->error.stack_base; |
174 | 14.8k | ctx->error.errcode = FZ_ERROR_NONE; |
175 | 14.8k | ctx->error.message[0] = 0; |
176 | | |
177 | 14.8k | ctx->warn.message[0] = 0; |
178 | 14.8k | ctx->warn.count = 0; |
179 | 14.8k | } |
180 | | |
181 | | fz_context * |
182 | | fz_new_context_imp(const fz_alloc_context *alloc, const fz_locks_context *locks, size_t max_store, const char *version) |
183 | 14.8k | { |
184 | 14.8k | fz_context *ctx; |
185 | | |
186 | 14.8k | if (strcmp(version, FZ_VERSION)) |
187 | 0 | { |
188 | 0 | fprintf(stderr, "cannot create context: incompatible header (%s) and library (%s) versions\n", version, FZ_VERSION); |
189 | 0 | return NULL; |
190 | 0 | } |
191 | | |
192 | 14.8k | if (!alloc) |
193 | 0 | alloc = &fz_alloc_default; |
194 | | |
195 | 14.8k | if (!locks) |
196 | 14.8k | locks = &fz_locks_default; |
197 | | |
198 | 14.8k | ctx = Memento_label(alloc->malloc(alloc->user, sizeof(fz_context)), "fz_context"); |
199 | 14.8k | if (!ctx) |
200 | 0 | { |
201 | 0 | fprintf(stderr, "cannot create context (phase 1)\n"); |
202 | 0 | return NULL; |
203 | 0 | } |
204 | 14.8k | memset(ctx, 0, sizeof *ctx); |
205 | | |
206 | 14.8k | ctx->user = NULL; |
207 | 14.8k | ctx->alloc = *alloc; |
208 | 14.8k | ctx->locks = *locks; |
209 | | |
210 | 14.8k | ctx->error.print = fz_default_error_callback; |
211 | 14.8k | ctx->warn.print = fz_default_warning_callback; |
212 | | |
213 | 14.8k | fz_init_error_context(ctx); |
214 | 14.8k | fz_init_aa_context(ctx); |
215 | 14.8k | fz_init_random_context(ctx); |
216 | | |
217 | | /* Now initialise sections that are shared */ |
218 | 29.7k | fz_try(ctx) |
219 | 29.7k | { |
220 | 14.8k | fz_new_store_context(ctx, max_store); |
221 | 14.8k | fz_new_glyph_cache_context(ctx); |
222 | 14.8k | fz_new_colorspace_context(ctx); |
223 | 14.8k | fz_new_font_context(ctx); |
224 | 14.8k | fz_new_document_handler_context(ctx); |
225 | 14.8k | fz_new_style_context(ctx); |
226 | 14.8k | fz_new_tuning_context(ctx); |
227 | 14.8k | } |
228 | 29.7k | fz_catch(ctx) |
229 | 0 | { |
230 | 0 | fprintf(stderr, "cannot create context (phase 2)\n"); |
231 | 0 | fz_drop_context(ctx); |
232 | 0 | return NULL; |
233 | 0 | } |
234 | 14.8k | return ctx; |
235 | 14.8k | } |
236 | | |
237 | | fz_context * |
238 | | fz_clone_context(fz_context *ctx) |
239 | 0 | { |
240 | 0 | fz_context *new_ctx; |
241 | | |
242 | | /* We cannot safely clone the context without having locking/ |
243 | | * unlocking functions. */ |
244 | 0 | if (ctx == NULL || (ctx->locks.lock == fz_locks_default.lock && ctx->locks.unlock == fz_locks_default.unlock)) |
245 | 0 | return NULL; |
246 | | |
247 | 0 | new_ctx = ctx->alloc.malloc(ctx->alloc.user, sizeof(fz_context)); |
248 | 0 | if (!new_ctx) |
249 | 0 | return NULL; |
250 | | |
251 | | /* First copy old context, including pointers to shared contexts */ |
252 | 0 | memcpy(new_ctx, ctx, sizeof (fz_context)); |
253 | | |
254 | | /* Reset error context to initial state. */ |
255 | 0 | fz_init_error_context(new_ctx); |
256 | | |
257 | | /* Then keep lock checking happy by keeping shared contexts with new context */ |
258 | 0 | fz_keep_document_handler_context(new_ctx); |
259 | 0 | fz_keep_style_context(new_ctx); |
260 | 0 | fz_keep_tuning_context(new_ctx); |
261 | 0 | fz_keep_font_context(new_ctx); |
262 | 0 | fz_keep_colorspace_context(new_ctx); |
263 | 0 | fz_keep_store_context(new_ctx); |
264 | 0 | fz_keep_glyph_cache(new_ctx); |
265 | |
|
266 | 0 | return new_ctx; |
267 | 0 | } |
268 | | |
269 | | void fz_set_user_context(fz_context *ctx, void *user) |
270 | 0 | { |
271 | 0 | if (ctx != NULL) |
272 | 0 | ctx->user = user; |
273 | 0 | } |
274 | | |
275 | | void *fz_user_context(fz_context *ctx) |
276 | 0 | { |
277 | 0 | if (ctx == NULL) |
278 | 0 | return NULL; |
279 | | |
280 | 0 | return ctx->user; |
281 | 0 | } |