Coverage Report

Created: 2023-06-07 06:20

/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
}