diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2013-06-17 16:34:58 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2013-06-18 17:37:13 +0200 |
commit | 8856f8521a42872a95579666b24ecfb65c5a20a1 (patch) | |
tree | eab5136996379f77d52699c25f8855ea36d06cc2 /include/mupdf/fitz.h | |
parent | 03e5755b93e90cc4c09daad4c79b6016bf4ce43c (diff) | |
download | mupdf-8856f8521a42872a95579666b24ecfb65c5a20a1.tar.xz |
Merge common and internal headers into one.
Diffstat (limited to 'include/mupdf/fitz.h')
-rw-r--r-- | include/mupdf/fitz.h | 1616 |
1 files changed, 1616 insertions, 0 deletions
diff --git a/include/mupdf/fitz.h b/include/mupdf/fitz.h index 02104b05..e199b5ee 100644 --- a/include/mupdf/fitz.h +++ b/include/mupdf/fitz.h @@ -3187,4 +3187,1620 @@ void fz_write_pcl(fz_context *ctx, fz_pixmap *pixmap, char *filename, int append void fz_write_pcl_bitmap(fz_context *ctx, fz_bitmap *bitmap, char *filename, int append, fz_pcl_options *pcl); +/* fitz-internal.h */ + +#ifdef _WIN32 /* Microsoft Visual C++ */ + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef __int64 int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; + +#else +#include <inttypes.h> +#endif + +struct fz_warn_context_s +{ + char message[256]; + int count; +}; + +fz_context *fz_clone_context_internal(fz_context *ctx); + +void fz_new_aa_context(fz_context *ctx); +void fz_free_aa_context(fz_context *ctx); +void fz_copy_aa_context(fz_context *dst, fz_context *src); + +/* Default allocator */ +extern fz_alloc_context fz_alloc_default; + +/* Default locks */ +extern fz_locks_context fz_locks_default; + +#if defined(MEMENTO) || defined(DEBUG) +#define FITZ_DEBUG_LOCKING +#endif + +#ifdef FITZ_DEBUG_LOCKING + +void fz_assert_lock_held(fz_context *ctx, int lock); +void fz_assert_lock_not_held(fz_context *ctx, int lock); +void fz_lock_debug_lock(fz_context *ctx, int lock); +void fz_lock_debug_unlock(fz_context *ctx, int lock); + +#else + +#define fz_assert_lock_held(A,B) do { } while (0) +#define fz_assert_lock_not_held(A,B) do { } while (0) +#define fz_lock_debug_lock(A,B) do { } while (0) +#define fz_lock_debug_unlock(A,B) do { } while (0) + +#endif /* !FITZ_DEBUG_LOCKING */ + +static inline void +fz_lock(fz_context *ctx, int lock) +{ + fz_lock_debug_lock(ctx, lock); + ctx->locks->lock(ctx->locks->user, lock); +} + +static inline void +fz_unlock(fz_context *ctx, int lock) +{ + fz_lock_debug_unlock(ctx, lock); + ctx->locks->unlock(ctx->locks->user, lock); +} + +/* ARM assembly specific defines */ + +#ifdef ARCH_ARM +#ifdef NDK_PROFILER +extern void __gnu_mcount_nc(void); +#define ENTER_PG "push {lr}\nbl __gnu_mcount_nc\n" +#else +#define ENTER_PG +#endif + +/* If we're compiling as thumb code, then we need to tell the compiler + * to enter and exit ARM mode around our assembly sections. If we move + * the ARM functions to a separate file and arrange for it to be compiled + * without thumb mode, we can save some time on entry. + */ +#ifdef ARCH_THUMB +#define ENTER_ARM ".balign 4\nmov r12,pc\nbx r12\n0:.arm\n" ENTER_PG +#define ENTER_THUMB "9:.thumb\n" ENTER_PG +#else +#define ENTER_ARM +#define ENTER_THUMB +#endif +#endif + +/* + * Basic runtime and utility functions + */ + +#ifdef CLUSTER +#define LOCAL_TRIG_FNS +#endif + +#ifdef LOCAL_TRIG_FNS +/* + * Trig functions + */ +static float +my_atan_table[258] = +{ +0.0000000000f, 0.00390623013f,0.00781234106f,0.0117182136f, +0.0156237286f, 0.0195287670f, 0.0234332099f, 0.0273369383f, +0.0312398334f, 0.0351417768f, 0.0390426500f, 0.0429423347f, +0.0468407129f, 0.0507376669f, 0.0546330792f, 0.0585268326f, +0.0624188100f, 0.0663088949f, 0.0701969711f, 0.0740829225f, +0.0779666338f, 0.0818479898f, 0.0857268758f, 0.0896031775f, +0.0934767812f, 0.0973475735f, 0.1012154420f, 0.1050802730f, +0.1089419570f, 0.1128003810f, 0.1166554350f, 0.1205070100f, +0.1243549950f, 0.1281992810f, 0.1320397620f, 0.1358763280f, +0.1397088740f, 0.1435372940f, 0.1473614810f, 0.1511813320f, +0.1549967420f, 0.1588076080f, 0.1626138290f, 0.1664153010f, +0.1702119250f, 0.1740036010f, 0.1777902290f, 0.1815717110f, +0.1853479500f, 0.1891188490f, 0.1928843120f, 0.1966442450f, +0.2003985540f, 0.2041471450f, 0.2078899270f, 0.2116268090f, +0.2153577000f, 0.2190825110f, 0.2228011540f, 0.2265135410f, +0.2302195870f, 0.2339192060f, 0.2376123140f, 0.2412988270f, +0.2449786630f, 0.2486517410f, 0.2523179810f, 0.2559773030f, +0.2596296290f, 0.2632748830f, 0.2669129880f, 0.2705438680f, +0.2741674510f, 0.2777836630f, 0.2813924330f, 0.2849936890f, +0.2885873620f, 0.2921733830f, 0.2957516860f, 0.2993222020f, +0.3028848680f, 0.3064396190f, 0.3099863910f, 0.3135251230f, +0.3170557530f, 0.3205782220f, 0.3240924700f, 0.3275984410f, +0.3310960770f, 0.3345853220f, 0.3380661230f, 0.3415384250f, +0.3450021770f, 0.3484573270f, 0.3519038250f, 0.3553416220f, +0.3587706700f, 0.3621909220f, 0.3656023320f, 0.3690048540f, +0.3723984470f, 0.3757830650f, 0.3791586690f, 0.3825252170f, +0.3858826690f, 0.3892309880f, 0.3925701350f, 0.3959000740f, +0.3992207700f, 0.4025321870f, 0.4058342930f, 0.4091270550f, +0.4124104420f, 0.4156844220f, 0.4189489670f, 0.4222040480f, +0.4254496370f, 0.4286857080f, 0.4319122350f, 0.4351291940f, +0.4383365600f, 0.4415343100f, 0.4447224240f, 0.4479008790f, +0.4510696560f, 0.4542287350f, 0.4573780990f, 0.4605177290f, +0.4636476090f, 0.4667677240f, 0.4698780580f, 0.4729785980f, +0.4760693300f, 0.4791502430f, 0.4822213240f, 0.4852825630f, +0.4883339510f, 0.4913754780f, 0.4944071350f, 0.4974289160f, +0.5004408130f, 0.5034428210f, 0.5064349340f, 0.5094171490f, +0.5123894600f, 0.5153518660f, 0.5183043630f, 0.5212469510f, +0.5241796290f, 0.5271023950f, 0.5300152510f, 0.5329181980f, +0.5358112380f, 0.5386943730f, 0.5415676050f, 0.5444309400f, +0.5472843810f, 0.5501279330f, 0.5529616020f, 0.5557853940f, +0.5585993150f, 0.5614033740f, 0.5641975770f, 0.5669819340f, +0.5697564530f, 0.5725211450f, 0.5752760180f, 0.5780210840f, +0.5807563530f, 0.5834818390f, 0.5861975510f, 0.5889035040f, +0.5915997100f, 0.5942861830f, 0.5969629370f, 0.5996299860f, +0.6022873460f, 0.6049350310f, 0.6075730580f, 0.6102014430f, +0.6128202020f, 0.6154293530f, 0.6180289120f, 0.6206188990f, +0.6231993300f, 0.6257702250f, 0.6283316020f, 0.6308834820f, +0.6334258830f, 0.6359588250f, 0.6384823300f, 0.6409964180f, +0.6435011090f, 0.6459964250f, 0.6484823880f, 0.6509590190f, +0.6534263410f, 0.6558843770f, 0.6583331480f, 0.6607726790f, +0.6632029930f, 0.6656241120f, 0.6680360620f, 0.6704388650f, +0.6728325470f, 0.6752171330f, 0.6775926450f, 0.6799591110f, +0.6823165550f, 0.6846650020f, 0.6870044780f, 0.6893350100f, +0.6916566220f, 0.6939693410f, 0.6962731940f, 0.6985682070f, +0.7008544080f, 0.7031318220f, 0.7054004770f, 0.7076604000f, +0.7099116190f, 0.7121541600f, 0.7143880520f, 0.7166133230f, +0.7188300000f, 0.7210381110f, 0.7232376840f, 0.7254287490f, +0.7276113330f, 0.7297854640f, 0.7319511710f, 0.7341084830f, +0.7362574290f, 0.7383980370f, 0.7405303370f, 0.7426543560f, +0.7447701260f, 0.7468776740f, 0.7489770290f, 0.7510682220f, +0.7531512810f, 0.7552262360f, 0.7572931160f, 0.7593519510f, +0.7614027700f, 0.7634456020f, 0.7654804790f, 0.7675074280f, +0.7695264800f, 0.7715376650f, 0.7735410110f, 0.7755365500f, +0.7775243100f, 0.7795043220f, 0.7814766150f, 0.7834412190f, +0.7853981630f, 0.7853981630f /* Extended by 1 for interpolation */ +}; + +static inline float my_sinf(float x) +{ + float x2, xn; + int i; + /* Map x into the -PI to PI range. We could do this using: + * x = fmodf(x, (float)(2.0 * M_PI)); + * but that's C99, and seems to misbehave with negative numbers + * on some platforms. */ + x -= (float)M_PI; + i = x / (float)(2.0f * M_PI); + x -= i * (float)(2.0f * M_PI); + if (x < 0.0f) + x += (float)(2.0f * M_PI); + x -= (float)M_PI; + if (x <= (float)(-M_PI/2.0)) + x = -(float)M_PI-x; + else if (x >= (float)(M_PI/2.0)) + x = (float)M_PI-x; + x2 = x*x; + xn = x*x2/6.0f; + x -= xn; + xn *= x2/20.0f; + x += xn; + xn *= x2/42.0f; + x -= xn; + xn *= x2/72.0f; + x += xn; + return x; +} + +static inline float my_atan2f(float o, float a) +{ + int negate = 0, flip = 0, i; + float r, s; + if (o == 0.0f) + { + if (a > 0) + return 0.0f; + else + return (float)M_PI; + } + if (o < 0) + o = -o, negate = 1; + if (a < 0) + a = -a, flip = 1; + if (o < a) + i = (int)(65536.0f*o/a + 0.5f); + else + i = (int)(65536.0f*a/o + 0.5f); + r = my_atan_table[i>>8]; + s = my_atan_table[(i>>8)+1]; + r += (s-r)*(i&255)/256.0f; + if (o >= a) + r = (float)(M_PI/2.0f) - r; + if (flip) + r = (float)M_PI - r; + if (negate) + r = -r; + return r; +} + +#define sinf(x) my_sinf(x) +#define cosf(x) my_sinf(((float)(M_PI/2.0f)) + (x)) +#define atan2f(x,y) my_atan2f((x),(y)) +#endif + +/* Range checking atof */ +float fz_atof(const char *s); + +/* atoi that copes with NULL */ +int fz_atoi(const char *s); + +/* + * Generic hash-table with fixed-length keys. + */ + +typedef struct fz_hash_table_s fz_hash_table; + +fz_hash_table *fz_new_hash_table(fz_context *ctx, int initialsize, int keylen, int lock); +void fz_empty_hash(fz_context *ctx, fz_hash_table *table); +void fz_free_hash(fz_context *ctx, fz_hash_table *table); + +void *fz_hash_find(fz_context *ctx, fz_hash_table *table, void *key); +void *fz_hash_insert(fz_context *ctx, fz_hash_table *table, void *key, void *val); +void *fz_hash_insert_with_pos(fz_context *ctx, fz_hash_table *table, void *key, void *val, unsigned *pos); +void fz_hash_remove(fz_context *ctx, fz_hash_table *table, void *key); +void fz_hash_remove_fast(fz_context *ctx, fz_hash_table *table, void *key, unsigned pos); + +int fz_hash_len(fz_context *ctx, fz_hash_table *table); +void *fz_hash_get_key(fz_context *ctx, fz_hash_table *table, int idx); +void *fz_hash_get_val(fz_context *ctx, fz_hash_table *table, int idx); + +#ifndef NDEBUG +void fz_print_hash(fz_context *ctx, FILE *out, fz_hash_table *table); +void fz_print_hash_details(fz_context *ctx, FILE *out, fz_hash_table *table, void (*details)(FILE *, void *)); +#endif + +/* + * Math and geometry + */ + +/* Multiply scaled two integers in the 0..255 range */ +static inline int fz_mul255(int a, int b) +{ + /* see Jim Blinn's book "Dirty Pixels" for how this works */ + int x = a * b + 128; + x += x >> 8; + return x >> 8; +} + +/* Expand a value A from the 0...255 range to the 0..256 range */ +#define FZ_EXPAND(A) ((A)+((A)>>7)) + +/* Combine values A (in any range) and B (in the 0..256 range), + * to give a single value in the same range as A was. */ +#define FZ_COMBINE(A,B) (((A)*(B))>>8) + +/* Combine values A and C (in the same (any) range) and B and D (in the + * 0..256 range), to give a single value in the same range as A and C were. */ +#define FZ_COMBINE2(A,B,C,D) (FZ_COMBINE((A), (B)) + FZ_COMBINE((C), (D))) + +/* Blend SRC and DST (in the same range) together according to + * AMOUNT (in the 0...256 range). */ +#define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8) + +void fz_gridfit_matrix(fz_matrix *m); +float fz_matrix_max_expansion(const fz_matrix *m); + +/* + * Basic crypto functions. + * Independent of the rest of fitz. + * For further encapsulation in filters, or not. + */ + +/* md5 digests */ + +typedef struct fz_md5_s fz_md5; + +struct fz_md5_s +{ + unsigned int state[4]; + unsigned int count[2]; + unsigned char buffer[64]; +}; + +void fz_md5_init(fz_md5 *state); +void fz_md5_update(fz_md5 *state, const unsigned char *input, unsigned inlen); +void fz_md5_final(fz_md5 *state, unsigned char digest[16]); + +/* sha-256 digests */ + +typedef struct fz_sha256_s fz_sha256; + +struct fz_sha256_s +{ + unsigned int state[8]; + unsigned int count[2]; + union { + unsigned char u8[64]; + unsigned int u32[16]; + } buffer; +}; + +void fz_sha256_init(fz_sha256 *state); +void fz_sha256_update(fz_sha256 *state, const unsigned char *input, unsigned int inlen); +void fz_sha256_final(fz_sha256 *state, unsigned char digest[32]); + +/* sha-512 digests */ + +typedef struct fz_sha512_s fz_sha512; + +struct fz_sha512_s +{ + uint64_t state[8]; + unsigned int count[2]; + union { + unsigned char u8[128]; + uint64_t u64[16]; + } buffer; +}; + +void fz_sha512_init(fz_sha512 *state); +void fz_sha512_update(fz_sha512 *state, const unsigned char *input, unsigned int inlen); +void fz_sha512_final(fz_sha512 *state, unsigned char digest[64]); + +/* sha-384 digests */ + +typedef struct fz_sha512_s fz_sha384; + +void fz_sha384_init(fz_sha384 *state); +void fz_sha384_update(fz_sha384 *state, const unsigned char *input, unsigned int inlen); +void fz_sha384_final(fz_sha384 *state, unsigned char digest[64]); + +/* arc4 crypto */ + +typedef struct fz_arc4_s fz_arc4; + +struct fz_arc4_s +{ + unsigned x; + unsigned y; + unsigned char state[256]; +}; + +void fz_arc4_init(fz_arc4 *state, const unsigned char *key, unsigned len); +void fz_arc4_encrypt(fz_arc4 *state, unsigned char *dest, const unsigned char *src, unsigned len); + +/* AES block cipher implementation from XYSSL */ + +typedef struct fz_aes_s fz_aes; + +#define AES_DECRYPT 0 +#define AES_ENCRYPT 1 + +struct fz_aes_s +{ + int nr; /* number of rounds */ + unsigned long *rk; /* AES round keys */ + unsigned long buf[68]; /* unaligned data */ +}; + +int aes_setkey_enc( fz_aes *ctx, const unsigned char *key, int keysize ); +int aes_setkey_dec( fz_aes *ctx, const unsigned char *key, int keysize ); +void aes_crypt_cbc( fz_aes *ctx, int mode, int length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/* + Resource store + + MuPDF stores decoded "objects" into a store for potential reuse. + If the size of the store gets too big, objects stored within it can + be evicted and freed to recover space. When MuPDF comes to decode + such an object, it will check to see if a version of this object is + already in the store - if it is, it will simply reuse it. If not, it + will decode it and place it into the store. + + All objects that can be placed into the store are derived from the + fz_storable type (i.e. this should be the first component of the + objects structure). This allows for consistent (thread safe) + reference counting, and includes a function that will be called to + free the object as soon as the reference count reaches zero. + + Most objects offer fz_keep_XXXX/fz_drop_XXXX functions derived + from fz_keep_storable/fz_drop_storable. Creation of such objects + includes a call to FZ_INIT_STORABLE to set up the fz_storable header. + */ + +typedef struct fz_storable_s fz_storable; + +typedef void (fz_store_free_fn)(fz_context *, fz_storable *); + +struct fz_storable_s { + int refs; + fz_store_free_fn *free; +}; + +#define FZ_INIT_STORABLE(S_,RC,FREE) \ + do { fz_storable *S = &(S_)->storable; S->refs = (RC); \ + S->free = (FREE); \ + } while (0) + +void *fz_keep_storable(fz_context *, fz_storable *); +void fz_drop_storable(fz_context *, fz_storable *); + +/* + The store can be seen as a dictionary that maps keys to fz_storable + values. In order to allow keys of different types to be stored, we + have a structure full of functions for each key 'type'; this + fz_store_type pointer is stored with each key, and tells the store + how to perform certain operations (like taking/dropping a reference, + comparing two keys, outputting details for debugging etc). + + The store uses a hash table internally for speed where possible. In + order for this to work, we need a mechanism for turning a generic + 'key' into 'a hashable string'. For this purpose the type structure + contains a make_hash_key function pointer that maps from a void * + to an fz_store_hash structure. If make_hash_key function returns 0, + then the key is determined not to be hashable, and the value is + not stored in the hash table. +*/ +typedef struct fz_store_hash_s fz_store_hash; + +struct fz_store_hash_s +{ + fz_store_free_fn *free; + union + { + struct + { + int i0; + int i1; + } i; + struct + { + void *ptr; + int i; + } pi; + struct + { + int id; + float m[4]; + } im; + } u; +}; + +typedef struct fz_store_type_s fz_store_type; + +struct fz_store_type_s +{ + int (*make_hash_key)(fz_store_hash *, void *); + void *(*keep_key)(fz_context *,void *); + void (*drop_key)(fz_context *,void *); + int (*cmp_key)(void *, void *); +#ifndef NDEBUG + void (*debug)(FILE *, void *); +#endif +}; + +/* + fz_store_new_context: Create a new store inside the context + + max: The maximum size (in bytes) that the store is allowed to grow + to. FZ_STORE_UNLIMITED means no limit. +*/ +void fz_new_store_context(fz_context *ctx, unsigned int max); + +/* + fz_drop_store_context: Drop a reference to the store. +*/ +void fz_drop_store_context(fz_context *ctx); + +/* + fz_keep_store_context: Take a reference to the store. +*/ +fz_store *fz_keep_store_context(fz_context *ctx); + +/* + fz_store_item: Add an item to the store. + + Add an item into the store, returning NULL for success. If an item + with the same key is found in the store, then our item will not be + inserted, and the function will return a pointer to that value + instead. This function takes its own reference to val, as required + (i.e. the caller maintains ownership of its own reference). + + key: The key to use to index the item. + + val: The value to store. + + itemsize: The size in bytes of the value (as counted towards the + store size). + + type: Functions used to manipulate the key. +*/ +void *fz_store_item(fz_context *ctx, void *key, void *val, unsigned int itemsize, fz_store_type *type); + +/* + fz_find_item: Find an item within the store. + + free: The function used to free the value (to ensure we get a value + of the correct type). + + key: The key to use to index the item. + + type: Functions used to manipulate the key. + + Returns NULL for not found, otherwise returns a pointer to the value + indexed by key to which a reference has been taken. +*/ +void *fz_find_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type); + +/* + fz_remove_item: Remove an item from the store. + + If an item indexed by the given key exists in the store, remove it. + + free: The function used to free the value (to ensure we get a value + of the correct type). + + key: The key to use to find the item to remove. + + type: Functions used to manipulate the key. +*/ +void fz_remove_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type); + +/* + fz_empty_store: Evict everything from the store. +*/ +void fz_empty_store(fz_context *ctx); + +/* + fz_store_scavenge: Internal function used as part of the scavenging + allocator; when we fail to allocate memory, before returning a + failure to the caller, we try to scavenge space within the store by + evicting at least 'size' bytes. The allocator then retries. + + size: The number of bytes we are trying to have free. + + phase: What phase of the scavenge we are in. Updated on exit. + + Returns non zero if we managed to free any memory. +*/ +int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase); + +/* + fz_print_store: Dump the contents of the store for debugging. +*/ +#ifndef NDEBUG +void fz_print_store(fz_context *ctx, FILE *out); +void fz_print_store_locked(fz_context *ctx, FILE *out); +#endif + +struct fz_buffer_s +{ + int refs; + unsigned char *data; + int cap, len; + int unused_bits; +}; + +/* + fz_new_buffer: Create a new buffer. + + capacity: Initial capacity. + + Returns pointer to new buffer. Throws exception on allocation + failure. +*/ +fz_buffer *fz_new_buffer(fz_context *ctx, int capacity); + +/* + fz_new_buffer: Create a new buffer. + + capacity: Initial capacity. + + Returns pointer to new buffer. Throws exception on allocation + failure. +*/ +fz_buffer *fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, int size); + +/* + fz_resize_buffer: Ensure that a buffer has a given capacity, + truncating data if required. + + buf: The buffer to alter. + + capacity: The desired capacity for the buffer. If the current size + of the buffer contents is smaller than capacity, it is truncated. + +*/ +void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int capacity); + +/* + fz_grow_buffer: Make some space within a buffer (i.e. ensure that + capacity > size). + + buf: The buffer to grow. + + May throw exception on failure to allocate. +*/ +void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); + +/* + fz_trim_buffer: Trim wasted capacity from a buffer. + + buf: The buffer to trim. +*/ +void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); + +/* + fz_buffer_cat: Concatenate buffers + + buf: first to concatenate and the holder of the result + extra: second to concatenate + + May throw exception on failure to allocate. +*/ +void fz_buffer_cat(fz_context *ctx, fz_buffer *buf, fz_buffer *extra); + +void fz_write_buffer(fz_context *ctx, fz_buffer *buf, const void *data, int len); + +void fz_write_buffer_byte(fz_context *ctx, fz_buffer *buf, int val); + +void fz_write_buffer_rune(fz_context *ctx, fz_buffer *buf, int val); + +void fz_write_buffer_bits(fz_context *ctx, fz_buffer *buf, int val, int bits); + +void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf); + +/* + fz_buffer_printf: print formatted to a buffer. The buffer will grow + as required. +*/ +int fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...); +int fz_buffer_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args); + +/* + fz_buffer_printf: print a string formatted as a pdf string to a buffer. + The buffer will grow. +*/ +void +fz_buffer_cat_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text); + +struct fz_stream_s +{ + fz_context *ctx; + int refs; + int error; + int eof; + int pos; + int avail; + int bits; + unsigned char *bp, *rp, *wp, *ep; + void *state; + int (*read)(fz_stream *stm, unsigned char *buf, int len); + void (*close)(fz_context *ctx, void *state); + void (*seek)(fz_stream *stm, int offset, int whence); + unsigned char buf[4096]; +}; + +fz_stream *fz_new_stream(fz_context *ctx, void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_context *, void *)); +fz_stream *fz_keep_stream(fz_stream *stm); +void fz_fill_buffer(fz_stream *stm); + +/* + fz_read_best: Attempt to read a stream into a buffer. If truncated + is NULL behaves as fz_read_all, otherwise does not throw exceptions + in the case of failure, but instead sets a truncated flag. + + stm: The stream to read from. + + initial: Suggested initial size for the buffer. + + truncated: Flag to store success/failure indication in. + + Returns a buffer created from reading from the stream. +*/ +fz_buffer *fz_read_best(fz_stream *stm, int initial, int *truncated); + +void fz_read_line(fz_stream *stm, char *buf, int max); + +static inline int fz_read_byte(fz_stream *stm) +{ + if (stm->rp == stm->wp) + { + fz_fill_buffer(stm); + return stm->rp < stm->wp ? *stm->rp++ : EOF; + } + return *stm->rp++; +} + +static inline int fz_peek_byte(fz_stream *stm) +{ + if (stm->rp == stm->wp) + { + fz_fill_buffer(stm); + return stm->rp < stm->wp ? *stm->rp : EOF; + } + return *stm->rp; +} + +static inline void fz_unread_byte(fz_stream *stm) +{ + if (stm->rp > stm->bp) + stm->rp--; +} + +static inline int fz_is_eof(fz_stream *stm) +{ + if (stm->rp == stm->wp) + { + if (stm->eof) + return 1; + return fz_peek_byte(stm) == EOF; + } + return 0; +} + +static inline unsigned int fz_read_bits(fz_stream *stm, int n) +{ + unsigned int x; + + if (n <= stm->avail) + { + stm->avail -= n; + x = (stm->bits >> stm->avail) & ((1 << n) - 1); + } + else + { + x = stm->bits & ((1 << stm->avail) - 1); + n -= stm->avail; + stm->avail = 0; + + while (n > 8) + { + x = (x << 8) | fz_read_byte(stm); + n -= 8; + } + + if (n > 0) + { + stm->bits = fz_read_byte(stm); + stm->avail = 8 - n; + x = (x << n) | (stm->bits >> stm->avail); + } + } + + return x; +} + +static inline void fz_sync_bits(fz_stream *stm) +{ + stm->avail = 0; +} + +static inline int fz_is_eof_bits(fz_stream *stm) +{ + return fz_is_eof(stm) && (stm->avail == 0 || stm->bits == EOF); +} + +static inline int fz_write_int32be(fz_output *out, int x) +{ + char data[4]; + + data[0] = x>>24; + data[1] = x>>16; + data[2] = x>>8; + data[3] = x; + + return fz_write(out, data, 4); +} + +static inline void +fz_write_byte(fz_output *out, int x) +{ + char data = x; + + fz_write(out, &data, 1); +} + +/* + * Data filters. + */ + +fz_stream *fz_open_copy(fz_stream *chain); +fz_stream *fz_open_null(fz_stream *chain, int len, int offset); +fz_stream *fz_open_concat(fz_context *ctx, int max, int pad); +void fz_concat_push(fz_stream *concat, fz_stream *chain); /* Ownership of chain is passed in */ +fz_stream *fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen); +fz_stream *fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen); +fz_stream *fz_open_a85d(fz_stream *chain); +fz_stream *fz_open_ahxd(fz_stream *chain); +fz_stream *fz_open_rld(fz_stream *chain); +fz_stream *fz_open_dctd(fz_stream *chain, int color_transform); +fz_stream *fz_open_resized_dctd(fz_stream *chain, int color_transform, int l2factor); +fz_stream *fz_open_faxd(fz_stream *chain, + int k, int end_of_line, int encoded_byte_align, + int columns, int rows, int end_of_block, int black_is_1); +fz_stream *fz_open_flated(fz_stream *chain); +fz_stream *fz_open_lzwd(fz_stream *chain, int early_change); +fz_stream *fz_open_predict(fz_stream *chain, int predictor, int columns, int colors, int bpc); +fz_stream *fz_open_jbig2d(fz_stream *chain, fz_buffer *global); + +/* + * Resources and other graphics related objects. + */ + +int fz_lookup_blendmode(char *name); +char *fz_blendmode_name(int blendmode); + +struct fz_bitmap_s +{ + int refs; + int w, h, stride, n; + int xres, yres; + unsigned char *samples; +}; + +fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n, int xres, int yres); + +void fz_bitmap_details(fz_bitmap *bitmap, int *w, int *h, int *n, int *stride); + +void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); + +/* + Pixmaps represent a set of pixels for a 2 dimensional region of a + plane. Each pixel has n components per pixel, the last of which is + always alpha. The data is in premultiplied alpha when rendering, but + non-premultiplied for colorspace conversions and rescaling. + + x, y: The minimum x and y coord of the region in pixels. + + w, h: The width and height of the region in pixels. + + n: The number of color components in the image. Always + includes a separate alpha channel. For mask images n=1, for greyscale + (plus alpha) images n=2, for rgb (plus alpha) images n=3. + + interpolate: A boolean flag set to non-zero if the image + will be drawn using linear interpolation, or set to zero if + image will be using nearest neighbour sampling. + + xres, yres: Image resolution in dpi. Default is 96 dpi. + + colorspace: Pointer to a colorspace object describing the colorspace + the pixmap is in. If NULL, the image is a mask. + + samples: A simple block of memory w * h * n bytes of memory in which + the components are stored. The first n bytes are components 0 to n-1 + for the pixel at (x,y). Each successive n bytes gives another pixel + in scanline order. Subsequent scanlines follow on with no padding. + + free_samples: Is zero when an application has provided its own + buffer for pixel data through fz_new_pixmap_with_bbox_and_data. + If not zero the buffer will be freed when fz_drop_pixmap is + called for the pixmap. +*/ +struct fz_pixmap_s +{ + fz_storable storable; + int x, y, w, h, n; + int interpolate; + int xres, yres; + fz_colorspace *colorspace; + unsigned char *samples; + int free_samples; +}; + +void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); + +void fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_irect *r); +void fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix); +fz_pixmap *fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity); +unsigned int fz_pixmap_size(fz_context *ctx, fz_pixmap *pix); + +fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_irect *clip); + +typedef struct fz_scale_cache_s fz_scale_cache; + +fz_scale_cache *fz_new_scale_cache(fz_context *ctx); +void fz_free_scale_cache(fz_context *ctx, fz_scale_cache *cache); +fz_pixmap *fz_scale_pixmap_cached(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, const fz_irect *clip, fz_scale_cache *cache_x, fz_scale_cache *cache_y); + +void fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor); + +fz_irect *fz_pixmap_bbox_no_ctx(fz_pixmap *src, fz_irect *bbox); + +typedef struct fz_compression_params_s fz_compression_params; + +typedef struct fz_compressed_buffer_s fz_compressed_buffer; +unsigned int fz_compressed_buffer_size(fz_compressed_buffer *buffer); + +fz_stream *fz_open_compressed_buffer(fz_context *ctx, fz_compressed_buffer *); +fz_stream *fz_open_image_decomp_stream(fz_context *ctx, fz_compressed_buffer *, int *l2factor); + +enum +{ + FZ_IMAGE_UNKNOWN = 0, + FZ_IMAGE_JPEG = 1, + FZ_IMAGE_JPX = 2, /* Placeholder until supported */ + FZ_IMAGE_FAX = 3, + FZ_IMAGE_JBIG2 = 4, /* Placeholder until supported */ + FZ_IMAGE_RAW = 5, + FZ_IMAGE_RLD = 6, + FZ_IMAGE_FLATE = 7, + FZ_IMAGE_LZW = 8, + FZ_IMAGE_PNG = 9, + FZ_IMAGE_TIFF = 10 +}; + +struct fz_compression_params_s +{ + int type; + union { + struct { + int color_transform; + } jpeg; + struct { + int smask_in_data; + } jpx; + struct { + int columns; + int rows; + int k; + int end_of_line; + int encoded_byte_align; + int end_of_block; + int black_is_1; + int damaged_rows_before_error; + } fax; + struct + { + int columns; + int colors; + int predictor; + int bpc; + } + flate; + struct + { + int columns; + int colors; + int predictor; + int bpc; + int early_change; + } lzw; + } u; +}; + +struct fz_compressed_buffer_s +{ + fz_compression_params params; + fz_buffer *buffer; +}; + +void fz_free_compressed_buffer(fz_context *ctx, fz_compressed_buffer *buf); + +fz_image *fz_new_image(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace, int xres, int yres, int interpolate, int imagemask, float *decode, int *colorkey, fz_compressed_buffer *buffer, fz_image *mask); +fz_image *fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, fz_image *mask); +fz_image *fz_new_image_from_data(fz_context *ctx, unsigned char *data, int len); +fz_image *fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer); +fz_pixmap *fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h); +void fz_free_image(fz_context *ctx, fz_storable *image); +fz_pixmap *fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int in_line, int indexed, int l2factor, int native_l2factor); +fz_pixmap *fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src); + +struct fz_image_s +{ + fz_storable storable; + int w, h, n, bpc; + fz_image *mask; + fz_colorspace *colorspace; + fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, int w, int h); + fz_compressed_buffer *buffer; + int colorkey[FZ_MAX_COLORS * 2]; + float decode[FZ_MAX_COLORS * 2]; + int imagemask; + int interpolate; + int usecolorkey; + fz_pixmap *tile; /* Private to the implementation */ + int xres; /* As given in the image, not necessarily as rendered */ + int yres; /* As given in the image, not necessarily as rendered */ +}; + +fz_pixmap *fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *cs, int indexed); +fz_pixmap *fz_load_png(fz_context *ctx, unsigned char *data, int size); +fz_pixmap *fz_load_tiff(fz_context *ctx, unsigned char *data, int size); + +void fz_load_jpeg_info(fz_context *ctx, unsigned char *data, int size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); +void fz_load_png_info(fz_context *ctx, unsigned char *data, int size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); +void fz_load_tiff_info(fz_context *ctx, unsigned char *data, int size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); + +struct fz_halftone_s +{ + int refs; + int n; + fz_pixmap *comp[1]; +}; + +fz_halftone *fz_new_halftone(fz_context *ctx, int num_comps); +fz_halftone *fz_default_halftone(fz_context *ctx, int num_comps); +void fz_drop_halftone(fz_context *ctx, fz_halftone *half); +fz_halftone *fz_keep_halftone(fz_context *ctx, fz_halftone *half); + +struct fz_colorspace_s +{ + fz_storable storable; + unsigned int size; + char name[16]; + int n; + void (*to_rgb)(fz_context *ctx, fz_colorspace *, float *src, float *rgb); + void (*from_rgb)(fz_context *ctx, fz_colorspace *, float *rgb, float *dst); + void (*free_data)(fz_context *Ctx, fz_colorspace *); + void *data; +}; + +fz_colorspace *fz_new_colorspace(fz_context *ctx, char *name, int n); +fz_colorspace *fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsigned char *lookup); +fz_colorspace *fz_keep_colorspace(fz_context *ctx, fz_colorspace *colorspace); +void fz_drop_colorspace(fz_context *ctx, fz_colorspace *colorspace); +void fz_free_colorspace_imp(fz_context *ctx, fz_storable *colorspace); + +void fz_convert_color(fz_context *ctx, fz_colorspace *dsts, float *dstv, fz_colorspace *srcs, float *srcv); + +void fz_new_colorspace_context(fz_context *ctx); +fz_colorspace_context *fz_keep_colorspace_context(fz_context *ctx); +void fz_drop_colorspace_context(fz_context *ctx); + +typedef struct fz_color_converter_s fz_color_converter; + +/* This structure is public because it allows us to avoid dynamic allocations. + * Callers should only rely on the convert entry - the rest of the structure + * is subject to change without notice. + */ +struct fz_color_converter_s +{ + void (*convert)(fz_color_converter *, float *, float *); + fz_context *ctx; + fz_colorspace *ds; + fz_colorspace *ss; +}; + +void fz_lookup_color_converter(fz_color_converter *cc, fz_context *ctx, fz_colorspace *ds, fz_colorspace *ss); + +/* + * Fonts come in two variants: + * Regular fonts are handled by FreeType. + * Type 3 fonts have callbacks to the interpreter. + */ + +char *ft_error_string(int err); + +struct fz_font_s +{ + int refs; + char name[32]; + + void *ft_face; /* has an FT_Face if used */ + int ft_substitute; /* ... substitute metrics */ + int ft_bold; /* ... synthesize bold */ + int ft_italic; /* ... synthesize italic */ + int ft_hint; /* ... force hinting for DynaLab fonts */ + + /* origin of font data */ + char *ft_file; + unsigned char *ft_data; + int ft_size; + + fz_matrix t3matrix; + void *t3resources; + fz_buffer **t3procs; /* has 256 entries if used */ + fz_display_list **t3lists; /* has 256 entries if used */ + float *t3widths; /* has 256 entries if used */ + char *t3flags; /* has 256 entries if used */ + void *t3doc; /* a pdf_document for the callback */ + void (*t3run)(void *doc, void *resources, fz_buffer *contents, fz_device *dev, const fz_matrix *ctm, void *gstate, int nestedDepth); + void (*t3freeres)(void *doc, void *resources); + + fz_rect bbox; /* font bbox is used only for t3 fonts */ + + /* per glyph bounding box cache */ + int use_glyph_bbox; + int bbox_count; + fz_rect *bbox_table; + + /* substitute metrics */ + int width_count; + int *width_table; /* in 1000 units */ +}; + +void fz_new_font_context(fz_context *ctx); +fz_font_context *fz_keep_font_context(fz_context *ctx); +void fz_drop_font_context(fz_context *ctx); + +fz_font *fz_new_type3_font(fz_context *ctx, char *name, const fz_matrix *matrix); + +fz_font *fz_new_font_from_memory(fz_context *ctx, char *name, unsigned char *data, int len, int index, int use_glyph_bbox); +fz_font *fz_new_font_from_file(fz_context *ctx, char *name, char *path, int index, int use_glyph_bbox); + +fz_font *fz_keep_font(fz_context *ctx, fz_font *font); +void fz_drop_font(fz_context *ctx, fz_font *font); + +void fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float xmax, float ymax); +fz_rect *fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz_rect *r); +int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid); + +#ifndef NDEBUG +void fz_print_font(fz_context *ctx, FILE *out, fz_font *font); +#endif + +/* + * Vector path buffer. + * It can be stroked and dashed, or be filled. + * It has a fill rule (nonzero or even_odd). + * + * When rendering, they are flattened, stroked and dashed straight + * into the Global Edge List. + */ + +typedef struct fz_path_s fz_path; +typedef struct fz_stroke_state_s fz_stroke_state; + +typedef union fz_path_item_s fz_path_item; + +typedef enum fz_path_item_kind_e +{ + FZ_MOVETO, + FZ_LINETO, + FZ_CURVETO, + FZ_CLOSE_PATH +} fz_path_item_kind; + +typedef enum fz_linecap_e +{ + FZ_LINECAP_BUTT = 0, + FZ_LINECAP_ROUND = 1, + FZ_LINECAP_SQUARE = 2, + FZ_LINECAP_TRIANGLE = 3 +} fz_linecap; + +typedef enum fz_linejoin_e +{ + FZ_LINEJOIN_MITER = 0, + FZ_LINEJOIN_ROUND = 1, + FZ_LINEJOIN_BEVEL = 2, + FZ_LINEJOIN_MITER_XPS = 3 +} fz_linejoin; + +union fz_path_item_s +{ + fz_path_item_kind k; + float v; +}; + +struct fz_path_s +{ + int len, cap; + fz_path_item *items; + int last; +}; + +struct fz_stroke_state_s +{ + int refs; + fz_linecap start_cap, dash_cap, end_cap; + fz_linejoin linejoin; + float linewidth; + float miterlimit; + float dash_phase; + int dash_len; + float dash_list[32]; +}; + +fz_path *fz_new_path(fz_context *ctx); +fz_point fz_currentpoint(fz_context *ctx, fz_path *path); +void fz_moveto(fz_context*, fz_path*, float x, float y); +void fz_lineto(fz_context*, fz_path*, float x, float y); +void fz_curveto(fz_context*,fz_path*, float, float, float, float, float, float); +void fz_curvetov(fz_context*,fz_path*, float, float, float, float); +void fz_curvetoy(fz_context*,fz_path*, float, float, float, float); +void fz_closepath(fz_context*,fz_path*); +void fz_free_path(fz_context *ctx, fz_path *path); + +void fz_transform_path(fz_context *ctx, fz_path *path, const fz_matrix *transform); + +fz_path *fz_clone_path(fz_context *ctx, fz_path *old); + +fz_rect *fz_bound_path(fz_context *ctx, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *r); +fz_rect *fz_adjust_rect_for_stroke(fz_rect *r, const fz_stroke_state *stroke, const fz_matrix *ctm); + +fz_stroke_state *fz_new_stroke_state(fz_context *ctx); +fz_stroke_state *fz_new_stroke_state_with_len(fz_context *ctx, int len); +fz_stroke_state *fz_keep_stroke_state(fz_context *ctx, fz_stroke_state *stroke); +void fz_drop_stroke_state(fz_context *ctx, fz_stroke_state *stroke); +fz_stroke_state *fz_unshare_stroke_state(fz_context *ctx, fz_stroke_state *shared); +fz_stroke_state *fz_unshare_stroke_state_with_len(fz_context *ctx, fz_stroke_state *shared, int len); + +#ifndef NDEBUG +void fz_print_path(fz_context *ctx, FILE *out, fz_path *, int indent); +#endif + +/* + * Glyph cache + */ + +void fz_new_glyph_cache_context(fz_context *ctx); +fz_glyph_cache *fz_keep_glyph_cache(fz_context *ctx); +void fz_drop_glyph_cache_context(fz_context *ctx); +void fz_purge_glyph_cache(fz_context *ctx); + +fz_path *fz_outline_ft_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm); +fz_path *fz_outline_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *ctm); +fz_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, const fz_matrix *trm, int aa); +fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, const fz_matrix *trm, fz_colorspace *model, fz_irect scissor); +fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, const fz_matrix *ctm, fz_stroke_state *state); +fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, const fz_matrix *, fz_colorspace *model, fz_irect scissor); +fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, const fz_matrix *, const fz_matrix *, fz_stroke_state *stroke, fz_irect scissor); +void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, const fz_matrix *trm, void *gstate, int nestedDepth); +void fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nestedDepth); + +/* + * Text buffer. + * + * The trm field contains the a, b, c and d coefficients. + * The e and f coefficients come from the individual elements, + * together they form the transform matrix for the glyph. + * + * Glyphs are referenced by glyph ID. + * The Unicode text equivalent is kept in a separate array + * with indexes into the glyph array. + */ + +typedef struct fz_text_s fz_text; +typedef struct fz_text_item_s fz_text_item; + +struct fz_text_item_s +{ + float x, y; + int gid; /* -1 for one gid to many ucs mappings */ + int ucs; /* -1 for one ucs to many gid mappings */ +}; + +struct fz_text_s +{ + fz_font *font; + fz_matrix trm; + int wmode; + int len, cap; + fz_text_item *items; +}; + +fz_text *fz_new_text(fz_context *ctx, fz_font *face, const fz_matrix *trm, int wmode); +void fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, float y); +void fz_free_text(fz_context *ctx, fz_text *text); +fz_rect *fz_bound_text(fz_context *ctx, fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *r); +fz_text *fz_clone_text(fz_context *ctx, fz_text *old); +void fz_print_text(fz_context *ctx, FILE *out, fz_text*); + +/* + * The generic function support. + */ + +typedef struct fz_function_s fz_function; + +void fz_eval_function(fz_context *ctx, fz_function *func, float *in, int inlen, float *out, int outlen); +fz_function *fz_keep_function(fz_context *ctx, fz_function *func); +void fz_drop_function(fz_context *ctx, fz_function *func); +unsigned int fz_function_size(fz_function *func); +#ifndef DEBUG +void pdf_debug_function(fz_function *func); +#endif + +enum +{ + FZ_FN_MAXN = FZ_MAX_COLORS, + FZ_FN_MAXM = FZ_MAX_COLORS +}; + +struct fz_function_s +{ + fz_storable storable; + unsigned int size; + int m; /* number of input values */ + int n; /* number of output values */ + void (*evaluate)(fz_context *ctx, fz_function *func, float *in, float *out); +#ifndef NDEBUG + void (*debug)(fz_function *func); +#endif +}; + +/* + * The shading code uses gouraud shaded triangle meshes. + */ + +enum +{ + FZ_FUNCTION_BASED = 1, + FZ_LINEAR = 2, + FZ_RADIAL = 3, + FZ_MESH_TYPE4 = 4, + FZ_MESH_TYPE5 = 5, + FZ_MESH_TYPE6 = 6, + FZ_MESH_TYPE7 = 7 +}; + +typedef struct fz_shade_s fz_shade; + +struct fz_shade_s +{ + fz_storable storable; + + fz_rect bbox; /* can be fz_infinite_rect */ + fz_colorspace *colorspace; + + fz_matrix matrix; /* matrix from pattern dict */ + int use_background; /* background color for fills but not 'sh' */ + float background[FZ_MAX_COLORS]; + + int use_function; + float function[256][FZ_MAX_COLORS + 1]; + + int type; /* function, linear, radial, mesh */ + union + { + struct + { + int extend[2]; + float coords[2][3]; /* (x,y,r) twice */ + } l_or_r; + struct + { + int vprow; + int bpflag; + int bpcoord; + int bpcomp; + float x0, x1; + float y0, y1; + float c0[FZ_MAX_COLORS]; + float c1[FZ_MAX_COLORS]; + } m; + struct + { + fz_matrix matrix; + int xdivs; + int ydivs; + float domain[2][2]; + float *fn_vals; + } f; + } u; + + fz_compressed_buffer *buffer; +}; + +fz_shade *fz_keep_shade(fz_context *ctx, fz_shade *shade); +void fz_drop_shade(fz_context *ctx, fz_shade *shade); +void fz_free_shade_imp(fz_context *ctx, fz_storable *shade); + +fz_rect *fz_bound_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_rect *r); +void fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, const fz_irect *bbox); + +/* + * Handy routine for processing mesh based shades + */ +typedef struct fz_vertex_s fz_vertex; + +struct fz_vertex_s +{ + fz_point p; + float c[FZ_MAX_COLORS]; +}; + +typedef struct fz_mesh_processor_s fz_mesh_processor; + +typedef void (fz_mesh_process_fn)(void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv); + +struct fz_mesh_processor_s { + fz_context *ctx; + fz_shade *shade; + fz_mesh_process_fn *process; + void *process_arg; + int ncomp; +}; + +void fz_process_mesh(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, + fz_mesh_process_fn *process, void *process_arg); + +#ifndef NDEBUG +void fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade); +#endif + +/* + * Scan converter + */ + +typedef struct fz_gel_s fz_gel; + +fz_gel *fz_new_gel(fz_context *ctx); +void fz_insert_gel(fz_gel *gel, float x0, float y0, float x1, float y1); +void fz_reset_gel(fz_gel *gel, const fz_irect *clip); +void fz_sort_gel(fz_gel *gel); +fz_irect *fz_bound_gel(const fz_gel *gel, fz_irect *bbox); +void fz_free_gel(fz_gel *gel); +int fz_is_rect_gel(fz_gel *gel); + +void fz_scan_convert(fz_gel *gel, int eofill, const fz_irect *clip, fz_pixmap *pix, unsigned char *colorbv); + +void fz_flatten_fill_path(fz_gel *gel, fz_path *path, const fz_matrix *ctm, float flatness); +void fz_flatten_stroke_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, float flatness, float linewidth); +void fz_flatten_dash_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, float flatness, float linewidth); + +fz_irect *fz_bound_path_accurate(fz_context *ctx, fz_irect *bbox, const fz_irect *scissor, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, float flatness, float linewidth); + +/* + * The device interface. + */ + +fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest); + +enum +{ + /* Flags */ + FZ_DEVFLAG_MASK = 1, + FZ_DEVFLAG_COLOR = 2, + FZ_DEVFLAG_UNCACHEABLE = 4, + FZ_DEVFLAG_FILLCOLOR_UNDEFINED = 8, + FZ_DEVFLAG_STROKECOLOR_UNDEFINED = 16, + FZ_DEVFLAG_STARTCAP_UNDEFINED = 32, + FZ_DEVFLAG_DASHCAP_UNDEFINED = 64, + FZ_DEVFLAG_ENDCAP_UNDEFINED = 128, + FZ_DEVFLAG_LINEJOIN_UNDEFINED = 256, + FZ_DEVFLAG_MITERLIMIT_UNDEFINED = 512, + FZ_DEVFLAG_LINEWIDTH_UNDEFINED = 1024, + /* Arguably we should have a bit for the dash pattern itself being + * undefined, but that causes problems; do we assume that it should + * always be set to non-dashing at the start of every glyph? */ +}; + +struct fz_device_s +{ + int hints; + int flags; + + void *user; + void (*free_user)(fz_device *); + fz_context *ctx; + + void (*begin_page)(fz_device *, const fz_rect *rect, const fz_matrix *ctm); + void (*end_page)(fz_device *); + + void (*fill_path)(fz_device *, fz_path *, int even_odd, const fz_matrix *, fz_colorspace *, float *color, float alpha); + void (*stroke_path)(fz_device *, fz_path *, fz_stroke_state *, const fz_matrix *, fz_colorspace *, float *color, float alpha); + void (*clip_path)(fz_device *, fz_path *, const fz_rect *rect, int even_odd, const fz_matrix *); + void (*clip_stroke_path)(fz_device *, fz_path *, const fz_rect *rect, fz_stroke_state *, const fz_matrix *); + + void (*fill_text)(fz_device *, fz_text *, const fz_matrix *, fz_colorspace *, float *color, float alpha); + void (*stroke_text)(fz_device *, fz_text *, fz_stroke_state *, const fz_matrix *, fz_colorspace *, float *color, float alpha); + void (*clip_text)(fz_device *, fz_text *, const fz_matrix *, int accumulate); + void (*clip_stroke_text)(fz_device *, fz_text *, fz_stroke_state *, const fz_matrix *); + void (*ignore_text)(fz_device *, fz_text *, const fz_matrix *); + + void (*fill_shade)(fz_device *, fz_shade *shd, const fz_matrix *ctm, float alpha); + void (*fill_image)(fz_device *, fz_image *img, const fz_matrix *ctm, float alpha); + void (*fill_image_mask)(fz_device *, fz_image *img, const fz_matrix *ctm, fz_colorspace *, float *color, float alpha); + void (*clip_image_mask)(fz_device *, fz_image *img, const fz_rect *rect, const fz_matrix *ctm); + + void (*pop_clip)(fz_device *); + + void (*begin_mask)(fz_device *, const fz_rect *, int luminosity, fz_colorspace *, float *bc); + void (*end_mask)(fz_device *); + void (*begin_group)(fz_device *, const fz_rect *, int isolated, int knockout, int blendmode, float alpha); + void (*end_group)(fz_device *); + + int (*begin_tile)(fz_device *, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id); + void (*end_tile)(fz_device *); + + int error_depth; + char errmess[256]; +}; + +void fz_begin_page(fz_device *dev, const fz_rect *rect, const fz_matrix *ctm); +void fz_end_page(fz_device *dev); +void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm); +void fz_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm); +void fz_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate); +void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm); +void fz_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm); +void fz_pop_clip(fz_device *dev); +void fz_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha); +void fz_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha); +void fz_fill_image_mask(fz_device *dev, fz_image *image, const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_image_mask(fz_device *dev, fz_image *image, const fz_rect *rect, const fz_matrix *ctm); +void fz_begin_mask(fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace *colorspace, float *bc); +void fz_end_mask(fz_device *dev); +void fz_begin_group(fz_device *dev, const fz_rect *area, int isolated, int knockout, int blendmode, float alpha); +void fz_end_group(fz_device *dev); +void fz_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm); +int fz_begin_tile_id(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id); +void fz_end_tile(fz_device *dev); + +fz_device *fz_new_device(fz_context *ctx, void *user); + +/* + * Plotting functions. + */ + +void fz_decode_tile(fz_pixmap *pix, float *decode); +void fz_decode_indexed_tile(fz_pixmap *pix, float *decode, int maxval); +void fz_unpack_tile(fz_pixmap *dst, unsigned char * restrict src, int n, int depth, int stride, int scale); + +void fz_paint_solid_alpha(unsigned char * restrict dp, int w, int alpha); +void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned char *color); + +void fz_paint_span(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha); +void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color); + +void fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha); +void fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, unsigned char *colorbv); + +void fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha); +void fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk); +void fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bbox); + +void fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int isolated, fz_pixmap *shape); +void fz_blend_pixel(unsigned char dp[3], unsigned char bp[3], unsigned char sp[3], int blendmode); + +enum +{ + /* PDF 1.4 -- standard separable */ + FZ_BLEND_NORMAL, + FZ_BLEND_MULTIPLY, + FZ_BLEND_SCREEN, + FZ_BLEND_OVERLAY, + FZ_BLEND_DARKEN, + FZ_BLEND_LIGHTEN, + FZ_BLEND_COLOR_DODGE, + FZ_BLEND_COLOR_BURN, + FZ_BLEND_HARD_LIGHT, + FZ_BLEND_SOFT_LIGHT, + FZ_BLEND_DIFFERENCE, + FZ_BLEND_EXCLUSION, + + /* PDF 1.4 -- standard non-separable */ + FZ_BLEND_HUE, + FZ_BLEND_SATURATION, + FZ_BLEND_COLOR, + FZ_BLEND_LUMINOSITY, + + /* For packing purposes */ + FZ_BLEND_MODEMASK = 15, + FZ_BLEND_ISOLATED = 16, + FZ_BLEND_KNOCKOUT = 32 +}; + +struct fz_document_s +{ + void (*close)(fz_document *); + int (*needs_password)(fz_document *doc); + int (*authenticate_password)(fz_document *doc, char *password); + fz_outline *(*load_outline)(fz_document *doc); + int (*count_pages)(fz_document *doc); + fz_page *(*load_page)(fz_document *doc, int number); + fz_link *(*load_links)(fz_document *doc, fz_page *page); + fz_rect *(*bound_page)(fz_document *doc, fz_page *page, fz_rect *); + void (*run_page_contents)(fz_document *doc, fz_page *page, fz_device *dev, const fz_matrix *transform, fz_cookie *cookie); + void (*run_annot)(fz_document *doc, fz_page *page, fz_annot *annot, fz_device *dev, const fz_matrix *transform, fz_cookie *cookie); + void (*free_page)(fz_document *doc, fz_page *page); + int (*meta)(fz_document *doc, int key, void *ptr, int size); + fz_transition *(*page_presentation)(fz_document *doc, fz_page *page, float *duration); + void (*write)(fz_document *doc, char *filename, fz_write_options *opts); + fz_annot *(*first_annot)(fz_document *doc, fz_page *page); + fz_annot *(*next_annot)(fz_document *doc, fz_annot *annot); + fz_rect *(*bound_annot)(fz_document *doc, fz_annot *annot, fz_rect *rect); +}; + #endif |