struct fz_context
{
void *user;
fz_alloc_context alloc;
fz_locks_context locks;
fz_error_context error;
fz_warn_context warn;
/* unshared contexts */
fz_aa_context aa;
uint16_t seed48[7];
#if FZ_ENABLE_ICC
int icc_enabled;
#endif
/* TODO: should these be unshared? */
fz_document_handler_context *handler;
fz_style_context *style;
fz_tuning_context *tuning;
/* shared contexts */
fz_output *stddbg;
fz_font_context *font;
fz_colorspace_context *colorspace;
fz_store *store;
fz_glyph_cache *glyph_cache;
};
/**
Allocator structure; holds callbacks and private data pointer.
*/
typedef struct
{
void *user;
void *(*malloc)(void *, size_t);
void *(*realloc)(void *, void *, size_t);
void (*free)(void *, void *);
} fz_alloc_context;
锁定功能
MuPDF 故意不了解任何特定的知识
线程系统。 因此,为了安全的多线程
操作,我们依赖于对客户端提供的函数的回调。
客户端应提供 FZ_LOCK_MAX 个互斥锁,
以及锁定/解锁它们中的每一个的功能。 这些可能是
递归互斥锁,但不是必须的。
如果客户端不打算使用多线程,那么它
可以传递 NULL 而不是锁结构。
为了避免死锁,我们有一个简单的规则
关于我们如何使用锁的内部:我们永远不能获取锁 n
当我们已经持有任何锁 i 时,其中 0 <= i <= n。 为了
为了验证这一点,我们有一些调试代码,可以
通过定义 FITZ_DEBUG_LOCKING 启用。
/**
Locking functions
MuPDF is kept deliberately free of any knowledge of particular
threading systems. As such, in order for safe multi-threaded
operation, we rely on callbacks to client provided functions.
A client is expected to provide FZ_LOCK_MAX number of mutexes,
and a function to lock/unlock each of them. These may be
recursive mutexes, but do not have to be.
If a client does not intend to use multiple threads, then it
may pass NULL instead of a lock structure.
In order to avoid deadlocks, we have one simple rule
internally as to how we use locks: We can never take lock n
when we already hold any lock i, where 0 <= i <= n. In order
to verify this, we have some debugging code, that can be
enabled by defining FITZ_DEBUG_LOCKING.
*/
typedef struct
{
void *user;
void (*lock)(void *user, int lock);
void (*unlock)(void *user, int lock);
} fz_locks_context;
enum {
FZ_LOCK_ALLOC = 0,
FZ_LOCK_FREETYPE,
FZ_LOCK_GLYPHCACHE,
FZ_LOCK_MAX
};
//这样的设计可以用于传递消息相关的结构给展示对象,用于展示
//例如窗口,或者日志,设计比较巧妙
typedef struct
{
int state, code;
fz_jmp_buf buffer;
} fz_error_stack_slot;
typedef struct
{
fz_error_stack_slot *top;
fz_error_stack_slot stack[256];
int errcode;
void *print_user;
void (*print)(void *user, const char *message);
char message[256];
} fz_error_context;
typedef struct
{
void *print_user;
void (*print)(void *user, const char *message);
int count;
char message[256];
} fz_warn_context;
typedef struct
{
int hscale;
int vscale;
int scale;
int bits;
int text_bits;
float min_line_width;
} fz_aa_context;
struct fz_document_handler_context
{
int refs;
int count;
const fz_document_handler *handler[FZ_DOCUMENT_HANDLER_MAX];
};
struct fz_style_context
{
int refs;
char *user_css;
int use_document_css;
};
struct fz_tuning_context
{
int refs;
fz_tune_image_decode_fn *image_decode;
void *image_decode_arg;
fz_tune_image_scale_fn *image_scale;
void *image_scale_arg;
};
struct fz_output
{
void *state;
fz_output_write_fn *write;
fz_output_seek_fn *seek;
fz_output_tell_fn *tell;
fz_output_close_fn *close;
fz_output_drop_fn *drop;
fz_stream_from_output_fn *as_stream;
fz_truncate_fn *truncate;
char *bp, *wp, *ep;
};
struct fz_font_context
{
int ctx_refs;
FT_Library ftlib;
struct FT_MemoryRec_ ftmemory;
int ftlib_refs;
fz_load_system_font_fn *load_font;
fz_load_system_cjk_font_fn *load_cjk_font;
fz_load_system_fallback_font_fn *load_fallback_font;
/* Cached fallback fonts */
fz_font *base14[14];
fz_font *cjk[4];
struct { fz_font *serif, *sans; } fallback[256];
fz_font *symbol1, *symbol2, *math, *music;
fz_font *emoji;
};
//里面的参数还需要解释
struct fz_colorspace_context
{
int ctx_refs;
fz_colorspace *gray, *rgb, *bgr, *cmyk, *lab;
#if FZ_ENABLE_ICC
void *icc_instance;
#endif
};
typedef struct fz_item
{
void *key;
fz_storable *val;
size_t size;
struct fz_item *next;
struct fz_item *prev;
fz_store *store;
const fz_store_type *type;
} fz_item;
/* Every entry in fz_store is protected by the alloc lock */
struct fz_store
{
int refs;
/* Every item in the store is kept in a doubly linked list, ordered
* by usage (so LRU entries are at the end). */
fz_item *head;
fz_item *tail;
/* We have a hash table that allows to quickly find a subset of the
* entries (those whose keys are indirect objects). */
fz_hash_table *hash;
/* We keep track of the size of the store, and keep it below max. */
size_t max;
size_t size;
int defer_reap_count;
int needs_reaping;
int scavenging;
};
typedef struct
{
fz_font *font;
int a, b;
int c, d;
unsigned short gid;
unsigned char e, f;
int aa;
} fz_glyph_key;
typedef struct fz_glyph_cache_entry
{
fz_glyph_key key;
unsigned hash;
struct fz_glyph_cache_entry *lru_prev;
struct fz_glyph_cache_entry *lru_next;
struct fz_glyph_cache_entry *bucket_next;
struct fz_glyph_cache_entry *bucket_prev;
fz_glyph *val;
} fz_glyph_cache_entry;
struct fz_glyph_cache
{
int refs;
size_t total;
#ifndef NDEBUG
int num_evictions;
ptrdiff_t evicted;
#endif
fz_glyph_cache_entry *entry[GLYPH_HASH_LEN];
fz_glyph_cache_entry *lru_head;
fz_glyph_cache_entry *lru_tail;
};