comparison mupdf-source/include/mupdf/fitz/system.h @ 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-2025 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 #ifndef MUPDF_FITZ_SYSTEM_H
24 #define MUPDF_FITZ_SYSTEM_H
25
26 /* Turn on valgrind pacification in debug builds. */
27 #ifndef NDEBUG
28 #ifndef PACIFY_VALGRIND
29 #define PACIFY_VALGRIND
30 #endif
31 #endif
32
33 /**
34 Include the standard libc headers.
35 */
36
37 #include <stddef.h> /* needed for size_t */
38 #include <stdarg.h> /* needed for va_list vararg functions */
39 #include <setjmp.h> /* needed for the try/catch macros */
40 #include <stdio.h> /* useful for debug printfs */
41
42 #ifdef __cplusplus
43 /* C++ doesn't support flexible array members... */
44 #define FZ_FLEXIBLE_ARRAY 1
45 #else
46 #define FZ_FLEXIBLE_ARRAY
47 #endif
48
49 #include "export.h"
50
51 #if defined(_MSC_VER) && (_MSC_VER < 1700) /* MSVC older than VS2012 */
52 typedef signed char int8_t;
53 typedef short int int16_t;
54 typedef int int32_t;
55 typedef __int64 int64_t;
56 typedef unsigned char uint8_t;
57 typedef unsigned short int uint16_t;
58 typedef unsigned int uint32_t;
59 typedef unsigned __int64 uint64_t;
60 #ifndef INT64_MAX
61 #define INT64_MAX 9223372036854775807i64
62 #endif
63 #else
64 #include <stdint.h> /* needed for int64_t */
65 #endif
66
67 #include "mupdf/memento.h"
68 #include "mupdf/fitz/track-usage.h"
69
70 #define nelem(x) (sizeof(x)/sizeof((x)[0]))
71
72 #ifndef PATH_MAX
73 #define PATH_MAX 4096
74 #endif
75
76 #define FZ_PI 3.14159265f
77 #define FZ_RADIAN 57.2957795f
78 #define FZ_DEGREE 0.017453292f
79 #define FZ_SQRT2 1.41421356f
80 #define FZ_LN2 0.69314718f
81
82 /**
83 Spot architectures where we have optimisations.
84 */
85
86 /* ARCH_ARM is only used for 32bit ARM stuff. */
87 #if defined(__arm__) || defined(__thumb__)
88 #ifndef ARCH_ARM
89 #define ARCH_ARM
90 #endif
91 #endif
92
93 /* Detect NEON */
94 #ifndef ARCH_HAS_NEON
95 #if defined(__ARM_NEON) || defined(__ARM_NEON__)
96 #define ARCH_HAS_NEON 1
97 #endif
98 #endif
99
100 #ifndef ARCH_HAS_NEON
101 #define ARCH_HAS_NEON 0
102 #endif
103
104
105 /* We assume that pretty much any X86 or X64 machine has SSE these days. */
106 #ifndef ARCH_HAS_SSE
107 #if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)
108 #define ARCH_HAS_SSE 1
109 #endif
110 #endif
111
112 #ifndef ARCH_HAS_SSE
113 #define ARCH_HAS_SSE 0
114 #endif
115
116
117 /**
118 Some differences in libc can be smoothed over
119 */
120
121 #ifndef __STRICT_ANSI__
122 #if defined(__APPLE__)
123 #ifndef HAVE_SIGSETJMP
124 #define HAVE_SIGSETJMP 1
125 #endif
126 #elif defined(__unix)
127 #ifndef __EMSCRIPTEN__
128 #ifndef HAVE_SIGSETJMP
129 #define HAVE_SIGSETJMP 1
130 #endif
131 #endif
132 #endif
133 #endif
134 #ifndef HAVE_SIGSETJMP
135 #define HAVE_SIGSETJMP 0
136 #endif
137
138 /**
139 Where possible (i.e. on platforms on which they are provided),
140 use sigsetjmp/siglongjmp in preference to setjmp/longjmp. We
141 don't alter signal handlers within mupdf, so there is no need
142 for us to store/restore them - hence we use the non-restoring
143 variants. This makes a large speed difference on MacOSX (and
144 probably other platforms too.
145 */
146 #if HAVE_SIGSETJMP
147 #define fz_setjmp(BUF) sigsetjmp(BUF, 0)
148 #define fz_longjmp(BUF,VAL) siglongjmp(BUF, VAL)
149 typedef sigjmp_buf fz_jmp_buf;
150 #else
151 #define fz_setjmp(BUF) setjmp(BUF)
152 #define fz_longjmp(BUF,VAL) longjmp(BUF,VAL)
153 typedef jmp_buf fz_jmp_buf;
154 #endif
155
156 /* these constants mirror the corresponding macros in stdio.h */
157 #ifndef EOF
158 #define EOF (-1)
159 #endif
160 #ifndef SEEK_SET
161 #define SEEK_SET 0
162 #endif
163 #ifndef SEEK_CUR
164 #define SEEK_CUR 1
165 #endif
166 #ifndef SEEK_END
167 #define SEEK_END 2
168 #endif
169
170 #ifdef _MSC_VER /* Microsoft Visual C */
171
172 /* MSVC up to VS2012 */
173 #if _MSC_VER < 1800
174 static __inline int signbit(double x)
175 {
176 union
177 {
178 double d;
179 __int64 i;
180 } u;
181 u.d = x;
182 return (int)(u.i>>63);
183 }
184 #endif
185
186 #pragma warning( disable: 4244 ) /* conversion from X to Y, possible loss of data */
187 #pragma warning( disable: 4701 ) /* Potentially uninitialized local variable 'name' used */
188 #pragma warning( disable: 4996 ) /* 'function': was declared deprecated */
189
190 #if _MSC_VER <= 1700 /* MSVC 2012 */
191 #define isnan(x) _isnan(x)
192 #define isinf(x) (!_finite(x))
193 #endif
194
195 #if _MSC_VER <= 1920 /* MSVC 2019 */
196 #define hypotf _hypotf
197 #endif
198 #define atoll _atoi64
199
200 #endif
201
202 #ifdef _WIN32
203
204 /* really a FILE* but we don't want to include stdio.h here */
205 void *fz_fopen_utf8(const char *name, const char *mode);
206 int fz_remove_utf8(const char *name);
207
208 char **fz_argv_from_wargv(int argc, wchar_t **wargv);
209 void fz_free_argv(int argc, char **argv);
210
211 #endif
212
213 /* Cope with systems (such as Windows) with no S_ISDIR */
214 #ifndef S_ISDIR
215 #define S_ISDIR(mode) ((mode) & S_IFDIR)
216 #endif
217
218 int64_t fz_stat_ctime(const char *path);
219 int64_t fz_stat_mtime(const char *path);
220 int fz_mkdir(char *path);
221
222
223 /* inline is standard in C++. For some compilers we can enable it within
224 * C too. Some compilers think they know better than we do about when
225 * to actually honour inline (particularly for large functions); use
226 * fz_forceinline to kick them into really inlining. */
227
228 #ifndef __cplusplus
229 #if defined (__STDC_VERSION_) && (__STDC_VERSION__ >= 199901L) /* C99 */
230 #elif defined(_MSC_VER) && (_MSC_VER >= 1500) /* MSVC 9 or newer */
231 #define inline __inline
232 #define fz_forceinline __forceinline
233 #elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC 3 or newer */
234 #define inline __inline
235 #else /* Unknown or ancient */
236 #define inline
237 #endif
238 #endif
239
240 #ifndef fz_forceinline
241 #define fz_forceinline inline
242 #endif
243
244 /* restrict is standard in C99, but not in all C++ compilers. */
245 #if defined (__STDC_VERSION_) && (__STDC_VERSION__ >= 199901L) /* C99 */
246 #define FZ_RESTRICT restrict
247 #elif defined(_MSC_VER) && (_MSC_VER >= 1600) /* MSVC 10 or newer */
248 #define FZ_RESTRICT __restrict
249 #elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC 3 or newer */
250 #define FZ_RESTRICT __restrict
251 #else /* Unknown or ancient */
252 #define FZ_RESTRICT
253 #endif
254
255 /* noreturn is a GCC extension */
256 #ifdef __GNUC__
257 #define FZ_NORETURN __attribute__((noreturn))
258 #else
259 #ifdef _MSC_VER
260 #define FZ_NORETURN __declspec(noreturn)
261 #else
262 #define FZ_NORETURN
263 #endif
264 #endif
265
266 /* Flag unused parameters, for use with 'static inline' functions in
267 * headers. */
268 #if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7)
269 #define FZ_UNUSED __attribute__((__unused__))
270 #else
271 #define FZ_UNUSED
272 #endif
273
274 /* GCC can do type checking of printf strings */
275 #ifdef __printflike
276 #define FZ_PRINTFLIKE(F,V) __printflike(F,V)
277 #else
278 #if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7)
279 #define FZ_PRINTFLIKE(F,V) __attribute__((__format__ (__printf__, F, V)))
280 #else
281 #define FZ_PRINTFLIKE(F,V)
282 #endif
283 #endif
284
285 /* ARM assembly specific defines */
286
287 #ifdef ARCH_ARM
288
289 /* If we're compiling as thumb code, then we need to tell the compiler
290 * to enter and exit ARM mode around our assembly sections. If we move
291 * the ARM functions to a separate file and arrange for it to be
292 * compiled without thumb mode, we can save some time on entry.
293 */
294 /* This is slightly suboptimal; __thumb__ and __thumb2__ become defined
295 * and undefined by #pragma arm/#pragma thumb - but we can't define a
296 * macro to track that. */
297 #if defined(__thumb__) || defined(__thumb2__)
298 #define ENTER_ARM ".balign 4\nmov r12,pc\nbx r12\n0:.arm\n"
299 #define ENTER_THUMB "9:.thumb\n"
300 #else
301 #define ENTER_ARM
302 #define ENTER_THUMB
303 #endif
304
305 #endif
306
307 /* Memory block alignment */
308
309 /* Most architectures are happy with blocks being aligned to the size
310 * of void *'s. Some (notably sparc) are not.
311 *
312 * Some architectures (notably amd64) are happy for pointers to be 32bit
313 * aligned even on 64bit systems. By making use of this we can save lots
314 * of memory in data structures (notably the display list).
315 *
316 * We attempt to cope with these vagaries via the following definitions.
317 */
318
319 /* All blocks allocated by mupdf's allocators are expected to be
320 * returned aligned to FZ_MEMORY_BLOCK_ALIGN_MOD. This is sizeof(void *)
321 * unless overwritten by a predefinition, or by a specific architecture
322 * being detected. */
323 #ifndef FZ_MEMORY_BLOCK_ALIGN_MOD
324 #if defined(sparc) || defined(__sparc) || defined(__sparc__)
325 #define FZ_MEMORY_BLOCK_ALIGN_MOD 8
326 #else
327 #define FZ_MEMORY_BLOCK_ALIGN_MOD sizeof(void *)
328 #endif
329 #endif
330
331 /* MuPDF will ensure that its use of pointers in packed structures
332 * (such as the display list) will be aligned to FZ_POINTER_ALIGN_MOD.
333 * This is the same as FZ_MEMORY_BLOCK_ALIGN_MOD unless overridden by
334 * a predefinition, or by a specific architecture being detected. */
335 #ifndef FZ_POINTER_ALIGN_MOD
336 #if defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__)
337 #define FZ_POINTER_ALIGN_MOD 4
338 #else
339 #define FZ_POINTER_ALIGN_MOD FZ_MEMORY_BLOCK_ALIGN_MOD
340 #endif
341 #endif
342
343 #ifdef CLUSTER
344 /* Include this first so our defines don't clash with the system
345 * definitions */
346 #include <math.h>
347 /**
348 * Trig functions
349 */
350 static float
351 my_atan_table[258] =
352 {
353 0.0000000000f, 0.00390623013f,0.00781234106f,0.0117182136f,
354 0.0156237286f, 0.0195287670f, 0.0234332099f, 0.0273369383f,
355 0.0312398334f, 0.0351417768f, 0.0390426500f, 0.0429423347f,
356 0.0468407129f, 0.0507376669f, 0.0546330792f, 0.0585268326f,
357 0.0624188100f, 0.0663088949f, 0.0701969711f, 0.0740829225f,
358 0.0779666338f, 0.0818479898f, 0.0857268758f, 0.0896031775f,
359 0.0934767812f, 0.0973475735f, 0.1012154420f, 0.1050802730f,
360 0.1089419570f, 0.1128003810f, 0.1166554350f, 0.1205070100f,
361 0.1243549950f, 0.1281992810f, 0.1320397620f, 0.1358763280f,
362 0.1397088740f, 0.1435372940f, 0.1473614810f, 0.1511813320f,
363 0.1549967420f, 0.1588076080f, 0.1626138290f, 0.1664153010f,
364 0.1702119250f, 0.1740036010f, 0.1777902290f, 0.1815717110f,
365 0.1853479500f, 0.1891188490f, 0.1928843120f, 0.1966442450f,
366 0.2003985540f, 0.2041471450f, 0.2078899270f, 0.2116268090f,
367 0.2153577000f, 0.2190825110f, 0.2228011540f, 0.2265135410f,
368 0.2302195870f, 0.2339192060f, 0.2376123140f, 0.2412988270f,
369 0.2449786630f, 0.2486517410f, 0.2523179810f, 0.2559773030f,
370 0.2596296290f, 0.2632748830f, 0.2669129880f, 0.2705438680f,
371 0.2741674510f, 0.2777836630f, 0.2813924330f, 0.2849936890f,
372 0.2885873620f, 0.2921733830f, 0.2957516860f, 0.2993222020f,
373 0.3028848680f, 0.3064396190f, 0.3099863910f, 0.3135251230f,
374 0.3170557530f, 0.3205782220f, 0.3240924700f, 0.3275984410f,
375 0.3310960770f, 0.3345853220f, 0.3380661230f, 0.3415384250f,
376 0.3450021770f, 0.3484573270f, 0.3519038250f, 0.3553416220f,
377 0.3587706700f, 0.3621909220f, 0.3656023320f, 0.3690048540f,
378 0.3723984470f, 0.3757830650f, 0.3791586690f, 0.3825252170f,
379 0.3858826690f, 0.3892309880f, 0.3925701350f, 0.3959000740f,
380 0.3992207700f, 0.4025321870f, 0.4058342930f, 0.4091270550f,
381 0.4124104420f, 0.4156844220f, 0.4189489670f, 0.4222040480f,
382 0.4254496370f, 0.4286857080f, 0.4319122350f, 0.4351291940f,
383 0.4383365600f, 0.4415343100f, 0.4447224240f, 0.4479008790f,
384 0.4510696560f, 0.4542287350f, 0.4573780990f, 0.4605177290f,
385 0.4636476090f, 0.4667677240f, 0.4698780580f, 0.4729785980f,
386 0.4760693300f, 0.4791502430f, 0.4822213240f, 0.4852825630f,
387 0.4883339510f, 0.4913754780f, 0.4944071350f, 0.4974289160f,
388 0.5004408130f, 0.5034428210f, 0.5064349340f, 0.5094171490f,
389 0.5123894600f, 0.5153518660f, 0.5183043630f, 0.5212469510f,
390 0.5241796290f, 0.5271023950f, 0.5300152510f, 0.5329181980f,
391 0.5358112380f, 0.5386943730f, 0.5415676050f, 0.5444309400f,
392 0.5472843810f, 0.5501279330f, 0.5529616020f, 0.5557853940f,
393 0.5585993150f, 0.5614033740f, 0.5641975770f, 0.5669819340f,
394 0.5697564530f, 0.5725211450f, 0.5752760180f, 0.5780210840f,
395 0.5807563530f, 0.5834818390f, 0.5861975510f, 0.5889035040f,
396 0.5915997100f, 0.5942861830f, 0.5969629370f, 0.5996299860f,
397 0.6022873460f, 0.6049350310f, 0.6075730580f, 0.6102014430f,
398 0.6128202020f, 0.6154293530f, 0.6180289120f, 0.6206188990f,
399 0.6231993300f, 0.6257702250f, 0.6283316020f, 0.6308834820f,
400 0.6334258830f, 0.6359588250f, 0.6384823300f, 0.6409964180f,
401 0.6435011090f, 0.6459964250f, 0.6484823880f, 0.6509590190f,
402 0.6534263410f, 0.6558843770f, 0.6583331480f, 0.6607726790f,
403 0.6632029930f, 0.6656241120f, 0.6680360620f, 0.6704388650f,
404 0.6728325470f, 0.6752171330f, 0.6775926450f, 0.6799591110f,
405 0.6823165550f, 0.6846650020f, 0.6870044780f, 0.6893350100f,
406 0.6916566220f, 0.6939693410f, 0.6962731940f, 0.6985682070f,
407 0.7008544080f, 0.7031318220f, 0.7054004770f, 0.7076604000f,
408 0.7099116190f, 0.7121541600f, 0.7143880520f, 0.7166133230f,
409 0.7188300000f, 0.7210381110f, 0.7232376840f, 0.7254287490f,
410 0.7276113330f, 0.7297854640f, 0.7319511710f, 0.7341084830f,
411 0.7362574290f, 0.7383980370f, 0.7405303370f, 0.7426543560f,
412 0.7447701260f, 0.7468776740f, 0.7489770290f, 0.7510682220f,
413 0.7531512810f, 0.7552262360f, 0.7572931160f, 0.7593519510f,
414 0.7614027700f, 0.7634456020f, 0.7654804790f, 0.7675074280f,
415 0.7695264800f, 0.7715376650f, 0.7735410110f, 0.7755365500f,
416 0.7775243100f, 0.7795043220f, 0.7814766150f, 0.7834412190f,
417 0.7853981630f, 0.7853981630f /* Extended by 1 for interpolation */
418 };
419
420 static inline float my_sinf(float x)
421 {
422 float x2, xn;
423 int i;
424 /* Map x into the -PI to PI range. We could do this using:
425 * x = fmodf(x, 2.0f * FZ_PI);
426 * but that's C99, and seems to misbehave with negative numbers
427 * on some platforms. */
428 x -= FZ_PI;
429 i = x / (2.0f * FZ_PI);
430 x -= i * 2.0f * FZ_PI;
431 if (x < 0.0f)
432 x += 2.0f * FZ_PI;
433 x -= FZ_PI;
434 if (x <= -FZ_PI / 2.0f)
435 x = -FZ_PI - x;
436 else if (x >= FZ_PI / 2.0f)
437 x = FZ_PI-x;
438 x2 = x * x;
439 xn = x * x2 / 6.0f;
440 x -= xn;
441 xn *= x2 / 20.0f;
442 x += xn;
443 xn *= x2 / 42.0f;
444 x -= xn;
445 xn *= x2 / 72.0f;
446 x += xn;
447 if (x > 1)
448 x = 1;
449 else if (x < -1)
450 x = -1;
451 return x;
452 }
453
454 static inline float my_atan2f(float o, float a)
455 {
456 int negate = 0, flip = 0, i;
457 float r, s;
458 if (o == 0.0f)
459 {
460 if (a > 0)
461 return 0.0f;
462 else
463 return FZ_PI;
464 }
465 if (o < 0)
466 o = -o, negate = 1;
467 if (a < 0)
468 a = -a, flip = 1;
469 if (o < a)
470 i = 65536.0f * o / a + 0.5f;
471 else
472 i = 65536.0f * a / o + 0.5f;
473 r = my_atan_table[i >> 8];
474 s = my_atan_table[(i >> 8) + 1];
475 r += (s - r) * (i & 255) / 256.0f;
476 if (o >= a)
477 r = FZ_PI / 2.0f - r;
478 if (flip)
479 r = FZ_PI - r;
480 if (negate)
481 r = -r;
482 return r;
483 }
484
485 #define sinf(x) my_sinf(x)
486 #define cosf(x) my_sinf(FZ_PI / 2.0f + (x))
487 #define atan2f(x,y) my_atan2f((x),(y))
488 #endif
489
490 static inline int fz_is_pow2(int a)
491 {
492 return (a != 0) && (a & (a-1)) == 0;
493 }
494
495 #endif