#ifndef MUPDF_FITZ_CONTEXT_H1#define MUPDF_FITZ_CONTEXT_H23#include "mupdf/fitz/version.h"4#include "mupdf/fitz/system.h"56/*7Contexts8*/910typedef struct fz_alloc_context_s fz_alloc_context;11typedef struct fz_error_context_s fz_error_context;12typedef struct fz_id_context_s fz_id_context;13typedef struct fz_warn_context_s fz_warn_context;14typedef struct fz_font_context_s fz_font_context;15typedef struct fz_colorspace_context_s fz_colorspace_context;16typedef struct fz_aa_context_s fz_aa_context;17typedef struct fz_locks_context_s fz_locks_context;18typedef struct fz_store_s fz_store;19typedef struct fz_glyph_cache_s fz_glyph_cache;20typedef struct fz_document_handler_context_s fz_document_handler_context;21typedef struct fz_context_s fz_context;2223struct fz_alloc_context_s24{25void *user;26void *(*malloc)(void *, unsigned int);27void *(*realloc)(void *, void *, unsigned int);28void (*free)(void *, void *);29};3031struct fz_error_context_s32{33int top;34struct {35int code;36fz_jmp_buf buffer;37} stack[256];38int errcode;39char message[256];40};4142void fz_var_imp(void *);43#define fz_var(var) fz_var_imp((void *)&(var))4445/*46Exception macro definitions. Just treat these as a black box - pay no47attention to the man behind the curtain.48*/4950#define fz_try(ctx) \51if (fz_push_try(ctx->error) && \52((ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0))\53{ do {5455#define fz_always(ctx) \56} while (0); \57} \58if (ctx->error->stack[ctx->error->top].code < 3) \59{ \60ctx->error->stack[ctx->error->top].code++; \61do { \6263#define fz_catch(ctx) \64} while(0); \65} \66if (ctx->error->stack[ctx->error->top--].code > 1)6768int fz_push_try(fz_error_context *ex);69FZ_NORETURN void fz_throw(fz_context *, int errcode, const char *, ...) __printflike(3, 4);70FZ_NORETURN void fz_rethrow(fz_context *);71FZ_NORETURN void fz_rethrow_message(fz_context *, const char *, ...) __printflike(2, 3);72void fz_warn(fz_context *ctx, const char *fmt, ...) __printflike(2, 3);73const char *fz_caught_message(fz_context *ctx);74int fz_caught(fz_context *ctx);75void fz_rethrow_if(fz_context *ctx, int errcode);7677enum78{79FZ_ERROR_NONE = 0,80FZ_ERROR_GENERIC = 1,81FZ_ERROR_SYNTAX = 2,82FZ_ERROR_TRYLATER = 3,83FZ_ERROR_ABORT = 4,84FZ_ERROR_COUNT85};8687/*88fz_flush_warnings: Flush any repeated warnings.8990Repeated warnings are buffered, counted and eventually printed91along with the number of repetitions. Call fz_flush_warnings92to force printing of the latest buffered warning and the93number of repetitions, for example to make sure that all94warnings are printed before exiting an application.9596Does not throw exceptions.97*/98void fz_flush_warnings(fz_context *ctx);99100struct fz_context_s101{102fz_alloc_context *alloc;103fz_locks_context *locks;104fz_id_context *id;105fz_error_context *error;106fz_warn_context *warn;107fz_font_context *font;108fz_colorspace_context *colorspace;109fz_aa_context *aa;110fz_store *store;111fz_glyph_cache *glyph_cache;112fz_document_handler_context *handler;113};114115/*116Specifies the maximum size in bytes of the resource store in117fz_context. Given as argument to fz_new_context.118119FZ_STORE_UNLIMITED: Let resource store grow unbounded.120121FZ_STORE_DEFAULT: A reasonable upper bound on the size, for122devices that are not memory constrained.123*/124enum {125FZ_STORE_UNLIMITED = 0,126FZ_STORE_DEFAULT = 256 << 20,127};128129/*130fz_new_context: Allocate context containing global state.131132The global state contains an exception stack, resource store,133etc. Most functions in MuPDF take a context argument to be134able to reference the global state. See fz_drop_context for135freeing an allocated context.136137alloc: Supply a custom memory allocator through a set of138function pointers. Set to NULL for the standard library139allocator. The context will keep the allocator pointer, so the140data it points to must not be modified or freed during the141lifetime of the context.142143locks: Supply a set of locks and functions to lock/unlock144them, intended for multi-threaded applications. Set to NULL145when using MuPDF in a single-threaded applications. The146context will keep the locks pointer, so the data it points to147must not be modified or freed during the lifetime of the148context.149150max_store: Maximum size in bytes of the resource store, before151it will start evicting cached resources such as fonts and152images. FZ_STORE_UNLIMITED can be used if a hard limit is not153desired. Use FZ_STORE_DEFAULT to get a reasonable size.154155Does not throw exceptions, but may return NULL.156*/157fz_context *fz_new_context_imp(fz_alloc_context *alloc, fz_locks_context *locks, unsigned int max_store, const char *version);158159#define fz_new_context(alloc, locks, max_store) fz_new_context_imp(alloc, locks, max_store, FZ_VERSION)160161/*162fz_clone_context: Make a clone of an existing context.163164This function is meant to be used in multi-threaded165applications where each thread requires its own context, yet166parts of the global state, for example caching, is shared.167168ctx: Context obtained from fz_new_context to make a copy of.169ctx must have had locks and lock/functions setup when created.170The two contexts will share the memory allocator, resource171store, locks and lock/unlock functions. They will each have172their own exception stacks though.173174Does not throw exception, but may return NULL.175*/176fz_context *fz_clone_context(fz_context *ctx);177178/*179fz_drop_context: Free a context and its global state.180181The context and all of its global state is freed, and any182buffered warnings are flushed (see fz_flush_warnings). If NULL183is passed in nothing will happen.184185Does not throw exceptions.186*/187void fz_drop_context(fz_context *ctx);188189/*190fz_aa_level: Get the number of bits of antialiasing we are191using. Between 0 and 8.192*/193int fz_aa_level(fz_context *ctx);194195/*196fz_set_aa_level: Set the number of bits of antialiasing we should use.197198bits: The number of bits of antialiasing to use (values are clamped199to within the 0 to 8 range).200*/201void fz_set_aa_level(fz_context *ctx, int bits);202203/*204Locking functions205206MuPDF is kept deliberately free of any knowledge of particular207threading systems. As such, in order for safe multi-threaded208operation, we rely on callbacks to client provided functions.209210A client is expected to provide FZ_LOCK_MAX number of mutexes,211and a function to lock/unlock each of them. These may be212recursive mutexes, but do not have to be.213214If a client does not intend to use multiple threads, then it215may pass NULL instead of a lock structure.216217In order to avoid deadlocks, we have one simple rule218internally as to how we use locks: We can never take lock n219when we already hold any lock i, where 0 <= i <= n. In order220to verify this, we have some debugging code, that can be221enabled by defining FITZ_DEBUG_LOCKING.222*/223224struct fz_locks_context_s225{226void *user;227void (*lock)(void *user, int lock);228void (*unlock)(void *user, int lock);229};230231enum {232FZ_LOCK_ALLOC = 0,233FZ_LOCK_FILE, /* Unused now */234FZ_LOCK_FREETYPE,235FZ_LOCK_GLYPHCACHE,236FZ_LOCK_MAX237};238239/*240Memory Allocation and Scavenging:241242All calls to MuPDFs allocator functions pass through to the243underlying allocators passed in when the initial context is244created, after locks are taken (using the supplied locking function)245to ensure that only one thread at a time calls through.246247If the underlying allocator fails, MuPDF attempts to make room for248the allocation by evicting elements from the store, then retrying.249250Any call to allocate may then result in several calls to the underlying251allocator, and result in elements that are only referred to by the252store being freed.253*/254255/*256fz_malloc: Allocate a block of memory (with scavenging)257258size: The number of bytes to allocate.259260Returns a pointer to the allocated block. May return NULL if size is2610. Throws exception on failure to allocate.262*/263void *fz_malloc(fz_context *ctx, unsigned int size);264265/*266fz_calloc: Allocate a zeroed block of memory (with scavenging)267268count: The number of objects to allocate space for.269270size: The size (in bytes) of each object.271272Returns a pointer to the allocated block. May return NULL if size273and/or count are 0. Throws exception on failure to allocate.274*/275void *fz_calloc(fz_context *ctx, unsigned int count, unsigned int size);276277/*278fz_malloc_struct: Allocate storage for a structure (with scavenging),279clear it, and (in Memento builds) tag the pointer as belonging to a280struct of this type.281282CTX: The context.283284STRUCT: The structure type.285286Returns a pointer to allocated (and cleared) structure. Throws287exception on failure to allocate.288*/289#define fz_malloc_struct(CTX, STRUCT) \290((STRUCT *)Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT))291292/*293fz_malloc_array: Allocate a block of (non zeroed) memory (with294scavenging). Equivalent to fz_calloc without the memory clearing.295296count: The number of objects to allocate space for.297298size: The size (in bytes) of each object.299300Returns a pointer to the allocated block. May return NULL if size301and/or count are 0. Throws exception on failure to allocate.302*/303void *fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size);304305/*306fz_resize_array: Resize a block of memory (with scavenging).307308p: The existing block to resize309310count: The number of objects to resize to.311312size: The size (in bytes) of each object.313314Returns a pointer to the resized block. May return NULL if size315and/or count are 0. Throws exception on failure to resize (original316block is left unchanged).317*/318void *fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size);319320/*321fz_strdup: Duplicate a C string (with scavenging)322323s: The string to duplicate.324325Returns a pointer to a duplicated string. Throws exception on failure326to allocate.327*/328char *fz_strdup(fz_context *ctx, const char *s);329330/*331fz_free: Frees an allocation.332333Does not throw exceptions.334*/335void fz_free(fz_context *ctx, void *p);336337/*338fz_malloc_no_throw: Allocate a block of memory (with scavenging)339340size: The number of bytes to allocate.341342Returns a pointer to the allocated block. May return NULL if size is3430. Returns NULL on failure to allocate.344*/345void *fz_malloc_no_throw(fz_context *ctx, unsigned int size);346347/*348fz_calloc_no_throw: Allocate a zeroed block of memory (with scavenging)349350count: The number of objects to allocate space for.351352size: The size (in bytes) of each object.353354Returns a pointer to the allocated block. May return NULL if size355and/or count are 0. Returns NULL on failure to allocate.356*/357void *fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size);358359/*360fz_malloc_array_no_throw: Allocate a block of (non zeroed) memory361(with scavenging). Equivalent to fz_calloc_no_throw without the362memory clearing.363364count: The number of objects to allocate space for.365366size: The size (in bytes) of each object.367368Returns a pointer to the allocated block. May return NULL if size369and/or count are 0. Returns NULL on failure to allocate.370*/371void *fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size);372373/*374fz_resize_array_no_throw: Resize a block of memory (with scavenging).375376p: The existing block to resize377378count: The number of objects to resize to.379380size: The size (in bytes) of each object.381382Returns a pointer to the resized block. May return NULL if size383and/or count are 0. Returns NULL on failure to resize (original384block is left unchanged).385*/386void *fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, unsigned int size);387388/*389fz_strdup_no_throw: Duplicate a C string (with scavenging)390391s: The string to duplicate.392393Returns a pointer to a duplicated string. Returns NULL on failure394to allocate.395*/396char *fz_strdup_no_throw(fz_context *ctx, const char *s);397398/*399fz_gen_id: Generate an id (guaranteed unique within this family of400contexts).401*/402int fz_gen_id(fz_context *ctx);403404struct fz_warn_context_s405{406char message[256];407int count;408};409410fz_context *fz_clone_context_internal(fz_context *ctx);411412void fz_new_aa_context(fz_context *ctx);413void fz_drop_aa_context(fz_context *ctx);414void fz_copy_aa_context(fz_context *dst, fz_context *src);415416void fz_new_document_handler_context(fz_context *ctx);417void fz_drop_document_handler_context(fz_context *ctx);418fz_document_handler_context *fz_keep_document_handler_context(fz_context *ctx);419420/* Default allocator */421extern fz_alloc_context fz_alloc_default;422423/* Default locks */424extern fz_locks_context fz_locks_default;425426#if defined(MEMENTO) || defined(DEBUG)427#define FITZ_DEBUG_LOCKING428#endif429430#ifdef FITZ_DEBUG_LOCKING431432void fz_assert_lock_held(fz_context *ctx, int lock);433void fz_assert_lock_not_held(fz_context *ctx, int lock);434void fz_lock_debug_lock(fz_context *ctx, int lock);435void fz_lock_debug_unlock(fz_context *ctx, int lock);436437#else438439#define fz_assert_lock_held(A,B) do { } while (0)440#define fz_assert_lock_not_held(A,B) do { } while (0)441#define fz_lock_debug_lock(A,B) do { } while (0)442#define fz_lock_debug_unlock(A,B) do { } while (0)443444#endif /* !FITZ_DEBUG_LOCKING */445446static inline void447fz_lock(fz_context *ctx, int lock)448{449fz_lock_debug_lock(ctx, lock);450ctx->locks->lock(ctx->locks->user, lock);451}452453static inline void454fz_unlock(fz_context *ctx, int lock)455{456fz_lock_debug_unlock(ctx, lock);457ctx->locks->unlock(ctx->locks->user, lock);458}459460static inline void *461fz_keep_imp(fz_context *ctx, void *p, int *refs)462{463if (p)464{465fz_lock(ctx, FZ_LOCK_ALLOC);466if (*refs > 0)467++*refs;468fz_unlock(ctx, FZ_LOCK_ALLOC);469}470return p;471}472473static inline void *474fz_keep_imp8(fz_context *ctx, void *p, int8_t *refs)475{476if (p)477{478fz_lock(ctx, FZ_LOCK_ALLOC);479if (*refs > 0)480++*refs;481fz_unlock(ctx, FZ_LOCK_ALLOC);482}483return p;484}485486static inline int487fz_drop_imp(fz_context *ctx, void *p, int *refs)488{489if (p)490{491int drop;492fz_lock(ctx, FZ_LOCK_ALLOC);493if (*refs > 0)494drop = --*refs == 0;495else496drop = 0;497fz_unlock(ctx, FZ_LOCK_ALLOC);498return drop;499}500return 0;501}502503static inline int504fz_drop_imp8(fz_context *ctx, void *p, int8_t *refs)505{506if (p)507{508int drop;509fz_lock(ctx, FZ_LOCK_ALLOC);510if (*refs > 0)511drop = --*refs == 0;512else513drop = 0;514fz_unlock(ctx, FZ_LOCK_ALLOC);515return drop;516}517return 0;518}519520#endif521522523