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