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