From c732cd69db005902289829867a71e0d271809aba Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 21 Feb 2012 22:47:03 +0100 Subject: Set default DPI in jpeg images if the file says 0. --- fitz/image_jpeg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fitz') diff --git a/fitz/image_jpeg.c b/fitz/image_jpeg.c index f53b6124..cef53d93 100644 --- a/fitz/image_jpeg.c +++ b/fitz/image_jpeg.c @@ -115,6 +115,9 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen) image->yres = cinfo.Y_density * 254 / 100; } + if (image->xres <= 0) image->xres = 72; + if (image->yres <= 0) image->yres = 72; + fz_clear_pixmap(ctx, image); row[0] = fz_malloc(ctx, cinfo.output_components * cinfo.output_width); -- cgit v1.2.3 From 7c19fd50ea7ee9dfd253220a0ea2cac4df7d6345 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Tue, 21 Feb 2012 17:17:30 +0000 Subject: Fix a double free on an error path. --- fitz/res_pixmap.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fitz') diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index dbed0842..500eb4be 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -65,6 +65,8 @@ fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h } fz_catch(ctx) { + if (colorspace) + fz_drop_colorspace(ctx, colorspace); fz_free(ctx, pix); fz_rethrow(ctx); } -- cgit v1.2.3 From f86c02284c259b9034f324dffe76969efa8b2e42 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Tue, 21 Feb 2012 17:09:10 +0000 Subject: Rework image handling for on demand decode Introduce a new 'fz_image' type; this type contains rudimentary information about images (such as native, size, colorspace etc) and a function to call to get a pixmap of that image (with a size hint). Instead of passing pixmaps through the device interface (and holding pixmaps in the display list) we now pass images instead. The rendering routines therefore call fz_image_to_pixmap to get pixmaps to render, and fz_pixmap_drop those afterwards. The file format handling routines therefore need to produce images rather than pixmaps; xps and cbz currently just wrap pixmaps as images. PDF is more involved. The stream handling routines in PDF have been altered so that they can recognise when the last stream entry in a filter dictionary is an image decoding filter. Rather than applying this filter, they read and store the parameters into a pdf_image_params structure, and stop decoding at that point. This allows us to read the compressed data for an image into memory as a block. We can then restart the image decode process later. pdf_images therefore consist of the compressed image data for images. When a pixmap is requested for such an image, the code checks to see if we have one (of an appropriate size), and if not, decodes it. The size hint is used to determine whether it is possible to subsample the image; currently this is only supported for JPEGs, but we could add generic subsampling code later. In order to handle caching the produced images, various changes have been made to the store and the underlying hash table. Previously the store was indexed purely by fz_obj keys; we don't have an fz_obj key any more, so have extended the store by adding a concept of a key 'type'. A key type is a pointer to a set of functions that keep/drop/compare and make a hashable key from a key pointer. We make a pdf_store.c file that contains functions to offer the existing fz_obj based functions, and add a new 'type' for keys (based on the fz_image handle, and the subsample factor) in the pdf_image.c file. While working on this, a problem became apparent in the existing store codel; fz_obj objects had no protection on their reference counts, hence an interpreter thread could try to alter a ref count at the same time as a malloc caused an eviction from the store. This has been solved by using the alloc lock as protection. This in turn requires some tweaks to the code to make sure we don't try and keep/drop fz_obj's from the store code while the alloc lock is held. A side effect of this work is that when a hash table is created, we inform it what lock should be used to protect its innards (if any). If the alloc lock is used, the insert method knows to drop/retake it to allow it to safely expand the hash table. Callers to the hash functions have the responsibility of taking/dropping the appropriate lock, and ensuring that they cope with the possibility that insert might drop the alloc lock, causing race conditions. --- fitz/base_hash.c | 97 +++++++++++++++++++++++++------------ fitz/dev_bbox.c | 4 +- fitz/dev_list.c | 16 +++---- fitz/dev_null.c | 6 +-- fitz/dev_trace.c | 6 +-- fitz/filt_dctd.c | 11 +++++ fitz/fitz.h | 72 ++++++++++++++++++++++++---- fitz/res_colorspace.c | 2 +- fitz/res_pixmap.c | 20 ++++++++ fitz/res_store.c | 130 ++++++++++++++++++++++++-------------------------- fitz/stm_read.c | 3 +- 11 files changed, 240 insertions(+), 127 deletions(-) (limited to 'fitz') diff --git a/fitz/base_hash.c b/fitz/base_hash.c index 630f6b6a..0fda86cd 100644 --- a/fitz/base_hash.c +++ b/fitz/base_hash.c @@ -22,6 +22,7 @@ struct fz_hash_table_s int keylen; int size; int load; + int lock; /* -1 or the lock used to protect this hash table */ fz_hash_entry *ents; }; @@ -42,7 +43,7 @@ static unsigned hash(unsigned char *s, int len) } fz_hash_table * -fz_new_hash_table(fz_context *ctx, int initialsize, int keylen) +fz_new_hash_table(fz_context *ctx, int initialsize, int keylen, int lock) { fz_hash_table *table; @@ -52,6 +53,7 @@ fz_new_hash_table(fz_context *ctx, int initialsize, int keylen) table->keylen = keylen; table->size = initialsize; table->load = 0; + table->lock = lock; fz_try(ctx) { table->ents = fz_malloc_array(ctx, table->size, sizeof(fz_hash_entry)); @@ -98,10 +100,45 @@ fz_free_hash(fz_context *ctx, fz_hash_table *table) fz_free(ctx, table); } +static void * +do_hash_insert(fz_context *ctx, fz_hash_table *table, void *key, void *val) +{ + fz_hash_entry *ents; + unsigned size; + unsigned pos; + + ents = table->ents; + size = table->size; + pos = hash(key, table->keylen) % size; + + if (table->lock >= 0) + fz_assert_lock_held(ctx, table->lock); + + while (1) + { + if (!ents[pos].val) + { + memcpy(ents[pos].key, key, table->keylen); + ents[pos].val = val; + table->load ++; + return NULL; + } + + if (memcmp(key, ents[pos].key, table->keylen) == 0) + { + fz_warn(ctx, "assert: overwrite hash slot"); + return ents[pos].val = val; + } + + pos = (pos + 1) % size; + } +} + static void fz_resize_hash(fz_context *ctx, fz_hash_table *table, int newsize) { fz_hash_entry *oldents = table->ents; + fz_hash_entry *newents = table->ents; int oldsize = table->size; int oldload = table->load; int i; @@ -112,7 +149,22 @@ fz_resize_hash(fz_context *ctx, fz_hash_table *table, int newsize) return; } - table->ents = fz_malloc_array(ctx, newsize, sizeof(fz_hash_entry)); + if (table->lock == FZ_LOCK_ALLOC) + fz_unlock(ctx, FZ_LOCK_ALLOC); + newents = fz_malloc_array(ctx, newsize, sizeof(fz_hash_entry)); + if (table->lock == FZ_LOCK_ALLOC) + fz_lock(ctx, FZ_LOCK_ALLOC); + if (table->lock >= 0) + { + if (table->size >= newsize) + { + /* Someone else fixed it before we could lock! */ + fz_unlock(ctx, table->lock); + fz_free(ctx, newents); + return; + } + } + table->ents = newents; memset(table->ents, 0, sizeof(fz_hash_entry) * newsize); table->size = newsize; table->load = 0; @@ -121,11 +173,15 @@ fz_resize_hash(fz_context *ctx, fz_hash_table *table, int newsize) { if (oldents[i].val) { - fz_hash_insert(ctx, table, oldents[i].key, oldents[i].val); + do_hash_insert(ctx, table, oldents[i].key, oldents[i].val); } } + if (table->lock == FZ_LOCK_ALLOC) + fz_unlock(ctx, FZ_LOCK_ALLOC); fz_free(ctx, oldents); + if (table->lock == FZ_LOCK_ALLOC) + fz_lock(ctx, FZ_LOCK_ALLOC); } void * @@ -135,6 +191,9 @@ fz_hash_find(fz_context *ctx, fz_hash_table *table, void *key) unsigned size = table->size; unsigned pos = hash(key, table->keylen) % size; + if (table->lock >= 0) + fz_assert_lock_held(ctx, table->lock); + while (1) { if (!ents[pos].val) @@ -150,37 +209,12 @@ 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) { - fz_hash_entry *ents; - unsigned size; - unsigned pos; - if (table->load > table->size * 8 / 10) { fz_resize_hash(ctx, table, table->size * 2); } - ents = table->ents; - size = table->size; - pos = hash(key, table->keylen) % size; - - while (1) - { - if (!ents[pos].val) - { - memcpy(ents[pos].key, key, table->keylen); - ents[pos].val = val; - table->load ++; - return NULL; - } - - if (memcmp(key, ents[pos].key, table->keylen) == 0) - { - fz_warn(ctx, "assert: overwrite hash slot"); - return ents[pos].val; - } - - pos = (pos + 1) % size; - } + return do_hash_insert(ctx, table, key, val); } void @@ -191,11 +225,14 @@ fz_hash_remove(fz_context *ctx, fz_hash_table *table, void *key) unsigned pos = hash(key, table->keylen) % size; unsigned hole, look, code; + if (table->lock >= 0) + fz_assert_lock_held(ctx, table->lock); + while (1) { if (!ents[pos].val) { - fz_warn(ctx, "assert: remove inexistent hash entry"); + fz_warn(ctx, "assert: remove non-existent hash entry"); return; } diff --git a/fitz/dev_bbox.c b/fitz/dev_bbox.c index 636ceb94..b015c585 100644 --- a/fitz/dev_bbox.c +++ b/fitz/dev_bbox.c @@ -47,7 +47,7 @@ fz_bbox_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) } static void -fz_bbox_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_bbox_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { fz_bbox *result = dev->user; fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, fz_unit_rect)); @@ -55,7 +55,7 @@ fz_bbox_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) } static void -fz_bbox_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, +fz_bbox_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_bbox_fill_image(dev, image, ctm, alpha); diff --git a/fitz/dev_list.c b/fitz/dev_list.c index adc691d0..1d82421e 100644 --- a/fitz/dev_list.c +++ b/fitz/dev_list.c @@ -37,7 +37,7 @@ struct fz_display_node_s fz_path *path; fz_text *text; fz_shade *shade; - fz_pixmap *image; + fz_image *image; int blendmode; } item; fz_stroke_state *stroke; @@ -207,7 +207,7 @@ fz_free_display_node(fz_context *ctx, fz_display_node *node) case FZ_CMD_FILL_IMAGE: case FZ_CMD_FILL_IMAGE_MASK: case FZ_CMD_CLIP_IMAGE_MASK: - fz_drop_pixmap(ctx, node->item.image); + fz_drop_image(ctx, node->item.image); break; case FZ_CMD_POP_CLIP: case FZ_CMD_BEGIN_MASK: @@ -435,35 +435,35 @@ fz_list_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) } static void -fz_list_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_list_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { fz_display_node *node; node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); node->rect = fz_transform_rect(ctm, fz_unit_rect); - node->item.image = fz_keep_pixmap(dev->ctx, image); + node->item.image = fz_keep_image(dev->ctx, image); fz_append_display_node(dev->user, node); } static void -fz_list_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, +fz_list_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_display_node *node; node = fz_new_display_node(dev->ctx, FZ_CMD_FILL_IMAGE_MASK, ctm, colorspace, color, alpha); node->rect = fz_transform_rect(ctm, fz_unit_rect); - node->item.image = fz_keep_pixmap(dev->ctx, image); + node->item.image = fz_keep_image(dev->ctx, image); fz_append_display_node(dev->user, node); } static void -fz_list_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) +fz_list_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm) { fz_display_node *node; node = fz_new_display_node(dev->ctx, FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); node->rect = fz_transform_rect(ctm, fz_unit_rect); if (rect) node->rect = fz_intersect_rect(node->rect, *rect); - node->item.image = fz_keep_pixmap(dev->ctx, image); + node->item.image = fz_keep_image(dev->ctx, image); fz_append_display_node(dev->user, node); } diff --git a/fitz/dev_null.c b/fitz/dev_null.c index b4ba5cbe..d817932d 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -103,14 +103,14 @@ fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) } void -fz_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { if (dev->fill_image) dev->fill_image(dev, image, ctm, alpha); } void -fz_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, +fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { if (dev->fill_image_mask) @@ -118,7 +118,7 @@ fz_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, } void -fz_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) +fz_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm) { if (dev->clip_image_mask) dev->clip_image_mask(dev, image, rect, ctm); diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index 1c2e1ed1..9faffc35 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -197,7 +197,7 @@ fz_trace_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) } static void -fz_trace_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) +fz_trace_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha) { printf("scale_num = 8/state->factor; + cinfo->scale_denom = 8; + jpeg_start_decompress(cinfo); state->stride = cinfo->output_width * cinfo->output_components; @@ -215,6 +219,12 @@ skip: /* Default: color_transform = -1 (unset) */ fz_stream * fz_open_dctd(fz_stream *chain, int color_transform) +{ + return fz_open_resized_dctd(chain, color_transform, 1); +} + +fz_stream * +fz_open_resized_dctd(fz_stream *chain, int color_transform, int factor) { fz_context *ctx = chain->ctx; fz_dctd *state = NULL; @@ -228,6 +238,7 @@ fz_open_dctd(fz_stream *chain, int color_transform) state->chain = chain; state->color_transform = color_transform; state->init = 0; + state->factor = factor; } fz_catch(ctx) { diff --git a/fitz/fitz.h b/fitz/fitz.h index d2672031..856df7e5 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -504,7 +504,7 @@ extern char *fz_optarg; typedef struct fz_hash_table_s fz_hash_table; -fz_hash_table *fz_new_hash_table(fz_context *ctx, int initialsize, int keylen); +fz_hash_table *fz_new_hash_table(fz_context *ctx, int initialsize, int keylen, int lock); void fz_debug_hash(fz_context *ctx, fz_hash_table *table); void fz_empty_hash(fz_context *ctx, fz_hash_table *table); void fz_free_hash(fz_context *ctx, fz_hash_table *table); @@ -810,6 +810,36 @@ enum { FZ_STORE_DEFAULT = 256 << 20, }; +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; + } 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 *); +}; + void fz_new_store_context(fz_context *ctx, unsigned int max); void fz_drop_store_context(fz_context *ctx); fz_store *fz_store_keep(fz_context *ctx); @@ -818,9 +848,9 @@ void fz_debug_store(fz_context *ctx); void *fz_keep_storable(fz_context *, fz_storable *); void fz_drop_storable(fz_context *, fz_storable *); -void fz_store_item(fz_context *ctx, fz_obj *key, void *val, unsigned int itemsize); -void *fz_find_item(fz_context *ctx, fz_store_free_fn *freefn, fz_obj *key); -void fz_remove_item(fz_context *ctx, fz_store_free_fn *freefn, fz_obj *key); +void *fz_store_item(fz_context *ctx, void *key, void *val, unsigned int itemsize, fz_store_type *type); +void *fz_find_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type); +void fz_remove_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type); void fz_empty_store(fz_context *ctx); int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase); @@ -959,6 +989,7 @@ 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 factor); 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); @@ -1023,6 +1054,27 @@ void fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename); void fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); void fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); +/* + * Images are either a reference to a pixmap, or details of how to make + * a pixmap. To know how to make a pixmap we need a block of compressed + * data (typically a stream decoded all the way until the image filter) + * and then the details of the params for the filter to do the final step. + */ +typedef struct fz_image_s fz_image; + +struct fz_image_s +{ + fz_storable storable; + int w, h; + fz_image *mask; + fz_colorspace *colorspace; + fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, int w, int h); +}; + +fz_pixmap *fz_image_to_pixmap(fz_context *, fz_image *, int w, int h); +void fz_drop_image(fz_context *ctx, fz_image *image); +fz_image *fz_keep_image(fz_context *ctx, fz_image *image); + fz_pixmap *fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *cs); fz_pixmap *fz_load_jpeg(fz_context *doc, unsigned char *data, int size); fz_pixmap *fz_load_png(fz_context *doc, unsigned char *data, int size); @@ -1413,9 +1465,9 @@ struct fz_device_s void (*ignore_text)(fz_device *, fz_text *, fz_matrix); void (*fill_shade)(fz_device *, fz_shade *shd, fz_matrix ctm, float alpha); - void (*fill_image)(fz_device *, fz_pixmap *img, fz_matrix ctm, float alpha); - void (*fill_image_mask)(fz_device *, fz_pixmap *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); - void (*clip_image_mask)(fz_device *, fz_pixmap *img, fz_rect *rect, fz_matrix ctm); + void (*fill_image)(fz_device *, fz_image *img, fz_matrix ctm, float alpha); + void (*fill_image_mask)(fz_device *, fz_image *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); + void (*clip_image_mask)(fz_device *, fz_image *img, fz_rect *rect, fz_matrix ctm); void (*pop_clip)(fz_device *); @@ -1439,9 +1491,9 @@ void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm); void fz_pop_clip(fz_device *dev); void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha); -void fz_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha); -void fz_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm); +void fz_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha); +void fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm); void fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc); void fz_end_mask(fz_device *dev); void fz_begin_group(fz_device *dev, fz_rect area, int isolated, int knockout, int blendmode, float alpha); diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 413da3ae..c25fc99f 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -465,7 +465,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) fz_hash_table *lookup; unsigned char *color; - lookup = fz_new_hash_table(ctx, 509, srcn); + lookup = fz_new_hash_table(ctx, 509, srcn, -1); for (y = 0; y < src->h; y++) { diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index 500eb4be..328a8c2d 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -551,3 +551,23 @@ fz_pixmap_size(fz_context *ctx, fz_pixmap * pix) return 0; return sizeof(*pix) + pix->n * pix->w * pix->h; } + +fz_pixmap * +fz_image_to_pixmap(fz_context *ctx, fz_image *image, int w, int h) +{ + if (image == NULL) + return NULL; + return image->get_pixmap(ctx, image, w, h); +} + +fz_image * +fz_keep_image(fz_context *ctx, fz_image *image) +{ + return (fz_image *)fz_keep_storable(ctx, &image->storable); +} + +void +fz_drop_image(fz_context *ctx, fz_image *image) +{ + fz_drop_storable(ctx, &image->storable); +} diff --git a/fitz/res_store.c b/fitz/res_store.c index 5eec1f0d..461ea7c8 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -1,21 +1,14 @@ #include "fitz.h" -#include "mupdf.h" struct fz_item_s { - fz_obj *key; + void *key; fz_storable *val; unsigned int size; fz_item *next; fz_item *prev; fz_store *store; -}; - -struct refkey -{ - fz_store_free_fn *free; - int num; - int gen; + fz_store_type *type; }; struct fz_store_s @@ -43,7 +36,7 @@ fz_new_store_context(fz_context *ctx, unsigned int max) store = fz_malloc_struct(ctx, fz_store); fz_try(ctx) { - store->hash = fz_new_hash_table(ctx, 4096, sizeof(struct refkey)); + store->hash = fz_new_hash_table(ctx, 4096, sizeof(fz_store_hash), FZ_LOCK_ALLOC); } fz_catch(ctx) { @@ -114,20 +107,19 @@ evict(fz_context *ctx, fz_item *item) store->head = item->next; /* Drop a reference to the value (freeing if required) */ drop = (item->val->refs > 0 && --item->val->refs == 0); - fz_unlock(ctx, FZ_LOCK_ALLOC); /* Remove from the hash table */ - if (fz_is_indirect(item->key)) + if (item->type->make_hash_key) { - struct refkey refkey; - refkey.free = item->val->free; - refkey.num = fz_to_num(item->key); - refkey.gen = fz_to_gen(item->key); - fz_hash_remove(ctx, store->hash, &refkey); + fz_store_hash hash = { NULL }; + hash.free = item->val->free; + if (item->type->make_hash_key(&hash, item->key)) + fz_hash_remove(ctx, store->hash, &hash); } + fz_unlock(ctx, FZ_LOCK_ALLOC); if (drop) item->val->free(ctx, item->val); /* Always drops the key and free the item */ - fz_drop_obj(item->key); + item->type->drop_key(ctx, item->key); fz_free(ctx, item); fz_lock(ctx, FZ_LOCK_ALLOC); } @@ -194,30 +186,21 @@ ensure_space(fz_context *ctx, unsigned int tofree) return count; } -void -fz_store_item(fz_context *ctx, fz_obj *key, void *val_, unsigned int itemsize) +void * +fz_store_item(fz_context *ctx, void *key, void *val_, unsigned int itemsize, fz_store_type *type) { fz_item *item = NULL; unsigned int size; fz_storable *val = (fz_storable *)val_; fz_store *store = ctx->store; - int indirect; - struct refkey refkey; + fz_store_hash hash = { NULL }; + int use_hash = 0; if (!store) - return; + return NULL; fz_var(item); - /* Form the key before we take the lock */ - indirect = fz_is_indirect(key); - if (indirect) - { - refkey.free = val->free; - refkey.num = fz_to_num(key); - refkey.gen = fz_to_gen(key); - } - /* If we fail for any reason, we swallow the exception and continue. * All that the above program will see is that we failed to store * the item. */ @@ -227,9 +210,16 @@ fz_store_item(fz_context *ctx, fz_obj *key, void *val_, unsigned int itemsize) } fz_catch(ctx) { - return; + return NULL; } + if (type->make_hash_key) + { + hash.free = val->free; + use_hash = type->make_hash_key(&hash, key); + } + + type->keep_key(ctx, key); fz_lock(ctx, FZ_LOCK_ALLOC); if (store->max != FZ_STORE_UNLIMITED) { @@ -242,34 +232,41 @@ fz_store_item(fz_context *ctx, fz_obj *key, void *val_, unsigned int itemsize) /* Failed to free any space */ fz_unlock(ctx, FZ_LOCK_ALLOC); fz_free(ctx, item); - return; + type->drop_key(ctx, key); + return NULL; } } } store->size += itemsize; - item->key = fz_keep_obj(key); + item->key = key; item->val = val; item->size = itemsize; item->next = NULL; + item->type = type; /* If we can index it fast, put it into the hash table */ - if (indirect) + if (use_hash) { - fz_unlock(ctx, FZ_LOCK_ALLOC); + fz_pixmap *existing; + fz_try(ctx) { - fz_hash_insert(ctx, store->hash, &refkey, item); + /* May drop and retake the lock */ + existing = fz_hash_insert(ctx, store->hash, &hash, item); } fz_catch(ctx) { - fz_free(ctx, item); - fz_lock(ctx, FZ_LOCK_ALLOC); store->size -= itemsize; fz_unlock(ctx, FZ_LOCK_ALLOC); - return; + fz_free(ctx, item); + return NULL; + } + if (existing) + { + fz_unlock(ctx, FZ_LOCK_ALLOC); + return existing; } - fz_lock(ctx, FZ_LOCK_ALLOC); } /* Now we can never fail, bump the ref */ if (val->refs > 0) @@ -283,15 +280,17 @@ fz_store_item(fz_context *ctx, fz_obj *key, void *val_, unsigned int itemsize) store->head = item; item->prev = NULL; fz_unlock(ctx, FZ_LOCK_ALLOC); + + return NULL; } void * -fz_find_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key) +fz_find_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type) { - struct refkey refkey; fz_item *item; fz_store *store = ctx->store; - int indirect; + fz_store_hash hash = { NULL }; + int use_hash = 0; if (!store) return NULL; @@ -299,27 +298,24 @@ fz_find_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key) if (!key) return NULL; - /* Form the key before we take the lock */ - indirect = fz_is_indirect(key); - if (indirect) + if (type->make_hash_key) { - refkey.free = free; - refkey.num = fz_to_num(key); - refkey.gen = fz_to_gen(key); + hash.free = free; + use_hash = type->make_hash_key(&hash, key); } fz_lock(ctx, FZ_LOCK_ALLOC); - if (indirect) + if (use_hash) { /* We can find objects keyed on indirected objects quickly */ - item = fz_hash_find(ctx, store->hash, &refkey); + item = fz_hash_find(ctx, store->hash, &hash); } else { /* Others we have to hunt for slowly */ for (item = store->head; item; item = item->next) { - if (item->val->free == free && !fz_objcmp(item->key, key)) + if (item->val->free == free && !type->cmp_key(item->key, key)) break; } } @@ -355,35 +351,33 @@ fz_find_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key) } void -fz_remove_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key) +fz_remove_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type) { - struct refkey refkey; fz_item *item; fz_store *store = ctx->store; - int drop, indirect; + int drop; + fz_store_hash hash; + int use_hash = 0; - /* Form the key before we take the lock */ - indirect = fz_is_indirect(key); - if (indirect) + if (type->make_hash_key) { - refkey.free = free; - refkey.num = fz_to_num(key); - refkey.gen = fz_to_gen(key); + hash.free = free; + use_hash = type->make_hash_key(&hash, key); } fz_lock(ctx, FZ_LOCK_ALLOC); - if (indirect) + if (use_hash) { /* We can find objects keyed on indirect objects quickly */ - item = fz_hash_find(ctx, store->hash, &refkey); + item = fz_hash_find(ctx, store->hash, &hash); if (item) - fz_hash_remove(ctx, store->hash, &refkey); + fz_hash_remove(ctx, store->hash, &hash); } else { /* Others we have to hunt for slowly */ for (item = store->head; item; item = item->next) - if (item->val->free == free && !fz_objcmp(item->key, key)) + if (item->val->free == free && !type->cmp_key(item->key, key)) break; } if (item) @@ -400,7 +394,7 @@ fz_remove_item(fz_context *ctx, fz_store_free_fn *free, fz_obj *key) fz_unlock(ctx, FZ_LOCK_ALLOC); if (drop) item->val->free(ctx, item->val); - fz_drop_obj(item->key); + type->drop_key(ctx, item->key); fz_free(ctx, item); } else diff --git a/fitz/stm_read.c b/fitz/stm_read.c index 2066b14c..81411c54 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -101,7 +101,7 @@ fz_read_all(fz_stream *stm, int initial) if (initial < 1024) initial = 1024; - buf = fz_new_buffer(ctx, initial); + buf = fz_new_buffer(ctx, initial+1); while (1) { @@ -110,7 +110,6 @@ fz_read_all(fz_stream *stm, int initial) if (buf->len / 200 > initial) { - fz_drop_buffer(ctx, buf); fz_throw(ctx, "compression bomb detected"); } -- cgit v1.2.3 From d28129c2ff6a78c50877426f90167d63334ab18a Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Thu, 23 Feb 2012 11:07:15 +0000 Subject: Add fz_trim_buffer function, and call it. Remove stray space at the end of buffers. --- fitz/fitz.h | 1 + fitz/stm_buffer.c | 12 ++++++++++++ fitz/stm_read.c | 1 + 3 files changed, 14 insertions(+) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 856df7e5..ddffa181 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -784,6 +784,7 @@ void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size); void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); +void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); /* * Resource store diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c index 7f9d521d..d70118e1 100644 --- a/fitz/stm_buffer.c +++ b/fitz/stm_buffer.c @@ -28,7 +28,12 @@ fz_buffer * fz_keep_buffer(fz_context *ctx, fz_buffer *buf) { if (buf) + { + if (buf->refs == 1 && buf->cap > buf->len+1) + fz_resize_buffer(ctx, buf, buf->len); buf->refs ++; + } + return buf; } @@ -58,3 +63,10 @@ fz_grow_buffer(fz_context *ctx, fz_buffer *buf) { fz_resize_buffer(ctx, buf, (buf->cap * 3) / 2); } + +void +fz_trim_buffer(fz_context *ctx, fz_buffer *buf) +{ + if (buf->cap > buf->len+1) + fz_resize_buffer(ctx, buf, buf->len); +} diff --git a/fitz/stm_read.c b/fitz/stm_read.c index 81411c54..c2d375f3 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -125,6 +125,7 @@ fz_read_all(fz_stream *stm, int initial) fz_drop_buffer(ctx, buf); fz_rethrow(ctx); } + fz_trim_buffer(ctx, buf); return buf; } -- cgit v1.2.3 From c3aace6725d08238273caef5d3606f52b2dd597f Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Mon, 6 Feb 2012 02:36:43 +0100 Subject: Add introductory MuPDF documentation. --- fitz/fitz.h | 128 ------------------------------------------------------------ 1 file changed, 128 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index ddffa181..7a13ef75 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -139,134 +139,6 @@ struct fz_error_context_s void fz_var_imp(void *); #define fz_var(var) fz_var_imp((void *)&(var)) -/* - -MuPDF uses a set of exception handling macros to simplify error return -and cleanup. Conceptually, they work a lot like C++'s try/catch system, -but do not require any special compiler support. - -The basic formulation is as follows: - - fz_try(ctx) - { - // Try to perform a task. Never 'return', 'goto' or 'longjmp' out - // of here. 'break' may be used to safely exit (just) the try block - // scope. - } - fz_always(ctx) - { - // Any code here is always executed, regardless of whether an - // exception was thrown within the try or not. Never 'return', 'goto' - // or longjmp out from here. 'break' may be used to safely exit (just) - // the always block scope. - } - fz_catch(ctx) - { - // This code is called (after any always block) only if something - // within the fz_try block (including any functions it called) threw - // an exception. The code here is expected to handle the exception - // (maybe record/report the error, cleanup any stray state etc) and - // can then either exit the block, or pass on the exception to a - // higher level (enclosing) fz_try block (using fz_throw, or - // fz_rethrow). - } - -The fz_always block is optional, and can safely be omitted. - -The macro based nature of this system has 3 main limitations: - -1) Never return from within try (or 'goto' or longjmp out of it). - This upsets the internal housekeeping of the macros and will cause - problems later on. The code will detect such things happening, but - by then it is too late to give a helpful error report as to where the - original infraction occurred. - -2) The fz_try(ctx) { ... } fz_always(ctx) { ... } fz_catch(ctx) { ... } - is not one atomic C statement. That is to say, if you do: - - if (condition) - fz_try(ctx) { ... } - fz_catch(ctx) { ... } - - then you will not get what you want. Use the following instead: - - if (condition) { - fz_try(ctx) { ... } - fz_catch(ctx) { ... } - } - -3) The macros are implemented using setjmp and longjmp, and so the standard - C restrictions on the use of those functions apply to fz_try/fz_catch - too. In particular, any "truly local" variable that is set between the - start of fz_try and something in fz_try throwing an exception may become - undefined as part of the process of throwing that exception. - - As a way of mitigating this problem, we provide an fz_var() macro that - tells the compiler to ensure that that variable is not unset by the - act of throwing the exception. - -A model piece of code using these macros then might be: - - house build_house(plans *p) - { - material m = NULL; - walls w = NULL; - roof r = NULL; - house h = NULL; - tiles t = make_tiles(); - - fz_var(w); - fz_var(r); - fz_var(h); - - fz_try(ctx) - { - fz_try(ctx) - { - m = make_bricks(); - } - fz_catch(ctx) - { - // No bricks available, make do with straw? - m = make_straw(); - } - w = make_walls(m, p); - r = make_roof(m, t); - h = combine(w, r); // Note, NOT: return combine(w,r); - } - fz_always(ctx) - { - drop_walls(w); - drop_roof(r); - drop_material(m); - drop_tiles(t); - } - fz_catch(ctx) - { - fz_throw(ctx, "build_house failed"); - } - return h; - } - -Things to note about this: - -a) If make_tiles throws an exception, this will immediately be handled - by some higher level exception handler. If it succeeds, t will be - set before fz_try starts, so there is no need to fz_var(t); - -b) We try first off to make some bricks as our building material. If - this fails, we fall back to straw. If this fails, we'll end up in - the fz_catch, and the process will fail neatly. - -c) We assume in this code that combine takes new reference to both the - walls and the roof it uses, and therefore that w and r need to be - cleaned up in all cases. - -d) We assume the standard C convention that it is safe to destroy - NULL things. - -*/ - /* Exception macro definitions. Just treat these as a black box - pay no * attention to the man behind the curtain. */ -- cgit v1.2.3 From 2bb18f5bc078ff2715644f74f318837fe320cd7c Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Thu, 2 Feb 2012 01:37:12 +0100 Subject: Document the most commonly used interface functions. --- fitz/fitz.h | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 312 insertions(+), 7 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 7a13ef75..fc4bd570 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -243,9 +243,46 @@ struct fz_context_s fz_glyph_cache *glyph_cache; }; +/* + fz_new_context: Allocate context containing global state. + + The global state contains exception stack, resource store, + etc. Most functions in MuPDF take a context argument to be + able to reference the global state. + + alloc: Supply a custom memory allocator through a set of + function pointers. Set to NULL for the standard library + allocator. The context will keep the allocator pointer, so it + must not be modified or freed during the lifetime of the + context. + + locks: Supply a set of locks and functions to lock/unlock + them, intended for multi-threaded environment. Set to NULL + when using MuPDF in a single-threaded environment. The context + will keep the locks pointer, so it must not be modified or + freed during the lifetime of the context. + + max_store: Maximum size in bytes of the resource store, before + it will start evicting cached resources such as fonts and + images. FZ_STORE_UNLIMITED can be used to not set a hard + upper limit. Use FZ_STORE_DEFAULT to get a reasonable size. + + Does not throw exceptions, but may return NULL. +*/ fz_context *fz_new_context(fz_alloc_context *alloc, fz_locks_context *locks, unsigned int max_store); + fz_context *fz_clone_context(fz_context *ctx); fz_context *fz_clone_context_internal(fz_context *ctx); + +/* + fz_free_context: Frees a context and its global state. + + The context and all of its global state is freed, and any + cached warnings are flushed. If NULL is passed in nothing will + happen. + + Does not throw exceptions. +*/ void fz_free_context(fz_context *ctx); void fz_new_aa_context(fz_context *ctx); @@ -457,19 +494,54 @@ struct fz_bbox_s int x1, y1; }; +/* + fz_identity: Identity transform matrix. +*/ extern const fz_matrix fz_identity; -fz_matrix fz_concat(fz_matrix one, fz_matrix two); +/* + fz_concat: Multiply two matrices. + + The order of the two matrices are important since matrix + multiplication is not commutative. +*/ +fz_matrix fz_concat(fz_matrix left, fz_matrix right); + +/* + fz_scale: Create a scaling matrix. + + sx, sy: Scaling factors along the X- and Y-axes. A scaling + factor of 1.0 will not cause any scaling along that relevant + axis. +*/ fz_matrix fz_scale(float sx, float sy); + fz_matrix fz_shear(float sx, float sy); -fz_matrix fz_rotate(float theta); + +/* + fz_rotate: Create a rotation matrix. +*/ +fz_matrix fz_rotate(float degrees); + fz_matrix fz_translate(float tx, float ty); fz_matrix fz_invert_matrix(fz_matrix m); int fz_is_rectilinear(fz_matrix m); float fz_matrix_expansion(fz_matrix m); float fz_matrix_max_expansion(fz_matrix m); -fz_bbox fz_round_rect(fz_rect r); + +/* + fz_round_rect: Convert a rect into a bounding box. + + Coordinates in a bounding box are integers, so rounding of the + rects coordinates takes place. The top left corner is rounded + upwards and left while the bottom right corner is rounded + downwards and to the right. There are no overflows, instead + the coordinates will be clamped to INT_MIN/INT_MAX. + + rect: The rect to be converted. +*/ +fz_bbox fz_round_rect(fz_rect rect); fz_bbox fz_intersect_bbox(fz_bbox a, fz_bbox b); fz_rect fz_intersect_rect(fz_rect a, fz_rect b); fz_bbox fz_union_bbox(fz_bbox a, fz_bbox b); @@ -477,7 +549,19 @@ fz_rect fz_union_rect(fz_rect a, fz_rect b); fz_point fz_transform_point(fz_matrix m, fz_point p); fz_point fz_transform_vector(fz_matrix m, fz_point p); -fz_rect fz_transform_rect(fz_matrix m, fz_rect r); + +/* + fz_transform_rect: Apply a transformation to a rect. + + transform: Transformation matrix to apply. See fz_concat, + fz_scale and fz_rotate of how to create a matrix. + + rect: The rect to be transformed. The two degenerate cases see + fz_empty_rect and fz_infinite_rect, may be used but the + resulting rect will be identical. +*/ +fz_rect fz_transform_rect(fz_matrix transform, fz_rect rect); + fz_bbox fz_transform_bbox(fz_matrix m, fz_bbox b); void fz_gridfit_matrix(fz_matrix *m); @@ -752,11 +836,47 @@ struct fz_stream_s unsigned char buf[4096]; }; -fz_stream *fz_open_fd(fz_context *ctx, int file); +/* + fz_open_file: Open a named file and wrap it in a stream. + + The stream is reference counted. + + filename: Path to a file as it would be given to open(2). +*/ fz_stream *fz_open_file(fz_context *ctx, const char *filename); -fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); /* only on win32 */ + +/* + fz_open_file_w: Open a named file and wrap it in a stream. + + This function is only available when compiling for Win32. The + stream is reference counted. + + filename: Wide character path to the file as it would be given + to _wopen(). +*/ +fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); + +/* + fz_open_fd: Wrap an open file descriptor in a stream. + + file: An open file descriptor supporting bidirectional + seeking. The stream will take ownership of the file + descriptor, so it may not be modified or closed after the call + to fz_open_fd. When the stream is closed it will also close + the file descriptor. +*/ +fz_stream *fz_open_fd(fz_context *ctx, int file); + fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); + +/* + fz_close: Close an open stream. + + Drops a reference for the stream. Once no references remain + the stream will be closed, as will any file descriptor the + stream is using. +*/ void fz_close(fz_stream *stm); void fz_lock_stream(fz_stream *stm); @@ -904,14 +1024,52 @@ struct fz_pixmap_s fz_bbox fz_bound_pixmap(fz_pixmap *pix); fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); + +/* + fz_new_pixmap_with_rect: Create a pixmap of a given size and + format. + + The bounding box specifies the size of the created pixmap and + where it will be located. The colorspace determines the number + of components per pixel, exluding alpha which is always + present. Pixmaps are reference counted, so drop references + using fz_drop_pixmap. + + colorspace: Colorspace format used for the created pixmap. The + pixmap will keep a reference to the colorspace. + + bbox: Bounding box specifcying location/size of created + pixmap. +*/ fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *, fz_bbox bbox); + fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *, fz_bbox bbox, unsigned char *samples); fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); fz_pixmap *fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix); + +/* + fz_drop_pixmap: Drop a reference and free a pixmap. + + pix: Pixmap whose reference count will be decremented. If no + reference remain the pixmap will also be freed. +*/ void fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix); + void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); + +/* + fz_clear_pixmap_with_value: Clears a pixmap with the given value + + pix: Pixmap obtained from fz_new_pixmap*. + + value: Values in the range 0 to 255 are accepted (higher + values get truncated). Each component sample for each pixel in + the pixmap will be set to this value, while alpha will always + be set to 255 (non-transparent). +*/ void fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value); + void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_bbox r); void fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox r); void fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix); @@ -1375,11 +1533,25 @@ void fz_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, floa void fz_end_tile(fz_device *dev); fz_device *fz_new_device(fz_context *ctx, void *user); + +/* + fz_free_device: Free a devices of any type and its resources. +*/ void fz_free_device(fz_device *dev); fz_device *fz_new_trace_device(fz_context *ctx); fz_device *fz_new_bbox_device(fz_context *ctx, fz_bbox *bboxp); + +/* + fz_new_draw_device: Create a device drawing on a pixmap. + + dest: Target pixmap for the draw device. See fz_new_pixmap* + for how to obtain a pixmap. The pixmap is not cleared by the + draw device, see fz_clear_pixmap* for how to clear it prior to + calling fz_new_draw_device. +*/ fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); + fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest); /* @@ -1419,6 +1591,40 @@ fz_device *fz_new_text_device(fz_context *ctx, fz_text_span *text); typedef struct fz_cookie_s fz_cookie; +/* + Provide two-way communication between application and library. + Intended for multi-threaded applications where one thread is + rendering pages and another thread wants read progress + feedback or abort a job that takes a long time to finish. The + communication is unsynchronized without locking. + + abort: The appliation should set this field to 0 before + calling fz_run_page to render a page. At any point when the + page is being rendered the application my set this field to 1 + which will cause the rendering to finish soon. This field is + checked periodically when the page is rendered, but exactly + when is not known, therefore there is no upper bound on + exactly when the the rendering will abort. If the application + did not provide a set of locks to fz_new_context, it must also + await the completion of fz_run_page before issuing another + call to fz_run_page. Note that once the application has set + this field to 1 after it called fz_run_page it may not change + the value again. + + progress: Communicates rendering progress back to the + application and is read only. Increments as a page is being + rendered. The value starts out at 0 and is limited to less + than or equal to progress_max, unless progress_max is -1. + + progress_max: Communicates known upper bound of rendering back + to the application and is read only. Maximum value that the + progress field may take. If there is no known upper bound on + how long the rendering may take this value is -1 and + progress is not limited. Note that the value of progress_max + may change from -1 to a positive value once an upper bound is + known, so take this into consideration when comparing the + value of progress to that of progress_max. +*/ struct fz_cookie_s { int abort; @@ -1432,11 +1638,37 @@ struct fz_cookie_s typedef struct fz_display_list_s fz_display_list; +/* + fz_new_display_list: Create an empty display list. + + A display list contains a page's objects (text, images, etc.) + in drawing order. Use fz_new_list_device for populating the list. +*/ fz_display_list *fz_new_display_list(fz_context *ctx); -void fz_free_display_list(fz_context *ctx, fz_display_list *list); + +/* + fz_new_list_device: Create a rendering device for a display list. + + When the device is rendering a page it will populate the + display list with the page's objects (text, images, etc.) in + drawing order. The display list can later be reused to render + a page many times without having to re-interpret the page from + the document file for each rendering. + + list: A display list that the list device takes ownership of. +*/ fz_device *fz_new_list_device(fz_context *ctx, fz_display_list *list); + void fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_bbox area, fz_cookie *cookie); +/* + fz_free_display_list: Frees a display list. + + list: Display list to be freed. Any objects put into the + display list by a list device will also be freed. +*/ +void fz_free_display_list(fz_context *ctx, fz_display_list *list); + /* * Plotting functions. */ @@ -1599,8 +1831,27 @@ struct fz_document_s void (*free_page)(fz_document *doc, fz_page *page); }; +/* + fz_open_document: Open a PDF, XPS or CBZ document. + + Open a document file and read its basic structure so pages and + objects can be located. MuPDF will try to repair broken + documents (without actually changing the file contents). + + The returned fz_document sould be provided when calling most + other fz_* functions. Note that it wraps the context, so those + functions implicitly can access the global state in context. + + filename: a path to a file as it would be given to open(2). +*/ fz_document *fz_open_document(fz_context *ctx, char *filename); +/* + fz_close_document: Closes and frees an opened document. + + The resource store in the context associated with fz_document + is emptied, and any allocations for the document are freed. +*/ void fz_close_document(fz_document *doc); int fz_needs_password(fz_document *doc); @@ -1608,11 +1859,65 @@ int fz_authenticate_password(fz_document *doc, char *password); fz_outline *fz_load_outline(fz_document *doc); +/* + fz_count_pages: Return number of pages in document + + May return 0 for documents without any pages at all. +*/ int fz_count_pages(fz_document *doc); + +/* + fz_load_page: Load a page and its resources. + + Locates the page number in an open document and loads the page + and its resources. After fz_load_page is it possible to + retrieve the size of the page using fz_bound_page, or to + render the page using fz_run_page_*. + + number: page number, 0 is the first page of the document. +*/ fz_page *fz_load_page(fz_document *doc, int number); + fz_link *fz_load_links(fz_document *doc, fz_page *page); + +/* + fz_bound_page: Determine the size of a page. + + Determine the page size in user space units, taking page + rotation into account. The page size is taken to be the crop + box if it exists (visible area after cropping), otherwise the + media box will be used (possibly including printing marks). +*/ fz_rect fz_bound_page(fz_document *doc, fz_page *page); + +/* + fz_run_page: Run a page through a device. + + page: Page obtained from fz_load_page. + + dev: Device obtained from fz_new_*_device. + + transform: Transform to apply to page. May include for example + scaling and rotation, see fz_scale, fz_rotate and fz_concat. + Set to fz_identity if no transformation is desired. + + cookie: Communication mechanism between caller and library + rendering the page. Intended for multi-threaded environments, + while single-threaded environments set cookie to NULL. The + caller may abort an ongoing rendering of a page. Cookie also + communicates progress information back to the caller. The + fields inside cookie are continually updated while the page is + rendering. +*/ void fz_run_page(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix transform, fz_cookie *cookie); + +/* + fz_free_page: Free a loaded page. + + page: A loaded page to be freed. Its own references to + resources are dropped, the resources themselves may still be + refered to by the resource store in the context. +*/ void fz_free_page(fz_document *doc, fz_page *page); #endif -- cgit v1.2.3 From 4420da5546c89849f43016c946525141013610e9 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Sun, 12 Feb 2012 16:38:47 +0100 Subject: Document some more functions. --- fitz/fitz.h | 101 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 24 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index fc4bd570..b55ff445 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -257,10 +257,10 @@ struct fz_context_s context. locks: Supply a set of locks and functions to lock/unlock - them, intended for multi-threaded environment. Set to NULL - when using MuPDF in a single-threaded environment. The context - will keep the locks pointer, so it must not be modified or - freed during the lifetime of the context. + them, intended for multi-threaded applications. Set to NULL + when using MuPDF in a single-threaded applications. The + context will keep the locks pointer, so it must not be + modified or freed during the lifetime of the context. max_store: Maximum size in bytes of the resource store, before it will start evicting cached resources such as fonts and @@ -271,6 +271,21 @@ struct fz_context_s */ fz_context *fz_new_context(fz_alloc_context *alloc, fz_locks_context *locks, unsigned int max_store); +/* + fz_clone_context: Make a clone of an existing context. + + This function is meant to be used in multi-threaded + applications where each thread requires its own context, yet + parts of the global state, for example caching, is shared. + + ctx: Context obtained from fz_new_context to make a copy of. + ctx must have had locks and lock/functions setup when created. + The two contexts will share the memory allocator, resource + store, locks and lock/unlock functions. They will each have + their own exception stacks though. + + Does not throw exception, but may return NULL. +*/ fz_context *fz_clone_context(fz_context *ctx); fz_context *fz_clone_context_internal(fz_context *ctx); @@ -288,24 +303,26 @@ void fz_free_context(fz_context *ctx); void fz_new_aa_context(fz_context *ctx); void fz_free_aa_context(fz_context *ctx); -/* 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 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 the address of a lock structure. - * - * In order to avoid deadlocks, we have 1 simple rules 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 - * built in, that is enabled by defining 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 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 the address of a lock structure. + + In order to avoid deadlocks, we have 1 simple rules 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 built in, that is enabled by + defining FITZ_DEBUG_LOCKING. +*/ #if defined(MEMENTO) || defined(DEBUG) #define FITZ_DEBUG_LOCKING @@ -1800,6 +1817,23 @@ void fz_free_link_dest(fz_context *ctx, fz_link_dest *dest); typedef struct fz_outline_s fz_outline; +/* + fz_outline represent one item in a document's hierarchical + outline (also know as table of contents). + + title: Title of outline item using UTF-8 encoding. May be NULL + if the outline item has no text string. + + dest: Destination in the document to be displayed when this + outline item is activated. May be FZ_LINK_NONE if the outline + item does not have a destination. + + next: The next outline item at the same level as this outline + item. May be NULL if not more outline items exist at this level. + + down: The outline items immediate children in the hierarchy. + May be NULL if no children exist. +*/ struct fz_outline_s { char *title; @@ -1854,9 +1888,28 @@ fz_document *fz_open_document(fz_context *ctx, char *filename); */ void fz_close_document(fz_document *doc); +/* + fz_needs_password: Checks for encrypted document. + + Encrypted documents that require only an empty password are + treated as if they were not encrypted, thus requiring no + password authentication. +*/ int fz_needs_password(fz_document *doc); + +/* + fz_authenticate_password: Test if password can decrypt a + document. + + password: The password string to be checked. It is assumed + that is in a suitable text encoding, as some document + specifications do not specify any particular text encoding. +*/ int fz_authenticate_password(fz_document *doc, char *password); +/* + fz_load_outline: Load the hierarchical document outline. +*/ fz_outline *fz_load_outline(fz_document *doc); /* @@ -1902,8 +1955,8 @@ fz_rect fz_bound_page(fz_document *doc, fz_page *page); Set to fz_identity if no transformation is desired. cookie: Communication mechanism between caller and library - rendering the page. Intended for multi-threaded environments, - while single-threaded environments set cookie to NULL. The + rendering the page. Intended for multi-threaded applications, + while single-threaded applications set cookie to NULL. The caller may abort an ongoing rendering of a page. Cookie also communicates progress information back to the caller. The fields inside cookie are continually updated while the page is -- cgit v1.2.3 From ca578b08dc1243dc6cbb3235272d52d9e2336925 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Sun, 12 Feb 2012 16:39:06 +0100 Subject: Continued documentation improvements. More changes still to come. --- fitz/fitz.h | 694 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 581 insertions(+), 113 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index b55ff445..cb7cfa4d 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -215,7 +215,6 @@ execution. Again this was felt to be too high a cost to use. ctx->error->top--;\ } \ else if (ctx->error->top--, 1) - */ void fz_push_try(fz_error_context *ex); @@ -229,6 +228,17 @@ struct fz_warn_context_s }; void fz_warn(fz_context *ctx, char *fmt, ...) __printflike(2, 3); +/* + fz_flush_warnings: Flush any repeated warnings. + + Repeated warnings are buffered, counted and eventually printed + along with the number of repetitions. Call fz_flush_warnings + to force printing of the latest buffered warning and the + number of repetitions, for example to make sure that all + warnings are printed before exiting an application. + + Does not throw exceptions. +*/ void fz_flush_warnings(fz_context *ctx); struct fz_context_s @@ -246,26 +256,28 @@ struct fz_context_s /* fz_new_context: Allocate context containing global state. - The global state contains exception stack, resource store, - etc. Most functions in MuPDF take a context argument to be - able to reference the global state. + The global state contains an exception stack, resource store, + etc. Most functions in MuPDF take a context argument to be + able to reference the global state. See fz_free_context for + freeing an allocated context. alloc: Supply a custom memory allocator through a set of function pointers. Set to NULL for the standard library - allocator. The context will keep the allocator pointer, so it - must not be modified or freed during the lifetime of the - context. + allocator. The context will keep the allocator pointer, so the + data it points to must not be modified or freed during the + lifetime of the context. locks: Supply a set of locks and functions to lock/unlock them, intended for multi-threaded applications. Set to NULL when using MuPDF in a single-threaded applications. The - context will keep the locks pointer, so it must not be - modified or freed during the lifetime of the context. + context will keep the locks pointer, so the data it points to + must not be modified or freed during the lifetime of the + context. max_store: Maximum size in bytes of the resource store, before it will start evicting cached resources such as fonts and - images. FZ_STORE_UNLIMITED can be used to not set a hard - upper limit. Use FZ_STORE_DEFAULT to get a reasonable size. + images. FZ_STORE_UNLIMITED can be used if a hard limit is not + desired. Use FZ_STORE_DEFAULT to get a reasonable size. Does not throw exceptions, but may return NULL. */ @@ -290,11 +302,11 @@ fz_context *fz_clone_context(fz_context *ctx); fz_context *fz_clone_context_internal(fz_context *ctx); /* - fz_free_context: Frees a context and its global state. + fz_free_context: Free a context and its global state. The context and all of its global state is freed, and any - cached warnings are flushed. If NULL is passed in nothing will - happen. + buffered warnings are flushed (see fz_flush_warnings). If NULL + is passed in nothing will happen. Does not throw exceptions. */ @@ -310,18 +322,18 @@ void fz_free_aa_context(fz_context *ctx); 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 mutexes, and a - function to lock/unlock each of them. These may be recursive - mutexes, but do not have to be. + 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 the address of a lock structure. + may pass NULL instead of a lock structure. - In order to avoid deadlocks, we have 1 simple rules 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 built in, that is enabled by - defining FITZ_DEBUG_LOCKING. + 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. */ #if defined(MEMENTO) || defined(DEBUG) @@ -390,6 +402,11 @@ void *fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size); void *fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size); char *fz_strdup(fz_context *ctx, char *s); +/* + fz_free: Frees an allocation. + + Does not throw exceptions. +*/ void fz_free(fz_context *ctx, void *p); /* The following returns NULL on failure to allocate */ @@ -476,35 +493,136 @@ typedef struct fz_point_s fz_point; typedef struct fz_rect_s fz_rect; typedef struct fz_bbox_s fz_bbox; +/* + A rectangle with sides of length one. + + The bottom left corner is at (0, 0) and the top right corner + is at (1, 1). +*/ extern const fz_rect fz_unit_rect; -extern const fz_rect fz_empty_rect; -extern const fz_rect fz_infinite_rect; +/* + A bounding box with sides of length one. See fz_unit_rect. +*/ extern const fz_bbox fz_unit_bbox; + +/* + An empty rectangle with an area equal to zero. + + Both the top left and bottom right corner are at (0, 0). +*/ +extern const fz_rect fz_empty_rect; + +/* + An empty bounding box. See fz_empty_rect. +*/ extern const fz_bbox fz_empty_bbox; + +/* + An infinite rectangle with negative area. + + The corner (x0, y0) is at (1, 1) while the corner (x1, y1) is + at (-1, -1). +*/ +extern const fz_rect fz_infinite_rect; + +/* + An infinite bounding box. See fz_infinite_rect. +*/ extern const fz_bbox fz_infinite_bbox; +/* + fz_is_empty_rect: Check if rectangle is empty. + + An empty rectangle is defined as one whose area is zero. +*/ #define fz_is_empty_rect(r) ((r).x0 == (r).x1) -#define fz_is_infinite_rect(r) ((r).x0 > (r).x1) + +/* + fz_is_empty_bbox: Check if bounding box is empty. + + Same definition of empty bounding boxes as for empty + rectangles. See fz_is_empty_rect. +*/ #define fz_is_empty_bbox(b) ((b).x0 == (b).x1) + +/* + fz_is_infinite: Check if rectangle is infinite. + + An infinite rectangle is defined as one where either of the + two relationships between corner coordinates are not true. +*/ +#define fz_is_infinite_rect(r) ((r).x0 > (r).x1) + +/* + fz_is_infinite_bbox: Check if bounding box is infinite. + + Same definition of infinite bounding boxes as for infinite + rectangles. See fz_is_infinite_rect. +*/ #define fz_is_infinite_bbox(b) ((b).x0 > (b).x1) +/* + fz_matrix is a a row-major 3x3 matrix used for representing + transformations of coordinates throughout MuPDF. + + Since all points reside in a two-dimensional space, one vector + is always a constant unit vector; hence only some elements may + vary in a matrix. Below is how the elements map between + different representations. + + / a b 0 \ + | c d 0 | normally represented as [ a b c d e f ]. + \ e f 1 / +*/ struct fz_matrix_s { float a, b, c, d, e, f; }; +/* + fz_point is a point in a two-dimensional space. +*/ struct fz_point_s { float x, y; }; +/* + fz_rect is a rectangle represented by two diagonally opposite + corners at arbitrary coordinates. + + Rectangles are always axis-aligned with the X- and Y- axes. + The relationship between the coordinates are that x0 <= x1 and + y0 <= y1 in all cases except for infinte rectangles. The area + of a rectangle is defined as (x1 - x0) * (y1 - y0). If either + x0 > x1 or y0 > y1 is true for a given rectangle then it is + defined to be infinite. + + To check for empty or infinite rectangles use fz_is_empty_rect + and fz_is_infinite_rect. Compare to fz_bbox which has corners + at integer coordinates. + + x0, y0: The top left corner. + + x1, y1: The botton right corner. +*/ struct fz_rect_s { float x0, y0; float x1, y1; }; +/* + fz_bbox is a bounding box similar to a fz_rect, except that + all corner coordinates are rounded to integer coordinates. + To check for empty or infinite bounding boxes use + fz_is_empty_bbox and fz_is_infinite_bbox. + + x0, y0: The top left corner. + + x1, y1: The botton right corner. +*/ struct fz_bbox_s { int x0, y0; @@ -521,65 +639,198 @@ extern const fz_matrix fz_identity; The order of the two matrices are important since matrix multiplication is not commutative. + + Does not throw exceptions. */ fz_matrix fz_concat(fz_matrix left, fz_matrix right); /* fz_scale: Create a scaling matrix. + The returned matrix is of the form [ sx 0 0 sy 0 0 ]. + sx, sy: Scaling factors along the X- and Y-axes. A scaling - factor of 1.0 will not cause any scaling along that relevant + factor of 1.0 will not cause any scaling along the relevant axis. + + Does not throw exceptions. */ fz_matrix fz_scale(float sx, float sy); +/* + fz_shear: Create a shearing matrix. + + The returned matrix is of the form [ 1 sy sx 1 0 0 ]. + + sx, sy: Shearing factors. A shearing factor of 0.0 will not + cause any shearing along the relevant axis. + + Does not throw exceptions. +*/ fz_matrix fz_shear(float sx, float sy); /* fz_rotate: Create a rotation matrix. + + The returned matrix is of the form + [ cos(deg) sin(deg) -sin(deg) cos(deg) 0 0 ]. + + degrees: Degrees of counter clockwise rotation. Values less + than zero and greater than 360 are handled as expected. + + Does not throw exceptions. */ fz_matrix fz_rotate(float degrees); +/* + fz_translate: Create a translation matrix. + + The returned matrix is of the form [ 1 0 0 1 tx ty ]. + + tx, ty: Translation distances along the X- and Y-axes. A + translation of 0 will not cause any translation along the + relevant axis. + + Does not throw exceptions. +*/ fz_matrix fz_translate(float tx, float ty); -fz_matrix fz_invert_matrix(fz_matrix m); + +/* + fz_invert_matrix: Create an inverse matrix. + + matrix: Matrix to invert. A degenerate matrix, where the + determinant is equal to zero, can not be inverted and the + original matrix is returned instead. + + Does not throw exceptions. +*/ +fz_matrix fz_invert_matrix(fz_matrix matrix); + +/* + fz_is_rectilinear: Check if a transformation is rectilinear. + + Rectilinear means that no shearing is present and that any + rotations present are a multiple of 90 degrees. Usually this + is used to make sure that axis-aligned rectangles before the + transformation are still axis-aligned rectangles afterwards. + + Does not throw exceptions. +*/ int fz_is_rectilinear(fz_matrix m); + float fz_matrix_expansion(fz_matrix m); float fz_matrix_max_expansion(fz_matrix m); - /* fz_round_rect: Convert a rect into a bounding box. Coordinates in a bounding box are integers, so rounding of the rects coordinates takes place. The top left corner is rounded upwards and left while the bottom right corner is rounded - downwards and to the right. There are no overflows, instead - the coordinates will be clamped to INT_MIN/INT_MAX. + downwards and to the right. Overflows or underflowing + coordinates are clamped to INT_MIN/INT_MAX. - rect: The rect to be converted. + Does not throw exceptions. */ fz_bbox fz_round_rect(fz_rect rect); -fz_bbox fz_intersect_bbox(fz_bbox a, fz_bbox b); + +/* + fz_intersect_rect: Compute intersection of two rectangles. + + Compute the largest axis-aligned rectangle that covers the + area covered by both given rectangles. If either rectangle is + empty then the intersection is also empty. If either rectangle + is infinite then the intersection is simply the non-infinite + rectangle. Should both rectangles be infinite, then the + intersection is also infinite. + + Does not throw exceptions. +*/ fz_rect fz_intersect_rect(fz_rect a, fz_rect b); -fz_bbox fz_union_bbox(fz_bbox a, fz_bbox b); + +/* + fz_intersect_bbox: Compute intersection of two bounding boxes. + + Similar to fz_intersect_rect but operates on two bounding + boxes instead of two rectangles. + + Does not throw exceptions. +*/ +fz_bbox fz_intersect_bbox(fz_bbox a, fz_bbox b); + +/* + fz_union_rect: Compute union of two rectangles. + + Compute the smallest axis-aligned rectangle that encompasses + both given rectangles. If either rectangle is infinite then + the union is also infinite. If either rectangle is empty then + the union is simply the non-empty rectangle. Should both + rectangles be empty, then the union is also empty. + + Does not throw exceptions. +*/ fz_rect fz_union_rect(fz_rect a, fz_rect b); -fz_point fz_transform_point(fz_matrix m, fz_point p); -fz_point fz_transform_vector(fz_matrix m, fz_point p); +/* + fz_union_bbox: Compute union of two bounding boxes. + + Similar to fz_union_rect but operates on two bounding boxes + instead of two rectangles. + + Does not throw exceptions. +*/ +fz_bbox fz_union_bbox(fz_bbox a, fz_bbox b); /* - fz_transform_rect: Apply a transformation to a rect. + fz_transform_point: Apply a transformation to a point. transform: Transformation matrix to apply. See fz_concat, - fz_scale and fz_rotate of how to create a matrix. + fz_scale, fz_rotate and fz_translate for how to create a + matrix. - rect: The rect to be transformed. The two degenerate cases see - fz_empty_rect and fz_infinite_rect, may be used but the - resulting rect will be identical. + Does not throw exceptions. +*/ +fz_point fz_transform_point(fz_matrix transform, fz_point point); + +/* + fz_transform_vector: Apply a transformation to a vector. + + transform: Transformation matrix to apply. See fz_concat, + fz_scale and fz_rotate for how to create a matrix. Any + translation will be ignored. + + Does not throw exceptions. +*/ +fz_point fz_transform_vector(fz_matrix transform, fz_point vector); + +/* + fz_transform_rect: Apply a transform to a rectangle. + + After the four corner points of the axis-aligned rectangle + have been transformed it may not longer be axis-aligned. So a + new axis-aligned rectangle is created covering at least the + area of the transformed rectangle. + + transform: Transformation matrix to apply. See fz_concat, + fz_scale and fz_rotate for how to create a matrix. + + rect: Rectangle to be transformed. The two special cases + fz_empty_rect and fz_infinite_rect, may be used but are + returned unchanged as expected. + + Does not throw exceptions. */ fz_rect fz_transform_rect(fz_matrix transform, fz_rect rect); -fz_bbox fz_transform_bbox(fz_matrix m, fz_bbox b); +/* + fz_transform_bbox: Transform a given bounding box. + + Similar to fz_transform_rect, but operates on a bounding box + instead of a rectangle. + + Does not throw exceptions. +*/ +fz_bbox fz_transform_bbox(fz_matrix matrix, fz_bbox bbox); void fz_gridfit_matrix(fz_matrix *m); @@ -739,9 +990,8 @@ void fz_set_str_len(fz_obj *obj, int newlen); /* private */ void *fz_get_indirect_document(fz_obj *obj); /* private */ /* - * Data buffers. - */ - + fz_buffer is a XXX +*/ typedef struct fz_buffer_s fz_buffer; struct fz_buffer_s @@ -779,6 +1029,15 @@ struct fz_storable_s { S->free = (FREE); \ } while (0) +/* + Specifies the maximum size in bytes of the resource store in + fz_context. Given as argument to fz_new_context. + + FZ_STORE_UNLIMITED: Let resource store grow unbounded. + + FZ_STORE_DEFAULT: A reasonable upper bound on the size, for + devices that are not memory constrained. +*/ enum { FZ_STORE_UNLIMITED = 0, FZ_STORE_DEFAULT = 256 << 20, @@ -829,10 +1088,14 @@ void fz_empty_store(fz_context *ctx); int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase); /* - * Buffered reader. - * Only the data between rp and wp is valid data. - */ + fz_stream is a buffered reader capable of seeking in both + directions. + Streams are reference counted, so references must be dropped + by a call to fz_close. + + Only the data between rp and wp is valid. +*/ typedef struct fz_stream_s fz_stream; struct fz_stream_s @@ -854,19 +1117,16 @@ struct fz_stream_s }; /* - fz_open_file: Open a named file and wrap it in a stream. - - The stream is reference counted. + fz_open_file: Open the named file and wrap it in a stream. filename: Path to a file as it would be given to open(2). */ fz_stream *fz_open_file(fz_context *ctx, const char *filename); /* - fz_open_file_w: Open a named file and wrap it in a stream. + fz_open_file_w: Open the named file and wrap it in a stream. - This function is only available when compiling for Win32. The - stream is reference counted. + This function is only available when compiling for Win32. filename: Wide character path to the file as it would be given to _wopen(). @@ -884,7 +1144,14 @@ fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); */ fz_stream *fz_open_fd(fz_context *ctx, int file); +/* + fz_open_buffer: XXX +*/ fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); + +/* + fz_open_memory: XXX +*/ fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); /* @@ -893,8 +1160,11 @@ fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); Drops a reference for the stream. Once no references remain the stream will be closed, as will any file descriptor the stream is using. + + Does not throw exceptions. */ void fz_close(fz_stream *stm); + void fz_lock_stream(fz_stream *stm); fz_stream *fz_new_stream(fz_context *ctx, void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_context *, void *)); @@ -1026,6 +1296,33 @@ char *fz_blendmode_name(int blendmode); typedef struct fz_pixmap_s fz_pixmap; typedef struct fz_colorspace_s fz_colorspace; +/* + fz_pixmap is an image XXX + + x, y: XXX + + w, h: The width and height of the image in pixels. + + n: The number of color components in the image. Always + includes a separate alpha channel. XXX RGBA=4 + + mask: XXX + + 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: XXX + + samples: + + free_samples: Is zero when an application has provided its own + buffer for pixel data through fz_new_pixmap_with_rect_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; @@ -1043,32 +1340,47 @@ fz_bbox fz_bound_pixmap(fz_pixmap *pix); fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); /* - fz_new_pixmap_with_rect: Create a pixmap of a given size and - format. + fz_new_pixmap_with_rect: Create a pixmap of a given size, + location and pixel format. The bounding box specifies the size of the created pixmap and where it will be located. The colorspace determines the number - of components per pixel, exluding alpha which is always - present. Pixmaps are reference counted, so drop references - using fz_drop_pixmap. + of components per pixel. Alpha is always present. Pixmaps are + reference counted, so drop references using fz_drop_pixmap. colorspace: Colorspace format used for the created pixmap. The pixmap will keep a reference to the colorspace. - bbox: Bounding box specifcying location/size of created - pixmap. + bbox: Bounding box specifying location/size of created pixmap. */ -fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *, fz_bbox bbox); +fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox); + +/* + fz_new_pixmap_with_rect_and_data: Create a pixmap using the + provided buffer for pixel data. + + While fz_new_pixmap_with_rect allocates its own buffer for + pixel data, fz_new_pixmap_with_rect_and_data lets the caller + allocate and provide a buffer to be used. Otherwise the two + functions are identical. -fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *, fz_bbox bbox, unsigned char *samples); + samples: An array of pixel samples. The created pixmap will + keep a pointer to the array so it must not be modified or + freed until the created pixmap is dropped and freed by + fz_drop_pixmap. +*/ +fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, +fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); fz_pixmap *fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix); /* fz_drop_pixmap: Drop a reference and free a pixmap. - pix: Pixmap whose reference count will be decremented. If no - reference remain the pixmap will also be freed. + Decrement the reference count for the pixmap. When no + references remain the pixmap will be freed. + + Does not throw exceptions. */ void fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix); @@ -1080,10 +1392,11 @@ void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); pix: Pixmap obtained from fz_new_pixmap*. - value: Values in the range 0 to 255 are accepted (higher - values get truncated). Each component sample for each pixel in - the pixmap will be set to this value, while alpha will always - be set to 255 (non-transparent). + value: Values in the range 0 to 255 are valid. Each component + sample for each pixel in the pixmap will be set to this value, + while alpha will always be set to 255 (non-transparent). + + Does not throw exceptions. */ void fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value); @@ -1129,7 +1442,7 @@ fz_pixmap *fz_load_png(fz_context *doc, unsigned char *data, int size); fz_pixmap *fz_load_tiff(fz_context *doc, unsigned char *data, int size); /* - * Bitmaps have 1 component per bit. Only used for creating halftoned versions + * Bitmaps have 1 bit per component. Only used for creating halftoned versions * of contone buffers, and saving out. Samples are stored msb first, akin to * pbms. */ @@ -1175,9 +1488,24 @@ fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht); * Colorspace resources. */ +/* + fz_device_gray: XXX +*/ extern fz_colorspace *fz_device_gray; + +/* + fz_device_rgb: XXX +*/ extern fz_colorspace *fz_device_rgb; + +/* + fz_device_bgr: XXX +*/ extern fz_colorspace *fz_device_bgr; + +/* + fz_device_cmyk: XXX +*/ extern fz_colorspace *fz_device_cmyk; struct fz_colorspace_s @@ -1556,16 +1884,31 @@ fz_device *fz_new_device(fz_context *ctx, void *user); */ void fz_free_device(fz_device *dev); +/* + fz_new_trace_device: Create a device to print a debug trace of + all device calls. + + XXX +*/ fz_device *fz_new_trace_device(fz_context *ctx); + +/* + fz_new_bbox_device: Create a device to compute the bounding + box of all marks on a page. + + The returned bounding box will be the union of all bounding + boxes of all objects on a page. +*/ fz_device *fz_new_bbox_device(fz_context *ctx, fz_bbox *bboxp); /* - fz_new_draw_device: Create a device drawing on a pixmap. + fz_new_draw_device: Create a device to draw on a pixmap. dest: Target pixmap for the draw device. See fz_new_pixmap* for how to obtain a pixmap. The pixmap is not cleared by the draw device, see fz_clear_pixmap* for how to clear it prior to - calling fz_new_draw_device. + calling fz_new_draw_device. Free the device by calling + fz_free_device. */ fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); @@ -1600,6 +1943,18 @@ void fz_free_text_span(fz_context *ctx, fz_text_span *line); void fz_debug_text_span(fz_text_span *line); void fz_debug_text_span_xml(fz_text_span *span); +/* + fz_new_text_device: Create a device to print the text on a + page in XML. + + The text on a page will be translated into a sequnce of XML + elements. For each text span the font, font size, writing mode + and end of line flag is printed. Since text can be placed at + arbitrary positions then heuristics must be used to try to + collect text spans together that are roughly located on the + same baseline. Each character in the text span will have its + UTF-8 character printed along with a bounding box containing it. +*/ fz_device *fz_new_text_device(fz_context *ctx, fz_text_span *text); /* @@ -1633,10 +1988,10 @@ typedef struct fz_cookie_s fz_cookie; rendered. The value starts out at 0 and is limited to less than or equal to progress_max, unless progress_max is -1. - progress_max: Communicates known upper bound of rendering back - to the application and is read only. Maximum value that the - progress field may take. If there is no known upper bound on - how long the rendering may take this value is -1 and + progress_max: Communicates the known upper bound of rendering + back to the application and is read only. The maximum value + that the progress field may take. If there is no known upper + bound on how long the rendering may take this value is -1 and progress is not limited. Note that the value of progress_max may change from -1 to a positive value once an upper bound is known, so take this into consideration when comparing the @@ -1653,13 +2008,25 @@ struct fz_cookie_s * Display list device -- record and play back device commands. */ +/* + fz_display_list is a list containing drawing commands (text, + images, etc.). The intent is two-fold: as a caching-mechanism + to reduce parsing of a page, and to be used as a data + structure in multi-threading where one thread parses the page + and another renders pages. + + Create a displaylist with fz_new_display_list, hand it over to + fz_new_list_device to have it populated, and later replay the + list (once or many times) by calling fz_run_display_list. When + the list is no longer needed free it with fz_free_display_list. +*/ typedef struct fz_display_list_s fz_display_list; /* fz_new_display_list: Create an empty display list. - A display list contains a page's objects (text, images, etc.) - in drawing order. Use fz_new_list_device for populating the list. + A display list contains drawing commands (text, images, etc.). + Use fz_new_list_device for populating the list. */ fz_display_list *fz_new_display_list(fz_context *ctx); @@ -1667,15 +2034,41 @@ fz_display_list *fz_new_display_list(fz_context *ctx); fz_new_list_device: Create a rendering device for a display list. When the device is rendering a page it will populate the - display list with the page's objects (text, images, etc.) in - drawing order. The display list can later be reused to render - a page many times without having to re-interpret the page from - the document file for each rendering. + display list with drawing commsnds (text, images, etc.). The + display list can later be reused to render a page many times + without having to re-interpret the page from the document file + for each rendering. Once the device is no longer needed, free + it with fz_free_device. list: A display list that the list device takes ownership of. */ fz_device *fz_new_list_device(fz_context *ctx, fz_display_list *list); +/* + fz_run_display_list: (Re)-run a display list through a device. + + list: A display list, created by fz_new_display_list and + populated with objects from a page by running fz_run_page on a + device obtained from fz_new_list_device. + + dev: Device obtained from fz_new_*_device. + + ctm: Transform to apply to display list contents. May include + for example scaling and rotation, see fz_scale, fz_rotate and + fz_concat. Set to fz_identity if no transformation is desired. + + area: Only the part of the contents of the display list + visible within this area will be considered when the list is + run through the device. This does not imply for tile objects + contained in the display list. + + cookie: Communication mechanism between caller and library + running the page. Intended for multi-threaded applications, + while single-threaded applications set cookie to NULL. The + caller may abort an ongoing page run. Cookie also communicates + progress information back to the caller. The fields inside + cookie are continually updated while the page is being run. +*/ void fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_bbox area, fz_cookie *cookie); /* @@ -1683,6 +2076,8 @@ void fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, f list: Display list to be freed. Any objects put into the display list by a list device will also be freed. + + Does not throw exceptions. */ void fz_free_display_list(fz_context *ctx, fz_display_list *list); @@ -1764,6 +2159,35 @@ enum { fz_link_flag_r_is_zoom = 64 /* rb.x is actually a zoom figure */ }; +/* + fz_link_dest: XXX + + kind: Set to one of FZ_LINK_* to tell what what type of link + destination this is, and where in the union to look for + information. XXX + + gotor.page: Page number, 0 is the first page of the document. XXX + + gotor.flags: A bitfield consisting of fz_link_flag_* telling + what parts of gotor.lt and gotor.rb are valid, whether + fitting to width/height should be used, or if an arbitrary + zoom factor is used. XXX + + gotor.lt: The top left corner of the destination bounding box. XXX + gotor.rb: The bottom right corner of the destination bounding box. XXX + + gotor.file_spec: XXX + + gotor.new_window: XXX + + uri.uri: XXX + uri.is_map: XXX + + launch.file_spec: XXX + launch.new_window: XXX + + named.named: XXX +*/ struct fz_link_dest_s { fz_link_kind kind; @@ -1800,6 +2224,25 @@ struct fz_link_dest_s ld; }; +/* + fz_link is a list of interactive links on a page. + + There is no relation between the order of the links in the + list and the order they appear on the page. The list of links + for a given page can be obtained from fz_load_links. + + A link is reference counted. Dropping a reference to a link is + done by calling fz_drop_link. + + rect: The hot zone. The area that can be clicked in + untransformed coordinates. + + dest: Link destinations come in two forms: Page and area that + an application should display when this link is activated. Or + as an URI that can be given to a browser. + + next: A pointer to the next link on the same page. +*/ struct fz_link_s { int refs; @@ -1810,7 +2253,14 @@ struct fz_link_s fz_link *fz_new_link(fz_context *ctx, fz_rect bbox, fz_link_dest dest); fz_link *fz_keep_link(fz_context *ctx, fz_link *link); + +/* + fz_drop_link: Drop and free a list of links. + + Does not throw exceptions. +*/ void fz_drop_link(fz_context *ctx, fz_link *link); + void fz_free_link_dest(fz_context *ctx, fz_link_dest *dest); /* Outline */ @@ -1818,8 +2268,8 @@ void fz_free_link_dest(fz_context *ctx, fz_link_dest *dest); typedef struct fz_outline_s fz_outline; /* - fz_outline represent one item in a document's hierarchical - outline (also know as table of contents). + fz_outline is a tree of the outline of a document (also known + as table of contents). title: Title of outline item using UTF-8 encoding. May be NULL if the outline item has no text string. @@ -1829,7 +2279,7 @@ typedef struct fz_outline_s fz_outline; item does not have a destination. next: The next outline item at the same level as this outline - item. May be NULL if not more outline items exist at this level. + item. May be NULL if no more outline items exist at this level. down: The outline items immediate children in the hierarchy. May be NULL if no children exist. @@ -1844,6 +2294,14 @@ struct fz_outline_s void fz_debug_outline_xml(fz_context *ctx, fz_outline *outline, int level); void fz_debug_outline(fz_context *ctx, fz_outline *outline, int level); + +/* + fz_free_outline: Free hierarchical outline. + + Free an outline obtained from fz_load_outline. + + Does not throw exceptions. +*/ void fz_free_outline(fz_context *ctx, fz_outline *outline); /* Document interface */ @@ -1872,74 +2330,86 @@ struct fz_document_s objects can be located. MuPDF will try to repair broken documents (without actually changing the file contents). - The returned fz_document sould be provided when calling most - other fz_* functions. Note that it wraps the context, so those - functions implicitly can access the global state in context. + The returned fz_document is used when calling most other + document related functions. Note that it wraps the context, so + those functions implicitly can access the global state in + context. filename: a path to a file as it would be given to open(2). */ fz_document *fz_open_document(fz_context *ctx, char *filename); /* - fz_close_document: Closes and frees an opened document. + fz_close_document: Close and free an open document. The resource store in the context associated with fz_document is emptied, and any allocations for the document are freed. + + Does not throw exceptions. */ void fz_close_document(fz_document *doc); /* - fz_needs_password: Checks for encrypted document. + fz_needs_password: Check if a document is encrypted with a + non-blank password. - Encrypted documents that require only an empty password are - treated as if they were not encrypted, thus requiring no - password authentication. + Does not throw exceptions. */ int fz_needs_password(fz_document *doc); /* - fz_authenticate_password: Test if password can decrypt a - document. + fz_authenticate_password: Test if the given password can + decrypt the document. - password: The password string to be checked. It is assumed - that is in a suitable text encoding, as some document - specifications do not specify any particular text encoding. + password: The password string to be checked. Some document + specifications do not specify any particular text encoding, so + neither do we. + + Does not throw exceptions. */ int fz_authenticate_password(fz_document *doc, char *password); /* fz_load_outline: Load the hierarchical document outline. + + Should be freed by fz_free_outline. */ fz_outline *fz_load_outline(fz_document *doc); /* - fz_count_pages: Return number of pages in document + fz_count_pages: Return the number of pages in document - May return 0 for documents without any pages at all. + May return 0 for documents with no pages. */ int fz_count_pages(fz_document *doc); /* - fz_load_page: Load a page and its resources. + fz_load_page: Load a page. - Locates the page number in an open document and loads the page - and its resources. After fz_load_page is it possible to - retrieve the size of the page using fz_bound_page, or to - render the page using fz_run_page_*. + After fz_load_page is it possible to retrieve the size of the + page using fz_bound_page, or to render the page using + fz_run_page_*. Free the page by calling fz_free_page. number: page number, 0 is the first page of the document. */ fz_page *fz_load_page(fz_document *doc, int number); +/* + fz_load_links: Load the list of links for a page. + + Returns a linked list of all the links on the page, each with + its clickable region and link destination. Each link is + reference counted so drop and free the list of links by + calling fz_drop_link on the pointer return from fz_load_links. + + page: Page obtained from fz_load_page. +*/ fz_link *fz_load_links(fz_document *doc, fz_page *page); /* - fz_bound_page: Determine the size of a page. + fz_bound_page: Determine the size of a page at 72 dpi. - Determine the page size in user space units, taking page - rotation into account. The page size is taken to be the crop - box if it exists (visible area after cropping), otherwise the - media box will be used (possibly including printing marks). + Does not throw exceptions. */ fz_rect fz_bound_page(fz_document *doc, fz_page *page); @@ -1967,9 +2437,7 @@ void fz_run_page(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix tran /* fz_free_page: Free a loaded page. - page: A loaded page to be freed. Its own references to - resources are dropped, the resources themselves may still be - refered to by the resource store in the context. + Does not throw exceptions. */ void fz_free_page(fz_document *doc, fz_page *page); -- cgit v1.2.3 From bbfe635555dce16858403706e2031dd3bfa1a9f1 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Sun, 26 Feb 2012 11:15:16 -0800 Subject: Move fz_obj to be pdf_obj. Currently, we are in the slightly strange position of having the PDF specific object types as part of fitz. Here we pull them out into the pdf layer instead. This has been made possible by the recent changes to make the store no longer be tied to having fz_obj's as keys. Most of this work is a simple huge rename; to help customers who may have code that use such functions we have provided a sed script to do the renaming; scripts/rename2.sed. Various other small tweaks are required; the store used to have some debugging code that still required knowledge of fz_obj types - we extract that into a nicer 'type' based function pointer. Also, the type 3 font handling used to have an fz_obj pointer for type 3 resources, and therefore needed to know how to free this; this has become a void * with a function to free it. --- fitz/base_context.c | 8 - fitz/base_object.c | 1265 --------------------------------------------------- fitz/fitz.h | 88 +--- fitz/res_font.c | 2 +- fitz/res_store.c | 12 +- 5 files changed, 10 insertions(+), 1365 deletions(-) delete mode 100644 fitz/base_object.c (limited to 'fitz') diff --git a/fitz/base_context.c b/fitz/base_context.c index fe69ff8e..d1ce63ae 100644 --- a/fitz/base_context.c +++ b/fitz/base_context.c @@ -1,13 +1,5 @@ #include "fitz.h" -static fz_obj * -fz_resolve_indirect_null(fz_obj *ref) -{ - return ref; -} - -fz_obj *(*fz_resolve_indirect)(fz_obj*) = fz_resolve_indirect_null; - void fz_free_context(fz_context *ctx) { diff --git a/fitz/base_object.c b/fitz/base_object.c deleted file mode 100644 index 964c5bb4..00000000 --- a/fitz/base_object.c +++ /dev/null @@ -1,1265 +0,0 @@ -#include "fitz.h" - -typedef enum fz_objkind_e -{ - FZ_NULL, - FZ_BOOL, - FZ_INT, - FZ_REAL, - FZ_STRING, - FZ_NAME, - FZ_ARRAY, - FZ_DICT, - FZ_INDIRECT -} fz_objkind; - -struct keyval -{ - fz_obj *k; - fz_obj *v; -}; - -struct fz_obj_s -{ - int refs; - fz_objkind kind; - fz_context *ctx; - union - { - int b; - int i; - float f; - struct { - unsigned short len; - char buf[1]; - } s; - char n[1]; - struct { - int len; - int cap; - fz_obj **items; - } a; - struct { - char sorted; - char marked; - int len; - int cap; - struct keyval *items; - } d; - struct { - int num; - int gen; - struct pdf_xref_s *xref; - } r; - } u; -}; - -fz_obj * -fz_new_null(fz_context *ctx) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(null)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_NULL; - return obj; -} - -fz_obj * -fz_new_bool(fz_context *ctx, int b) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(bool)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_BOOL; - obj->u.b = b; - return obj; -} - -fz_obj * -fz_new_int(fz_context *ctx, int i) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(int)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_INT; - obj->u.i = i; - return obj; -} - -fz_obj * -fz_new_real(fz_context *ctx, float f) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(real)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_REAL; - obj->u.f = f; - return obj; -} - -fz_obj * -fz_new_string(fz_context *ctx, char *str, int len) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, offsetof(fz_obj, u.s.buf) + len + 1), "fz_obj(string)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_STRING; - obj->u.s.len = len; - memcpy(obj->u.s.buf, str, len); - obj->u.s.buf[len] = '\0'; - return obj; -} - -fz_obj * -fz_new_name(fz_context *ctx, char *str) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, offsetof(fz_obj, u.n) + strlen(str) + 1), "fz_obj(name)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_NAME; - strcpy(obj->u.n, str); - return obj; -} - -fz_obj * -fz_new_indirect(fz_context *ctx, int num, int gen, void *xref) -{ - fz_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(indirect)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_INDIRECT; - obj->u.r.num = num; - obj->u.r.gen = gen; - obj->u.r.xref = xref; - return obj; -} - -fz_obj * -fz_keep_obj(fz_obj *obj) -{ - assert(obj); - obj->refs ++; - return obj; -} - -int fz_is_indirect(fz_obj *obj) -{ - return obj ? obj->kind == FZ_INDIRECT : 0; -} - -#define RESOLVE(obj) \ - do { \ - if (obj && obj->kind == FZ_INDIRECT) \ - {\ - fz_assert_lock_not_held(obj->ctx, FZ_LOCK_FILE); \ - obj = fz_resolve_indirect(obj); \ - } \ - } while (0) - -int fz_is_null(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_NULL : 0; -} - -int fz_is_bool(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_BOOL : 0; -} - -int fz_is_int(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_INT : 0; -} - -int fz_is_real(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_REAL : 0; -} - -int fz_is_string(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_STRING : 0; -} - -int fz_is_name(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_NAME : 0; -} - -int fz_is_array(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_ARRAY : 0; -} - -int fz_is_dict(fz_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == FZ_DICT : 0; -} - -int fz_to_bool(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - return obj->kind == FZ_BOOL ? obj->u.b : 0; -} - -int fz_to_int(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - if (obj->kind == FZ_INT) - return obj->u.i; - if (obj->kind == FZ_REAL) - return (int)(obj->u.f + 0.5f); /* No roundf in MSVC */ - return 0; -} - -float fz_to_real(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - if (obj->kind == FZ_REAL) - return obj->u.f; - if (obj->kind == FZ_INT) - return obj->u.i; - return 0; -} - -char *fz_to_name(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_NAME) - return ""; - return obj->u.n; -} - -char *fz_to_str_buf(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_STRING) - return ""; - return obj->u.s.buf; -} - -int fz_to_str_len(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_STRING) - return 0; - return obj->u.s.len; -} - -/* for use by pdf_crypt_obj_imp to decrypt AES string in place */ -void fz_set_str_len(fz_obj *obj, int newlen) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_STRING) - return; /* This should never happen */ - if (newlen > obj->u.s.len) - return; /* This should never happen */ - obj->u.s.len = newlen; -} - -fz_obj *fz_to_dict(fz_obj *obj) -{ - RESOLVE(obj); - return (obj && obj->kind == FZ_DICT ? obj : NULL); -} - -int fz_to_num(fz_obj *obj) -{ - if (!obj || obj->kind != FZ_INDIRECT) - return 0; - return obj->u.r.num; -} - -int fz_to_gen(fz_obj *obj) -{ - if (!obj || obj->kind != FZ_INDIRECT) - return 0; - return obj->u.r.gen; -} - -void *fz_get_indirect_document(fz_obj *obj) -{ - if (!obj || obj->kind != FZ_INDIRECT) - return NULL; - return obj->u.r.xref; -} - -int -fz_objcmp(fz_obj *a, fz_obj *b) -{ - int i; - - if (a == b) - return 0; - - if (!a || !b) - return 1; - - if (a->kind != b->kind) - return 1; - - switch (a->kind) - { - case FZ_NULL: - return 0; - - case FZ_BOOL: - return a->u.b - b->u.b; - - case FZ_INT: - return a->u.i - b->u.i; - - case FZ_REAL: - if (a->u.f < b->u.f) - return -1; - if (a->u.f > b->u.f) - return 1; - return 0; - - case FZ_STRING: - if (a->u.s.len < b->u.s.len) - { - if (memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len) <= 0) - return -1; - return 1; - } - if (a->u.s.len > b->u.s.len) - { - if (memcmp(a->u.s.buf, b->u.s.buf, b->u.s.len) >= 0) - return 1; - return -1; - } - return memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len); - - case FZ_NAME: - return strcmp(a->u.n, b->u.n); - - case FZ_INDIRECT: - if (a->u.r.num == b->u.r.num) - return a->u.r.gen - b->u.r.gen; - return a->u.r.num - b->u.r.num; - - case FZ_ARRAY: - if (a->u.a.len != b->u.a.len) - return a->u.a.len - b->u.a.len; - for (i = 0; i < a->u.a.len; i++) - if (fz_objcmp(a->u.a.items[i], b->u.a.items[i])) - return 1; - return 0; - - case FZ_DICT: - if (a->u.d.len != b->u.d.len) - return a->u.d.len - b->u.d.len; - for (i = 0; i < a->u.d.len; i++) - { - if (fz_objcmp(a->u.d.items[i].k, b->u.d.items[i].k)) - return 1; - if (fz_objcmp(a->u.d.items[i].v, b->u.d.items[i].v)) - return 1; - } - return 0; - - } - return 1; -} - -static char * -fz_objkindstr(fz_obj *obj) -{ - if (!obj) - return ""; - switch (obj->kind) - { - case FZ_NULL: return "null"; - case FZ_BOOL: return "boolean"; - case FZ_INT: return "integer"; - case FZ_REAL: return "real"; - case FZ_STRING: return "string"; - case FZ_NAME: return "name"; - case FZ_ARRAY: return "array"; - case FZ_DICT: return "dictionary"; - case FZ_INDIRECT: return "reference"; - } - return ""; -} - -fz_obj * -fz_new_array(fz_context *ctx, int initialcap) -{ - fz_obj *obj; - int i; - - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(array)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_ARRAY; - - obj->u.a.len = 0; - obj->u.a.cap = initialcap > 1 ? initialcap : 6; - - fz_try(ctx) - { - obj->u.a.items = Memento_label(fz_malloc_array(ctx, obj->u.a.cap, sizeof(fz_obj*)), "fz_obj(array items)"); - } - fz_catch(ctx) - { - fz_free(ctx, obj); - fz_rethrow(ctx); - } - for (i = 0; i < obj->u.a.cap; i++) - obj->u.a.items[i] = NULL; - - return obj; -} - -static void -fz_array_grow(fz_obj *obj) -{ - int i; - - obj->u.a.cap = (obj->u.a.cap * 3) / 2; - obj->u.a.items = fz_resize_array(obj->ctx, obj->u.a.items, obj->u.a.cap, sizeof(fz_obj*)); - - for (i = obj->u.a.len ; i < obj->u.a.cap; i++) - obj->u.a.items[i] = NULL; -} - -fz_obj * -fz_copy_array(fz_context *ctx, fz_obj *obj) -{ - fz_obj *arr; - int i; - int n; - - RESOLVE(obj); - if (!obj || obj->kind != FZ_ARRAY) - fz_warn(ctx, "assert: not an array (%s)", fz_objkindstr(obj)); - - arr = fz_new_array(ctx, fz_array_len(obj)); - n = fz_array_len(obj); - for (i = 0; i < n; i++) - fz_array_push(arr, fz_array_get(obj, i)); - - return arr; -} - -int -fz_array_len(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_ARRAY) - return 0; - return obj->u.a.len; -} - -fz_obj * -fz_array_get(fz_obj *obj, int i) -{ - RESOLVE(obj); - - if (!obj || obj->kind != FZ_ARRAY) - return NULL; - - if (i < 0 || i >= obj->u.a.len) - return NULL; - - return obj->u.a.items[i]; -} - -void -fz_array_put(fz_obj *obj, int i, fz_obj *item) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != FZ_ARRAY) - fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); - else if (i < 0) - fz_warn(obj->ctx, "assert: index %d < 0", i); - else if (i >= obj->u.a.len) - fz_warn(obj->ctx, "assert: index %d > length %d", i, obj->u.a.len); - else - { - if (obj->u.a.items[i]) - fz_drop_obj(obj->u.a.items[i]); - obj->u.a.items[i] = fz_keep_obj(item); - } -} - -void -fz_array_push(fz_obj *obj, fz_obj *item) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != FZ_ARRAY) - fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); - else - { - if (obj->u.a.len + 1 > obj->u.a.cap) - fz_array_grow(obj); - obj->u.a.items[obj->u.a.len] = fz_keep_obj(item); - obj->u.a.len++; - } -} - -void -fz_array_insert(fz_obj *obj, fz_obj *item) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != FZ_ARRAY) - fz_warn(obj->ctx, "assert: not an array (%s)", fz_objkindstr(obj)); - else - { - if (obj->u.a.len + 1 > obj->u.a.cap) - fz_array_grow(obj); - memmove(obj->u.a.items + 1, obj->u.a.items, obj->u.a.len * sizeof(fz_obj*)); - obj->u.a.items[0] = fz_keep_obj(item); - obj->u.a.len++; - } -} - -int -fz_array_contains(fz_obj *arr, fz_obj *obj) -{ - int i; - - for (i = 0; i < fz_array_len(arr); i++) - if (!fz_objcmp(fz_array_get(arr, i), obj)) - return 1; - - return 0; -} - -/* dicts may only have names as keys! */ - -static int keyvalcmp(const void *ap, const void *bp) -{ - const struct keyval *a = ap; - const struct keyval *b = bp; - return strcmp(fz_to_name(a->k), fz_to_name(b->k)); -} - -fz_obj * -fz_new_dict(fz_context *ctx, int initialcap) -{ - fz_obj *obj; - int i; - - obj = Memento_label(fz_malloc(ctx, sizeof(fz_obj)), "fz_obj(dict)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = FZ_DICT; - - obj->u.d.sorted = 0; - obj->u.d.marked = 0; - obj->u.d.len = 0; - obj->u.d.cap = initialcap > 1 ? initialcap : 10; - - fz_try(ctx) - { - obj->u.d.items = Memento_label(fz_malloc_array(ctx, obj->u.d.cap, sizeof(struct keyval)), "fz_obj(dict items)"); - } - fz_catch(ctx) - { - fz_free(ctx, obj); - fz_rethrow(ctx); - } - for (i = 0; i < obj->u.d.cap; i++) - { - obj->u.d.items[i].k = NULL; - obj->u.d.items[i].v = NULL; - } - - return obj; -} - -static void -fz_dict_grow(fz_obj *obj) -{ - int i; - - obj->u.d.cap = (obj->u.d.cap * 3) / 2; - obj->u.d.items = fz_resize_array(obj->ctx, obj->u.d.items, obj->u.d.cap, sizeof(struct keyval)); - - for (i = obj->u.d.len; i < obj->u.d.cap; i++) - { - obj->u.d.items[i].k = NULL; - obj->u.d.items[i].v = NULL; - } -} - -fz_obj * -fz_copy_dict(fz_context *ctx, fz_obj *obj) -{ - fz_obj *dict; - int i, n; - - RESOLVE(obj); - if (obj && obj->kind != FZ_DICT) - fz_warn(ctx, "assert: not a dict (%s)", fz_objkindstr(obj)); - - n = fz_dict_len(obj); - dict = fz_new_dict(ctx, n); - for (i = 0; i < n; i++) - fz_dict_put(dict, fz_dict_get_key(obj, i), fz_dict_get_val(obj, i)); - - return dict; -} - -int -fz_dict_len(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return 0; - return obj->u.d.len; -} - -fz_obj * -fz_dict_get_key(fz_obj *obj, int i) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return NULL; - - if (i < 0 || i >= obj->u.d.len) - return NULL; - - return obj->u.d.items[i].k; -} - -fz_obj * -fz_dict_get_val(fz_obj *obj, int i) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return NULL; - - if (i < 0 || i >= obj->u.d.len) - return NULL; - - return obj->u.d.items[i].v; -} - -static int -fz_dict_finds(fz_obj *obj, char *key, int *location) -{ - if (obj->u.d.sorted && obj->u.d.len > 0) - { - int l = 0; - int r = obj->u.d.len - 1; - - if (strcmp(fz_to_name(obj->u.d.items[r].k), key) < 0) - { - if (location) - *location = r + 1; - return -1; - } - - while (l <= r) - { - int m = (l + r) >> 1; - int c = -strcmp(fz_to_name(obj->u.d.items[m].k), key); - if (c < 0) - r = m - 1; - else if (c > 0) - l = m + 1; - else - return m; - - if (location) - *location = l; - } - } - - else - { - int i; - for (i = 0; i < obj->u.d.len; i++) - if (strcmp(fz_to_name(obj->u.d.items[i].k), key) == 0) - return i; - - if (location) - *location = obj->u.d.len; - } - - return -1; -} - -fz_obj * -fz_dict_gets(fz_obj *obj, char *key) -{ - int i; - - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return NULL; - - i = fz_dict_finds(obj, key, NULL); - if (i >= 0) - return obj->u.d.items[i].v; - - return NULL; -} - -fz_obj * -fz_dict_get(fz_obj *obj, fz_obj *key) -{ - if (!key || key->kind != FZ_NAME) - return NULL; - return fz_dict_gets(obj, fz_to_name(key)); -} - -fz_obj * -fz_dict_getsa(fz_obj *obj, char *key, char *abbrev) -{ - fz_obj *v; - v = fz_dict_gets(obj, key); - if (v) - return v; - return fz_dict_gets(obj, abbrev); -} - -void -fz_dict_put(fz_obj *obj, fz_obj *key, fz_obj *val) -{ - int location; - char *s; - int i; - - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - { - fz_warn(obj->ctx, "assert: not a dict (%s)", fz_objkindstr(obj)); - return; - } - - RESOLVE(key); - if (!key || key->kind != FZ_NAME) - { - fz_warn(obj->ctx, "assert: key is not a name (%s)", fz_objkindstr(obj)); - return; - } - else - s = fz_to_name(key); - - if (!val) - { - fz_warn(obj->ctx, "assert: val does not exist for key (%s)", s); - return; - } - - if (obj->u.d.len > 100 && !obj->u.d.sorted) - fz_sort_dict(obj); - - i = fz_dict_finds(obj, s, &location); - if (i >= 0 && i < obj->u.d.len) - { - fz_drop_obj(obj->u.d.items[i].v); - obj->u.d.items[i].v = fz_keep_obj(val); - } - else - { - if (obj->u.d.len + 1 > obj->u.d.cap) - fz_dict_grow(obj); - - i = location; - if (obj->u.d.sorted && obj->u.d.len > 0) - memmove(&obj->u.d.items[i + 1], - &obj->u.d.items[i], - (obj->u.d.len - i) * sizeof(struct keyval)); - - obj->u.d.items[i].k = fz_keep_obj(key); - obj->u.d.items[i].v = fz_keep_obj(val); - obj->u.d.len ++; - } -} - -void -fz_dict_puts(fz_obj *obj, char *key, fz_obj *val) -{ - fz_obj *keyobj = fz_new_name(obj->ctx, key); - fz_dict_put(obj, keyobj, val); - fz_drop_obj(keyobj); -} - -void -fz_dict_dels(fz_obj *obj, char *key) -{ - RESOLVE(obj); - - if (!obj || obj->kind != FZ_DICT) - fz_warn(obj->ctx, "assert: not a dict (%s)", fz_objkindstr(obj)); - else - { - int i = fz_dict_finds(obj, key, NULL); - if (i >= 0) - { - fz_drop_obj(obj->u.d.items[i].k); - fz_drop_obj(obj->u.d.items[i].v); - obj->u.d.sorted = 0; - obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1]; - obj->u.d.len --; - } - } -} - -void -fz_dict_del(fz_obj *obj, fz_obj *key) -{ - RESOLVE(key); - if (!key || key->kind != FZ_NAME) - fz_warn(obj->ctx, "assert: key is not a name (%s)", fz_objkindstr(obj)); - else - fz_dict_dels(obj, key->u.n); -} - -void -fz_sort_dict(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return; - if (!obj->u.d.sorted) - { - qsort(obj->u.d.items, obj->u.d.len, sizeof(struct keyval), keyvalcmp); - obj->u.d.sorted = 1; - } -} - -int -fz_dict_marked(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return 0; - return obj->u.d.marked; -} - -int -fz_dict_mark(fz_obj *obj) -{ - int marked; - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return 0; - marked = obj->u.d.marked; - obj->u.d.marked = 1; - return marked; -} - -void -fz_dict_unmark(fz_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != FZ_DICT) - return; - obj->u.d.marked = 0; -} - -static void -fz_free_array(fz_obj *obj) -{ - int i; - - for (i = 0; i < obj->u.a.len; i++) - if (obj->u.a.items[i]) - fz_drop_obj(obj->u.a.items[i]); - - fz_free(obj->ctx, obj->u.a.items); - fz_free(obj->ctx, obj); -} - -static void -fz_free_dict(fz_obj *obj) -{ - int i; - - for (i = 0; i < obj->u.d.len; i++) { - if (obj->u.d.items[i].k) - fz_drop_obj(obj->u.d.items[i].k); - if (obj->u.d.items[i].v) - fz_drop_obj(obj->u.d.items[i].v); - } - - fz_free(obj->ctx, obj->u.d.items); - fz_free(obj->ctx, obj); -} - -void -fz_drop_obj(fz_obj *obj) -{ - if (!obj) - return; - if (--obj->refs) - return; - if (obj->kind == FZ_ARRAY) - fz_free_array(obj); - else if (obj->kind == FZ_DICT) - fz_free_dict(obj); - else - fz_free(obj->ctx, obj); -} - -/* Pretty printing objects */ - -struct fmt -{ - char *buf; - int cap; - int len; - int indent; - int tight; - int col; - int sep; - int last; -}; - -static void fmt_obj(struct fmt *fmt, fz_obj *obj); - -static inline int iswhite(int ch) -{ - return - ch == '\000' || - ch == '\011' || - ch == '\012' || - ch == '\014' || - ch == '\015' || - ch == '\040'; -} - -static inline int isdelim(int ch) -{ - return ch == '(' || ch == ')' || - ch == '<' || ch == '>' || - ch == '[' || ch == ']' || - ch == '{' || ch == '}' || - ch == '/' || - ch == '%'; -} - -static inline void fmt_putc(struct fmt *fmt, int c) -{ - if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) { - fmt->sep = 0; - fmt_putc(fmt, ' '); - } - fmt->sep = 0; - - if (fmt->buf && fmt->len < fmt->cap) - fmt->buf[fmt->len] = c; - - if (c == '\n') - fmt->col = 0; - else - fmt->col ++; - - fmt->len ++; - - fmt->last = c; -} - -static inline void fmt_indent(struct fmt *fmt) -{ - int i = fmt->indent; - while (i--) { - fmt_putc(fmt, ' '); - fmt_putc(fmt, ' '); - } -} - -static inline void fmt_puts(struct fmt *fmt, char *s) -{ - while (*s) - fmt_putc(fmt, *s++); -} - -static inline void fmt_sep(struct fmt *fmt) -{ - fmt->sep = 1; -} - -static void fmt_str(struct fmt *fmt, fz_obj *obj) -{ - char *s = fz_to_str_buf(obj); - int n = fz_to_str_len(obj); - int i, c; - - fmt_putc(fmt, '('); - for (i = 0; i < n; i++) - { - c = (unsigned char)s[i]; - if (c == '\n') - fmt_puts(fmt, "\\n"); - else if (c == '\r') - fmt_puts(fmt, "\\r"); - else if (c == '\t') - fmt_puts(fmt, "\\t"); - else if (c == '\b') - fmt_puts(fmt, "\\b"); - else if (c == '\f') - fmt_puts(fmt, "\\f"); - else if (c == '(') - fmt_puts(fmt, "\\("); - else if (c == ')') - fmt_puts(fmt, "\\)"); - else if (c < 32 || c >= 127) { - char buf[16]; - fmt_putc(fmt, '\\'); - sprintf(buf, "%03o", c); - fmt_puts(fmt, buf); - } - else - fmt_putc(fmt, c); - } - fmt_putc(fmt, ')'); -} - -static void fmt_hex(struct fmt *fmt, fz_obj *obj) -{ - char *s = fz_to_str_buf(obj); - int n = fz_to_str_len(obj); - int i, b, c; - - fmt_putc(fmt, '<'); - for (i = 0; i < n; i++) { - b = (unsigned char) s[i]; - c = (b >> 4) & 0x0f; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - c = (b) & 0x0f; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - } - fmt_putc(fmt, '>'); -} - -static void fmt_name(struct fmt *fmt, fz_obj *obj) -{ - unsigned char *s = (unsigned char *) fz_to_name(obj); - int i, c; - - fmt_putc(fmt, '/'); - - for (i = 0; s[i]; i++) - { - if (isdelim(s[i]) || iswhite(s[i]) || - s[i] == '#' || s[i] < 32 || s[i] >= 127) - { - fmt_putc(fmt, '#'); - c = (s[i] >> 4) & 0xf; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - c = s[i] & 0xf; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - } - else - { - fmt_putc(fmt, s[i]); - } - } -} - -static void fmt_array(struct fmt *fmt, fz_obj *obj) -{ - int i, n; - - n = fz_array_len(obj); - if (fmt->tight) { - fmt_putc(fmt, '['); - for (i = 0; i < n; i++) { - fmt_obj(fmt, fz_array_get(obj, i)); - fmt_sep(fmt); - } - fmt_putc(fmt, ']'); - } - else { - fmt_puts(fmt, "[ "); - for (i = 0; i < n; i++) { - if (fmt->col > 60) { - fmt_putc(fmt, '\n'); - fmt_indent(fmt); - } - fmt_obj(fmt, fz_array_get(obj, i)); - fmt_putc(fmt, ' '); - } - fmt_putc(fmt, ']'); - fmt_sep(fmt); - } -} - -static void fmt_dict(struct fmt *fmt, fz_obj *obj) -{ - int i, n; - fz_obj *key, *val; - - n = fz_dict_len(obj); - if (fmt->tight) { - fmt_puts(fmt, "<<"); - for (i = 0; i < n; i++) { - fmt_obj(fmt, fz_dict_get_key(obj, i)); - fmt_sep(fmt); - fmt_obj(fmt, fz_dict_get_val(obj, i)); - fmt_sep(fmt); - } - fmt_puts(fmt, ">>"); - } - else { - fmt_puts(fmt, "<<\n"); - fmt->indent ++; - for (i = 0; i < n; i++) { - key = fz_dict_get_key(obj, i); - val = fz_dict_get_val(obj, i); - fmt_indent(fmt); - fmt_obj(fmt, key); - fmt_putc(fmt, ' '); - if (!fz_is_indirect(val) && fz_is_array(val)) - fmt->indent ++; - fmt_obj(fmt, val); - fmt_putc(fmt, '\n'); - if (!fz_is_indirect(val) && fz_is_array(val)) - fmt->indent --; - } - fmt->indent --; - fmt_indent(fmt); - fmt_puts(fmt, ">>"); - } -} - -static void fmt_obj(struct fmt *fmt, fz_obj *obj) -{ - char buf[256]; - - if (!obj) - fmt_puts(fmt, ""); - else if (fz_is_indirect(obj)) - { - sprintf(buf, "%d %d R", fz_to_num(obj), fz_to_gen(obj)); - fmt_puts(fmt, buf); - } - else if (fz_is_null(obj)) - fmt_puts(fmt, "null"); - else if (fz_is_bool(obj)) - fmt_puts(fmt, fz_to_bool(obj) ? "true" : "false"); - else if (fz_is_int(obj)) - { - sprintf(buf, "%d", fz_to_int(obj)); - fmt_puts(fmt, buf); - } - else if (fz_is_real(obj)) - { - sprintf(buf, "%g", fz_to_real(obj)); - if (strchr(buf, 'e')) /* bad news! */ - sprintf(buf, fabsf(fz_to_real(obj)) > 1 ? "%1.1f" : "%1.8f", fz_to_real(obj)); - fmt_puts(fmt, buf); - } - else if (fz_is_string(obj)) - { - char *str = fz_to_str_buf(obj); - int len = fz_to_str_len(obj); - int added = 0; - int i, c; - for (i = 0; i < len; i++) { - c = (unsigned char)str[i]; - if (strchr("()\\\n\r\t\b\f", c)) - added ++; - else if (c < 32 || c >= 127) - added += 3; - } - if (added < len) - fmt_str(fmt, obj); - else - fmt_hex(fmt, obj); - } - else if (fz_is_name(obj)) - fmt_name(fmt, obj); - else if (fz_is_array(obj)) - fmt_array(fmt, obj); - else if (fz_is_dict(obj)) - fmt_dict(fmt, obj); - else - fmt_puts(fmt, ""); -} - -static int -fz_sprint_obj(char *s, int n, fz_obj *obj, int tight) -{ - struct fmt fmt; - - fmt.indent = 0; - fmt.col = 0; - fmt.sep = 0; - fmt.last = 0; - - fmt.tight = tight; - fmt.buf = s; - fmt.cap = n; - fmt.len = 0; - fmt_obj(&fmt, obj); - - if (fmt.buf && fmt.len < fmt.cap) - fmt.buf[fmt.len] = '\0'; - - return fmt.len; -} - -int -fz_fprint_obj(FILE *fp, fz_obj *obj, int tight) -{ - char buf[1024]; - char *ptr; - int n; - - n = fz_sprint_obj(NULL, 0, obj, tight); - if ((n + 1) < sizeof buf) - { - fz_sprint_obj(buf, sizeof buf, obj, tight); - fputs(buf, fp); - fputc('\n', fp); - } - else - { - ptr = fz_malloc(obj->ctx, n + 1); - fz_sprint_obj(ptr, n + 1, obj, tight); - fputs(ptr, fp); - fputc('\n', fp); - fz_free(obj->ctx, ptr); - } - return n; -} - -void -fz_debug_obj(fz_obj *obj) -{ - fz_fprint_obj(stdout, obj, 0); -} - -void -fz_debug_ref(fz_obj *ref) -{ - fz_debug_obj(fz_resolve_indirect(ref)); -} diff --git a/fitz/fitz.h b/fitz/fitz.h index cb7cfa4d..e24d3fbb 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -54,7 +54,6 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #define snprintf _snprintf -#define strtoll _strtoi64 #else /* Unix or close enough */ @@ -908,87 +907,6 @@ void aes_crypt_cbc( fz_aes *ctx, int mode, int length, const unsigned char *input, unsigned char *output ); -/* - * Dynamic objects. - * The same type of objects as found in PDF and PostScript. - * Used by the filters and the mupdf parser. - */ - -typedef struct fz_obj_s fz_obj; - -extern fz_obj *(*fz_resolve_indirect)(fz_obj *obj); - -fz_obj *fz_new_null(fz_context *ctx); -fz_obj *fz_new_bool(fz_context *ctx, int b); -fz_obj *fz_new_int(fz_context *ctx, int i); -fz_obj *fz_new_real(fz_context *ctx, float f); -fz_obj *fz_new_name(fz_context *ctx, char *str); -fz_obj *fz_new_string(fz_context *ctx, char *str, int len); -fz_obj *fz_new_indirect(fz_context *ctx, int num, int gen, void *doc); - -fz_obj *fz_new_array(fz_context *ctx, int initialcap); -fz_obj *fz_new_dict(fz_context *ctx, int initialcap); -fz_obj *fz_copy_array(fz_context *ctx, fz_obj *array); -fz_obj *fz_copy_dict(fz_context *ctx, fz_obj *dict); - -fz_obj *fz_keep_obj(fz_obj *obj); -void fz_drop_obj(fz_obj *obj); - -/* type queries */ -int fz_is_null(fz_obj *obj); -int fz_is_bool(fz_obj *obj); -int fz_is_int(fz_obj *obj); -int fz_is_real(fz_obj *obj); -int fz_is_name(fz_obj *obj); -int fz_is_string(fz_obj *obj); -int fz_is_array(fz_obj *obj); -int fz_is_dict(fz_obj *obj); -int fz_is_indirect(fz_obj *obj); - -int fz_objcmp(fz_obj *a, fz_obj *b); - -/* dict marking and unmarking functions - to avoid infinite recursions */ -int fz_dict_marked(fz_obj *obj); -int fz_dict_mark(fz_obj *obj); -void fz_dict_unmark(fz_obj *obj); - -/* safe, silent failure, no error reporting on type mismatches */ -int fz_to_bool(fz_obj *obj); -int fz_to_int(fz_obj *obj); -float fz_to_real(fz_obj *obj); -char *fz_to_name(fz_obj *obj); -char *fz_to_str_buf(fz_obj *obj); -fz_obj *fz_to_dict(fz_obj *obj); -int fz_to_str_len(fz_obj *obj); -int fz_to_num(fz_obj *obj); -int fz_to_gen(fz_obj *obj); - -int fz_array_len(fz_obj *array); -fz_obj *fz_array_get(fz_obj *array, int i); -void fz_array_put(fz_obj *array, int i, fz_obj *obj); -void fz_array_push(fz_obj *array, fz_obj *obj); -void fz_array_insert(fz_obj *array, fz_obj *obj); -int fz_array_contains(fz_obj *array, fz_obj *obj); - -int fz_dict_len(fz_obj *dict); -fz_obj *fz_dict_get_key(fz_obj *dict, int idx); -fz_obj *fz_dict_get_val(fz_obj *dict, int idx); -fz_obj *fz_dict_get(fz_obj *dict, fz_obj *key); -fz_obj *fz_dict_gets(fz_obj *dict, char *key); -fz_obj *fz_dict_getsa(fz_obj *dict, char *key, char *abbrev); -void fz_dict_put(fz_obj *dict, fz_obj *key, fz_obj *val); -void fz_dict_puts(fz_obj *dict, char *key, fz_obj *val); -void fz_dict_del(fz_obj *dict, fz_obj *key); -void fz_dict_dels(fz_obj *dict, char *key); -void fz_sort_dict(fz_obj *dict); - -int fz_fprint_obj(FILE *fp, fz_obj *obj, int tight); -void fz_debug_obj(fz_obj *obj); -void fz_debug_ref(fz_obj *obj); - -void fz_set_str_len(fz_obj *obj, int newlen); /* private */ -void *fz_get_indirect_document(fz_obj *obj); /* private */ - /* fz_buffer is a XXX */ @@ -1071,6 +989,7 @@ struct fz_store_type_s void *(*keep_key)(fz_context *,void *); void (*drop_key)(fz_context *,void *); int (*cmp_key)(void *, void *); + void (*debug)(void *); }; void fz_new_store_context(fz_context *ctx, unsigned int max); @@ -1558,12 +1477,13 @@ struct fz_font_s int ft_size; fz_matrix t3matrix; - fz_obj *t3resources; + void *t3resources; fz_buffer **t3procs; /* 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, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate); + void (*t3run)(void *doc, void *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate); + void (*t3freeres)(void *doc, void *resources); fz_rect bbox; /* font bbox is used only for t3 fonts */ diff --git a/fitz/res_font.c b/fitz/res_font.c index 7a194da6..e44be9b6 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -93,7 +93,7 @@ fz_drop_font(fz_context *ctx, fz_font *font) if (font->t3procs) { if (font->t3resources) - fz_drop_obj(font->t3resources); + font->t3freeres(font->t3doc, font->t3resources); for (i = 0; i < 256; i++) if (font->t3procs[i]) fz_drop_buffer(ctx, font->t3procs[i]); diff --git a/fitz/res_store.c b/fitz/res_store.c index 461ea7c8..8f9c1ad8 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -459,17 +459,15 @@ fz_debug_store(fz_context *ctx) for (item = store->head; item; item = next) { next = item->next; - next->val->refs++; + if (next) + next->val->refs++; printf("store[*][refs=%d][size=%d] ", item->val->refs, item->size); fz_unlock(ctx, FZ_LOCK_ALLOC); - if (fz_is_indirect(item->key)) - { - printf("(%d %d R) ", fz_to_num(item->key), fz_to_gen(item->key)); - } else - fz_debug_obj(item->key); + item->type->debug(item->key); printf(" = %p\n", item->val); fz_lock(ctx, FZ_LOCK_ALLOC); - next->val->refs--; + if (next) + next->val->refs--; } fz_unlock(ctx, FZ_LOCK_ALLOC); } -- cgit v1.2.3 From 46ddb6ea2c7fa8c56006d39dc41836fa6c59f40d Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Wed, 29 Feb 2012 18:39:16 +0000 Subject: Fix typo in hash table code. When detecting a clash when inserting into a hash table (which should only ever happen in multithreaded cases), we should give a warning, and return the existing item from the table. The current code doesn't do this due to a stupid typo. Fixed here. CLUSTER_UNTESTED as we don't test multithreaded operation in the cluster. --- fitz/base_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fitz') diff --git a/fitz/base_hash.c b/fitz/base_hash.c index 0fda86cd..76c95304 100644 --- a/fitz/base_hash.c +++ b/fitz/base_hash.c @@ -127,7 +127,7 @@ do_hash_insert(fz_context *ctx, fz_hash_table *table, void *key, void *val) if (memcmp(key, ents[pos].key, table->keylen) == 0) { fz_warn(ctx, "assert: overwrite hash slot"); - return ents[pos].val = val; + return ents[pos].val; } pos = (pos + 1) % size; -- cgit v1.2.3 From 4a80adff52b8f4fc4f7f0aba8d3583953ddde824 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Wed, 29 Feb 2012 20:18:39 +0000 Subject: On MacOS/iOS use _setjmp/_longjmp rather than setjmp/longjmp. On Apple OSs setjmp/longjmp also mess with the signal handlers; we don't use signals, so we don't need the slowdown this causes. CLUSTER_UNTESTED as not tested on cluster. --- fitz/base_error.c | 2 +- fitz/fitz.h | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'fitz') diff --git a/fitz/base_error.c b/fitz/base_error.c index 6b54fb69..f3ca4efa 100644 --- a/fitz/base_error.c +++ b/fitz/base_error.c @@ -46,7 +46,7 @@ void fz_warn(fz_context *ctx, char *fmt, ...) static void throw(fz_error_context *ex) { if (ex->top >= 0) { - longjmp(ex->stack[ex->top].buffer, 1); + fz_longjmp(ex->stack[ex->top].buffer, 1); } else { fprintf(stderr, "uncaught exception: %s\n", ex->message); LOGE("uncaught exception: %s\n", ex->message); diff --git a/fitz/fitz.h b/fitz/fitz.h index e24d3fbb..0d0d657a 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -22,6 +22,14 @@ #include "memento.h" +#ifdef __APPLE__ +#define fz_setjmp _setjmp +#define fz_longjmp _longjmp +#else +#define fz_setjmp setjmp +#define fz_longjmp longjmp +#endif + #ifdef __ANDROID__ #include #define LOG_TAG "libmupdf" @@ -143,7 +151,7 @@ void fz_var_imp(void *); #define fz_try(ctx) \ if (fz_push_try(ctx->error), \ - (ctx->error->stack[ctx->error->top].code = setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ + (ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ { do { #define fz_always(ctx) \ @@ -169,7 +177,7 @@ instead. This was held as too high a price to pay to drop limitation 2. #define fz_try(ctx) \ if (fz_push_try(ctx->error), \ - (ctx->error->stack[ctx->error->top].code = setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ + (ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ { do { #define fz_always_(ctx, label) \ @@ -197,7 +205,7 @@ execution. Again this was felt to be too high a cost to use. #define fz_try(ctx) \ if (fz_push_try(ctx->error), \ - (ctx->error->stack[ctx->error->top].code = setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ + (ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ { do { #define fz_always(ctx) \ -- cgit v1.2.3 From 152ce17e73ab54e0f619ec2088b34a4a5e53f421 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Thu, 1 Mar 2012 14:45:44 +0000 Subject: Remove mask entry from fz_pixmap as never used any more. Also, the attempts to keep it up to date were causing race conditions in multithreading cases. --- fitz/fitz.h | 3 --- fitz/res_colorspace.c | 2 -- fitz/res_pixmap.c | 3 --- 3 files changed, 8 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 0d0d657a..825ed4ba 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1233,8 +1233,6 @@ typedef struct fz_colorspace_s fz_colorspace; n: The number of color components in the image. Always includes a separate alpha channel. XXX RGBA=4 - mask: XXX - 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. @@ -1254,7 +1252,6 @@ struct fz_pixmap_s { fz_storable storable; int x, y, w, h, n; - fz_pixmap *mask; /* explicit soft/image mask */ int interpolate; int xres, yres; fz_colorspace *colorspace; diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index c25fc99f..3cdc0fa3 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -506,8 +506,6 @@ fz_convert_pixmap(fz_context *ctx, fz_pixmap *sp, fz_pixmap *dp) assert(ss && ds); - if (sp->mask) - dp->mask = fz_keep_pixmap(ctx, sp->mask); dp->interpolate = sp->interpolate; if (ss == fz_device_gray) diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index 328a8c2d..1b254f36 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -17,8 +17,6 @@ fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix_) { fz_pixmap *pix = (fz_pixmap *)pix_; - if (pix->mask) - fz_drop_pixmap(ctx, pix->mask); if (pix->colorspace) fz_drop_colorspace(ctx, pix->colorspace); if (pix->free_samples) @@ -37,7 +35,6 @@ fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h pix->y = 0; pix->w = w; pix->h = h; - pix->mask = NULL; pix->interpolate = 1; pix->xres = 96; pix->yres = 96; -- cgit v1.2.3 From c6aa389a2c3430396a5e818bbb849410ab29d617 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Thu, 1 Mar 2012 15:25:43 +0000 Subject: Setjmp/longjmp exception tweaks. First, fix a couple of the 'alternative formulations' of the try/catch code in the comments. Secondly, work around a Mac OS X compiler bug. --- fitz/fitz.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 825ed4ba..f72aecb9 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -210,7 +210,7 @@ execution. Again this was felt to be too high a cost to use. #define fz_always(ctx) \ } while (0); \ - longjmp(ctx->error->stack[ctx->error->top].buffer, 3); \ + fz_longjmp(ctx->error->stack[ctx->error->top].buffer, 3); \ } \ else if (ctx->error->stack[ctx->error->top].code & 1) \ { do { @@ -218,7 +218,7 @@ execution. Again this was felt to be too high a cost to use. #define fz_catch(ctx) \ } while(0); \ if (ctx->error->stack[ctx->error->top].code == 1) \ - longjmp(ctx->error->stack[ctx->error->top].buffer, 2); \ + fz_longjmp(ctx->error->stack[ctx->error->top].buffer, 2); \ ctx->error->top--;\ } \ else if (ctx->error->top--, 1) -- cgit v1.2.3 From bcf7519882ba6f7b8f4b8047fb1f94bc9bd1ec6e Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Thu, 1 Mar 2012 16:38:01 +0000 Subject: Fix incorrect handling of race condition. When inserting an item into the store we check for an identically keyed item being there already (for instance a pixmap created from an image I at factor F may find that such a pixmap has already been inserted). The correct thing to do is to return the old one so we can use that in preference. The code was attempting to do this, but was returning a pointer to the fz_item rather than to the item->val. Fixed here. --- fitz/res_store.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/res_store.c b/fitz/res_store.c index 8f9c1ad8..0e3e7214 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -248,7 +248,7 @@ fz_store_item(fz_context *ctx, void *key, void *val_, unsigned int itemsize, fz_ /* If we can index it fast, put it into the hash table */ if (use_hash) { - fz_pixmap *existing; + fz_item *existing; fz_try(ctx) { @@ -265,7 +265,8 @@ fz_store_item(fz_context *ctx, void *key, void *val_, unsigned int itemsize, fz_ if (existing) { fz_unlock(ctx, FZ_LOCK_ALLOC); - return existing; + fz_free(ctx, item); + return existing->val; } } /* Now we can never fail, bump the ref */ -- cgit v1.2.3 From ea671d1254dad3b9ef5a8fbdd9729c3ada2a49b2 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Thu, 1 Mar 2012 19:42:28 +0000 Subject: Add some more docs to fitz.h Add docs for fz_store, fz_image, fz_halftones. Move fz_item definition into res_store.c as it does not need to be external. Rename fz_store_context to fz_keep_store_context to be consistent. --- fitz/base_context.c | 2 +- fitz/fitz.h | 178 ++++++++++++++++++++++++++++++++++++++++++++++------ fitz/res_store.c | 4 +- 3 files changed, 162 insertions(+), 22 deletions(-) (limited to 'fitz') diff --git a/fitz/base_context.c b/fitz/base_context.c index d1ce63ae..2eeb6683 100644 --- a/fitz/base_context.c +++ b/fitz/base_context.c @@ -122,7 +122,7 @@ fz_clone_context_internal(fz_context *ctx) if (ctx == NULL || ctx->alloc == NULL) return NULL; new_ctx = new_context_phase1(ctx->alloc, ctx->locks); - new_ctx->store = fz_store_keep(ctx); + new_ctx->store = fz_keep_store_context(ctx); new_ctx->glyph_cache = fz_keep_glyph_cache(ctx); new_ctx->font = fz_keep_font_context(ctx); return new_ctx; diff --git a/fitz/fitz.h b/fitz/fitz.h index f72aecb9..594bc4e9 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -936,13 +936,28 @@ void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); /* - * Resource store + 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 struct fz_item_s fz_item; - typedef void (fz_store_free_fn)(fz_context *, fz_storable *); struct fz_storable_s { @@ -955,6 +970,9 @@ struct fz_storable_s { S->free = (FREE); \ } while (0) +void *fz_keep_storable(fz_context *, fz_storable *); +void fz_drop_storable(fz_context *, fz_storable *); + /* Specifies the maximum size in bytes of the resource store in fz_context. Given as argument to fz_new_context. @@ -969,6 +987,22 @@ enum { FZ_STORE_DEFAULT = 256 << 20, }; +/* + 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 @@ -1000,18 +1034,95 @@ struct fz_store_type_s void (*debug)(void *); }; +/* + 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_store *fz_store_keep(fz_context *ctx); + +/* + fz_keep_store_context: Take a reference to the store. +*/ +fz_store *fz_keep_store_context(fz_context *ctx); + +/* + fz_debug_store: Dump the contents of the store for debugging. +*/ void fz_debug_store(fz_context *ctx); -void *fz_keep_storable(fz_context *, fz_storable *); -void fz_drop_storable(fz_context *, fz_storable *); +/* + 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); /* @@ -1340,10 +1451,10 @@ void fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int saveal void fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); /* - * Images are either a reference to a pixmap, or details of how to make - * a pixmap. To know how to make a pixmap we need a block of compressed - * data (typically a stream decoded all the way until the image filter) - * and then the details of the params for the filter to do the final step. + Images are storable objects from which we can obtain fz_pixmaps. + These may be implemented as simple wrappers around a pixmap, or as + more complex things that decode at different subsample settings on + demand. */ typedef struct fz_image_s fz_image; @@ -1356,8 +1467,37 @@ struct fz_image_s fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, int w, int h); }; -fz_pixmap *fz_image_to_pixmap(fz_context *, fz_image *, int w, int h); +/* + fz_image_to_pixmap: Called to get a handle to a pixmap from an image. + + image: The image to retrieve a pixmap from. + + w: The desired width (in pixels). This may be completely ignored, but + may serve as an indication of a suitable subsample factor to use for + image types that support this. + + h: The desired height (in pixels). This may be completely ignored, but + may serve as an indication of a suitable subsample factor to use for + image types that support this. + + Returns a non NULL pixmap pointer. May throw exceptions. +*/ +fz_pixmap *fz_image_to_pixmap(fz_context *ctx, fz_image *image, int w, int h); + +/* + fz_drop_image: Drop a reference to an image. + + image: The image to drop a reference to. +*/ void fz_drop_image(fz_context *ctx, fz_image *image); + +/* + fz_keep_image: Increment the reference count of an image. + + image: The image to take a reference to. + + Returns a pointer to the image. +*/ fz_image *fz_keep_image(fz_context *ctx, fz_image *image); fz_pixmap *fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *cs); @@ -1366,11 +1506,10 @@ fz_pixmap *fz_load_png(fz_context *doc, unsigned char *data, int size); fz_pixmap *fz_load_tiff(fz_context *doc, unsigned char *data, int size); /* - * Bitmaps have 1 bit per component. Only used for creating halftoned versions - * of contone buffers, and saving out. Samples are stored msb first, akin to - * pbms. - */ - + Bitmaps have 1 bit per component. Only used for creating halftoned + versions of contone buffers, and saving out. Samples are stored msb + first, akin to pbms. +*/ typedef struct fz_bitmap_s fz_bitmap; struct fz_bitmap_s @@ -1388,10 +1527,9 @@ void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); void fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename); /* - * A halftone is a set of threshold tiles, one per component. Each threshold - * tile is a pixmap, possibly of varying sizes and phases. - */ - + A halftone is a set of threshold tiles, one per component. Each + threshold tile is a pixmap, possibly of varying sizes and phases. +*/ typedef struct fz_halftone_s fz_halftone; struct fz_halftone_s diff --git a/fitz/res_store.c b/fitz/res_store.c index 0e3e7214..2a7680e3 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -1,5 +1,7 @@ #include "fitz.h" +typedef struct fz_item_s fz_item; + struct fz_item_s { void *key; @@ -420,7 +422,7 @@ fz_empty_store(fz_context *ctx) } fz_store * -fz_store_keep(fz_context *ctx) +fz_keep_store_context(fz_context *ctx) { if (ctx == NULL || ctx->store == NULL) return NULL; -- cgit v1.2.3 From c5c6aa47e4fbc0323c36065a6f8acaaed609f852 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Fri, 2 Mar 2012 16:10:48 +0000 Subject: Fix race condition in fz_render_ft_glyph We were dropping the FREETYPE lock before completing the copy out of the glyph. --- fitz/res_font.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/res_font.c b/fitz/res_font.c index e44be9b6..e4a4d23a 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -393,6 +393,7 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) FT_Matrix m; FT_Vector v; FT_Error fterr; + fz_pixmap *result; trm = fz_adjust_ft_glyph_width(ctx, font, gid, trm); @@ -477,9 +478,10 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) fz_unlock(ctx, FZ_LOCK_FREETYPE); return NULL; } - fz_unlock(ctx, FZ_LOCK_FREETYPE); - return fz_copy_ft_bitmap(ctx, face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap); + result = fz_copy_ft_bitmap(ctx, face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap); + fz_unlock(ctx, FZ_LOCK_FREETYPE); + return result; } fz_pixmap * -- cgit v1.2.3 From a958c1e2effd97d8f17779ab975d72ee67b1ab09 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 2 Mar 2012 01:13:29 +0100 Subject: Tweak compression bomb detection. --- fitz/stm_read.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fitz') diff --git a/fitz/stm_read.c b/fitz/stm_read.c index c2d375f3..a95c62c0 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -1,5 +1,7 @@ #include "fitz.h" +#define MIN_BOMB (100 << 20) + int fz_read(fz_stream *stm, unsigned char *buf, int len) { @@ -108,7 +110,7 @@ fz_read_all(fz_stream *stm, int initial) if (buf->len == buf->cap) fz_grow_buffer(ctx, buf); - if (buf->len / 200 > initial) + if (buf->len >= MIN_BOMB && buf->len / 200 > initial) { fz_throw(ctx, "compression bomb detected"); } -- cgit v1.2.3 From dae93920d513842f6c9a96e833043f3f6f8e0681 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Tue, 6 Mar 2012 19:34:06 +0000 Subject: Fix ref counting bugs in race condition correction code. When we attempt to insert a key/value pair into the store, we have to allow for the possibility that a racing thread may have already inserted an equivalent key/value. We have special code in place to handle this eventuality; if we spot an existing entry, we take the existing one in preference to our new key/value pair. This means that fz_store_item needs to take a new reference to any existing thing it finds before returning it. Currently the only store user that is exposed to this possibility is pdf_image; it spots an existing tile being returned, and was inadvertently double freeing the key. --- fitz/res_store.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/res_store.c b/fitz/res_store.c index 2a7680e3..cc635052 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -266,14 +266,15 @@ fz_store_item(fz_context *ctx, void *key, void *val_, unsigned int itemsize, fz_ } if (existing) { + /* Take a new reference */ + existing->val->refs++; fz_unlock(ctx, FZ_LOCK_ALLOC); fz_free(ctx, item); return existing->val; } } /* Now we can never fail, bump the ref */ - if (val->refs > 0) - val->refs++; + val->refs++; /* Regardless of whether it's indexed, it goes into the linked list */ item->next = store->head; if (item->next) -- cgit v1.2.3 From a14bb1748d3827e542fbff47488f67e0dfa3b15d Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Tue, 6 Mar 2012 21:33:46 +0000 Subject: Fix memory corruption I'd foolishly removed a check in the previous commit that was needed. refs can be < 0 for static resources. --- fitz/res_store.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fitz') diff --git a/fitz/res_store.c b/fitz/res_store.c index cc635052..df9c6e33 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -274,7 +274,8 @@ fz_store_item(fz_context *ctx, void *key, void *val_, unsigned int itemsize, fz_ } } /* Now we can never fail, bump the ref */ - val->refs++; + if (val->refs > 0) + val->refs++; /* Regardless of whether it's indexed, it goes into the linked list */ item->next = store->head; if (item->next) -- cgit v1.2.3 From d55162d649a12d62a1d1c738d99ca9dee7de575d Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Fri, 2 Mar 2012 14:13:05 +0000 Subject: Split fitz.h/mupdf.h into internal/external headers. Attempt to separate public API from internal functions. --- fitz/base_context.c | 2 +- fitz/base_error.c | 2 +- fitz/base_geometry.c | 2 +- fitz/base_hash.c | 2 +- fitz/base_memory.c | 2 +- fitz/base_string.c | 2 +- fitz/crypt_aes.c | 2 +- fitz/crypt_arc4.c | 2 +- fitz/crypt_md5.c | 2 +- fitz/crypt_sha2.c | 2 +- fitz/dev_bbox.c | 2 +- fitz/dev_list.c | 2 +- fitz/dev_null.c | 2 +- fitz/dev_text.c | 2 +- fitz/dev_trace.c | 2 +- fitz/doc_document.c | 2 +- fitz/doc_link.c | 2 +- fitz/doc_outline.c | 2 +- fitz/filt_basic.c | 2 +- fitz/filt_dctd.c | 2 +- fitz/filt_faxd.c | 2 +- fitz/filt_flate.c | 2 +- fitz/filt_jbig2d.c | 2 +- fitz/filt_lzwd.c | 2 +- fitz/filt_predict.c | 2 +- fitz/fitz-internal.h | 1088 +++++++++++++++++++++++++++++++++++++++++ fitz/fitz.h | 1276 ++++--------------------------------------------- fitz/image_jpeg.c | 2 +- fitz/image_jpx.c | 2 +- fitz/image_md5.c | 11 + fitz/image_png.c | 2 +- fitz/image_save.c | 32 ++ fitz/image_tiff.c | 2 +- fitz/res_bitmap.c | 23 +- fitz/res_colorspace.c | 2 +- fitz/res_font.c | 2 +- fitz/res_halftone.c | 2 +- fitz/res_path.c | 2 +- fitz/res_pixmap.c | 23 +- fitz/res_shade.c | 2 +- fitz/res_store.c | 2 +- fitz/res_text.c | 2 +- fitz/stm_buffer.c | 2 +- fitz/stm_open.c | 2 +- fitz/stm_read.c | 2 +- 45 files changed, 1309 insertions(+), 1222 deletions(-) create mode 100644 fitz/fitz-internal.h create mode 100644 fitz/image_md5.c create mode 100644 fitz/image_save.c (limited to 'fitz') diff --git a/fitz/base_context.c b/fitz/base_context.c index 2eeb6683..7e3c0bdd 100644 --- a/fitz/base_context.c +++ b/fitz/base_context.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" void fz_free_context(fz_context *ctx) diff --git a/fitz/base_error.c b/fitz/base_error.c index f3ca4efa..71a32a2e 100644 --- a/fitz/base_error.c +++ b/fitz/base_error.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* Warning context */ diff --git a/fitz/base_geometry.c b/fitz/base_geometry.c index fc5ce517..84134179 100644 --- a/fitz/base_geometry.c +++ b/fitz/base_geometry.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #define MAX4(a,b,c,d) MAX(MAX(a,b), MAX(c,d)) #define MIN4(a,b,c,d) MIN(MIN(a,b), MIN(c,d)) diff --git a/fitz/base_hash.c b/fitz/base_hash.c index 76c95304..59ed8872 100644 --- a/fitz/base_hash.c +++ b/fitz/base_hash.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* Simple hashtable with open addressing linear probe. diff --git a/fitz/base_memory.c b/fitz/base_memory.c index c9ec2628..32c7ff84 100644 --- a/fitz/base_memory.c +++ b/fitz/base_memory.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" static void * do_scavenging_malloc(fz_context *ctx, unsigned int size) diff --git a/fitz/base_string.c b/fitz/base_string.c index dd9f8ea2..6fdfef62 100644 --- a/fitz/base_string.c +++ b/fitz/base_string.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" int fz_is_big_endian(void) diff --git a/fitz/crypt_aes.c b/fitz/crypt_aes.c index afdff0fe..4d8c4498 100644 --- a/fitz/crypt_aes.c +++ b/fitz/crypt_aes.c @@ -36,7 +36,7 @@ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf */ -#include "fitz.h" +#include "fitz-internal.h" #define aes_context fz_aes diff --git a/fitz/crypt_arc4.c b/fitz/crypt_arc4.c index 272891ce..596bf652 100644 --- a/fitz/crypt_arc4.c +++ b/fitz/crypt_arc4.c @@ -21,7 +21,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "fitz.h" +#include "fitz-internal.h" void fz_arc4_init(fz_arc4 *arc4, const unsigned char *key, unsigned keylen) diff --git a/fitz/crypt_md5.c b/fitz/crypt_md5.c index b6e06845..87c0909d 100644 --- a/fitz/crypt_md5.c +++ b/fitz/crypt_md5.c @@ -23,7 +23,7 @@ These notices must be retained in any copies of any part of this documentation and/or software. */ -#include "fitz.h" +#include "fitz-internal.h" /* Constants for MD5Transform routine */ enum diff --git a/fitz/crypt_sha2.c b/fitz/crypt_sha2.c index f17146c6..64284cfa 100644 --- a/fitz/crypt_sha2.c +++ b/fitz/crypt_sha2.c @@ -7,7 +7,7 @@ This file has been put into the public domain. You can do whatever you want with this file. */ -#include "fitz.h" +#include "fitz-internal.h" static inline int isbigendian(void) { diff --git a/fitz/dev_bbox.c b/fitz/dev_bbox.c index b015c585..163780d0 100644 --- a/fitz/dev_bbox.c +++ b/fitz/dev_bbox.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* TODO: add clip stack and use to intersect bboxes */ diff --git a/fitz/dev_list.c b/fitz/dev_list.c index 1d82421e..d0dfabc5 100644 --- a/fitz/dev_list.c +++ b/fitz/dev_list.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" typedef struct fz_display_node_s fz_display_node; diff --git a/fitz/dev_null.c b/fitz/dev_null.c index d817932d..886cebe1 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_device * fz_new_device(fz_context *ctx, void *user) diff --git a/fitz/dev_text.c b/fitz/dev_text.c index d38fab21..618a2e6e 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #define LINE_DIST 0.9f #define SPACE_DIST 0.2f diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index 9faffc35..f75f19d5 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" static void fz_trace_matrix(fz_matrix ctm) diff --git a/fitz/doc_document.c b/fitz/doc_document.c index ca13af72..2da7a110 100644 --- a/fitz/doc_document.c +++ b/fitz/doc_document.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* Yuck! Promiscuous we are. */ extern struct pdf_document *pdf_open_document(fz_context *ctx, char *filename); diff --git a/fitz/doc_link.c b/fitz/doc_link.c index 71f5dfbf..d558d18a 100644 --- a/fitz/doc_link.c +++ b/fitz/doc_link.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" void fz_free_link_dest(fz_context *ctx, fz_link_dest *dest) diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c index b69debaf..a00c56f1 100644 --- a/fitz/doc_outline.c +++ b/fitz/doc_outline.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" void fz_free_outline(fz_context *ctx, fz_outline *outline) diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c index ae239fed..09d63402 100644 --- a/fitz/filt_basic.c +++ b/fitz/filt_basic.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* Pretend we have a filter that just copies data forever */ diff --git a/fitz/filt_dctd.c b/fitz/filt_dctd.c index 3abe0468..23744f01 100644 --- a/fitz/filt_dctd.c +++ b/fitz/filt_dctd.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #include #include diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c index 4e522eb5..ada7e87b 100644 --- a/fitz/filt_faxd.c +++ b/fitz/filt_faxd.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* Fax G3/G4 decoder */ diff --git a/fitz/filt_flate.c b/fitz/filt_flate.c index 2eb0c563..24b6c081 100644 --- a/fitz/filt_flate.c +++ b/fitz/filt_flate.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #include diff --git a/fitz/filt_jbig2d.c b/fitz/filt_jbig2d.c index 3afcbcb0..415534c0 100644 --- a/fitz/filt_jbig2d.c +++ b/fitz/filt_jbig2d.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #ifdef _WIN32 /* Microsoft Visual C++ */ diff --git a/fitz/filt_lzwd.c b/fitz/filt_lzwd.c index ac952ccf..3ee4d34c 100644 --- a/fitz/filt_lzwd.c +++ b/fitz/filt_lzwd.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* TODO: error checking */ diff --git a/fitz/filt_predict.c b/fitz/filt_predict.c index 8221c251..e68743d3 100644 --- a/fitz/filt_predict.c +++ b/fitz/filt_predict.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* TODO: check if this works with 16bpp images */ diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h new file mode 100644 index 00000000..4ede601d --- /dev/null +++ b/fitz/fitz-internal.h @@ -0,0 +1,1088 @@ +#ifndef _FITZ_INTERNAL_H_ +#define _FITZ_INTERNAL_H_ + +#include "fitz.h" + +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); + +#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); +} + + +/* + * Basic runtime and utility functions + */ + +/* Range checking atof */ +float fz_atof(const char *s); + +/* utf-8 encoding and decoding */ +int chartorune(int *rune, char *str); +int runetochar(char *str, int *rune); +int runelen(int c); + +/* + * 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_debug_hash(fz_context *ctx, fz_hash_table *table); +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_remove(fz_context *ctx, fz_hash_table *table, void *key); + +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); + +/* + * 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) + + +float fz_matrix_expansion(fz_matrix m); +float fz_matrix_max_expansion(fz_matrix m); + + +void fz_gridfit_matrix(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]); + +/* 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 */ +}; + +void aes_setkey_enc( fz_aes *ctx, const unsigned char *key, int keysize ); +void 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 ); + +struct fz_buffer_s +{ + int refs; + unsigned char *data; + int cap, len; +}; + +fz_buffer *fz_new_buffer(fz_context *ctx, int size); + +void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size); +void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); +void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); + +/* + 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; + } 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 *); + void (*debug)(void *); +}; + +/* + 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_debug_store: Dump the contents of the store for debugging. +*/ +void fz_debug_store(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); + +struct fz_stream_s +{ + fz_context *ctx; + int refs; + int error; + int eof; + int pos; + int avail; + int bits; + int locked; + 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_open_file: Open the named file and wrap it in a stream. + + filename: Path to a file as it would be given to open(2). +*/ +fz_stream *fz_open_file(fz_context *ctx, const char *filename); + +/* + fz_open_file_w: Open the named file and wrap it in a stream. + + This function is only available when compiling for Win32. + + filename: Wide character path to the file as it would be given + to _wopen(). +*/ +fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); + + +/* + fz_open_buffer: XXX +*/ +fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); + +/* + fz_open_memory: XXX +*/ +fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); + +void fz_lock_stream(fz_stream *stm); + +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); + +int fz_tell(fz_stream *stm); +void fz_seek(fz_stream *stm, int offset, int whence); + +int fz_read(fz_stream *stm, unsigned char *buf, int len); +void fz_read_line(fz_stream *stm, char *buf, int max); +fz_buffer *fz_read_all(fz_stream *stm, int initial); + +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); +} + +/* + * Data filters. + */ + +fz_stream *fz_open_copy(fz_stream *chain); +fz_stream *fz_open_null(fz_stream *chain, int len); +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 factor); +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. + */ + +enum { FZ_MAX_COLORS = 32 }; + +int fz_find_blendmode(char *name); +char *fz_blendmode_name(int blendmode); + +/* + fz_pixmap is an image XXX + + x, y: XXX + + w, h: The width and height of the image in pixels. + + n: The number of color components in the image. Always + includes a separate alpha channel. XXX RGBA=4 + + 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: XXX + + samples: + + free_samples: Is zero when an application has provided its own + buffer for pixel data through fz_new_pixmap_with_rect_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; +}; + + +fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); + +/* + fz_new_pixmap_with_rect_and_data: Create a pixmap using the + provided buffer for pixel data. + + While fz_new_pixmap_with_rect allocates its own buffer for + pixel data, fz_new_pixmap_with_rect_and_data lets the caller + allocate and provide a buffer to be used. Otherwise the two + functions are identical. + + samples: An array of pixel samples. The created pixmap will + keep a pointer to the array so it must not be modified or + freed until the created pixmap is dropped and freed by + fz_drop_pixmap. +*/ +fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, +fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); +fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); + +void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); + +void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_bbox r); +void fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox 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_bbox *clip); + +struct fz_image_s +{ + fz_storable storable; + int w, h; + fz_image *mask; + fz_colorspace *colorspace; + fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, int w, int h); +}; + +fz_pixmap *fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *cs); +fz_pixmap *fz_load_jpeg(fz_context *doc, unsigned char *data, int size); +fz_pixmap *fz_load_png(fz_context *doc, unsigned char *data, int size); +fz_pixmap *fz_load_tiff(fz_context *doc, unsigned char *data, int size); + +struct fz_bitmap_s +{ + int refs; + int w, h, stride, n; + unsigned char *samples; +}; + +fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); +fz_bitmap *fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit); +void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); + + +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_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_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 *srcs, float *srcv, fz_colorspace *dsts, float *dstv); +void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); + +fz_colorspace *fz_find_device_colorspace(char *name); + +/* + * 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 */ + 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, fz_matrix ctm, void *gstate); + 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, fz_matrix matrix); + +fz_font *fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index, int use_glyph_bbox); +fz_font *fz_new_font_from_file(fz_context *ctx, 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_debug_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, fz_matrix trm); +int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid); + +/* + * 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 +{ + 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); +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, 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, fz_stroke_state *stroke, fz_matrix ctm); +void fz_debug_path(fz_context *ctx, fz_path *, int indent); + +/* + * 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_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm); +fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); +fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); +fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorspace *model); +fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke); +void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate); + +/* + * 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, 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, fz_matrix ctm); +fz_text *fz_clone_text(fz_context *ctx, fz_text *old); +void fz_debug_text(fz_context *ctx, fz_text*, int indent); + +/* + * The shading code uses gouraud shaded triangle meshes. + */ + +enum +{ + FZ_LINEAR, + FZ_RADIAL, + FZ_MESH, +}; + +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; /* linear, radial, mesh */ + int extend[2]; + + int mesh_len; + int mesh_cap; + float *mesh; /* [x y 0], [x y r], [x y t] or [x y c1 ... cn] */ +}; + +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); +void fz_debug_shade(fz_context *ctx, fz_shade *shade); + +fz_rect fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm); +void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); + +/* + * 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, fz_bbox clip); +void fz_sort_gel(fz_gel *gel); +fz_bbox fz_bound_gel(fz_gel *gel); +void fz_free_gel(fz_gel *gel); +int fz_is_rect_gel(fz_gel *gel); + +void fz_scan_convert(fz_gel *gel, int eofill, fz_bbox clip, fz_pixmap *pix, unsigned char *colorbv); + +void fz_flatten_fill_path(fz_gel *gel, fz_path *path, fz_matrix ctm, float flatness); +void fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); +void fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); + +/* + * The device interface. + */ + +enum +{ + /* Hints */ + FZ_IGNORE_IMAGE = 1, + FZ_IGNORE_SHADE = 2, + + /* 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 (*fill_path)(fz_device *, fz_path *, int even_odd, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*stroke_path)(fz_device *, fz_path *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*clip_path)(fz_device *, fz_path *, fz_rect *rect, int even_odd, fz_matrix); + void (*clip_stroke_path)(fz_device *, fz_path *, fz_rect *rect, fz_stroke_state *, fz_matrix); + + void (*fill_text)(fz_device *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*stroke_text)(fz_device *, fz_text *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*clip_text)(fz_device *, fz_text *, fz_matrix, int accumulate); + void (*clip_stroke_text)(fz_device *, fz_text *, fz_stroke_state *, fz_matrix); + void (*ignore_text)(fz_device *, fz_text *, fz_matrix); + + void (*fill_shade)(fz_device *, fz_shade *shd, fz_matrix ctm, float alpha); + void (*fill_image)(fz_device *, fz_image *img, fz_matrix ctm, float alpha); + void (*fill_image_mask)(fz_device *, fz_image *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); + void (*clip_image_mask)(fz_device *, fz_image *img, fz_rect *rect, fz_matrix ctm); + + void (*pop_clip)(fz_device *); + + void (*begin_mask)(fz_device *, fz_rect, int luminosity, fz_colorspace *, float *bc); + void (*end_mask)(fz_device *); + void (*begin_group)(fz_device *, fz_rect, int isolated, int knockout, int blendmode, float alpha); + void (*end_group)(fz_device *); + + void (*begin_tile)(fz_device *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); + void (*end_tile)(fz_device *); +}; + +void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm); +void fz_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm); +void fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate); +void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm); +void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm); +void fz_pop_clip(fz_device *dev); +void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha); +void fz_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha); +void fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); +void fz_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm); +void fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc); +void fz_end_mask(fz_device *dev); +void fz_begin_group(fz_device *dev, 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, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); +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, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha); +void fz_paint_image_with_color(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, 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_rect(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_bbox 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); + void (*run_page)(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix transform, fz_cookie *cookie); + void (*free_page)(fz_document *doc, fz_page *page); +}; + +#endif diff --git a/fitz/fitz.h b/fitz/fitz.h index 594bc4e9..732f2fc7 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -2,8 +2,8 @@ #define _FITZ_H_ /* - * Include the standard libc headers. - */ + Include the standard libc headers. +*/ #include #include @@ -48,8 +48,8 @@ #define CLAMP(x,a,b) ( (x) > (b) ? (b) : ( (x) < (a) ? (a) : (x) ) ) /* - * Some differences in libc can be smoothed over - */ + Some differences in libc can be smoothed over +*/ #ifdef _MSC_VER /* Microsoft Visual C */ @@ -82,8 +82,8 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #endif /* - * Variadic macros, inline and restrict keywords - */ + Variadic macros, inline and restrict keywords +*/ #if __STDC_VERSION__ == 199901L /* C99 */ #elif _MSC_VER >= 1500 /* MSVC 9 or newer */ @@ -98,8 +98,8 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #endif /* - * GCC can do type checking of printf strings - */ + GCC can do type checking of printf strings +*/ #ifndef __printflike #if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 @@ -146,8 +146,10 @@ struct fz_error_context_s void fz_var_imp(void *); #define fz_var(var) fz_var_imp((void *)&(var)) -/* Exception macro definitions. Just treat these as a black box - pay no - * attention to the man behind the curtain. */ +/* + Exception macro definitions. Just treat these as a black box - pay no + attention to the man behind the curtain. +*/ #define fz_try(ctx) \ if (fz_push_try(ctx->error), \ @@ -164,77 +166,11 @@ void fz_var_imp(void *); } \ if (ctx->error->stack[ctx->error->top--].code) -/* - -We also include a couple of other formulations of the macros, with -different strengths and weaknesses. These will be removed shortly, but -I want them in git for at least 1 revision so I have a record of them. - -A formulation of try/always/catch that lifts limitation 2 above, but -has problems when try/catch are nested in the same function; the inner -nestings need to use fz_always_(ctx, label) and fz_catch_(ctx, label) -instead. This was held as too high a price to pay to drop limitation 2. - -#define fz_try(ctx) \ - if (fz_push_try(ctx->error), \ - (ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ - { do { - -#define fz_always_(ctx, label) \ - } while (0); \ - goto ALWAYS_LABEL_ ## label ; \ - } \ - else if (ctx->error->stack[ctx->error->top].code) \ - { ALWAYS_LABEL_ ## label : \ - do { - -#define fz_catch_(ctx, label) \ - } while(0); \ - if (ctx->error->stack[ctx->error->top--].code) \ - goto CATCH_LABEL_ ## label; \ - } \ - else if (ctx->error->top--, 1) \ - CATCH_LABEL ## label: - -#define fz_always(ctx) fz_always_(ctx, TOP) -#define fz_catch(ctx) fz_catch_(ctx, TOP) - -Another alternative formulation, that again removes limitation 2, but at -the cost of an always block always costing us 1 extra longjmp per -execution. Again this was felt to be too high a cost to use. - -#define fz_try(ctx) \ - if (fz_push_try(ctx->error), \ - (ctx->error->stack[ctx->error->top].code = fz_setjmp(ctx->error->stack[ctx->error->top].buffer)) == 0) \ - { do { - -#define fz_always(ctx) \ - } while (0); \ - fz_longjmp(ctx->error->stack[ctx->error->top].buffer, 3); \ - } \ - else if (ctx->error->stack[ctx->error->top].code & 1) \ - { do { - -#define fz_catch(ctx) \ - } while(0); \ - if (ctx->error->stack[ctx->error->top].code == 1) \ - fz_longjmp(ctx->error->stack[ctx->error->top].buffer, 2); \ - ctx->error->top--;\ - } \ - else if (ctx->error->top--, 1) -*/ - void fz_push_try(fz_error_context *ex); void fz_throw(fz_context *, char *, ...) __printflike(2, 3); void fz_rethrow(fz_context *); - -struct fz_warn_context_s -{ - char message[256]; - int count; -}; - void fz_warn(fz_context *ctx, char *fmt, ...) __printflike(2, 3); + /* fz_flush_warnings: Flush any repeated warnings. @@ -260,6 +196,20 @@ struct fz_context_s fz_glyph_cache *glyph_cache; }; +/* + Specifies the maximum size in bytes of the resource store in + fz_context. Given as argument to fz_new_context. + + FZ_STORE_UNLIMITED: Let resource store grow unbounded. + + FZ_STORE_DEFAULT: A reasonable upper bound on the size, for + devices that are not memory constrained. +*/ +enum { + FZ_STORE_UNLIMITED = 0, + FZ_STORE_DEFAULT = 256 << 20, +}; + /* fz_new_context: Allocate context containing global state. @@ -306,7 +256,6 @@ fz_context *fz_new_context(fz_alloc_context *alloc, fz_locks_context *locks, uns Does not throw exception, but may return NULL. */ fz_context *fz_clone_context(fz_context *ctx); -fz_context *fz_clone_context_internal(fz_context *ctx); /* fz_free_context: Free a context and its global state. @@ -319,8 +268,19 @@ fz_context *fz_clone_context_internal(fz_context *ctx); */ void fz_free_context(fz_context *ctx); -void fz_new_aa_context(fz_context *ctx); -void fz_free_aa_context(fz_context *ctx); +/* + fz_get_aa_level: Get the number of bits of antialiasing we are + using. Between 0 and 8. +*/ +int fz_get_aa_level(fz_context *ctx); + +/* + fz_set_aa_level: Set the number of bits of antialiasing we should use. + + bits: The number of bits of antialiasing to use (values are clamped + to within the 0 to 8 range). +*/ +void fz_set_aa_level(fz_context *ctx, int bits); /* Locking functions @@ -343,15 +303,11 @@ void fz_free_aa_context(fz_context *ctx); enabled by defining FITZ_DEBUG_LOCKING. */ -#if defined(MEMENTO) || defined(DEBUG) -#define FITZ_DEBUG_LOCKING -#endif - struct fz_locks_context_s { void *user; - void (*lock)(void *, int); - void (*unlock)(void *, int); + void (*lock)(void *user, int lock); + void (*unlock)(void *user, int lock); }; enum { @@ -365,43 +321,6 @@ enum { /* Default locks */ extern fz_locks_context fz_locks_default; -#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); -} - - -/* - * Basic runtime and utility functions - */ - -/* memory allocation */ - /* The following throw exceptions on failure to allocate */ void *fz_malloc(fz_context *ctx, unsigned int size); void *fz_calloc(fz_context *ctx, unsigned int count, unsigned int size); @@ -416,7 +335,7 @@ char *fz_strdup(fz_context *ctx, char *s); */ void fz_free(fz_context *ctx, void *p); -/* The following returns NULL on failure to allocate */ +/* The following return NULL on failure to allocate */ void *fz_malloc_no_throw(fz_context *ctx, unsigned int size); void *fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size); void *fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size); @@ -427,74 +346,19 @@ char *fz_strdup_no_throw(fz_context *ctx, char *s); #define fz_malloc_struct(CTX, STRUCT) \ Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT) -/* runtime (hah!) test for endian-ness */ -int fz_is_big_endian(void); - /* safe string functions */ char *fz_strsep(char **stringp, const char *delim); int fz_strlcpy(char *dst, const char *src, int n); int fz_strlcat(char *dst, const char *src, int n); -/* Range checking atof */ -float fz_atof(const char *s); - -/* utf-8 encoding and decoding */ -int chartorune(int *rune, char *str); -int runetochar(char *str, int *rune); -int runelen(int c); +/* runtime (hah!) test for endian-ness */ +int fz_is_big_endian(void); /* getopt */ extern int fz_getopt(int nargc, char * const *nargv, const char *ostr); extern int fz_optind; extern char *fz_optarg; -/* - * 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_debug_hash(fz_context *ctx, fz_hash_table *table); -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_remove(fz_context *ctx, fz_hash_table *table, void *key); - -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); - -/* - * 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) - typedef struct fz_matrix_s fz_matrix; typedef struct fz_point_s fz_point; typedef struct fz_rect_s fz_rect; @@ -628,7 +492,7 @@ struct fz_rect_s x0, y0: The top left corner. - x1, y1: The botton right corner. + x1, y1: The bottom right corner. */ struct fz_bbox_s { @@ -725,9 +589,6 @@ fz_matrix fz_invert_matrix(fz_matrix matrix); */ int fz_is_rectilinear(fz_matrix m); -float fz_matrix_expansion(fz_matrix m); -float fz_matrix_max_expansion(fz_matrix m); - /* fz_round_rect: Convert a rect into a bounding box. @@ -839,291 +700,14 @@ fz_rect fz_transform_rect(fz_matrix transform, fz_rect rect); */ fz_bbox fz_transform_bbox(fz_matrix matrix, fz_bbox bbox); -void fz_gridfit_matrix(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]); - -/* 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 */ -}; - -void aes_setkey_enc( fz_aes *ctx, const unsigned char *key, int keysize ); -void 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 ); - /* fz_buffer is a XXX */ typedef struct fz_buffer_s fz_buffer; -struct fz_buffer_s -{ - int refs; - unsigned char *data; - int cap, len; -}; - -fz_buffer *fz_new_buffer(fz_context *ctx, int size); fz_buffer *fz_keep_buffer(fz_context *ctx, fz_buffer *buf); -void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); - -void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size); -void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); -void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); - -/* - 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 *); - -/* - Specifies the maximum size in bytes of the resource store in - fz_context. Given as argument to fz_new_context. - - FZ_STORE_UNLIMITED: Let resource store grow unbounded. - - FZ_STORE_DEFAULT: A reasonable upper bound on the size, for - devices that are not memory constrained. -*/ -enum { - FZ_STORE_UNLIMITED = 0, - FZ_STORE_DEFAULT = 256 << 20, -}; - -/* - 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; - } 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 *); - void (*debug)(void *); -}; - -/* - 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_debug_store: Dump the contents of the store for debugging. -*/ -void fz_debug_store(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); +void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); /* fz_stream is a buffered reader capable of seeking in both @@ -1136,41 +720,6 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase); */ typedef struct fz_stream_s fz_stream; -struct fz_stream_s -{ - fz_context *ctx; - int refs; - int error; - int eof; - int pos; - int avail; - int bits; - int locked; - 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_open_file: Open the named file and wrap it in a stream. - - filename: Path to a file as it would be given to open(2). -*/ -fz_stream *fz_open_file(fz_context *ctx, const char *filename); - -/* - fz_open_file_w: Open the named file and wrap it in a stream. - - This function is only available when compiling for Win32. - - filename: Wide character path to the file as it would be given - to _wopen(). -*/ -fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); - /* fz_open_fd: Wrap an open file descriptor in a stream. @@ -1182,16 +731,6 @@ fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); */ fz_stream *fz_open_fd(fz_context *ctx, int file); -/* - fz_open_buffer: XXX -*/ -fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); - -/* - fz_open_memory: XXX -*/ -fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); - /* fz_close: Close an open stream. @@ -1203,177 +742,27 @@ fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); */ void fz_close(fz_stream *stm); -void fz_lock_stream(fz_stream *stm); - -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); - -int fz_tell(fz_stream *stm); -void fz_seek(fz_stream *stm, int offset, int whence); - -int fz_read(fz_stream *stm, unsigned char *buf, int len); -void fz_read_line(fz_stream *stm, char *buf, int max); -fz_buffer *fz_read_all(fz_stream *stm, int initial); - -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); -} - /* - * Data filters. - */ - -fz_stream *fz_open_copy(fz_stream *chain); -fz_stream *fz_open_null(fz_stream *chain, int len); -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 factor); -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. - */ - -enum { FZ_MAX_COLORS = 32 }; + Bitmaps have 1 bit per component. Only used for creating halftoned + versions of contone buffers, and saving out. Samples are stored msb + first, akin to pbms. +*/ +typedef struct fz_bitmap_s fz_bitmap; -int fz_find_blendmode(char *name); -char *fz_blendmode_name(int blendmode); +void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); /* - * Pixmaps have n components per pixel. the last is always alpha. - * premultiplied alpha when rendering, but non-premultiplied for colorspace - * conversions and rescaling. - */ - + 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. +*/ typedef struct fz_pixmap_s fz_pixmap; -typedef struct fz_colorspace_s fz_colorspace; - -/* - fz_pixmap is an image XXX - - x, y: XXX - - w, h: The width and height of the image in pixels. - - n: The number of color components in the image. Always - includes a separate alpha channel. XXX RGBA=4 - - 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: XXX - - samples: - - free_samples: Is zero when an application has provided its own - buffer for pixel data through fz_new_pixmap_with_rect_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; -}; +typedef struct fz_colorspace_s fz_colorspace; fz_bbox fz_bound_pixmap(fz_pixmap *pix); -fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); - /* fz_new_pixmap_with_rect: Create a pixmap of a given size, location and pixel format. @@ -1391,22 +780,12 @@ fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, i fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox); /* - fz_new_pixmap_with_rect_and_data: Create a pixmap using the - provided buffer for pixel data. + fz_keep_pixmap: Take a reference to a pixmap. - While fz_new_pixmap_with_rect allocates its own buffer for - pixel data, fz_new_pixmap_with_rect_and_data lets the caller - allocate and provide a buffer to be used. Otherwise the two - functions are identical. + pix: The pixmap to increment the reference for. - samples: An array of pixel samples. The created pixmap will - keep a pointer to the array so it must not be modified or - freed until the created pixmap is dropped and freed by - fz_drop_pixmap. + Returns pix. Does not throw exceptions. */ -fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, -fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); -fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); fz_pixmap *fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix); /* @@ -1419,8 +798,26 @@ fz_pixmap *fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix); */ void fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix); -void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); -void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); +/* + fz_pixmap_colorspace: Return the colorspace of a pixmap + + Returns colorspace. Does not throw exceptions. +*/ +fz_colorspace *fz_pixmap_colorspace(fz_context *ctx, fz_pixmap *pix); + +/* + fz_pixmap_components: Return the number of components in a pixmap. + + Returns the number of components. Does not throw exceptions. +*/ +int fz_pixmap_components(fz_context *ctx, fz_pixmap *pix); + +/* + fz_pixmap_pixels: Returns a pointer to the pixel data of a pixmap. + + Returns the pointer. Does not throw exceptions. +*/ +unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix); /* fz_clear_pixmap_with_value: Clears a pixmap with the given value @@ -1435,20 +832,17 @@ void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); */ void fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value); -void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_bbox r); -void fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox r); -void fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix); -void fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix); -fz_pixmap *fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity); +void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); void fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix); +void fz_invert_pixmap_rect(fz_pixmap *image, fz_bbox rect); void fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma); -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_bbox *clip); - +void fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix); +void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *name, int rgb); void fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename); void fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); void fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); +void fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename); +void fz_md5_pixmap(unsigned char digest[16], fz_pixmap *pixmap); /* Images are storable objects from which we can obtain fz_pixmaps. @@ -1458,15 +852,6 @@ void fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int saveal */ typedef struct fz_image_s fz_image; -struct fz_image_s -{ - fz_storable storable; - int w, h; - fz_image *mask; - fz_colorspace *colorspace; - fz_pixmap *(*get_pixmap)(fz_context *, fz_image *, int w, int h); -}; - /* fz_image_to_pixmap: Called to get a handle to a pixmap from an image. @@ -1500,55 +885,19 @@ void fz_drop_image(fz_context *ctx, fz_image *image); */ fz_image *fz_keep_image(fz_context *ctx, fz_image *image); -fz_pixmap *fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *cs); -fz_pixmap *fz_load_jpeg(fz_context *doc, unsigned char *data, int size); -fz_pixmap *fz_load_png(fz_context *doc, unsigned char *data, int size); -fz_pixmap *fz_load_tiff(fz_context *doc, unsigned char *data, int size); - -/* - Bitmaps have 1 bit per component. Only used for creating halftoned - versions of contone buffers, and saving out. Samples are stored msb - first, akin to pbms. -*/ -typedef struct fz_bitmap_s fz_bitmap; - -struct fz_bitmap_s -{ - int refs; - int w, h, stride, n; - unsigned char *samples; -}; - -fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); -fz_bitmap *fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit); -void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); -void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); - -void fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename); - /* A halftone is a set of threshold tiles, one per component. Each threshold tile is a pixmap, possibly of varying sizes and phases. */ typedef struct fz_halftone_s fz_halftone; -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_get_default_halftone(fz_context *ctx, int num_comps); -fz_halftone *fz_keep_halftone(fz_context *ctx, fz_halftone *half); void fz_drop_halftone(fz_context *ctx, fz_halftone *half); - fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht); /* - * Colorspace resources. - */ + Colorspace resources. +*/ /* fz_device_gray: XXX @@ -1570,377 +919,9 @@ extern fz_colorspace *fz_device_bgr; */ extern fz_colorspace *fz_device_cmyk; -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_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 *srcs, float *srcv, fz_colorspace *dsts, float *dstv); -void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); - -fz_colorspace *fz_find_device_colorspace(char *name); - -/* - * Fonts come in two variants: - * Regular fonts are handled by FreeType. - * Type 3 fonts have callbacks to the interpreter. - */ - typedef struct fz_device_s fz_device; typedef struct fz_font_s fz_font; -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 */ - 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, fz_matrix ctm, void *gstate); - 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, fz_matrix matrix); - -fz_font *fz_new_font_from_memory(fz_context *ctx, unsigned char *data, int len, int index, int use_glyph_bbox); -fz_font *fz_new_font_from_file(fz_context *ctx, 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_debug_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, fz_matrix trm); -int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid); - -/* - * 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 -{ - 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); -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, 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, fz_stroke_state *stroke, fz_matrix ctm); -void fz_debug_path(fz_context *ctx, fz_path *, int indent); - -/* - * 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_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm); -fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); -fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); -fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorspace *model); -fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke); -void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate); - -/* - * 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, 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, fz_matrix ctm); -fz_text *fz_clone_text(fz_context *ctx, fz_text *old); -void fz_debug_text(fz_context *ctx, fz_text*, int indent); - -/* - * The shading code uses gouraud shaded triangle meshes. - */ - -enum -{ - FZ_LINEAR, - FZ_RADIAL, - FZ_MESH, -}; - -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; /* linear, radial, mesh */ - int extend[2]; - - int mesh_len; - int mesh_cap; - float *mesh; /* [x y 0], [x y r], [x y t] or [x y c1 ... cn] */ -}; - -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); -void fz_debug_shade(fz_context *ctx, fz_shade *shade); - -fz_rect fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm); -void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); - -/* - * Scan converter - */ - -int fz_get_aa_level(fz_context *ctx); -void fz_set_aa_level(fz_context *ctx, int bits); - -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, fz_bbox clip); -void fz_sort_gel(fz_gel *gel); -fz_bbox fz_bound_gel(fz_gel *gel); -void fz_free_gel(fz_gel *gel); -int fz_is_rect_gel(fz_gel *gel); - -void fz_scan_convert(fz_gel *gel, int eofill, fz_bbox clip, fz_pixmap *pix, unsigned char *colorbv); - -void fz_flatten_fill_path(fz_gel *gel, fz_path *path, fz_matrix ctm, float flatness); -void fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); -void fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); - -/* - * The device interface. - */ - -enum -{ - /* Hints */ - FZ_IGNORE_IMAGE = 1, - FZ_IGNORE_SHADE = 2, - - /* 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 (*fill_path)(fz_device *, fz_path *, int even_odd, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*stroke_path)(fz_device *, fz_path *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*clip_path)(fz_device *, fz_path *, fz_rect *rect, int even_odd, fz_matrix); - void (*clip_stroke_path)(fz_device *, fz_path *, fz_rect *rect, fz_stroke_state *, fz_matrix); - - void (*fill_text)(fz_device *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*stroke_text)(fz_device *, fz_text *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); - void (*clip_text)(fz_device *, fz_text *, fz_matrix, int accumulate); - void (*clip_stroke_text)(fz_device *, fz_text *, fz_stroke_state *, fz_matrix); - void (*ignore_text)(fz_device *, fz_text *, fz_matrix); - - void (*fill_shade)(fz_device *, fz_shade *shd, fz_matrix ctm, float alpha); - void (*fill_image)(fz_device *, fz_image *img, fz_matrix ctm, float alpha); - void (*fill_image_mask)(fz_device *, fz_image *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); - void (*clip_image_mask)(fz_device *, fz_image *img, fz_rect *rect, fz_matrix ctm); - - void (*pop_clip)(fz_device *); - - void (*begin_mask)(fz_device *, fz_rect, int luminosity, fz_colorspace *, float *bc); - void (*end_mask)(fz_device *); - void (*begin_group)(fz_device *, fz_rect, int isolated, int knockout, int blendmode, float alpha); - void (*end_group)(fz_device *); - - void (*begin_tile)(fz_device *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); - void (*end_tile)(fz_device *); -}; - -void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm); -void fz_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm); -void fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate); -void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm); -void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm); -void fz_pop_clip(fz_device *dev); -void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha); -void fz_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha); -void fz_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm); -void fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc); -void fz_end_mask(fz_device *dev); -void fz_begin_group(fz_device *dev, 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, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); -void fz_end_tile(fz_device *dev); - -fz_device *fz_new_device(fz_context *ctx, void *user); /* fz_free_device: Free a devices of any type and its resources. @@ -1978,9 +959,8 @@ fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest); /* - * Text extraction device - */ - + Text extraction device +*/ typedef struct fz_text_span_s fz_text_span; typedef struct fz_text_char_s fz_text_char; @@ -2068,8 +1048,8 @@ struct fz_cookie_s }; /* - * Display list device -- record and play back device commands. - */ + Display list device -- record and play back device commands. +*/ /* fz_display_list is a list containing drawing commands (text, @@ -2144,58 +1124,6 @@ void fz_run_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, f */ void fz_free_display_list(fz_context *ctx, fz_display_list *list); -/* - * 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, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha); -void fz_paint_image_with_color(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, 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_rect(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_bbox 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 -}; - /* Links */ typedef struct fz_link_s fz_link; @@ -2372,20 +1300,6 @@ void fz_free_outline(fz_context *ctx, fz_outline *outline); typedef struct fz_document_s fz_document; typedef struct fz_page_s fz_page; /* doesn't have a definition -- always cast to *_page */ -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); - void (*run_page)(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix transform, fz_cookie *cookie); - void (*free_page)(fz_document *doc, fz_page *page); -}; - /* fz_open_document: Open a PDF, XPS or CBZ document. @@ -2504,4 +1418,4 @@ void fz_run_page(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix tran */ void fz_free_page(fz_document *doc, fz_page *page); -#endif +#endif /* _FITZ_H_ */ diff --git a/fitz/image_jpeg.c b/fitz/image_jpeg.c index cef53d93..2840adbf 100644 --- a/fitz/image_jpeg.c +++ b/fitz/image_jpeg.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #include #include diff --git a/fitz/image_jpx.c b/fitz/image_jpx.c index 4d76b4e8..b2fc3601 100644 --- a/fitz/image_jpx.c +++ b/fitz/image_jpx.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #define OPJ_STATIC #include diff --git a/fitz/image_md5.c b/fitz/image_md5.c new file mode 100644 index 00000000..c82c7066 --- /dev/null +++ b/fitz/image_md5.c @@ -0,0 +1,11 @@ +#include "fitz-internal.h" + +void fz_md5_pixmap(unsigned char digest[16], fz_pixmap *pix) +{ + fz_md5 md5; + + fz_md5_init(&md5); + if (pix) + fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n); + fz_md5_final(&md5, digest); +} diff --git a/fitz/image_png.c b/fitz/image_png.c index b3fe39cc..e2092c10 100644 --- a/fitz/image_png.c +++ b/fitz/image_png.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #include diff --git a/fitz/image_save.c b/fitz/image_save.c new file mode 100644 index 00000000..ef5dbfa5 --- /dev/null +++ b/fitz/image_save.c @@ -0,0 +1,32 @@ +#include "fitz-internal.h" + +void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *file, int rgb) +{ + char name[1024]; + fz_pixmap *converted = NULL; + + if (!img) + return; + + if (rgb && img->colorspace && img->colorspace != fz_device_rgb) + { + converted = fz_new_pixmap_with_rect(ctx, fz_device_rgb, fz_bound_pixmap(img)); + fz_convert_pixmap(ctx, img, converted); + img = converted; + } + + if (img->n <= 4) + { + sprintf(name, "%s.png", file); + printf("extracting image %s\n", name); + fz_write_png(ctx, img, name, 0); + } + else + { + sprintf(name, "%s.pam", file); + printf("extracting image %s\n", name); + fz_write_pam(ctx, img, name, 0); + } + + fz_drop_pixmap(ctx, converted); +} diff --git a/fitz/image_tiff.c b/fitz/image_tiff.c index fff91a9e..76f08447 100644 --- a/fitz/image_tiff.c +++ b/fitz/image_tiff.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" /* * TIFF image loader. Should be enough to support TIFF files in XPS. diff --git a/fitz/res_bitmap.c b/fitz/res_bitmap.c index 2aa28b02..62cdd8ca 100644 --- a/fitz/res_bitmap.c +++ b/fitz/res_bitmap.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_bitmap * fz_new_bitmap(fz_context *ctx, int w, int h, int n) @@ -74,3 +74,24 @@ fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename) fclose(fp); } + +fz_colorspace *fz_pixmap_colorspace(fz_context *ctx, fz_pixmap *pix) +{ + if (!pix) + return NULL; + return pix->colorspace; +} + +int fz_pixmap_components(fz_context *ctx, fz_pixmap *pix) +{ + if (!pix) + return 0; + return pix->n; +} + +unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix) +{ + if (!pix) + return NULL; + return pix->samples; +} diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 3cdc0fa3..1c26d1b3 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #define SLOWCMYK diff --git a/fitz/res_font.c b/fitz/res_font.c index e4a4d23a..93e578b5 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #include #include FT_FREETYPE_H diff --git a/fitz/res_halftone.c b/fitz/res_halftone.c index 7258ad01..b7728eb5 100644 --- a/fitz/res_halftone.c +++ b/fitz/res_halftone.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_halftone * fz_new_halftone(fz_context *ctx, int comps) diff --git a/fitz/res_path.c b/fitz/res_path.c index a645f9d5..4964a09e 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -1,5 +1,5 @@ #include -#include "fitz.h" +#include "fitz-internal.h" fz_path * fz_new_path(fz_context *ctx) diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index 1b254f36..fc40135e 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_pixmap * fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix) @@ -282,6 +282,27 @@ fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix) } } +void fz_invert_pixmap_rect(fz_pixmap *image, fz_bbox rect) +{ + unsigned char *p; + int x, y, n; + + int x0 = CLAMP(rect.x0 - image->x, 0, image->w - 1); + int x1 = CLAMP(rect.x1 - image->x, 0, image->w - 1); + int y0 = CLAMP(rect.y0 - image->y, 0, image->h - 1); + int y1 = CLAMP(rect.y1 - image->y, 0, image->h - 1); + + for (y = y0; y < y1; y++) + { + p = image->samples + (y * image->w + x0) * image->n; + for (x = x0; x < x1; x++) + { + for (n = image->n; n > 0; n--, p++) + *p = 255 - *p; + } + } +} + void fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma) { diff --git a/fitz/res_shade.c b/fitz/res_shade.c index 3fdf2e15..f8f11a81 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_shade * fz_keep_shade(fz_context *ctx, fz_shade *shade) diff --git a/fitz/res_store.c b/fitz/res_store.c index df9c6e33..e85aead9 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" typedef struct fz_item_s fz_item; diff --git a/fitz/res_text.c b/fitz/res_text.c index cdfaaa98..433ff8f9 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_text * fz_new_text(fz_context *ctx, fz_font *font, fz_matrix trm, int wmode) diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c index d70118e1..b5728d57 100644 --- a/fitz/stm_buffer.c +++ b/fitz/stm_buffer.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_buffer * fz_new_buffer(fz_context *ctx, int size) diff --git a/fitz/stm_open.c b/fitz/stm_open.c index e634f729..1e303825 100644 --- a/fitz/stm_open.c +++ b/fitz/stm_open.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" fz_stream * fz_new_stream(fz_context *ctx, void *state, diff --git a/fitz/stm_read.c b/fitz/stm_read.c index a95c62c0..216d2207 100644 --- a/fitz/stm_read.c +++ b/fitz/stm_read.c @@ -1,4 +1,4 @@ -#include "fitz.h" +#include "fitz-internal.h" #define MIN_BOMB (100 << 20) -- cgit v1.2.3 From 16c6f406911b9c93491a244cfe1ec37603284489 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 7 Mar 2012 15:31:36 +0100 Subject: Splitting tweaks. --- fitz/base_string.c | 7 ---- fitz/fitz-internal.h | 97 ++-------------------------------------------------- fitz/fitz.h | 92 +++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 109 deletions(-) (limited to 'fitz') diff --git a/fitz/base_string.c b/fitz/base_string.c index 6fdfef62..8ab09438 100644 --- a/fitz/base_string.c +++ b/fitz/base_string.c @@ -1,12 +1,5 @@ #include "fitz-internal.h" -int -fz_is_big_endian(void) -{ - static const int one = 1; - return *(char*)&one == 0; -} - char * fz_strsep(char **stringp, const char *delim) { diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 4ede601d..f9175c65 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -1,5 +1,5 @@ -#ifndef _FITZ_INTERNAL_H_ -#define _FITZ_INTERNAL_H_ +#ifndef FITZ_INTERNAL_H +#define FITZ_INTERNAL_H #include "fitz.h" @@ -57,11 +57,6 @@ fz_unlock(fz_context *ctx, int lock) /* Range checking atof */ float fz_atof(const char *s); -/* utf-8 encoding and decoding */ -int chartorune(int *rune, char *str); -int runetochar(char *str, int *rune); -int runelen(int c); - /* * Generic hash-table with fixed-length keys. */ @@ -109,11 +104,6 @@ static inline int fz_mul255(int a, int b) * AMOUNT (in the 0...256 range). */ #define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8) - -float fz_matrix_expansion(fz_matrix m); -float fz_matrix_max_expansion(fz_matrix m); - - void fz_gridfit_matrix(fz_matrix *m); /* @@ -190,19 +180,6 @@ void aes_crypt_cbc( fz_aes *ctx, int mode, int length, const unsigned char *input, unsigned char *output ); -struct fz_buffer_s -{ - int refs; - unsigned char *data; - int cap, len; -}; - -fz_buffer *fz_new_buffer(fz_context *ctx, int size); - -void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size); -void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); -void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); - /* Resource store @@ -397,46 +374,13 @@ struct fz_stream_s unsigned char buf[4096]; }; -/* - fz_open_file: Open the named file and wrap it in a stream. - - filename: Path to a file as it would be given to open(2). -*/ -fz_stream *fz_open_file(fz_context *ctx, const char *filename); - -/* - fz_open_file_w: Open the named file and wrap it in a stream. - - This function is only available when compiling for Win32. - - filename: Wide character path to the file as it would be given - to _wopen(). -*/ -fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); - - -/* - fz_open_buffer: XXX -*/ -fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); - -/* - fz_open_memory: XXX -*/ -fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); - void fz_lock_stream(fz_stream *stm); 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); -int fz_tell(fz_stream *stm); -void fz_seek(fz_stream *stm, int offset, int whence); - -int fz_read(fz_stream *stm, unsigned char *buf, int len); void fz_read_line(fz_stream *stm, char *buf, int max); -fz_buffer *fz_read_all(fz_stream *stm, int initial); static inline int fz_read_byte(fz_stream *stm) { @@ -583,27 +527,6 @@ struct fz_pixmap_s int free_samples; }; - -fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); - -/* - fz_new_pixmap_with_rect_and_data: Create a pixmap using the - provided buffer for pixel data. - - While fz_new_pixmap_with_rect allocates its own buffer for - pixel data, fz_new_pixmap_with_rect_and_data lets the caller - allocate and provide a buffer to be used. Otherwise the two - functions are identical. - - samples: An array of pixel samples. The created pixmap will - keep a pointer to the array so it must not be modified or - freed until the created pixmap is dropped and freed by - fz_drop_pixmap. -*/ -fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, -fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); -fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); - void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_bbox r); @@ -628,18 +551,6 @@ fz_pixmap *fz_load_jpeg(fz_context *doc, unsigned char *data, int size); fz_pixmap *fz_load_png(fz_context *doc, unsigned char *data, int size); fz_pixmap *fz_load_tiff(fz_context *doc, unsigned char *data, int size); -struct fz_bitmap_s -{ - int refs; - int w, h, stride, n; - unsigned char *samples; -}; - -fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); -fz_bitmap *fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit); -void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); - - struct fz_halftone_s { int refs; @@ -650,7 +561,6 @@ struct fz_halftone_s fz_halftone *fz_new_halftone(fz_context *ctx, int num_comps); fz_halftone *fz_keep_halftone(fz_context *ctx, fz_halftone *half); - struct fz_colorspace_s { fz_storable storable; @@ -669,9 +579,6 @@ 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 *srcs, float *srcv, fz_colorspace *dsts, float *dstv); -void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); - -fz_colorspace *fz_find_device_colorspace(char *name); /* * Fonts come in two variants: diff --git a/fitz/fitz.h b/fitz/fitz.h index 732f2fc7..4de15e0e 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1,5 +1,5 @@ -#ifndef _FITZ_H_ -#define _FITZ_H_ +#ifndef FITZ_H +#define FITZ_H /* Include the standard libc headers. @@ -351,8 +351,10 @@ char *fz_strsep(char **stringp, const char *delim); int fz_strlcpy(char *dst, const char *src, int n); int fz_strlcat(char *dst, const char *src, int n); -/* runtime (hah!) test for endian-ness */ -int fz_is_big_endian(void); +/* utf-8 encoding and decoding */ +int chartorune(int *rune, char *str); +int runetochar(char *str, int *rune); +int runelen(int c); /* getopt */ extern int fz_getopt(int nargc, char * const *nargv, const char *ostr); @@ -589,6 +591,12 @@ fz_matrix fz_invert_matrix(fz_matrix matrix); */ int fz_is_rectilinear(fz_matrix m); +/* + fz_matrix_expansion: Calculate average scaling factor of matrix. +*/ +float fz_matrix_expansion(fz_matrix m); /* sumatrapdf */ +float fz_matrix_max_expansion(fz_matrix m); + /* fz_round_rect: Convert a rect into a bounding box. @@ -701,14 +709,25 @@ fz_rect fz_transform_rect(fz_matrix transform, fz_rect rect); fz_bbox fz_transform_bbox(fz_matrix matrix, fz_bbox bbox); /* - fz_buffer is a XXX + fz_buffer is a wrapper around a dynamically allocated array of bytes */ typedef struct fz_buffer_s fz_buffer; -fz_buffer *fz_keep_buffer(fz_context *ctx, fz_buffer *buf); +struct fz_buffer_s +{ + int refs; + unsigned char *data; + int cap, len; +}; +fz_buffer *fz_new_buffer(fz_context *ctx, int size); +fz_buffer *fz_keep_buffer(fz_context *ctx, fz_buffer *buf); void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); +void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size); +void fz_grow_buffer(fz_context *ctx, fz_buffer *buf); +void fz_trim_buffer(fz_context *ctx, fz_buffer *buf); + /* fz_stream is a buffered reader capable of seeking in both directions. @@ -720,6 +739,23 @@ void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); */ typedef struct fz_stream_s fz_stream; +/* + fz_open_file: Open the named file and wrap it in a stream. + + filename: Path to a file as it would be given to open(2). +*/ +fz_stream *fz_open_file(fz_context *ctx, const char *filename); + +/* + fz_open_file_w: Open the named file and wrap it in a stream. + + This function is only available when compiling for Win32. + + filename: Wide character path to the file as it would be given + to _wopen(). +*/ +fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); + /* fz_open_fd: Wrap an open file descriptor in a stream. @@ -731,6 +767,16 @@ typedef struct fz_stream_s fz_stream; */ fz_stream *fz_open_fd(fz_context *ctx, int file); +/* + fz_open_memory: XXX +*/ +fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); + +/* + fz_open_buffer: XXX +*/ +fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); + /* fz_close: Close an open stream. @@ -742,6 +788,11 @@ fz_stream *fz_open_fd(fz_context *ctx, int file); */ void fz_close(fz_stream *stm); +int fz_tell(fz_stream *stm); +void fz_seek(fz_stream *stm, int offset, int whence); +int fz_read(fz_stream *stm, unsigned char *buf, int len); +fz_buffer *fz_read_all(fz_stream *stm, int initial); + /* Bitmaps have 1 bit per component. Only used for creating halftoned versions of contone buffers, and saving out. Samples are stored msb @@ -749,6 +800,16 @@ void fz_close(fz_stream *stm); */ typedef struct fz_bitmap_s fz_bitmap; +struct fz_bitmap_s +{ + int refs; + int w, h, stride, n; + unsigned char *samples; +}; + +fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); +fz_bitmap *fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit); +void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); /* @@ -763,6 +824,8 @@ typedef struct fz_colorspace_s fz_colorspace; fz_bbox fz_bound_pixmap(fz_pixmap *pix); +fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); + /* fz_new_pixmap_with_rect: Create a pixmap of a given size, location and pixel format. @@ -779,6 +842,17 @@ fz_bbox fz_bound_pixmap(fz_pixmap *pix); */ fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox); +fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); + +/* + fz_keep_pixmap: Take a reference to a pixmap. + + pix: The pixmap to increment the reference for. + + Returns pix. Does not throw exceptions. +*/ +fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); + /* fz_keep_pixmap: Take a reference to a pixmap. @@ -899,6 +973,10 @@ fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht); Colorspace resources. */ +void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); + +fz_colorspace *fz_find_device_colorspace(char *name); + /* fz_device_gray: XXX */ @@ -1418,4 +1496,4 @@ void fz_run_page(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix tran */ void fz_free_page(fz_document *doc, fz_page *page); -#endif /* _FITZ_H_ */ +#endif -- cgit v1.2.3 From c4e870b5422207e6ca31eb2cd6694ba44faec21e Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Wed, 7 Mar 2012 17:08:41 +0000 Subject: Tweak Halftone functions A NULL halftone pointer passed to fz_halftone_pixmap is now taken to mean "use the default halftone". This means we can remove most of the halftone functions from the public API until (post 1.0) we decide to flesh out the functionality. --- fitz/fitz-internal.h | 2 ++ fitz/fitz.h | 16 ++++++++++++++-- fitz/res_halftone.c | 9 ++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index f9175c65..efc08a41 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -559,6 +559,8 @@ struct fz_halftone_s }; fz_halftone *fz_new_halftone(fz_context *ctx, int num_comps); +fz_halftone *fz_get_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 diff --git a/fitz/fitz.h b/fitz/fitz.h index 4de15e0e..a6a197ca 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -962,11 +962,23 @@ fz_image *fz_keep_image(fz_context *ctx, fz_image *image); /* A halftone is a set of threshold tiles, one per component. Each threshold tile is a pixmap, possibly of varying sizes and phases. + Currently, we only provide one 'default' halftone tile for operating + on 1 component plus alpha pixmaps (where the alpha is ignored). This + is signified by an fz_halftone pointer to NULL. */ typedef struct fz_halftone_s fz_halftone; -fz_halftone *fz_get_default_halftone(fz_context *ctx, int num_comps); -void fz_drop_halftone(fz_context *ctx, fz_halftone *half); +/* + fz_halftone_pixmap: Make a bitmap from a pixmap and a halftone. + + pix: The pixmap to generate from. Currently must be a single color + component + alpha (where the alpha is assumed to be solid). + + ht: The halftone to use. NULL implies the default halftone. + + Returns the resultant bitmap. Throws exceptions in the case of + failure to allocate. +*/ fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht); /* diff --git a/fitz/res_halftone.c b/fitz/res_halftone.c index b7728eb5..ec26571e 100644 --- a/fitz/res_halftone.c +++ b/fitz/res_halftone.c @@ -162,13 +162,18 @@ fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht) fz_bitmap *out; unsigned char *ht_line, *o, *p; int w, h, x, y, n, pstride, ostride; + fz_halftone *ht_orig = ht; - if (!pix || !ht) + if (!pix) return NULL; assert(pix->n == 2); /* Mono + Alpha */ n = pix->n-1; /* Remove alpha */ + if (ht == NULL) + { + ht = fz_get_default_halftone(ctx, n); + } ht_line = fz_malloc(ctx, pix->w * n); out = fz_new_bitmap(ctx, pix->w, pix->h, n); o = out->samples; @@ -187,5 +192,7 @@ fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht) o += ostride; p += pstride; } + if (!ht_orig) + fz_drop_halftone(ctx, ht); return out; } -- cgit v1.2.3 From 7a2973ba2c4865f42d02a4f878ce51ab7d72c394 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Wed, 7 Mar 2012 20:53:31 +0000 Subject: More release tidyups. Add some function documentation to fitz.h. Add fz_ prefix to runetochar, chartorune, runelen etc. Change fz_runetochar to avoid passing unnecessary pointer. --- fitz/base_string.c | 15 ++-- fitz/dev_text.c | 4 +- fitz/fitz-internal.h | 19 +++++ fitz/fitz.h | 210 +++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 225 insertions(+), 23 deletions(-) (limited to 'fitz') diff --git a/fitz/base_string.c b/fitz/base_string.c index 8ab09438..7587f96b 100644 --- a/fitz/base_string.c +++ b/fitz/base_string.c @@ -29,8 +29,8 @@ fz_strlcpy(char *dst, const char *src, int siz) if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; + while (*s++) + ; } return(s - src - 1); /* count does not include NUL */ @@ -101,7 +101,7 @@ enum }; int -chartorune(int *rune, char *str) +fz_chartorune(int *rune, char *str) { int c, c1, c2, c3; long l; @@ -176,16 +176,15 @@ bad: } int -runetochar(char *str, int *rune) +fz_runetochar(char *str, int rune) { /* Runes are signed, so convert to unsigned for range check. */ - unsigned long c; + unsigned long c = (unsigned long)rune; /* * one character sequence * 00000-0007F => 00-7F */ - c = *rune; if(c <= Rune1) { str[0] = c; return 1; @@ -233,10 +232,10 @@ runetochar(char *str, int *rune) } int -runelen(int c) +fz_runelen(int c) { char str[10]; - return runetochar(str, &c); + return fz_runetochar(str, c); } float fz_atof(const char *s) diff --git a/fitz/dev_text.c b/fitz/dev_text.c index 618a2e6e..79d8c137 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -172,7 +172,7 @@ fz_debug_text_span_xml(fz_text_span *span) putchar(c); else { - n = runetochar(buf, &c); + n = fz_runetochar(buf, c); for (k = 0; k < n; k++) putchar(buf[k]); } @@ -204,7 +204,7 @@ fz_debug_text_span(fz_text_span *span) putchar(c); else { - n = runetochar(buf, &c); + n = fz_runetochar(buf, c); for (k = 0; k < n; k++) putchar(buf[k]); } diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index efc08a41..04ce19e5 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -15,6 +15,9 @@ 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); +/* Default locks */ +extern fz_locks_context fz_locks_default; + #if defined(MEMENTO) || defined(DEBUG) #define FITZ_DEBUG_LOCKING #endif @@ -54,6 +57,22 @@ fz_unlock(fz_context *ctx, int lock) * Basic runtime and utility functions */ +/* + fz_malloc_struct: Allocate storage for a structure (with scavenging), + clear it, and (in Memento builds) tag the pointer as belonging to a + struct of this type. + + CTX: The context. + + STRUCT: The structure type. + + Returns a pointer to allocated (and cleared) structure. Throws + exception on failure to allocate. +*/ +/* alloc and zero a struct, and tag it for memento */ +#define fz_malloc_struct(CTX, STRUCT) \ + Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT) + /* Range checking atof */ float fz_atof(const char *s); diff --git a/fitz/fitz.h b/fitz/fitz.h index a6a197ca..f9d5c567 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -318,14 +318,80 @@ enum { FZ_LOCK_MAX }; -/* Default locks */ -extern fz_locks_context fz_locks_default; +/* + Memory Allocation and Scavenging: + + All calls to MuPDFs allocator functions pass through to the + underlying allocators passed in when the initial context is + created, after locks are taken (using the supplied locking function) + to ensure that only one thread at a time calls through. + + If the underlying allocator fails, MuPDF attempts to make room for + the allocation by evicting elements from the store, then retrying. + + Any call to allocate may then result in several calls to the underlying + allocator, and result in elements that are only referred to by the + store being freed. +*/ + +/* + fz_malloc: Allocate a block of memory (with scavenging) -/* The following throw exceptions on failure to allocate */ + size: The number of bytes to allocate. + + Returns a pointer to the allocated block. May return NULL if size is + 0. Throws exception on failure to allocate. +*/ void *fz_malloc(fz_context *ctx, unsigned int size); + +/* + fz_calloc: Allocate a zeroed block of memory (with scavenging) + + count: The number of objects to allocate space for. + + size: The size (in bytes) of each object. + + Returns a pointer to the allocated block. May return NULL if size + and/or count are 0. Throws exception on failure to allocate. +*/ void *fz_calloc(fz_context *ctx, unsigned int count, unsigned int size); + +/* + fz_malloc_array: Allocate a block of (non zeroed) memory (with + scavenging). Equivalent to fz_calloc without the memory clearing. + + count: The number of objects to allocate space for. + + size: The size (in bytes) of each object. + + Returns a pointer to the allocated block. May return NULL if size + and/or count are 0. Throws exception on failure to allocate. +*/ void *fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size); + +/* + fz_resize_array: Resize a block of memory (with scavenging). + + p: The existing block to resize + + count: The number of objects to resize to. + + size: The size (in bytes) of each object. + + Returns a pointer to the resized block. May return NULL if size + and/or count are 0. Throws exception on failure to resize (original + block is left unchanged). +*/ void *fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size); + +/* + fz_strdup: Duplicate a C string (with scavenging) + + s: The string to duplicate. + + Returns a pointer to a duplicated string. Throws exception on failure + to allocate. +*/ char *fz_strdup(fz_context *ctx, char *s); /* @@ -335,26 +401,144 @@ char *fz_strdup(fz_context *ctx, char *s); */ void fz_free(fz_context *ctx, void *p); -/* The following return NULL on failure to allocate */ +/* + fz_malloc_no_throw: Allocate a block of memory (with scavenging) + + size: The number of bytes to allocate. + + Returns a pointer to the allocated block. May return NULL if size is + 0. Returns NULL on failure to allocate. +*/ void *fz_malloc_no_throw(fz_context *ctx, unsigned int size); -void *fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size); + +/* + fz_calloc_no_throw: Allocate a zeroed block of memory (with scavenging) + + count: The number of objects to allocate space for. + + size: The size (in bytes) of each object. + + Returns a pointer to the allocated block. May return NULL if size + and/or count are 0. Returns NULL on failure to allocate. +*/ void *fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size); + +/* + fz_malloc_array_no_throw: Allocate a block of (non zeroed) memory + (with scavenging). Equivalent to fz_calloc_no_throw without the + memory clearing. + + count: The number of objects to allocate space for. + + size: The size (in bytes) of each object. + + Returns a pointer to the allocated block. May return NULL if size + and/or count are 0. Returns NULL on failure to allocate. +*/ +void *fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size); + +/* + fz_resize_array_no_throw: Resize a block of memory (with scavenging). + + p: The existing block to resize + + count: The number of objects to resize to. + + size: The size (in bytes) of each object. + + Returns a pointer to the resized block. May return NULL if size + and/or count are 0. Returns NULL on failure to resize (original + block is left unchanged). +*/ void *fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, unsigned int size); -char *fz_strdup_no_throw(fz_context *ctx, char *s); -/* alloc and zero a struct, and tag it for memento */ -#define fz_malloc_struct(CTX, STRUCT) \ - Memento_label(fz_calloc(CTX,1,sizeof(STRUCT)), #STRUCT) +/* + fz_strdup_no_throw: Duplicate a C string (with scavenging) + + s: The string to duplicate. + + Returns a pointer to a duplicated string. Returns NULL on failure + to allocate. +*/ +char *fz_strdup_no_throw(fz_context *ctx, char *s); /* safe string functions */ +/* + fz_strsep: Given a pointer to a C string (or a pointer to NULL) break + it at the first occurence of a delimiter char (from a given set). + + stringp: Pointer to a C string pointer (or NULL). Updated on exit to + point to the first char of the string after the delimiter that was + found. The string pointed to by stringp will be corrupted by this + call (as the found delimiter will be overwritten by 0). + + delim: A C string of acceptable delimiter characters. + + Returns a pointer to a C string containing the chars of stringp up + to the first delimiter char (or the end of the string), or NULL. +*/ char *fz_strsep(char **stringp, const char *delim); + +/* + fz_strlcpy: Copy at most n-1 chars of a string into a destination + buffer with null termination, returning the real length of the + initial string (excluding terminator). + + dst: Destination buffer, at least n bytes long. + + src: C string (non-NULL). + + n: Size of dst buffer in bytes. + + Returns the length (excluding terminator) of src. +*/ int fz_strlcpy(char *dst, const char *src, int n); + +/* + fz_strlcat: Concatenate 2 strings, with a maximum length. + + dst: pointer to first string in a buffer of n bytes. + + src: pointer to string to concatenate. + + n: Size (in bytes) of buffer that dst is in. + + Returns the real length that a concatenated dst + src would have been + (not including terminator). +*/ int fz_strlcat(char *dst, const char *src, int n); -/* utf-8 encoding and decoding */ -int chartorune(int *rune, char *str); -int runetochar(char *str, int *rune); -int runelen(int c); +/* + fz_chartorune: UTF8 decode a string of chars to a rune. + + rune: Pointer to an int to assign the decoded 'rune' to. + + str: Pointer to a UTF8 encoded string + + Returns the number of bytes consumed. Does not throw exceptions. +*/ +int fz_chartorune(int *rune, char *str); + +/* + runetochar: UTF8 encode a run to a string of chars. + + str: Pointer to a place to put the UTF8 encoded string. + + rune: Pointer to a 'rune'. + + Returns the number of bytes the rune took to output. Does not throw + exceptions. +*/ +int fz_runetochar(char *str, int rune); + +/* + fz_runelen: Count many chars are required to represent a rune. + + rune: The rune to encode. + + Returns the number of bytes required to represent this run in UTF8. +*/ +int fz_runelen(int rune); /* getopt */ extern int fz_getopt(int nargc, char * const *nargv, const char *ostr); -- cgit v1.2.3 From b69540172265a037ad3c72ea85453b6d89de5e0a Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Wed, 7 Mar 2012 21:19:10 +0000 Subject: Add more function level docs. --- fitz/fitz.h | 210 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 155 insertions(+), 55 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index f9d5c567..2b432e13 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -545,10 +545,57 @@ extern int fz_getopt(int nargc, char * const *nargv, const char *ostr); extern int fz_optind; extern char *fz_optarg; -typedef struct fz_matrix_s fz_matrix; +/* + fz_point is a point in a two-dimensional space. +*/ typedef struct fz_point_s fz_point; +struct fz_point_s +{ + float x, y; +}; + +/* + fz_rect is a rectangle represented by two diagonally opposite + corners at arbitrary coordinates. + + Rectangles are always axis-aligned with the X- and Y- axes. + The relationship between the coordinates are that x0 <= x1 and + y0 <= y1 in all cases except for infinte rectangles. The area + of a rectangle is defined as (x1 - x0) * (y1 - y0). If either + x0 > x1 or y0 > y1 is true for a given rectangle then it is + defined to be infinite. + + To check for empty or infinite rectangles use fz_is_empty_rect + and fz_is_infinite_rect. Compare to fz_bbox which has corners + at integer coordinates. + + x0, y0: The top left corner. + + x1, y1: The botton right corner. +*/ typedef struct fz_rect_s fz_rect; +struct fz_rect_s +{ + float x0, y0; + float x1, y1; +}; + +/* + fz_bbox is a bounding box similar to a fz_rect, except that + all corner coordinates are rounded to integer coordinates. + To check for empty or infinite bounding boxes use + fz_is_empty_bbox and fz_is_infinite_bbox. + + x0, y0: The top left corner. + + x1, y1: The bottom right corner. +*/ typedef struct fz_bbox_s fz_bbox; +struct fz_bbox_s +{ + int x0, y0; + int x1, y1; +}; /* A rectangle with sides of length one. @@ -632,59 +679,12 @@ extern const fz_bbox fz_infinite_bbox; | c d 0 | normally represented as [ a b c d e f ]. \ e f 1 / */ +typedef struct fz_matrix_s fz_matrix; struct fz_matrix_s { float a, b, c, d, e, f; }; -/* - fz_point is a point in a two-dimensional space. -*/ -struct fz_point_s -{ - float x, y; -}; - -/* - fz_rect is a rectangle represented by two diagonally opposite - corners at arbitrary coordinates. - - Rectangles are always axis-aligned with the X- and Y- axes. - The relationship between the coordinates are that x0 <= x1 and - y0 <= y1 in all cases except for infinte rectangles. The area - of a rectangle is defined as (x1 - x0) * (y1 - y0). If either - x0 > x1 or y0 > y1 is true for a given rectangle then it is - defined to be infinite. - - To check for empty or infinite rectangles use fz_is_empty_rect - and fz_is_infinite_rect. Compare to fz_bbox which has corners - at integer coordinates. - - x0, y0: The top left corner. - - x1, y1: The botton right corner. -*/ -struct fz_rect_s -{ - float x0, y0; - float x1, y1; -}; - -/* - fz_bbox is a bounding box similar to a fz_rect, except that - all corner coordinates are rounded to integer coordinates. - To check for empty or infinite bounding boxes use - fz_is_empty_bbox and fz_is_infinite_bbox. - - x0, y0: The top left corner. - - x1, y1: The bottom right corner. -*/ -struct fz_bbox_s -{ - int x0, y0; - int x1, y1; -}; /* fz_identity: Identity transform matrix. @@ -893,7 +893,10 @@ fz_rect fz_transform_rect(fz_matrix transform, fz_rect rect); fz_bbox fz_transform_bbox(fz_matrix matrix, fz_bbox bbox); /* - fz_buffer is a wrapper around a dynamically allocated array of bytes + fz_buffer is a wrapper around a dynamically allocated array of bytes. + + Buffers have a capacity (the number of bytes storage immediately + available) and a current size. */ typedef struct fz_buffer_s fz_buffer; @@ -904,12 +907,59 @@ struct fz_buffer_s int cap, len; }; -fz_buffer *fz_new_buffer(fz_context *ctx, int size); +/* + 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_keep_buffer: Increment the reference count for a buffer. + + buf: The buffer to increment the reference count for. + + Returns a pointer to the buffer. Does not throw exceptions. +*/ fz_buffer *fz_keep_buffer(fz_context *ctx, fz_buffer *buf); + +/* + fz_drop_buffer: Decrement the reference count for a buffer. + + buf: The buffer to decrement the reference count for. +*/ void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); -void fz_resize_buffer(fz_context *ctx, fz_buffer *buf, 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); /* @@ -952,12 +1002,26 @@ fz_stream *fz_open_file_w(fz_context *ctx, const wchar_t *filename); fz_stream *fz_open_fd(fz_context *ctx, int file); /* - fz_open_memory: XXX + fz_open_memory: Open a block of memory as a stream. + + data: Pointer to start of data block. Ownership of the data block is + NOT passed in. + + len: Number of bytes in data block. + + Returns pointer to newly created stream. May throw exceptions on + failure to allocate. */ fz_stream *fz_open_memory(fz_context *ctx, unsigned char *data, int len); /* - fz_open_buffer: XXX + fz_open_buffer: Open a buffer as a stream. + + buf: The buffer to open. Ownership of the buffer is NOT passed in + (this function takes it's own reference). + + Returns pointer to newly created stream. May throw exceptions on + failure to allocate. */ fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); @@ -972,9 +1036,45 @@ fz_stream *fz_open_buffer(fz_context *ctx, fz_buffer *buf); */ void fz_close(fz_stream *stm); +/* + fz_tell: return the current reading position within a stream +*/ int fz_tell(fz_stream *stm); + +/* + fz_seek: Seek within a stream. + + stm: The stream to seek within. + + offset: The offset to seek to. + + whence: From where the offset is measured (see fseek). +*/ void fz_seek(fz_stream *stm, int offset, int whence); -int fz_read(fz_stream *stm, unsigned char *buf, int len); + +/* + fz_read: Read from a stream into a given data block. + + stm: The stream to read from. + + data: The data block to read into. + + len: The length of the data block (in bytes). + + Returns the number of bytes read. May throw exceptions. +*/ +int fz_read(fz_stream *stm, unsigned char *data, int len); + +/* + fz_read_all: Read all of a stream into a buffer. + + stm: The stream to read from + + initial: Suggested initial size for the buffer. + + Returns a buffer created from reading from the stream. May throw + exceptions on failure to allocate. +*/ fz_buffer *fz_read_all(fz_stream *stm, int initial); /* -- cgit v1.2.3 From 3db3054ec8223b6bd01d8d8144b4863c9ca8fd2d Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 12 Mar 2012 12:56:16 +0000 Subject: More API tidying. Make fz_clone_context copy existing AA settings. Add accessor function for fz_bitmap. Add more documentation for various functions/types. --- fitz/base_context.c | 2 + fitz/fitz-internal.h | 40 +++++++-- fitz/fitz.h | 229 +++++++++++++++++++++++++++++++++++++++------------ fitz/image_md5.c | 2 +- fitz/res_bitmap.c | 24 ++++++ 5 files changed, 237 insertions(+), 60 deletions(-) (limited to 'fitz') diff --git a/fitz/base_context.c b/fitz/base_context.c index 7e3c0bdd..075a3d02 100644 --- a/fitz/base_context.c +++ b/fitz/base_context.c @@ -122,6 +122,8 @@ fz_clone_context_internal(fz_context *ctx) if (ctx == NULL || ctx->alloc == NULL) return NULL; new_ctx = new_context_phase1(ctx->alloc, ctx->locks); + /* Inherit AA defaults from old context. */ + fz_copy_aa_context(new_ctx, ctx); new_ctx->store = fz_keep_store_context(ctx); new_ctx->glyph_cache = fz_keep_glyph_cache(ctx); new_ctx->font = fz_keep_font_context(ctx); diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 04ce19e5..4c41564b 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -14,6 +14,7 @@ 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 locks */ extern fz_locks_context fz_locks_default; @@ -510,15 +511,32 @@ enum { FZ_MAX_COLORS = 32 }; int fz_find_blendmode(char *name); char *fz_blendmode_name(int blendmode); +struct fz_bitmap_s +{ + int refs; + int w, h, stride, n; + unsigned char *samples; +}; + +fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); + +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); + /* - fz_pixmap is an image XXX + 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: XXX + x, y: The minimum x and y coord of the region in pixels. - w, h: The width and height of the image 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. XXX RGBA=4 + 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 @@ -526,9 +544,13 @@ char *fz_blendmode_name(int blendmode); xres, yres: Image resolution in dpi. Default is 96 dpi. - colorspace: XXX + colorspace: Pointer to a colorspace object describing the colorspace + the pixmap is in. If NULL, the image is a mask. - samples: + 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_rect_and_data. @@ -546,6 +568,10 @@ struct fz_pixmap_s int free_samples; }; +fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); + +fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); + void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); void fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *pix, int value, fz_bbox r); @@ -863,6 +889,8 @@ void fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, f * The device interface. */ +fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest); + enum { /* Hints */ diff --git a/fitz/fitz.h b/fitz/fitz.h index 2b432e13..849b07a8 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1084,18 +1084,64 @@ fz_buffer *fz_read_all(fz_stream *stm, int initial); */ typedef struct fz_bitmap_s fz_bitmap; -struct fz_bitmap_s -{ - int refs; - int w, h, stride, n; - unsigned char *samples; -}; +/* + fz_keep_bitmap: Take a reference to a bitmap. + + bit: The bitmap to increment the reference for. -fz_bitmap *fz_new_bitmap(fz_context *ctx, int w, int h, int n); + Returns bit. Does not throw exceptions. +*/ fz_bitmap *fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit); -void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); + +/* + fz_drop_bitmap: Drop a reference and free a bitmap. + + Decrement the reference count for the bitmap. When no + references remain the pixmap will be freed. + + Does not throw exceptions. +*/ void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); +/* + An fz_colorspace object represents an abstract colorspace. While + this should be treated as a black box by callers of the library at + this stage, know that it encapsulates knowledge of how to convert + colors to and from the colorspace, any lookup tables generated, the + number of components in the colorspace etc. +*/ +typedef struct fz_colorspace_s fz_colorspace; + +/* + fz_find_device_colorspace: Find a standard colorspace based upon + it's name. +*/ +fz_colorspace *fz_find_device_colorspace(char *name); + +/* + fz_device_gray: Abstract colorspace representing device specific + gray. +*/ +extern fz_colorspace *fz_device_gray; + +/* + fz_device_rgb: Abstract colorspace representing device specific + rgb. +*/ +extern fz_colorspace *fz_device_rgb; + +/* + fz_device_bgr: Abstract colorspace representing device specific + bgr. +*/ +extern fz_colorspace *fz_device_bgr; + +/* + fz_device_cmyk: Abstract colorspace representing device specific + CMYK. +*/ +extern fz_colorspace *fz_device_cmyk; + /* 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 @@ -1104,11 +1150,27 @@ void fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit); */ typedef struct fz_pixmap_s fz_pixmap; -typedef struct fz_colorspace_s fz_colorspace; +/* + fz_bound_pixmap: Return a bounding box for a pixmap. + Returns an exact bounding box for the supplied pixmap. +*/ fz_bbox fz_bound_pixmap(fz_pixmap *pix); -fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); +/* + fz_new_pixmap: Create a new pixmap, with it's origin at (0,0) + + cs: The colorspace to use for the pixmap, or NULL for an alpha + plane/mask. + + w: The width of the pixmap (in pixels) + + h: The height of the pixmap (in pixels) + + Returns a pointer to the new pixmap. Throws exception on failure to + allocate. +*/ +fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h); /* fz_new_pixmap_with_rect: Create a pixmap of a given size, @@ -1126,17 +1188,6 @@ fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *, int w, int h); */ fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox); -fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); - -/* - fz_keep_pixmap: Take a reference to a pixmap. - - pix: The pixmap to increment the reference for. - - Returns pix. Does not throw exceptions. -*/ -fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); - /* fz_keep_pixmap: Take a reference to a pixmap. @@ -1178,9 +1229,9 @@ int fz_pixmap_components(fz_context *ctx, fz_pixmap *pix); unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix); /* - fz_clear_pixmap_with_value: Clears a pixmap with the given value + fz_clear_pixmap_with_value: Clears a pixmap with the given value. - pix: Pixmap obtained from fz_new_pixmap*. + pix: The pixmap to clear. value: Values in the range 0 to 255 are valid. Each component sample for each pixel in the pixmap will be set to this value, @@ -1190,17 +1241,106 @@ unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix); */ void fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value); +/* + fz_clear_pixmap_with_value: Sets all components (including alpha) of + all pixels in a pixmap to 0. + + pix: The pixmap to clear. + + Does not throw exceptions. +*/ void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); + +/* + fz_invert_pixmap: Invert all the pixels in a pixmap. All components + of all pixels are inverted (except alpha, which is unchanged). + + Does not throw exceptions. +*/ void fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix); + +/* + fz_invert_pixmap: Invert all the pixels in a given rectangle of a + pixmap. All components of all pixels in the rectangle are inverted + (except alpha, which is unchanged). + + Does not throw exceptions. +*/ void fz_invert_pixmap_rect(fz_pixmap *image, fz_bbox rect); + +/* + fz_gamma_pixmap: Apply gamma correction to a pixmap. All components + of all pixels are modified (except alpha, which is unchanged). + + gamma: The gamma value to apply; 1.0 for no change. + + Does not throw exceptions. +*/ void fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma); + +/* + fz_unmultiply_pixmap: Convert a pixmap from premultiplied to + non-premultiplied format. + + Does not throw exceptions. +*/ void fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix); + +/* + fz_convert_pixmap: Convert from one pixmap to another (assumed to be + the same size, but possibly with a different colorspace). + + src: the source pixmap. + + dst: the destination pixmap. +*/ +void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); + +/* + fz_save_pixmap: Save a pixmap out. + + name: The prefix for the name of the pixmap. The pixmap will be saved + as "name.png" if the pixmap is RGB or Greyscale, "name.pam" otherwise. + + rgb: If non zero, the pixmap is converted to rgb (if possible) before + saving. +*/ void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *name, int rgb); + +/* + fz_write_pnm: Save a pixmap as a pnm + + filename: The filename to save as (including extension). +*/ void fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename); + +/* + fz_write_pam: Save a pixmap as a pam + + filename: The filename to save as (including extension). +*/ void fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); + +/* + fz_write_png: Save a pixmap as a png + + filename: The filename to save as (including extension). +*/ void fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); + +/* + fz_write_pbm: Save a bitmap as a pbm + + filename: The filename to save as (including extension). +*/ void fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename); -void fz_md5_pixmap(unsigned char digest[16], fz_pixmap *pixmap); + +/* + fz_md5_pixmap: Return the md5 digest for a pixmap + + filename: The filename to save as (including extension). +*/ +void fz_md5_pixmap(fz_pixmap *pixmap, unsigned char digest[16]); /* Images are storable objects from which we can obtain fz_pixmaps. @@ -1266,37 +1406,24 @@ typedef struct fz_halftone_s fz_halftone; fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht); /* - Colorspace resources. -*/ - -void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); - -fz_colorspace *fz_find_device_colorspace(char *name); - -/* - fz_device_gray: XXX + An abstract font handle. Currently there are no public API functions + for handling these. */ -extern fz_colorspace *fz_device_gray; - -/* - fz_device_rgb: XXX -*/ -extern fz_colorspace *fz_device_rgb; - -/* - fz_device_bgr: XXX -*/ -extern fz_colorspace *fz_device_bgr; +typedef struct fz_font_s fz_font; /* - fz_device_cmyk: XXX + The different format handlers (pdf, xps etc) interpret pages to a + device. These devices can then process the stream of calls they + recieve in various ways: + The trace device outputs debugging information for the calls. + The draw device will render them. + The list device stores them in a list to play back later. + The text device performs text extraction and searching. + The bbox device calculates the bounding box for the page. + Other devices can (and will) be written in future. */ -extern fz_colorspace *fz_device_cmyk; - typedef struct fz_device_s fz_device; -typedef struct fz_font_s fz_font; - /* fz_free_device: Free a devices of any type and its resources. */ @@ -1305,8 +1432,6 @@ void fz_free_device(fz_device *dev); /* fz_new_trace_device: Create a device to print a debug trace of all device calls. - - XXX */ fz_device *fz_new_trace_device(fz_context *ctx); @@ -1330,8 +1455,6 @@ fz_device *fz_new_bbox_device(fz_context *ctx, fz_bbox *bboxp); */ fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); -fz_device *fz_new_draw_device_type3(fz_context *ctx, fz_pixmap *dest); - /* Text extraction device */ diff --git a/fitz/image_md5.c b/fitz/image_md5.c index c82c7066..86ba0a12 100644 --- a/fitz/image_md5.c +++ b/fitz/image_md5.c @@ -1,6 +1,6 @@ #include "fitz-internal.h" -void fz_md5_pixmap(unsigned char digest[16], fz_pixmap *pix) +void fz_md5_pixmap(fz_pixmap *pix, unsigned char digest[16]) { fz_md5 md5; diff --git a/fitz/res_bitmap.c b/fitz/res_bitmap.c index 62cdd8ca..25e88187 100644 --- a/fitz/res_bitmap.c +++ b/fitz/res_bitmap.c @@ -95,3 +95,27 @@ unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix) return NULL; return pix->samples; } + +void fz_bitmap_details(fz_bitmap *bit, int *w, int *h, int *n, int *stride) +{ + if (!bit) + { + if (w) + *w = 0; + if (h) + *h = 0; + if (n) + *n = 0; + if (stride) + *stride = 0; + return; + } + if (w) + *w = bit->w; + if (h) + *h = bit->h; + if (n) + *n = bit->n; + if (stride) + *w = bit->stride; +} -- cgit v1.2.3 From a7a180366686298fa7f7aae686152e5a759d3a89 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Thu, 16 Feb 2012 01:08:05 +0100 Subject: Take care of boundary conditions in ps function evaluation. Floating point numbers are now clamped, division by zero is approximated by minimum or maximum value and NaN results in 1.0. --- fitz/fitz.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 594bc4e9..d80204f0 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -15,7 +15,7 @@ #include #include #include /* INT_MAX & co */ -#include /* FLT_EPSILON */ +#include /* FLT_EPSILON, FLT_MAX & co */ #include /* O_RDONLY & co */ #include @@ -46,6 +46,7 @@ #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) #define MAX(a,b) ( (a) > (b) ? (a) : (b) ) #define CLAMP(x,a,b) ( (x) > (b) ? (b) : ( (x) < (a) ? (a) : (x) ) ) +#define DIV_BY_ZERO(a, b, min, max) (((a) < 0) ^ ((b) < 0) ? (min) : (max)) /* * Some differences in libc can be smoothed over @@ -62,6 +63,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #define snprintf _snprintf +#define isnan _isnan #else /* Unix or close enough */ -- cgit v1.2.3 From 71e34dd2493b41836db5a9b539ac7ab38e18ddd5 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Sun, 19 Feb 2012 18:06:50 +0100 Subject: Clamp real numbers when parsing. Instead of returning in 1.0 for underflow/overflow, return minimum value for underflow and maximum value for overflow. NaN returns 1.0. --- fitz/base_string.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/base_string.c b/fitz/base_string.c index dd9f8ea2..2c8877c8 100644 --- a/fitz/base_string.c +++ b/fitz/base_string.c @@ -256,10 +256,11 @@ float fz_atof(const char *s) * as we convert to a float. */ errno = 0; d = strtod(s, NULL); - if (errno == ERANGE || d > FLT_MAX || d < -FLT_MAX) { + if (errno == ERANGE || isnan(d)) { /* Return 1.0, as it's a small known value that won't cause a - * divide by 0. */ + divide by 0. */ return 1.0; } + d = CLAMP(d, -FLT_MAX, FLT_MAX); return (float)d; } -- cgit v1.2.3 From b75dd982f18ce02781ce2a36e630860153f96ec9 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Thu, 23 Feb 2012 02:19:12 +0100 Subject: Test both coordinates when checking for empty/infinite rect and bboxes. --- fitz/fitz.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index d80204f0..6427537f 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -545,7 +545,7 @@ extern const fz_bbox fz_infinite_bbox; An empty rectangle is defined as one whose area is zero. */ -#define fz_is_empty_rect(r) ((r).x0 == (r).x1) +#define fz_is_empty_rect(r) ((r).x0 == (r).x1 || (r).y0 == (r).y1) /* fz_is_empty_bbox: Check if bounding box is empty. @@ -553,7 +553,7 @@ extern const fz_bbox fz_infinite_bbox; Same definition of empty bounding boxes as for empty rectangles. See fz_is_empty_rect. */ -#define fz_is_empty_bbox(b) ((b).x0 == (b).x1) +#define fz_is_empty_bbox(b) ((b).x0 == (b).x1 || (b).y0 == (b).y1) /* fz_is_infinite: Check if rectangle is infinite. @@ -561,7 +561,7 @@ extern const fz_bbox fz_infinite_bbox; An infinite rectangle is defined as one where either of the two relationships between corner coordinates are not true. */ -#define fz_is_infinite_rect(r) ((r).x0 > (r).x1) +#define fz_is_infinite_rect(r) ((r).x0 > (r).x1 || (r).y0 > (r).y1) /* fz_is_infinite_bbox: Check if bounding box is infinite. @@ -569,7 +569,7 @@ extern const fz_bbox fz_infinite_bbox; Same definition of infinite bounding boxes as for infinite rectangles. See fz_is_infinite_rect. */ -#define fz_is_infinite_bbox(b) ((b).x0 > (b).x1) +#define fz_is_infinite_bbox(b) ((b).x0 > (b).x1 || (b).y0 > (b).y1) /* fz_matrix is a a row-major 3x3 matrix used for representing -- cgit v1.2.3 From 2b7f3d1035f4bae9c189e0e6fcbb907ca46538c4 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 12 Mar 2012 14:45:25 +0000 Subject: Change order of params in fz_convert_pixmap to C standard. C's standard is copy(dst, src), so we move to adopt that here. Hopefully no one is calling this routine other than us - if they are, then I apologise! Better to aim for consistency before we freeze the API at v1.0 than to carry an inconsistent API around ever after. --- fitz/fitz.h | 6 +++--- fitz/image_jpx.c | 2 +- fitz/image_save.c | 2 +- fitz/image_tiff.c | 2 +- fitz/res_colorspace.c | 56 +++++++++++++++++++++++++-------------------------- 5 files changed, 34 insertions(+), 34 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 03cb6f25..fedf6ea4 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1292,11 +1292,11 @@ void fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix); fz_convert_pixmap: Convert from one pixmap to another (assumed to be the same size, but possibly with a different colorspace). - src: the source pixmap. + dst: the source pixmap. - dst: the destination pixmap. + src: the destination pixmap. */ -void fz_convert_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst); +void fz_convert_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src); /* fz_save_pixmap: Save a pixmap out. diff --git a/fitz/image_jpx.c b/fitz/image_jpx.c index b2fc3601..ac1db35a 100644 --- a/fitz/image_jpx.c +++ b/fitz/image_jpx.c @@ -144,7 +144,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs if (n == 4) { fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb, w, h); - fz_convert_pixmap(ctx, img, tmp); + fz_convert_pixmap(ctx, tmp, img); fz_drop_pixmap(ctx, img); img = tmp; } diff --git a/fitz/image_save.c b/fitz/image_save.c index ef5dbfa5..29d3e8fc 100644 --- a/fitz/image_save.c +++ b/fitz/image_save.c @@ -11,7 +11,7 @@ void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *file, int rgb) if (rgb && img->colorspace && img->colorspace != fz_device_rgb) { converted = fz_new_pixmap_with_rect(ctx, fz_device_rgb, fz_bound_pixmap(img)); - fz_convert_pixmap(ctx, img, converted); + fz_convert_pixmap(ctx, converted, img); img = converted; } diff --git a/fitz/image_tiff.c b/fitz/image_tiff.c index 76f08447..ffd0ea88 100644 --- a/fitz/image_tiff.c +++ b/fitz/image_tiff.c @@ -789,7 +789,7 @@ fz_load_tiff(fz_context *ctx, unsigned char *buf, int len) if (image->n == 5) { fz_pixmap *rgb = fz_new_pixmap(tiff.ctx, fz_device_rgb, image->w, image->h); - fz_convert_pixmap(tiff.ctx, image, rgb); + fz_convert_pixmap(tiff.ctx, rgb, image); rgb->xres = image->xres; rgb->yres = image->yres; fz_drop_pixmap(ctx, image); diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 1c26d1b3..45d57113 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -180,7 +180,7 @@ fz_find_device_colorspace(char *name) /* Fast pixmap color conversions */ -static void fast_gray_to_rgb(fz_pixmap *src, fz_pixmap *dst) +static void fast_gray_to_rgb(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -196,7 +196,7 @@ static void fast_gray_to_rgb(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_gray_to_cmyk(fz_pixmap *src, fz_pixmap *dst) +static void fast_gray_to_cmyk(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -213,7 +213,7 @@ static void fast_gray_to_cmyk(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_rgb_to_gray(fz_pixmap *src, fz_pixmap *dst) +static void fast_rgb_to_gray(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -227,7 +227,7 @@ static void fast_rgb_to_gray(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_bgr_to_gray(fz_pixmap *src, fz_pixmap *dst) +static void fast_bgr_to_gray(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -241,7 +241,7 @@ static void fast_bgr_to_gray(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_rgb_to_cmyk(fz_pixmap *src, fz_pixmap *dst) +static void fast_rgb_to_cmyk(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -262,7 +262,7 @@ static void fast_rgb_to_cmyk(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_bgr_to_cmyk(fz_pixmap *src, fz_pixmap *dst) +static void fast_bgr_to_cmyk(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -283,7 +283,7 @@ static void fast_bgr_to_cmyk(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_cmyk_to_gray(fz_pixmap *src, fz_pixmap *dst) +static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -300,7 +300,7 @@ static void fast_cmyk_to_gray(fz_pixmap *src, fz_pixmap *dst) } } -static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) +static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -328,7 +328,7 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) } } -static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) +static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -356,7 +356,7 @@ static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) } } -static void fast_rgb_to_bgr(fz_pixmap *src, fz_pixmap *dst) +static void fast_rgb_to_bgr(fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; @@ -373,7 +373,7 @@ static void fast_rgb_to_bgr(fz_pixmap *src, fz_pixmap *dst) } static void -fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) +fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) { float srcv[FZ_MAX_COLORS]; float dstv[FZ_MAX_COLORS]; @@ -499,7 +499,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *src, fz_pixmap *dst) } void -fz_convert_pixmap(fz_context *ctx, fz_pixmap *sp, fz_pixmap *dp) +fz_convert_pixmap(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp) { fz_colorspace *ss = sp->colorspace; fz_colorspace *ds = dp->colorspace; @@ -510,37 +510,37 @@ fz_convert_pixmap(fz_context *ctx, fz_pixmap *sp, fz_pixmap *dp) if (ss == fz_device_gray) { - if (ds == fz_device_rgb) fast_gray_to_rgb(sp, dp); - else if (ds == fz_device_bgr) fast_gray_to_rgb(sp, dp); /* bgr == rgb here */ - else if (ds == fz_device_cmyk) fast_gray_to_cmyk(sp, dp); - else fz_std_conv_pixmap(ctx, sp, dp); + if (ds == fz_device_rgb) fast_gray_to_rgb(dp, sp); + else if (ds == fz_device_bgr) fast_gray_to_rgb(dp, sp); /* bgr == rgb here */ + else if (ds == fz_device_cmyk) fast_gray_to_cmyk(dp, sp); + else fz_std_conv_pixmap(ctx, dp, sp); } else if (ss == fz_device_rgb) { - if (ds == fz_device_gray) fast_rgb_to_gray(sp, dp); - else if (ds == fz_device_bgr) fast_rgb_to_bgr(sp, dp); - else if (ds == fz_device_cmyk) fast_rgb_to_cmyk(sp, dp); - else fz_std_conv_pixmap(ctx, sp, dp); + if (ds == fz_device_gray) fast_rgb_to_gray(dp, sp); + else if (ds == fz_device_bgr) fast_rgb_to_bgr(dp, sp); + else if (ds == fz_device_cmyk) fast_rgb_to_cmyk(dp, sp); + else fz_std_conv_pixmap(ctx, dp, sp); } else if (ss == fz_device_bgr) { - if (ds == fz_device_gray) fast_bgr_to_gray(sp, dp); - else if (ds == fz_device_rgb) fast_rgb_to_bgr(sp, dp); /* bgr = rgb here */ + if (ds == fz_device_gray) fast_bgr_to_gray(dp, sp); + else if (ds == fz_device_rgb) fast_rgb_to_bgr(dp, sp); /* bgr = rgb here */ else if (ds == fz_device_cmyk) fast_bgr_to_cmyk(sp, dp); - else fz_std_conv_pixmap(ctx, sp, dp); + else fz_std_conv_pixmap(ctx, dp, sp); } else if (ss == fz_device_cmyk) { - if (ds == fz_device_gray) fast_cmyk_to_gray(sp, dp); - else if (ds == fz_device_bgr) fast_cmyk_to_bgr(ctx, sp, dp); - else if (ds == fz_device_rgb) fast_cmyk_to_rgb(ctx, sp, dp); - else fz_std_conv_pixmap(ctx, sp, dp); + if (ds == fz_device_gray) fast_cmyk_to_gray(dp, sp); + else if (ds == fz_device_bgr) fast_cmyk_to_bgr(ctx, dp, sp); + else if (ds == fz_device_rgb) fast_cmyk_to_rgb(ctx, dp, sp); + else fz_std_conv_pixmap(ctx, dp, sp); } - else fz_std_conv_pixmap(ctx, sp, dp); + else fz_std_conv_pixmap(ctx, dp, sp); } /* Convert a single color */ -- cgit v1.2.3 From e49c70808fba2d0d2a691d1568d766bfeee863f0 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 12 Mar 2012 15:05:16 +0000 Subject: Change order of params in fz_convert_color to C standard. C's standard is copy(dst, src), so we move to adopt that here. Hopefully no one is calling this routine other than us - if they are, then I apologise! Better to aim for consistency before we freeze the API at v1.0 than to carry an inconsistent API around ever after. --- fitz/fitz-internal.h | 2 +- fitz/res_colorspace.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 4c41564b..5c4e9514 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -625,7 +625,7 @@ 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 *srcs, float *srcv, fz_colorspace *dsts, float *dstv); +void fz_convert_color(fz_context *ctx, fz_colorspace *dsts, float *dstv, fz_colorspace *srcs, float *srcv); /* * Fonts come in two variants: diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 45d57113..03d5967b 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -404,7 +404,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) srcv[1] = *s++ - 128; srcv[2] = *s++ - 128; - fz_convert_color(ctx, ss, srcv, ds, dstv); + fz_convert_color(ctx, ds, dstv, ss, srcv); for (k = 0; k < dstn; k++) *d++ = dstv[k] * 255; @@ -424,7 +424,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) for (k = 0; k < srcn; k++) srcv[k] = *s++ / 255.0f; - fz_convert_color(ctx, ss, srcv, ds, dstv); + fz_convert_color(ctx, ds, dstv, ss, srcv); for (k = 0; k < dstn; k++) *d++ = dstv[k] * 255; @@ -442,7 +442,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) for (i = 0; i < 256; i++) { srcv[0] = i / 255.0f; - fz_convert_color(ctx, ss, srcv, ds, dstv); + fz_convert_color(ctx, ds, dstv, ss, srcv); for (k = 0; k < dstn; k++) lookup[i * dstn + k] = dstv[k] * 255; } @@ -483,7 +483,7 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) { for (k = 0; k < srcn; k++) srcv[k] = *s++ / 255.0f; - fz_convert_color(ctx, ss, srcv, ds, dstv); + fz_convert_color(ctx, ds, dstv, ss, srcv); for (k = 0; k < dstn; k++) *d++ = dstv[k] * 255; @@ -567,7 +567,7 @@ fz_std_conv_color(fz_context *ctx, fz_colorspace *srcs, float *srcv, fz_colorspa } void -fz_convert_color(fz_context *ctx, fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) +fz_convert_color(fz_context *ctx, fz_colorspace *ds, float *dv, fz_colorspace *ss, float *sv) { if (ss == fz_device_gray) { -- cgit v1.2.3 From 2bd952f3fa8241aad0626f39343cffa9855c2d8c Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 12 Mar 2012 15:57:28 +0000 Subject: More API work. Details of buffers hidden in fitz-internal.h. Public API now just lets us keep/drop and get storage details for a buffer. fz_debug_outline{,_xml} lose the 'level' param in their public API. fz_matrix_max_expansion hidden, as it's only used internally. Document fz_setjmp/fz_longjmp and Apple specific hackery. --- fitz/doc_outline.c | 22 ++++++++++++---- fitz/fitz-internal.h | 47 ++++++++++++++++++++++++++++++++++ fitz/fitz.h | 72 ++++++++++++++++++---------------------------------- fitz/stm_buffer.c | 8 ++++++ 4 files changed, 97 insertions(+), 52 deletions(-) (limited to 'fitz') diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c index a00c56f1..4847b919 100644 --- a/fitz/doc_outline.c +++ b/fitz/doc_outline.c @@ -14,8 +14,8 @@ fz_free_outline(fz_context *ctx, fz_outline *outline) } } -void -fz_debug_outline_xml(fz_context *ctx, fz_outline *outline, int level) +static void +do_debug_outline_xml(fz_outline *outline, int level) { while (outline) { @@ -23,7 +23,7 @@ fz_debug_outline_xml(fz_context *ctx, fz_outline *outline, int level) if (outline->down) { printf(">\n"); - fz_debug_outline_xml(ctx, outline->down, level + 1); + do_debug_outline_xml(outline->down, level + 1); printf("\n"); } else @@ -35,7 +35,13 @@ fz_debug_outline_xml(fz_context *ctx, fz_outline *outline, int level) } void -fz_debug_outline(fz_context *ctx, fz_outline *outline, int level) +fz_debug_outline_xml(fz_context *ctx, fz_outline *outline) +{ + do_debug_outline_xml(outline, 0); +} + +static void +do_debug_outline(fz_outline *outline, int level) { int i; while (outline) @@ -44,7 +50,13 @@ fz_debug_outline(fz_context *ctx, fz_outline *outline, int level) putchar('\t'); printf("%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); if (outline->down) - fz_debug_outline(ctx, outline->down, level + 1); + do_debug_outline(outline->down, level + 1); outline = outline->next; } } + +void +fz_debug_outline(fz_context *ctx, fz_outline *outline) +{ + do_debug_outline(outline, 0); +} diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 5c4e9514..f9604443 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -125,6 +125,7 @@ static inline int fz_mul255(int a, int b) #define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8) void fz_gridfit_matrix(fz_matrix *m); +float fz_matrix_max_expansion(fz_matrix m); /* * Basic crypto functions. @@ -376,6 +377,52 @@ void fz_empty_store(fz_context *ctx); */ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase); +struct fz_buffer_s +{ + int refs; + unsigned char *data; + int cap, len; +}; + +/* + 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_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); + struct fz_stream_s { fz_context *ctx; diff --git a/fitz/fitz.h b/fitz/fitz.h index fedf6ea4..4592f315 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -22,6 +22,12 @@ #include "memento.h" +/* + Some versions of setjmp/longjmp (notably MacOSX and ios) store/restore + signal handlers too. We don't alter signal handlers within mupdf, so + there is no need for us to store/restore - hence we use the + non-restoring variants. This makes a large speed difference. +*/ #ifdef __APPLE__ #define fz_setjmp _setjmp #define fz_longjmp _longjmp @@ -781,7 +787,6 @@ int fz_is_rectilinear(fz_matrix m); fz_matrix_expansion: Calculate average scaling factor of matrix. */ float fz_matrix_expansion(fz_matrix m); /* sumatrapdf */ -float fz_matrix_max_expansion(fz_matrix m); /* fz_round_rect: Convert a rect into a bounding box. @@ -902,23 +907,6 @@ fz_bbox fz_transform_bbox(fz_matrix matrix, fz_bbox bbox); */ typedef struct fz_buffer_s fz_buffer; -struct fz_buffer_s -{ - int refs; - unsigned char *data; - int cap, len; -}; - -/* - 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_keep_buffer: Increment the reference count for a buffer. @@ -936,33 +924,14 @@ fz_buffer *fz_keep_buffer(fz_context *ctx, fz_buffer *buf); void fz_drop_buffer(fz_context *ctx, fz_buffer *buf); /* - fz_resize_buffer: Ensure that a buffer has a given capacity, - truncating data if required. - - buf: The buffer to alter. + fz_buffer_storage: Retrieve information on the storage currently used + by a buffer. - capacity: The desired capacity for the buffer. If the current size - of the buffer contents is smaller than capacity, it is truncated. + data: Pointer to place to retrieve data pointer. + Returns length of stream. */ -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); +int fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **data); /* fz_stream is a buffered reader capable of seeking in both @@ -1782,8 +1751,16 @@ struct fz_outline_s fz_outline *down; }; -void fz_debug_outline_xml(fz_context *ctx, fz_outline *outline, int level); -void fz_debug_outline(fz_context *ctx, fz_outline *outline, int level); +/* + fz_debug_outline_xml: Dump the given outlines to stdout as (pseudo) + XML. +*/ +void fz_debug_outline_xml(fz_context *ctx, fz_outline *outline); + +/* + fz_debug_outline: Dump the given outlines to stdout as text. +*/ +void fz_debug_outline(fz_context *ctx, fz_outline *outline); /* fz_free_outline: Free hierarchical outline. @@ -1794,10 +1771,11 @@ void fz_debug_outline(fz_context *ctx, fz_outline *outline, int level); */ void fz_free_outline(fz_context *ctx, fz_outline *outline); -/* Document interface */ - +/* + Document interface +*/ typedef struct fz_document_s fz_document; -typedef struct fz_page_s fz_page; /* doesn't have a definition -- always cast to *_page */ +typedef struct fz_page_s fz_page; /* fz_open_document: Open a PDF, XPS or CBZ document. diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c index b5728d57..4be0165a 100644 --- a/fitz/stm_buffer.c +++ b/fitz/stm_buffer.c @@ -70,3 +70,11 @@ fz_trim_buffer(fz_context *ctx, fz_buffer *buf) if (buf->cap > buf->len+1) fz_resize_buffer(ctx, buf, buf->len); } + +int +fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap) +{ + if (datap) + *datap = (buf ? buf->data : NULL); + return (buf ? buf->len : 0); +} -- cgit v1.2.3 From 5060043a33b32dfdd8ffacc88e8ca05b5e8271a9 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 12 Mar 2012 16:34:00 +0000 Subject: Store AA level used to render a glyph in the glyphcache. In the existing code, glyphs are stored/retrieved from the glyphcache with no reference to the antialias level used to create them. This means that if we are using different aa levels in different threads, we can retrieve 'non-matching' glyphs and hence get rendering indeterminisms. Fixed simply here by storing the aa level in the glyphcache too. --- fitz/fitz.h | 2 +- fitz/res_font.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 6427537f..1ec1eb97 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1747,7 +1747,7 @@ 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_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm); +fz_pixmap *fz_render_ft_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, int aa); fz_pixmap *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); fz_pixmap *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); fz_pixmap *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz_colorspace *model); diff --git a/fitz/res_font.c b/fitz/res_font.c index e4a4d23a..f6207e80 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -387,7 +387,7 @@ fz_copy_ft_bitmap(fz_context *ctx, int left, int top, FT_Bitmap *bitmap) /* The glyph cache lock is always taken when this is called. */ fz_pixmap * -fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) +fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, int aa) { FT_Face face = font->ft_face; FT_Matrix m; @@ -421,7 +421,7 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm) fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr)); FT_Set_Transform(face, &m, &v); - if (fz_get_aa_level(ctx) == 0) + if (aa == 0) { /* If you really want grid fitting, enable this code. */ float scale = fz_matrix_expansion(trm); -- cgit v1.2.3 From bc1c06ddd335f899025470dde7e839a82d792972 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 12 Mar 2012 18:38:14 +0100 Subject: Move fz_alloc_default to internal header. --- fitz/fitz-internal.h | 3 +++ fitz/fitz.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 0f4b47c7..16b65ccd 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -16,6 +16,9 @@ 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; diff --git a/fitz/fitz.h b/fitz/fitz.h index 4592f315..c01de8ac 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -138,9 +138,6 @@ struct fz_alloc_context_s void (*free)(void *, void *); }; -/* Default allocator */ -extern fz_alloc_context fz_alloc_default; - struct fz_error_context_s { int top; -- cgit v1.2.3 From 0b0e2af392428b5dbc88d6fbd2f6b5181e85165f Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 6 Mar 2012 17:41:04 +0100 Subject: Create style sheet and group extracted text into blocks, lines and spans. --- fitz/dev_text.c | 689 +++++++++++++++++++++++++++++++++++++++++--------------- fitz/fitz.h | 102 +++++++-- 2 files changed, 582 insertions(+), 209 deletions(-) (limited to 'fitz') diff --git a/fitz/dev_text.c b/fitz/dev_text.c index 79d8c137..7a56b56c 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -2,6 +2,7 @@ #define LINE_DIST 0.9f #define SPACE_DIST 0.2f +#define PARAGRAPH_DIST 0.5f #include #include FT_FREETYPE_H @@ -11,60 +12,211 @@ typedef struct fz_text_device_s fz_text_device; struct fz_text_device_s { + fz_text_sheet *sheet; + fz_text_page *page; + fz_text_line cur_line; + fz_text_span cur_span; fz_point point; - fz_text_span *head; - fz_text_span *span; }; -fz_text_span * -fz_new_text_span(fz_context *ctx) +fz_text_sheet * +fz_new_text_sheet(fz_context *ctx) { - fz_text_span *span; - span = fz_malloc_struct(ctx, fz_text_span); - span->font = NULL; - span->wmode = 0; - span->size = 0; - span->len = 0; - span->cap = 0; - span->text = NULL; - span->next = NULL; - span->eol = 0; - return span; + fz_text_sheet *sheet = fz_malloc(ctx, sizeof *sheet); + sheet->maxid = 0; + sheet->style = NULL; + return sheet; } void -fz_free_text_span(fz_context *ctx, fz_text_span *span) +fz_free_text_sheet(fz_context *ctx, fz_text_sheet *sheet) +{ + fz_text_style *style = sheet->style; + while (style) + { + fz_text_style *next = style->next; + fz_drop_font(ctx, style->font); + fz_free(ctx, style); + style = next; + } +} + +static fz_text_style * +fz_find_text_style_imp(fz_context *ctx, fz_text_sheet *sheet, + float size, fz_font *font, int wmode, int script) +{ + fz_text_style *style; + + for (style = sheet->style; style; style = style->next) + { + if (style->font == font && + style->size == size && + style->wmode == wmode && + style->script == script) /* FIXME: others */ + { + return style; + } + } + + /* Better make a new one and add it to our list */ + style = fz_malloc(ctx, sizeof *style); + style->id = sheet->maxid++; + style->font = fz_keep_font(ctx, font); + style->size = size; + style->wmode = wmode; + style->script = script; + style->next = sheet->style; + sheet->style = style; + return style; +} + +static fz_text_style * +fz_find_text_style(fz_context *ctx, fz_text_sheet *sheet, fz_text *text, fz_matrix *ctm, + fz_colorspace *colorspace, float *color, float alpha, fz_stroke_state *stroke) { - fz_text_span *next; + float size = 1.0f; + fz_font *font = text ? text->font : NULL; + int wmode = text ? text->wmode : 0; + if (ctm && text) + { + fz_matrix tm = text->trm; + fz_matrix trm; + tm.e = 0; + tm.f = 0; + trm = fz_concat(tm, *ctm); + size = fz_matrix_expansion(trm); + } + return fz_find_text_style_imp(ctx, sheet, size, font, wmode, 0); +} - while (span) +fz_text_page * +fz_new_text_page(fz_context *ctx, fz_rect mediabox) +{ + fz_text_page *page = fz_malloc(ctx, sizeof(*page)); + page->mediabox = mediabox; + page->len = 0; + page->cap = 0; + page->blocks = NULL; + return page; +} + +void +fz_free_text_page(fz_context *ctx, fz_text_page *page) +{ + fz_text_block *block; + fz_text_line *line; + fz_text_span *span; + for (block = page->blocks; block < page->blocks + page->len; block++) { - if (span->font) - fz_drop_font(ctx, span->font); - next = span->next; - fz_free(ctx, span->text); - fz_free(ctx, span); - span = next; + for (line = block->lines; line < block->lines + block->len; line++) + { + for (span = line->spans; span < line->spans + line->len; span++) + { + fz_free(ctx, span->text); + } + fz_free(ctx, line->spans); + } + fz_free(ctx, block->lines); } + fz_free(ctx, page->blocks); + fz_free(ctx, page); } static void -fz_add_text_char_imp(fz_context *ctx, fz_text_span *span, int c, fz_bbox bbox) +append_char(fz_context *ctx, fz_text_span *span, int c, fz_rect bbox) { - if (span->len + 1 >= span->cap) + if (span->len == span->cap) { - span->cap = span->cap > 1 ? (span->cap * 3) / 2 : 80; - span->text = fz_resize_array(ctx, span->text, span->cap, sizeof(fz_text_char)); + span->cap = MAX(64, span->cap * 2); + span->text = fz_resize_array(ctx, span->text, span->cap, sizeof(*span->text)); } + span->bbox = fz_union_rect(span->bbox, bbox); span->text[span->len].c = c; span->text[span->len].bbox = bbox; - span->len ++; + span->len++; +} + +static void +init_span(fz_context *ctx, fz_text_span *span, fz_text_style *style) +{ + span->style = style; + span->bbox = fz_empty_rect; + span->len = span->cap = 0; + span->text = NULL; +} + +static void +append_span(fz_context *ctx, fz_text_line *line, fz_text_span *span) +{ + if (line->len == line->cap) + { + line->cap = MAX(8, line->cap * 2); + line->spans = fz_resize_array(ctx, line->spans, line->cap, sizeof(*line->spans)); + } + line->bbox = fz_union_rect(line->bbox, span->bbox); + line->spans[line->len++] = *span; } -static fz_bbox -fz_split_bbox(fz_bbox bbox, int i, int n) +static void +init_line(fz_context *ctx, fz_text_line *line) +{ + line->bbox = fz_empty_rect; + line->len = line->cap = 0; + line->spans = NULL; +} + +static void +append_line(fz_context *ctx, fz_text_block *block, fz_text_line *line) { - float w = (float)(bbox.x1 - bbox.x0) / n; + if (block->len == block->cap) + { + block->cap = MAX(16, block->cap * 2); + block->lines = fz_resize_array(ctx, block->lines, block->cap, sizeof *block->lines); + } + block->bbox = fz_union_rect(block->bbox, line->bbox); + block->lines[block->len++] = *line; +} + +static fz_text_block * +find_block_for_line(fz_context *ctx, fz_text_page *page, fz_text_line *line) +{ + float size = line->len > 0 && line->spans[0].len > 0 ? line->spans[0].style->size : 1; + int i; + + for (i = 0; i < page->len; i++) + { + fz_text_block *block = page->blocks + i; + int w = block->bbox.x1 - block->bbox.x0; + if (block->bbox.y0 - line->bbox.y1 < size * PARAGRAPH_DIST) + if (line->bbox.x0 < block->bbox.x1 && line->bbox.x1 > block->bbox.x0) + if (ABS(line->bbox.x0 - block->bbox.x0) < w / 4) + return block; + } + + if (page->len == page->cap) + { + page->cap = MAX(16, page->cap * 2); + page->blocks = fz_resize_array(ctx, page->blocks, page->cap, sizeof(*page->blocks)); + } + + page->blocks[page->len].bbox = fz_empty_rect; + page->blocks[page->len].len = 0; + page->blocks[page->len].cap = 0; + page->blocks[page->len].lines = NULL; + + return &page->blocks[page->len++]; +} + +static void +insert_line(fz_context *ctx, fz_text_page *page, fz_text_line *line) +{ + append_line(ctx, find_block_for_line(ctx, page, line), line); +} + +static fz_rect +fz_split_bbox(fz_rect bbox, int i, int n) +{ + float w = (bbox.x1 - bbox.x0) / n; float x0 = bbox.x0; bbox.x0 = x0 + i * w; bbox.x1 = x0 + (i + 1) * w; @@ -72,154 +224,71 @@ fz_split_bbox(fz_bbox bbox, int i, int n) } static void -fz_add_text_char(fz_context *ctx, fz_text_span **last, fz_font *font, float size, int wmode, int c, fz_bbox bbox) +fz_flush_text_line(fz_context *ctx, fz_text_device *dev, fz_text_style *style) { - fz_text_span *span = *last; - - if (!span->font) - { - span->font = fz_keep_font(ctx, font); - span->size = size; - } + append_span(ctx, &dev->cur_line, &dev->cur_span); + insert_line(ctx, dev->page, &dev->cur_line); + init_span(ctx, &dev->cur_span, style); + init_line(ctx, &dev->cur_line); +} - if ((span->font != font || span->size != size || span->wmode != wmode) && c != 32) +static void +fz_add_text_char_imp(fz_context *ctx, fz_text_device *dev, fz_text_style *style, int c, fz_rect bbox) +{ + if (!dev->cur_span.style) + dev->cur_span.style = style; + if (style != dev->cur_span.style) { - span = fz_new_text_span(ctx); - span->font = fz_keep_font(ctx, font); - span->size = size; - span->wmode = wmode; - (*last)->next = span; - *last = span; + append_span(ctx, &dev->cur_line, &dev->cur_span); + init_span(ctx, &dev->cur_span, style); } + append_char(ctx, &dev->cur_span, c, bbox); +} +static void +fz_add_text_char(fz_context *ctx, fz_text_device *dev, fz_text_style *style, int c, fz_rect bbox) +{ switch (c) { case -1: /* ignore when one unicode character maps to multiple glyphs */ break; case 0xFB00: /* ff */ - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 1, 2)); break; case 0xFB01: /* fi */ - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(ctx, span, 'i', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, dev, style, 'i', fz_split_bbox(bbox, 1, 2)); break; case 0xFB02: /* fl */ - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(ctx, span, 'l', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, dev, style, 'l', fz_split_bbox(bbox, 1, 2)); break; case 0xFB03: /* ffi */ - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 3)); - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 1, 3)); - fz_add_text_char_imp(ctx, span, 'i', fz_split_bbox(bbox, 2, 3)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 0, 3)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 1, 3)); + fz_add_text_char_imp(ctx, dev, style, 'i', fz_split_bbox(bbox, 2, 3)); break; case 0xFB04: /* ffl */ - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 0, 3)); - fz_add_text_char_imp(ctx, span, 'f', fz_split_bbox(bbox, 1, 3)); - fz_add_text_char_imp(ctx, span, 'l', fz_split_bbox(bbox, 2, 3)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 0, 3)); + fz_add_text_char_imp(ctx, dev, style, 'f', fz_split_bbox(bbox, 1, 3)); + fz_add_text_char_imp(ctx, dev, style, 'l', fz_split_bbox(bbox, 2, 3)); break; case 0xFB05: /* long st */ case 0xFB06: /* st */ - fz_add_text_char_imp(ctx, span, 's', fz_split_bbox(bbox, 0, 2)); - fz_add_text_char_imp(ctx, span, 't', fz_split_bbox(bbox, 1, 2)); + fz_add_text_char_imp(ctx, dev, style, 's', fz_split_bbox(bbox, 0, 2)); + fz_add_text_char_imp(ctx, dev, style, 't', fz_split_bbox(bbox, 1, 2)); break; default: - fz_add_text_char_imp(ctx, span, c, bbox); + fz_add_text_char_imp(ctx, dev, style, c, bbox); break; } } static void -fz_divide_text_chars(fz_text_span **last, int n, fz_bbox bbox) -{ - fz_text_span *span = *last; - int i, x; - x = span->len - n; - if (x >= 0) - for (i = 0; i < n; i++) - span->text[x + i].bbox = fz_split_bbox(bbox, i, n); -} - -static void -fz_add_text_newline(fz_context *ctx, fz_text_span **last, fz_font *font, float size, int wmode) -{ - fz_text_span *span; - span = fz_new_text_span(ctx); - span->font = fz_keep_font(ctx, font); - span->size = size; - span->wmode = wmode; - (*last)->eol = 1; - (*last)->next = span; - *last = span; -} - -void -fz_debug_text_span_xml(fz_text_span *span) -{ - char buf[10]; - int c, n, k, i; - - while (span) - { - printf("\n", - span->font ? span->font->name : "NULL", span->size, span->wmode, span->eol); - - for (i = 0; i < span->len; i++) - { - printf("\ttext[i].c; - if (c < 128) - putchar(c); - else - { - n = fz_runetochar(buf, c); - for (k = 0; k < n; k++) - putchar(buf[k]); - } - printf("\" bbox=\"%d %d %d %d\" />\n", - span->text[i].bbox.x0, - span->text[i].bbox.y0, - span->text[i].bbox.x1, - span->text[i].bbox.y1); - } - - printf("\n"); - - span = span->next; - } -} - -void -fz_debug_text_span(fz_text_span *span) -{ - char buf[10]; - int c, n, k, i; - - while (span) - { - for (i = 0; i < span->len; i++) - { - c = span->text[i].c; - if (c < 128) - putchar(c); - else - { - n = fz_runetochar(buf, c); - for (k = 0; k < n; k++) - putchar(buf[k]); - } - } - - if (span->eol) - putchar('\n'); - - span = span->next; - } -} - -static void -fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point *pen) +fz_text_extract(fz_context *ctx, fz_text_device *dev, fz_text *text, fz_matrix ctm, fz_text_style *style) { + fz_point *pen = &dev->point; fz_font *font = text->font; FT_Face face = font->ft_face; fz_matrix tm = text->trm; @@ -233,19 +302,20 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat float ascender = 1; float descender = 0; int multi; - int i, err; + int i, j, err; if (text->len == 0) return; - fz_lock(ctx, FZ_LOCK_FREETYPE); if (font->ft_face) { + fz_lock(ctx, FZ_LOCK_FREETYPE); err = FT_Set_Char_Size(font->ft_face, 64, 64, 72, 72); if (err) fz_warn(ctx, "freetype set character size: %s", ft_error_string(err)); ascender = (float)face->ascender / face->units_per_EM; descender = (float)face->descender / face->units_per_EM; + fz_unlock(ctx, FZ_LOCK_FREETYPE); } rect = fz_empty_rect; @@ -264,6 +334,7 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat tm.e = 0; tm.f = 0; trm = fz_concat(tm, ctm); + dir = fz_transform_vector(trm, dir); dist = sqrtf(dir.x * dir.x + dir.y * dir.y); ndir.x = dir.x / dist; @@ -271,19 +342,10 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat size = fz_matrix_expansion(trm); - multi = 1; + int lastchar = ' '; for (i = 0; i < text->len; i++) { - if (text->items[i].gid < 0) - { - fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); - multi ++; - fz_divide_text_chars(last, multi, fz_round_rect(rect)); - continue; - } - multi = 1; - /* Calculate new pen location and delta */ tm.e = text->items[i].x; tm.f = text->items[i].y; @@ -305,20 +367,19 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat if (dist > size * LINE_DIST) { - fz_add_text_newline(ctx, last, font, size, text->wmode); + fz_flush_text_line(ctx, dev, style); + lastchar = ' '; } - else if (fabsf(dot) > 0.95f && dist > size * SPACE_DIST) + else if (fabsf(dot) > 0.95f && dist > size * SPACE_DIST && lastchar != ' ') { - if ((*last)->len > 0 && (*last)->text[(*last)->len - 1].c != ' ') - { - fz_rect spacerect; - spacerect.x0 = -0.2f; - spacerect.y0 = 0; - spacerect.x1 = 0; - spacerect.y1 = 1; - spacerect = fz_transform_rect(trm, spacerect); - fz_add_text_char(ctx, last, font, size, text->wmode, ' ', fz_round_rect(spacerect)); - } + fz_rect spacerect; + spacerect.x0 = -0.2f; + spacerect.y0 = 0; + spacerect.x1 = 0; + spacerect.y1 = 1; + spacerect = fz_transform_rect(trm, spacerect); + fz_add_text_char(ctx, dev, style, ' ', spacerect); + lastchar = ' '; } } @@ -331,8 +392,13 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat /* TODO: freetype returns broken vertical metrics */ /* if (text->wmode) mask |= FT_LOAD_VERTICAL_LAYOUT; */ + fz_lock(ctx, FZ_LOCK_FREETYPE); + err = FT_Set_Char_Size(font->ft_face, 64, 64, 72, 72); + if (err) + fz_warn(ctx, "freetype set character size: %s", ft_error_string(err)); FT_Get_Advance(font->ft_face, text->items[i].gid, mask, &ftadv); adv = ftadv / 65536.0f; + fz_unlock(ctx, FZ_LOCK_FREETYPE); rect.x0 = 0; rect.y0 = descender; @@ -352,9 +418,27 @@ fz_text_extract_span(fz_context *ctx, fz_text_span **last, fz_text *text, fz_mat pen->x = trm.e + dir.x * adv; pen->y = trm.f + dir.y * adv; - fz_add_text_char(ctx, last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); + /* Check for one glyph to many char mapping */ + for (j = i + 1; j < text->len; j++) + if (text->items[j].gid >= 0) + break; + multi = j - i; + + if (multi == 1) + { + fz_add_text_char(ctx, dev, style, text->items[i].ucs, rect); + } + else + { + for (j = 0; j < multi; j++) + { + fz_rect part = fz_split_bbox(rect, j, multi); + fz_add_text_char(ctx, dev, style, text->items[i].ucs, part); + } + } + + lastchar = text->items[i].ucs; } - fz_unlock(ctx, FZ_LOCK_FREETYPE); } static void @@ -362,7 +446,9 @@ fz_text_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { fz_text_device *tdev = dev->user; - fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); + fz_text_style *style; + style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, colorspace, color, alpha, NULL); + fz_text_extract(dev->ctx, tdev, text, ctm, style); } static void @@ -370,36 +456,57 @@ fz_text_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_m fz_colorspace *colorspace, float *color, float alpha) { fz_text_device *tdev = dev->user; - fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); + fz_text_style *style; + style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, colorspace, color, alpha, stroke); + fz_text_extract(dev->ctx, tdev, text, ctm, style); } static void fz_text_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { fz_text_device *tdev = dev->user; - fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); + fz_text_style *style; + style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, NULL); + fz_text_extract(dev->ctx, tdev, text, ctm, style); } static void fz_text_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) { fz_text_device *tdev = dev->user; - fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); + fz_text_style *style; + style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, stroke); + fz_text_extract(dev->ctx, tdev, text, ctm, style); } static void fz_text_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { fz_text_device *tdev = dev->user; - fz_text_extract_span(dev->ctx, &tdev->span, text, ctm, &tdev->point); + fz_text_style *style; + style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, NULL); + fz_text_extract(dev->ctx, tdev, text, ctm, style); +} + +static int cmp_block(const void *av, const void *bv) +{ + const fz_text_block *a = av; + const fz_text_block *b = bv; + int x = a->bbox.x0 - b->bbox.x0; + if (x) return x; + return -(a->bbox.y0 - b->bbox.y0); } static void fz_text_free_user(fz_device *dev) { + fz_context *ctx = dev->ctx; fz_text_device *tdev = dev->user; - tdev->span->eol = 1; + append_span(ctx, &tdev->cur_line, &tdev->cur_span); + insert_line(ctx, tdev->page, &tdev->cur_line); + + qsort(tdev->page->blocks, tdev->page->len, sizeof *tdev->page->blocks, cmp_block); /* TODO: unicode NFC normalization */ /* TODO: bidi logical reordering */ @@ -408,15 +515,19 @@ fz_text_free_user(fz_device *dev) } fz_device * -fz_new_text_device(fz_context *ctx, fz_text_span *root) +fz_new_text_device(fz_context *ctx, fz_text_sheet *sheet, fz_text_page *page) { fz_device *dev; + fz_text_device *tdev = fz_malloc_struct(ctx, fz_text_device); - tdev->head = root; - tdev->span = root; + tdev->sheet = sheet; + tdev->page = page; tdev->point.x = -1; tdev->point.y = -1; + init_line(ctx, &tdev->cur_line); + init_span(ctx, &tdev->cur_span, NULL); + dev = fz_new_device(ctx, tdev); dev->hints = FZ_IGNORE_IMAGE | FZ_IGNORE_SHADE; dev->free_user = fz_text_free_user; @@ -427,3 +538,209 @@ fz_new_text_device(fz_context *ctx, fz_text_span *root) dev->ignore_text = fz_text_ignore_text; return dev; } + +/* XML, HTML and plain-text output */ + +static int font_is_bold(fz_font *font) +{ + FT_Face face = font->ft_face; + if (face && (face->style_flags & FT_STYLE_FLAG_BOLD)) + return 1; + if (strstr(font->name, "Bold")) + return 1; + return 0; +} + +static int font_is_italic(fz_font *font) +{ + FT_Face face = font->ft_face; + if (face && (face->style_flags & FT_STYLE_FLAG_ITALIC)) + return 1; + if (strstr(font->name, "Italic") || strstr(font->name, "Oblique")) + return 1; + return 0; +} + +static void +fz_print_style_begin(FILE *out, fz_text_style *style) +{ + int script = style->script; + fprintf(out, "", style->id); + while (script-- > 0) + fprintf(out, ""); + while (++script < 0) + fprintf(out, ""); +} + +static void +fz_print_style_end(FILE *out, fz_text_style *style) +{ + int script = style->script; + while (script-- > 0) + fprintf(out, ""); + while (++script < 0) + fprintf(out, ""); + fprintf(out, ""); +} + +static void +fz_print_style(FILE *out, fz_text_style *style) +{ + char *s = strchr(style->font->name, '+'); + s = s ? s + 1 : style->font->name; + fprintf(out, "span.s%d{font-family:\"%s\";font-size:%gpt;", + style->id, s, style->size); + if (font_is_italic(style->font)) + fprintf(out, "font-style:italic;"); + if (font_is_bold(style->font)) + fprintf(out, "font-weight:bold;"); + fprintf(out, "}\n"); +} + +void +fz_print_text_sheet(FILE *out, fz_text_sheet *sheet) +{ + fz_text_style *style; + for (style = sheet->style; style; style = style->next) + fz_print_style(out, style); +} + +void +fz_print_text_page_html(FILE *out, fz_text_page *page) +{ + int block_n, line_n, span_n, ch_n; + fz_text_style *style = NULL; + fz_text_block *block; + fz_text_line *line; + fz_text_span *span; + + fprintf(out, "
\n"); + + for (block_n = 0; block_n < page->len; block_n++) + { + block = &page->blocks[block_n]; + fprintf(out, "
\n"); + for (line_n = 0; line_n < block->len; line_n++) + { + line = &block->lines[line_n]; + fprintf(out, "

"); + style = NULL; + + for (span_n = 0; span_n < line->len; span_n++) + { + span = &line->spans[span_n]; + if (style != span->style) + { + if (style != NULL) + fz_print_style_end(out, style); + fz_print_style_begin(out, span->style); + style = span->style; + } + + for (ch_n = 0; ch_n < span->len; ch_n++) + { + fz_text_char *ch = &span->text[ch_n]; + if (ch->c == '<') + fprintf(out, "<"); + else if (ch->c == '>') + fprintf(out, ">"); + else if (ch->c == '&') + fprintf(out, "&"); + else if (ch->c >= 32 && ch->c <= 127) + fprintf(out, "%c", ch->c); + else + fprintf(out, "&#x%x;", ch->c); + } + } + fz_print_style_end(out, style); + fprintf(out, "

\n"); + } + fprintf(out, "
\n"); + } + + fprintf(out, "
\n"); +} + +void +fz_print_text_page_xml(FILE *out, fz_text_page *page) +{ + fz_text_block *block; + fz_text_line *line; + fz_text_span *span; + fz_text_char *ch; + char *s; + + fprintf(out, "\n"); + for (block = page->blocks; block < page->blocks + page->len; block++) + { + fprintf(out, "\n", + block->bbox.x0, block->bbox.y0, block->bbox.x1, block->bbox.y1); + for (line = block->lines; line < block->lines + block->len; line++) + { + fprintf(out, "\n", + line->bbox.x0, line->bbox.y0, line->bbox.x1, line->bbox.y1); + for (span = line->spans; span < line->spans + line->len; span++) + { + fz_text_style *style = span->style; + s = strchr(style->font->name, '+'); + s = s ? s + 1 : style->font->name; + fprintf(out, "\n", + span->bbox.x0, span->bbox.y0, span->bbox.x1, span->bbox.y1, + s, style->size); + for (ch = span->text; ch < span->text + span->len; ch++) + { + fprintf(out, "bbox.x0, ch->bbox.y0, ch->bbox.x1, ch->bbox.y1); + switch (ch->c) + { + case '<': fprintf(out, "<"); break; + case '>': fprintf(out, ">"); break; + case '&': fprintf(out, "&"); break; + case '"': fprintf(out, """); break; + case '\'': fprintf(out, "'"); break; + default: + if (ch->c >= 32 && ch->c <= 127) + fprintf(out, "%c", ch->c); + else + fprintf(out, "&#x%x;", ch->c); + break; + } + fprintf(out, "\"/>\n"); + } + fprintf(out, "\n"); + } + fprintf(out, "\n"); + } + fprintf(out, "\n"); + } + fprintf(out, "\n"); +} + +void +fz_print_text_page(FILE *out, fz_text_page *page) +{ + fz_text_block *block; + fz_text_line *line; + fz_text_span *span; + fz_text_char *ch; + char utf[10]; + int i, n; + + for (block = page->blocks; block < page->blocks + page->len; block++) + { + for (line = block->lines; line < block->lines + block->len; line++) + { + for (span = line->spans; span < line->spans + line->len; span++) + { + for (ch = span->text; ch < span->text + span->len; ch++) + { + n = fz_runetochar(utf, ch->c); + for (i = 0; i < n; i++) + putc(utf[i], out); + } + } + fprintf(out, "\n"); + } + fprintf(out, "\n"); + } +} diff --git a/fitz/fitz.h b/fitz/fitz.h index c01de8ac..8570f077 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1424,46 +1424,102 @@ fz_device *fz_new_bbox_device(fz_context *ctx, fz_bbox *bboxp); fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); /* - Text extraction device -*/ -typedef struct fz_text_span_s fz_text_span; + * Text extraction device + */ + +typedef struct fz_text_style_s fz_text_style; typedef struct fz_text_char_s fz_text_char; +typedef struct fz_text_span_s fz_text_span; +typedef struct fz_text_line_s fz_text_line; +typedef struct fz_text_block_s fz_text_block; + +typedef struct fz_text_sheet_s fz_text_sheet; +typedef struct fz_text_page_s fz_text_page; + +struct fz_text_style_s +{ + int id; + fz_font *font; + float size; + int wmode; + int script; + /* etc... */ + fz_text_style *next; +}; + +struct fz_text_sheet_s +{ + int maxid; + fz_text_style *style; +}; struct fz_text_char_s { + fz_rect bbox; int c; - fz_bbox bbox; }; struct fz_text_span_s { - fz_font *font; - float size; - int wmode; + fz_rect bbox; int len, cap; fz_text_char *text; - fz_text_span *next; - int eol; + fz_text_style *style; +}; + +struct fz_text_line_s +{ + fz_rect bbox; + int len, cap; + fz_text_span *spans; +}; + +struct fz_text_block_s +{ + fz_rect bbox; + int len, cap; + fz_text_line *lines; }; -fz_text_span *fz_new_text_span(fz_context *ctx); -void fz_free_text_span(fz_context *ctx, fz_text_span *line); -void fz_debug_text_span(fz_text_span *line); -void fz_debug_text_span_xml(fz_text_span *span); +struct fz_text_page_s +{ + fz_rect mediabox; + int len, cap; + fz_text_block *blocks; +}; /* - fz_new_text_device: Create a device to print the text on a - page in XML. + fz_new_text_device: Create a device to extract the text on a page. - The text on a page will be translated into a sequnce of XML - elements. For each text span the font, font size, writing mode - and end of line flag is printed. Since text can be placed at - arbitrary positions then heuristics must be used to try to - collect text spans together that are roughly located on the - same baseline. Each character in the text span will have its - UTF-8 character printed along with a bounding box containing it. + Gather and sort the text on a page into spans of uniform style, + arranged into lines and blocks by reading order. The reading order + is determined by various heuristics, so may not be accurate. */ -fz_device *fz_new_text_device(fz_context *ctx, fz_text_span *text); +fz_device *fz_new_text_device(fz_context *ctx, fz_text_sheet *sheet, fz_text_page *page); + +/* + fz_new_text_sheet: Create an empty style sheet. + + The style sheet is filled out by the text device, creating + one style for each unique font, color, size combination that + is used. +*/ +fz_text_sheet *fz_new_text_sheet(fz_context *ctx); +void fz_free_text_sheet(fz_context *ctx, fz_text_sheet *sheet); + +/* + fz_new_text_page: Create an empty text page. + + The text page is filled out by the text device to contain the blocks, + lines and spans of text on the page. +*/ +fz_text_page *fz_new_text_page(fz_context *ctx, fz_rect mediabox); +void fz_free_text_page(fz_context *ctx, fz_text_page *page); + +void fz_print_text_sheet(FILE *out, fz_text_sheet *sheet); +void fz_print_text_page_html(FILE *out, fz_text_page *page); +void fz_print_text_page_xml(FILE *out, fz_text_page *page); +void fz_print_text_page(FILE *out, fz_text_page *page); /* * Cookie support - simple communication channel between app/library. -- cgit v1.2.3 From 9cbfb766564d0e80d259e3e0a919d72a75bbb6ee Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 13 Mar 2012 12:40:09 +0100 Subject: Split XPS header. Update Makefile dependencies. Add pixmap w/h accessors. --- fitz/fitz.h | 10 ++++++++++ fitz/res_pixmap.c | 12 ++++++++++++ 2 files changed, 22 insertions(+) (limited to 'fitz') diff --git a/fitz/fitz.h b/fitz/fitz.h index 8570f077..85e1feea 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1125,6 +1125,16 @@ typedef struct fz_pixmap_s fz_pixmap; */ fz_bbox fz_bound_pixmap(fz_pixmap *pix); +/* + fz_pixmap_width: Return the width of the pixmap in pixels. +*/ +int fz_pixmap_width(fz_context *ctx, fz_pixmap *pix); + +/* + fz_pixmap_height: Return the height of the pixmap in pixels. +*/ +int fz_pixmap_height(fz_context *ctx, fz_pixmap *pix); + /* fz_new_pixmap: Create a new pixmap, with it's origin at (0,0) diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index fc40135e..7aaf8ce0 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -110,6 +110,18 @@ fz_bound_pixmap(fz_pixmap *pix) return bbox; } +int +fz_pixmap_width(fz_context *ctx, fz_pixmap *pix) +{ + return pix->w; +} + +int +fz_pixmap_height(fz_context *ctx, fz_pixmap *pix) +{ + return pix->h; +} + void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix) { -- cgit v1.2.3 From 48652e529ed1c0ae23cfd45f14d9655ad2849c89 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 13 Mar 2012 13:57:11 +0100 Subject: Rename some functions and accessors to be more consistent. Debug printing functions: debug -> print. Accessors: get noun attribute -> noun attribute. Find -> lookup when the returned value is not reference counted. pixmap_with_rect -> pixmap_with_bbox. We are reserving the word "find" to mean lookups that give ownership of objects to the caller. Lookup is used in other places where the ownership is not transferred, or simple values are returned. The rename is done by the sed script in scripts/rename3.sed --- fitz/base_hash.c | 2 +- fitz/dev_text.c | 20 ++++++++++---------- fitz/dev_trace.c | 10 +++++----- fitz/doc_outline.c | 4 ++-- fitz/fitz-internal.h | 22 +++++++++++----------- fitz/fitz.h | 24 ++++++++++++------------ fitz/image_save.c | 4 ++-- fitz/res_bitmap.c | 2 +- fitz/res_font.c | 8 ++++---- fitz/res_halftone.c | 4 ++-- fitz/res_path.c | 2 +- fitz/res_pixmap.c | 6 +++--- fitz/res_shade.c | 2 +- fitz/res_store.c | 8 ++++---- fitz/res_text.c | 2 +- 15 files changed, 60 insertions(+), 60 deletions(-) (limited to 'fitz') diff --git a/fitz/base_hash.c b/fitz/base_hash.c index 59ed8872..bf56b9bc 100644 --- a/fitz/base_hash.c +++ b/fitz/base_hash.c @@ -268,7 +268,7 @@ fz_hash_remove(fz_context *ctx, fz_hash_table *table, void *key) } void -fz_debug_hash(fz_context *ctx, fz_hash_table *table) +fz_print_hash(fz_context *ctx, fz_hash_table *table) { int i, k; diff --git a/fitz/dev_text.c b/fitz/dev_text.c index 7a56b56c..b92372a1 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -42,7 +42,7 @@ fz_free_text_sheet(fz_context *ctx, fz_text_sheet *sheet) } static fz_text_style * -fz_find_text_style_imp(fz_context *ctx, fz_text_sheet *sheet, +fz_lookup_text_style_imp(fz_context *ctx, fz_text_sheet *sheet, float size, fz_font *font, int wmode, int script) { fz_text_style *style; @@ -71,7 +71,7 @@ fz_find_text_style_imp(fz_context *ctx, fz_text_sheet *sheet, } static fz_text_style * -fz_find_text_style(fz_context *ctx, fz_text_sheet *sheet, fz_text *text, fz_matrix *ctm, +fz_lookup_text_style(fz_context *ctx, fz_text_sheet *sheet, fz_text *text, fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha, fz_stroke_state *stroke) { float size = 1.0f; @@ -86,7 +86,7 @@ fz_find_text_style(fz_context *ctx, fz_text_sheet *sheet, fz_text *text, fz_matr trm = fz_concat(tm, *ctm); size = fz_matrix_expansion(trm); } - return fz_find_text_style_imp(ctx, sheet, size, font, wmode, 0); + return fz_lookup_text_style_imp(ctx, sheet, size, font, wmode, 0); } fz_text_page * @@ -178,7 +178,7 @@ append_line(fz_context *ctx, fz_text_block *block, fz_text_line *line) } static fz_text_block * -find_block_for_line(fz_context *ctx, fz_text_page *page, fz_text_line *line) +lookup_block_for_line(fz_context *ctx, fz_text_page *page, fz_text_line *line) { float size = line->len > 0 && line->spans[0].len > 0 ? line->spans[0].style->size : 1; int i; @@ -210,7 +210,7 @@ find_block_for_line(fz_context *ctx, fz_text_page *page, fz_text_line *line) static void insert_line(fz_context *ctx, fz_text_page *page, fz_text_line *line) { - append_line(ctx, find_block_for_line(ctx, page, line), line); + append_line(ctx, lookup_block_for_line(ctx, page, line), line); } static fz_rect @@ -447,7 +447,7 @@ fz_text_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, { fz_text_device *tdev = dev->user; fz_text_style *style; - style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, colorspace, color, alpha, NULL); + style = fz_lookup_text_style(dev->ctx, tdev->sheet, text, &ctm, colorspace, color, alpha, NULL); fz_text_extract(dev->ctx, tdev, text, ctm, style); } @@ -457,7 +457,7 @@ fz_text_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_m { fz_text_device *tdev = dev->user; fz_text_style *style; - style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, colorspace, color, alpha, stroke); + style = fz_lookup_text_style(dev->ctx, tdev->sheet, text, &ctm, colorspace, color, alpha, stroke); fz_text_extract(dev->ctx, tdev, text, ctm, style); } @@ -466,7 +466,7 @@ fz_text_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) { fz_text_device *tdev = dev->user; fz_text_style *style; - style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, NULL); + style = fz_lookup_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, NULL); fz_text_extract(dev->ctx, tdev, text, ctm, style); } @@ -475,7 +475,7 @@ fz_text_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, { fz_text_device *tdev = dev->user; fz_text_style *style; - style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, stroke); + style = fz_lookup_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, stroke); fz_text_extract(dev->ctx, tdev, text, ctm, style); } @@ -484,7 +484,7 @@ fz_text_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) { fz_text_device *tdev = dev->user; fz_text_style *style; - style = fz_find_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, NULL); + style = fz_lookup_text_style(dev->ctx, tdev->sheet, text, &ctm, NULL, NULL, 0, NULL); fz_text_extract(dev->ctx, tdev, text, ctm, style); } diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index f75f19d5..33406130 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -145,7 +145,7 @@ fz_trace_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_debug_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, text, 0); printf("\n"); } @@ -158,7 +158,7 @@ fz_trace_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_ fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_debug_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, text, 0); printf("\n"); } @@ -170,7 +170,7 @@ fz_trace_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_debug_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, text, 0); printf("\n"); } @@ -181,7 +181,7 @@ fz_trace_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_debug_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, text, 0); printf("\n"); } @@ -192,7 +192,7 @@ fz_trace_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_debug_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, text, 0); printf("\n"); } diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c index 4847b919..023abd23 100644 --- a/fitz/doc_outline.c +++ b/fitz/doc_outline.c @@ -35,7 +35,7 @@ do_debug_outline_xml(fz_outline *outline, int level) } void -fz_debug_outline_xml(fz_context *ctx, fz_outline *outline) +fz_print_outline_xml(fz_context *ctx, fz_outline *outline) { do_debug_outline_xml(outline, 0); } @@ -56,7 +56,7 @@ do_debug_outline(fz_outline *outline, int level) } void -fz_debug_outline(fz_context *ctx, fz_outline *outline) +fz_print_outline(fz_context *ctx, fz_outline *outline) { do_debug_outline(outline, 0); } diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 16b65ccd..6d4b292b 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -87,7 +87,7 @@ float fz_atof(const char *s); 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_debug_hash(fz_context *ctx, fz_hash_table *table); +void fz_print_hash(fz_context *ctx, fz_hash_table *table); void fz_empty_hash(fz_context *ctx, fz_hash_table *table); void fz_free_hash(fz_context *ctx, fz_hash_table *table); @@ -308,9 +308,9 @@ void fz_drop_store_context(fz_context *ctx); fz_store *fz_keep_store_context(fz_context *ctx); /* - fz_debug_store: Dump the contents of the store for debugging. + fz_print_store: Dump the contents of the store for debugging. */ -void fz_debug_store(fz_context *ctx); +void fz_print_store(fz_context *ctx); /* fz_store_item: Add an item to the store. @@ -558,7 +558,7 @@ fz_stream *fz_open_jbig2d(fz_stream *chain, fz_buffer *global); enum { FZ_MAX_COLORS = 32 }; -int fz_find_blendmode(char *name); +int fz_lookup_blendmode(char *name); char *fz_blendmode_name(int blendmode); struct fz_bitmap_s @@ -603,7 +603,7 @@ void fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit); 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_rect_and_data. + 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. */ @@ -620,7 +620,7 @@ struct fz_pixmap_s fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples); -fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); +fz_pixmap *fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox, unsigned char *samples); void fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix); @@ -654,7 +654,7 @@ struct fz_halftone_s }; fz_halftone *fz_new_halftone(fz_context *ctx, int num_comps); -fz_halftone *fz_get_default_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); @@ -734,7 +734,7 @@ fz_font *fz_new_font_from_file(fz_context *ctx, char *path, int index, int use_g fz_font *fz_keep_font(fz_context *ctx, fz_font *font); void fz_drop_font(fz_context *ctx, fz_font *font); -void fz_debug_font(fz_context *ctx, fz_font *font); +void fz_print_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, fz_matrix trm); @@ -816,7 +816,7 @@ void fz_transform_path(fz_context *ctx, fz_path *path, 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, fz_stroke_state *stroke, fz_matrix ctm); -void fz_debug_path(fz_context *ctx, fz_path *, int indent); +void fz_print_path(fz_context *ctx, fz_path *, int indent); /* * Glyph cache @@ -870,7 +870,7 @@ void fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, floa void fz_free_text(fz_context *ctx, fz_text *text); fz_rect fz_bound_text(fz_context *ctx, fz_text *text, fz_matrix ctm); fz_text *fz_clone_text(fz_context *ctx, fz_text *old); -void fz_debug_text(fz_context *ctx, fz_text*, int indent); +void fz_print_text(fz_context *ctx, fz_text*, int indent); /* * The shading code uses gouraud shaded triangle meshes. @@ -910,7 +910,7 @@ struct fz_shade_s 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); -void fz_debug_shade(fz_context *ctx, fz_shade *shade); +void fz_print_shade(fz_context *ctx, fz_shade *shade); fz_rect fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm); void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); diff --git a/fitz/fitz.h b/fitz/fitz.h index 85e1feea..33379df7 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -274,10 +274,10 @@ fz_context *fz_clone_context(fz_context *ctx); void fz_free_context(fz_context *ctx); /* - fz_get_aa_level: Get the number of bits of antialiasing we are + fz_aa_level: Get the number of bits of antialiasing we are using. Between 0 and 8. */ -int fz_get_aa_level(fz_context *ctx); +int fz_aa_level(fz_context *ctx); /* fz_set_aa_level: Set the number of bits of antialiasing we should use. @@ -1151,7 +1151,7 @@ int fz_pixmap_height(fz_context *ctx, fz_pixmap *pix); fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h); /* - fz_new_pixmap_with_rect: Create a pixmap of a given size, + fz_new_pixmap_with_bbox: Create a pixmap of a given size, location and pixel format. The bounding box specifies the size of the created pixmap and @@ -1164,7 +1164,7 @@ fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h); bbox: Bounding box specifying location/size of created pixmap. */ -fz_pixmap *fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox); +fz_pixmap *fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_bbox bbox); /* fz_keep_pixmap: Take a reference to a pixmap. @@ -1200,11 +1200,11 @@ fz_colorspace *fz_pixmap_colorspace(fz_context *ctx, fz_pixmap *pix); int fz_pixmap_components(fz_context *ctx, fz_pixmap *pix); /* - fz_pixmap_pixels: Returns a pointer to the pixel data of a pixmap. + fz_pixmap_samples: Returns a pointer to the pixel data of a pixmap. Returns the pointer. Does not throw exceptions. */ -unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix); +unsigned char *fz_pixmap_samples(fz_context *ctx, fz_pixmap *pix); /* fz_clear_pixmap_with_value: Clears a pixmap with the given value. @@ -1275,7 +1275,7 @@ void fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix); void fz_convert_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src); /* - fz_save_pixmap: Save a pixmap out. + fz_write_pixmap: Save a pixmap out. name: The prefix for the name of the pixmap. The pixmap will be saved as "name.png" if the pixmap is RGB or Greyscale, "name.pam" otherwise. @@ -1283,7 +1283,7 @@ void fz_convert_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src); rgb: If non zero, the pixmap is converted to rgb (if possible) before saving. */ -void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *name, int rgb); +void fz_write_pixmap(fz_context *ctx, fz_pixmap *img, char *name, int rgb); /* fz_write_pnm: Save a pixmap as a pnm @@ -1815,15 +1815,15 @@ struct fz_outline_s }; /* - fz_debug_outline_xml: Dump the given outlines to stdout as (pseudo) + fz_print_outline_xml: Dump the given outlines to stdout as (pseudo) XML. */ -void fz_debug_outline_xml(fz_context *ctx, fz_outline *outline); +void fz_print_outline_xml(fz_context *ctx, fz_outline *outline); /* - fz_debug_outline: Dump the given outlines to stdout as text. + fz_print_outline: Dump the given outlines to stdout as text. */ -void fz_debug_outline(fz_context *ctx, fz_outline *outline); +void fz_print_outline(fz_context *ctx, fz_outline *outline); /* fz_free_outline: Free hierarchical outline. diff --git a/fitz/image_save.c b/fitz/image_save.c index 29d3e8fc..614d18ce 100644 --- a/fitz/image_save.c +++ b/fitz/image_save.c @@ -1,6 +1,6 @@ #include "fitz-internal.h" -void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *file, int rgb) +void fz_write_pixmap(fz_context *ctx, fz_pixmap *img, char *file, int rgb) { char name[1024]; fz_pixmap *converted = NULL; @@ -10,7 +10,7 @@ void fz_save_pixmap(fz_context *ctx, fz_pixmap *img, char *file, int rgb) if (rgb && img->colorspace && img->colorspace != fz_device_rgb) { - converted = fz_new_pixmap_with_rect(ctx, fz_device_rgb, fz_bound_pixmap(img)); + converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, fz_bound_pixmap(img)); fz_convert_pixmap(ctx, converted, img); img = converted; } diff --git a/fitz/res_bitmap.c b/fitz/res_bitmap.c index 25e88187..1bd2827d 100644 --- a/fitz/res_bitmap.c +++ b/fitz/res_bitmap.c @@ -89,7 +89,7 @@ int fz_pixmap_components(fz_context *ctx, fz_pixmap *pix) return pix->n; } -unsigned char *fz_pixmap_pixels(fz_context *ctx, fz_pixmap *pix) +unsigned char *fz_pixmap_samples(fz_context *ctx, fz_pixmap *pix) { if (!pix) return NULL; diff --git a/fitz/res_font.c b/fitz/res_font.c index dd4e68da..438d5ba7 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -471,7 +471,7 @@ fz_render_ft_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, int a FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32); } - fterr = FT_Render_Glyph(face->glyph, fz_get_aa_level(ctx) > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); + fterr = FT_Render_Glyph(face->glyph, fz_aa_level(ctx) > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); if (fterr) { fz_warn(ctx, "freetype render glyph (gid %d): %s", gid, ft_error_string(fterr)); @@ -575,7 +575,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr FT_Stroker_Done(stroker); - fterr = FT_Glyph_To_Bitmap(&glyph, fz_get_aa_level(ctx) > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); + fterr = FT_Glyph_To_Bitmap(&glyph, fz_aa_level(ctx) > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); if (fterr) { fz_warn(ctx, "FT_Glyph_To_Bitmap: %s", ft_error_string(fterr)); @@ -756,7 +756,7 @@ fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_co bbox.x1++; bbox.y1++; - glyph = fz_new_pixmap_with_rect(ctx, model ? model : fz_device_gray, bbox); + glyph = fz_new_pixmap_with_bbox(ctx, model ? model : fz_device_gray, bbox); fz_clear_pixmap(ctx, glyph); ctm = fz_concat(font->t3matrix, trm); @@ -808,7 +808,7 @@ fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gi } void -fz_debug_font(fz_context *ctx, fz_font *font) +fz_print_font(fz_context *ctx, fz_font *font) { printf("font '%s' {\n", font->name); diff --git a/fitz/res_halftone.c b/fitz/res_halftone.c index ec26571e..daad6e37 100644 --- a/fitz/res_halftone.c +++ b/fitz/res_halftone.c @@ -56,7 +56,7 @@ static unsigned char mono_ht[] = 0xF2, 0x72, 0xD2, 0x52, 0xFA, 0x7A, 0xDA, 0x5A, 0xF0, 0x70, 0xD0, 0x50, 0xF8, 0x78, 0xD8, 0x58 }; -fz_halftone *fz_get_default_halftone(fz_context *ctx, int num_comps) +fz_halftone *fz_default_halftone(fz_context *ctx, int num_comps) { fz_halftone *ht = fz_new_halftone(ctx, num_comps); assert(num_comps == 1); /* Only support 1 component for now */ @@ -172,7 +172,7 @@ fz_bitmap *fz_halftone_pixmap(fz_context *ctx, fz_pixmap *pix, fz_halftone *ht) n = pix->n-1; /* Remove alpha */ if (ht == NULL) { - ht = fz_get_default_halftone(ctx, n); + ht = fz_default_halftone(ctx, n); } ht_line = fz_malloc(ctx, pix->w * n); out = fz_new_bitmap(ctx, pix->w, pix->h, n); diff --git a/fitz/res_path.c b/fitz/res_path.c index 4964a09e..9c2072c1 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -316,7 +316,7 @@ fz_transform_path(fz_context *ctx, fz_path *path, fz_matrix ctm) } void -fz_debug_path(fz_context *ctx, fz_path *path, int indent) +fz_print_path(fz_context *ctx, fz_path *path, int indent) { float x, y; int i = 0; diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index 7aaf8ce0..11875ad1 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -80,7 +80,7 @@ fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h) } fz_pixmap * -fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r) +fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r) { fz_pixmap *pixmap; pixmap = fz_new_pixmap(ctx, colorspace, r.x1 - r.x0, r.y1 - r.y0); @@ -90,7 +90,7 @@ fz_new_pixmap_with_rect(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r) } fz_pixmap * -fz_new_pixmap_with_rect_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r, unsigned char *samples) +fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_bbox r, unsigned char *samples) { fz_pixmap *pixmap; pixmap = fz_new_pixmap_with_data(ctx, colorspace, r.x1 - r.x0, r.y1 - r.y0, samples); @@ -261,7 +261,7 @@ fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity) assert(gray->n == 2); - alpha = fz_new_pixmap_with_rect(ctx, NULL, fz_bound_pixmap(gray)); + alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_bound_pixmap(gray)); dp = alpha->samples; sp = gray->samples; if (!luminosity) diff --git a/fitz/res_shade.c b/fitz/res_shade.c index f8f11a81..59e3887e 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -68,7 +68,7 @@ fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm) } void -fz_debug_shade(fz_context *ctx, fz_shade *shade) +fz_print_shade(fz_context *ctx, fz_shade *shade) { int i, j, n; float *vertex; diff --git a/fitz/res_store.c b/fitz/res_store.c index e85aead9..1de4f240 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -453,7 +453,7 @@ fz_drop_store_context(fz_context *ctx) } void -fz_debug_store(fz_context *ctx) +fz_print_store(fz_context *ctx) { fz_item *item, *next; fz_store *store = ctx->store; @@ -521,7 +521,7 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) #ifdef DEBUG_SCAVENGING printf("Scavenging: store=%d size=%d phase=%d\n", store->size, size, *phase); - fz_debug_store(ctx); + fz_print_store(ctx); Memento_stats(); #endif do @@ -549,7 +549,7 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) { #ifdef DEBUG_SCAVENGING printf("scavenged: store=%d\n", store->size); - fz_debug_store(ctx); + fz_print_store(ctx); Memento_stats(); #endif return 1; @@ -559,7 +559,7 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) #ifdef DEBUG_SCAVENGING printf("scavenging failed\n"); - fz_debug_store(ctx); + fz_print_store(ctx); Memento_listBlocks(); #endif return 0; diff --git a/fitz/res_text.c b/fitz/res_text.c index 433ff8f9..43b4471a 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -123,7 +123,7 @@ static int isxmlmeta(int c) return c < 32 || c >= 128 || c == '&' || c == '<' || c == '>' || c == '\'' || c == '"'; } -void fz_debug_text(fz_context *ctx, fz_text *text, int indent) +void fz_print_text(fz_context *ctx, fz_text *text, int indent) { int i, n; for (i = 0; i < text->len; i++) -- cgit v1.2.3 From 7eca6b0d05443e85ecd7bb107dccf410696364aa Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 13 Mar 2012 13:36:39 +0100 Subject: Add ctx argument and rename fz_bound_pixmap to fz_pixmap_bbox. --- fitz/fitz-internal.h | 2 ++ fitz/fitz.h | 6 +++--- fitz/image_save.c | 2 +- fitz/res_colorspace.c | 2 +- fitz/res_pixmap.c | 21 ++++++++++++++++----- 5 files changed, 23 insertions(+), 10 deletions(-) (limited to 'fitz') diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 6d4b292b..2e9508a6 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -632,6 +632,8 @@ 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_bbox *clip); +fz_bbox fz_pixmap_bbox_no_ctx(fz_pixmap *src); + struct fz_image_s { fz_storable storable; diff --git a/fitz/fitz.h b/fitz/fitz.h index 33379df7..964bd7f7 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1084,7 +1084,7 @@ typedef struct fz_colorspace_s fz_colorspace; fz_find_device_colorspace: Find a standard colorspace based upon it's name. */ -fz_colorspace *fz_find_device_colorspace(char *name); +fz_colorspace *fz_find_device_colorspace(fz_context *ctx, char *name); /* fz_device_gray: Abstract colorspace representing device specific @@ -1119,11 +1119,11 @@ extern fz_colorspace *fz_device_cmyk; typedef struct fz_pixmap_s fz_pixmap; /* - fz_bound_pixmap: Return a bounding box for a pixmap. + fz_pixmap_bbox: Return a bounding box for a pixmap. Returns an exact bounding box for the supplied pixmap. */ -fz_bbox fz_bound_pixmap(fz_pixmap *pix); +fz_bbox fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix); /* fz_pixmap_width: Return the width of the pixmap in pixels. diff --git a/fitz/image_save.c b/fitz/image_save.c index 614d18ce..95be1cd3 100644 --- a/fitz/image_save.c +++ b/fitz/image_save.c @@ -10,7 +10,7 @@ void fz_write_pixmap(fz_context *ctx, fz_pixmap *img, char *file, int rgb) if (rgb && img->colorspace && img->colorspace != fz_device_rgb) { - converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, fz_bound_pixmap(img)); + converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb, fz_pixmap_bbox(ctx, img)); fz_convert_pixmap(ctx, converted, img); img = converted; } diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c index 03d5967b..587db381 100644 --- a/fitz/res_colorspace.c +++ b/fitz/res_colorspace.c @@ -164,7 +164,7 @@ fz_colorspace *fz_device_bgr = &k_device_bgr; fz_colorspace *fz_device_cmyk = &k_device_cmyk; fz_colorspace * -fz_find_device_colorspace(char *name) +fz_find_device_colorspace(fz_context *ctx, char *name) { if (!strcmp(name, "DeviceGray")) return fz_device_gray; diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c index 11875ad1..a160b6ca 100644 --- a/fitz/res_pixmap.c +++ b/fitz/res_pixmap.c @@ -100,7 +100,18 @@ fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, fz_ } fz_bbox -fz_bound_pixmap(fz_pixmap *pix) +fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix) +{ + fz_bbox bbox; + bbox.x0 = pix->x; + bbox.y0 = pix->y; + bbox.x1 = pix->x + pix->w; + bbox.y1 = pix->y + pix->h; + return bbox; +} + +fz_bbox +fz_pixmap_bbox_no_ctx(fz_pixmap *pix) { fz_bbox bbox; bbox.x0 = pix->x; @@ -156,8 +167,8 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, fz_bbox r) unsigned char *destp; int y, w, destspan, srcspan; - r = fz_intersect_bbox(r, fz_bound_pixmap(dest)); - r = fz_intersect_bbox(r, fz_bound_pixmap(src)); + r = fz_intersect_bbox(r, fz_pixmap_bbox(ctx, dest)); + r = fz_intersect_bbox(r, fz_pixmap_bbox(ctx, src)); w = r.x1 - r.x0; y = r.y1 - r.y0; if (w <= 0 || y <= 0) @@ -183,7 +194,7 @@ fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, fz_ unsigned char *destp; int x, y, w, k, destspan; - r = fz_intersect_bbox(r, fz_bound_pixmap(dest)); + r = fz_intersect_bbox(r, fz_pixmap_bbox(ctx, dest)); w = r.x1 - r.x0; y = r.y1 - r.y0; if (w <= 0 || y <= 0) @@ -261,7 +272,7 @@ fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity) assert(gray->n == 2); - alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_bound_pixmap(gray)); + alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray)); dp = alpha->samples; sp = gray->samples; if (!luminosity) -- cgit v1.2.3 From 7fa60e876f733f3bd90787145d9a7eb0eb91e9a2 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Tue, 13 Mar 2012 15:10:18 +0000 Subject: Fix building on windows. Fix a couple of silly problems (one gccism, and one windows specific bug). --- fitz/dev_text.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fitz') diff --git a/fitz/dev_text.c b/fitz/dev_text.c index b92372a1..bb6aaac9 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -303,6 +303,7 @@ fz_text_extract(fz_context *ctx, fz_text_device *dev, fz_text *text, fz_matrix c float descender = 0; int multi; int i, j, err; + int lastchar = ' '; if (text->len == 0) return; @@ -342,8 +343,6 @@ fz_text_extract(fz_context *ctx, fz_text_device *dev, fz_text *text, fz_matrix c size = fz_matrix_expansion(trm); - int lastchar = ' '; - for (i = 0; i < text->len; i++) { /* Calculate new pen location and delta */ -- cgit v1.2.3 From 7888b56b928707329a84a61eca8f8e75ef6a745a Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Tue, 13 Mar 2012 15:11:32 +0000 Subject: Make fz_print functions all take a FILE *. Also tidy up the taking of fz_context *'s, and hide an unwanted indent param. --- fitz/base_hash.c | 12 ++++++------ fitz/dev_text.c | 8 ++++---- fitz/dev_trace.c | 10 +++++----- fitz/doc_outline.c | 28 ++++++++++++++-------------- fitz/fitz-internal.h | 12 ++++++------ fitz/fitz.h | 35 +++++++++++++++++++++++------------ fitz/res_font.c | 14 +++++++------- fitz/res_path.c | 16 ++++++++-------- fitz/res_shade.c | 34 +++++++++++++++++----------------- fitz/res_store.c | 14 +++++++------- fitz/res_text.c | 17 ++++++++++++----- 11 files changed, 109 insertions(+), 91 deletions(-) (limited to 'fitz') diff --git a/fitz/base_hash.c b/fitz/base_hash.c index bf56b9bc..4ba02f4d 100644 --- a/fitz/base_hash.c +++ b/fitz/base_hash.c @@ -268,22 +268,22 @@ fz_hash_remove(fz_context *ctx, fz_hash_table *table, void *key) } void -fz_print_hash(fz_context *ctx, fz_hash_table *table) +fz_print_hash(fz_context *ctx, FILE *out, fz_hash_table *table) { int i, k; - printf("cache load %d / %d\n", table->load, table->size); + fprintf(out, "cache load %d / %d\n", table->load, table->size); for (i = 0; i < table->size; i++) { if (!table->ents[i].val) - printf("table % 4d: empty\n", i); + fprintf(out, "table % 4d: empty\n", i); else { - printf("table % 4d: key=", i); + fprintf(out, "table % 4d: key=", i); for (k = 0; k < MAX_KEY_LEN; k++) - printf("%02x", ((char*)table->ents[i].key)[k]); - printf(" val=$%p\n", table->ents[i].val); + fprintf(out, "%02x", ((char*)table->ents[i].key)[k]); + fprintf(out, " val=$%p\n", table->ents[i].val); } } } diff --git a/fitz/dev_text.c b/fitz/dev_text.c index bb6aaac9..7a059e5a 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -597,7 +597,7 @@ fz_print_style(FILE *out, fz_text_style *style) } void -fz_print_text_sheet(FILE *out, fz_text_sheet *sheet) +fz_print_text_sheet(fz_context *ctx, FILE *out, fz_text_sheet *sheet) { fz_text_style *style; for (style = sheet->style; style; style = style->next) @@ -605,7 +605,7 @@ fz_print_text_sheet(FILE *out, fz_text_sheet *sheet) } void -fz_print_text_page_html(FILE *out, fz_text_page *page) +fz_print_text_page_html(fz_context *ctx, FILE *out, fz_text_page *page) { int block_n, line_n, span_n, ch_n; fz_text_style *style = NULL; @@ -661,7 +661,7 @@ fz_print_text_page_html(FILE *out, fz_text_page *page) } void -fz_print_text_page_xml(FILE *out, fz_text_page *page) +fz_print_text_page_xml(fz_context *ctx, FILE *out, fz_text_page *page) { fz_text_block *block; fz_text_line *line; @@ -716,7 +716,7 @@ fz_print_text_page_xml(FILE *out, fz_text_page *page) } void -fz_print_text_page(FILE *out, fz_text_page *page) +fz_print_text_page(fz_context *ctx, FILE *out, fz_text_page *page) { fz_text_block *block; fz_text_line *line; diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index 33406130..b3c73ff2 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -145,7 +145,7 @@ fz_trace_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_print_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, stdout, text); printf("\n"); } @@ -158,7 +158,7 @@ fz_trace_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_ fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_print_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, stdout, text); printf("\n"); } @@ -170,7 +170,7 @@ fz_trace_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_print_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, stdout, text); printf("\n"); } @@ -181,7 +181,7 @@ fz_trace_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_print_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, stdout, text); printf("\n"); } @@ -192,7 +192,7 @@ fz_trace_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) fz_trace_matrix(ctm); fz_trace_trm(text->trm); printf(">\n"); - fz_print_text(dev->ctx, text, 0); + fz_print_text(dev->ctx, stdout, text); printf("\n"); } diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c index 023abd23..71694851 100644 --- a/fitz/doc_outline.c +++ b/fitz/doc_outline.c @@ -15,48 +15,48 @@ fz_free_outline(fz_context *ctx, fz_outline *outline) } static void -do_debug_outline_xml(fz_outline *outline, int level) +do_debug_outline_xml(FILE *out, fz_outline *outline, int level) { while (outline) { - printf("title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); + fprintf(out, "title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); if (outline->down) { - printf(">\n"); - do_debug_outline_xml(outline->down, level + 1); - printf("\n"); + fprintf(out, ">\n"); + do_debug_outline_xml(out, outline->down, level + 1); + fprintf(out, "\n"); } else { - printf(" />\n"); + fprintf(out, " />\n"); } outline = outline->next; } } void -fz_print_outline_xml(fz_context *ctx, fz_outline *outline) +fz_print_outline_xml(fz_context *ctx, FILE *out, fz_outline *outline) { - do_debug_outline_xml(outline, 0); + do_debug_outline_xml(out, outline, 0); } static void -do_debug_outline(fz_outline *outline, int level) +do_debug_outline(FILE *out, fz_outline *outline, int level) { int i; while (outline) { for (i = 0; i < level; i++) - putchar('\t'); - printf("%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); + fputc('\t', out); + fprintf(out, "%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0); if (outline->down) - do_debug_outline(outline->down, level + 1); + do_debug_outline(out, outline->down, level + 1); outline = outline->next; } } void -fz_print_outline(fz_context *ctx, fz_outline *outline) +fz_print_outline(fz_context *ctx, FILE *out, fz_outline *outline) { - do_debug_outline(outline, 0); + do_debug_outline(out, outline, 0); } diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 2e9508a6..300f4900 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -87,7 +87,7 @@ float fz_atof(const char *s); 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_print_hash(fz_context *ctx, fz_hash_table *table); +void fz_print_hash(fz_context *ctx, FILE *out, fz_hash_table *table); void fz_empty_hash(fz_context *ctx, fz_hash_table *table); void fz_free_hash(fz_context *ctx, fz_hash_table *table); @@ -310,7 +310,7 @@ fz_store *fz_keep_store_context(fz_context *ctx); /* fz_print_store: Dump the contents of the store for debugging. */ -void fz_print_store(fz_context *ctx); +void fz_print_store(fz_context *ctx, FILE *out); /* fz_store_item: Add an item to the store. @@ -736,7 +736,7 @@ fz_font *fz_new_font_from_file(fz_context *ctx, char *path, int index, int use_g fz_font *fz_keep_font(fz_context *ctx, fz_font *font); void fz_drop_font(fz_context *ctx, fz_font *font); -void fz_print_font(fz_context *ctx, fz_font *font); +void fz_print_font(fz_context *ctx, FILE *out, 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, fz_matrix trm); @@ -818,7 +818,7 @@ void fz_transform_path(fz_context *ctx, fz_path *path, 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, fz_stroke_state *stroke, fz_matrix ctm); -void fz_print_path(fz_context *ctx, fz_path *, int indent); +void fz_print_path(fz_context *ctx, FILE *out, fz_path *, int indent); /* * Glyph cache @@ -872,7 +872,7 @@ void fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, floa void fz_free_text(fz_context *ctx, fz_text *text); fz_rect fz_bound_text(fz_context *ctx, fz_text *text, fz_matrix ctm); fz_text *fz_clone_text(fz_context *ctx, fz_text *old); -void fz_print_text(fz_context *ctx, fz_text*, int indent); +void fz_print_text(fz_context *ctx, FILE *out, fz_text*); /* * The shading code uses gouraud shaded triangle meshes. @@ -912,7 +912,7 @@ struct fz_shade_s 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); -void fz_print_shade(fz_context *ctx, fz_shade *shade); +void fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade); fz_rect fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm); void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); diff --git a/fitz/fitz.h b/fitz/fitz.h index 964bd7f7..a7fcbac4 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -118,7 +118,9 @@ int gettimeofday(struct timeval *tv, struct timezone *tz); #endif #endif -/* Contexts */ +/* + Contexts +*/ typedef struct fz_alloc_context_s fz_alloc_context; typedef struct fz_error_context_s fz_error_context; @@ -467,7 +469,9 @@ void *fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, uns */ char *fz_strdup_no_throw(fz_context *ctx, char *s); -/* safe string functions */ +/* + Safe string functions +*/ /* fz_strsep: Given a pointer to a C string (or a pointer to NULL) break it at the first occurence of a delimiter char (from a given set). @@ -1434,7 +1438,7 @@ fz_device *fz_new_bbox_device(fz_context *ctx, fz_bbox *bboxp); fz_device *fz_new_draw_device(fz_context *ctx, fz_pixmap *dest); /* - * Text extraction device + Text extraction device: Used for searching, format conversion etc. */ typedef struct fz_text_style_s fz_text_style; @@ -1526,10 +1530,10 @@ void fz_free_text_sheet(fz_context *ctx, fz_text_sheet *sheet); fz_text_page *fz_new_text_page(fz_context *ctx, fz_rect mediabox); void fz_free_text_page(fz_context *ctx, fz_text_page *page); -void fz_print_text_sheet(FILE *out, fz_text_sheet *sheet); -void fz_print_text_page_html(FILE *out, fz_text_page *page); -void fz_print_text_page_xml(FILE *out, fz_text_page *page); -void fz_print_text_page(FILE *out, fz_text_page *page); +void fz_print_text_sheet(fz_context *ctx, FILE *out, fz_text_sheet *sheet); +void fz_print_text_page_html(fz_context *ctx, FILE *out, fz_text_page *page); +void fz_print_text_page_xml(fz_context *ctx, FILE *out, fz_text_page *page); +void fz_print_text_page(fz_context *ctx, FILE *out, fz_text_page *page); /* * Cookie support - simple communication channel between app/library. @@ -1815,15 +1819,22 @@ struct fz_outline_s }; /* - fz_print_outline_xml: Dump the given outlines to stdout as (pseudo) - XML. + fz_print_outline_xml: Dump the given outlines as (pseudo) XML. + + out: The file handle to output to. + + outline: The outlines to output. */ -void fz_print_outline_xml(fz_context *ctx, fz_outline *outline); +void fz_print_outline_xml(fz_context *ctx, FILE *out, fz_outline *outline); /* - fz_print_outline: Dump the given outlines to stdout as text. + fz_print_outline: Dump the given outlines to as text. + + out: The file handle to output to. + + outline: The outlines to output. */ -void fz_print_outline(fz_context *ctx, fz_outline *outline); +void fz_print_outline(fz_context *ctx, FILE *out, fz_outline *outline); /* fz_free_outline: Free hierarchical outline. diff --git a/fitz/res_font.c b/fitz/res_font.c index 438d5ba7..c1db35d8 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -808,29 +808,29 @@ fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gi } void -fz_print_font(fz_context *ctx, fz_font *font) +fz_print_font(fz_context *ctx, FILE *out, fz_font *font) { - printf("font '%s' {\n", font->name); + fprintf(out, "font '%s' {\n", font->name); if (font->ft_face) { - printf("\tfreetype face %p\n", font->ft_face); + fprintf(out, "\tfreetype face %p\n", font->ft_face); if (font->ft_substitute) - printf("\tsubstitute font\n"); + fprintf(out, "\tsubstitute font\n"); } if (font->t3procs) { - printf("\ttype3 matrix [%g %g %g %g]\n", + fprintf(out, "\ttype3 matrix [%g %g %g %g]\n", font->t3matrix.a, font->t3matrix.b, font->t3matrix.c, font->t3matrix.d); - printf("\ttype3 bbox [%g %g %g %g]\n", + fprintf(out, "\ttype3 bbox [%g %g %g %g]\n", font->bbox.x0, font->bbox.y0, font->bbox.x1, font->bbox.y1); } - printf("}\n"); + fprintf(out, "}\n"); } fz_rect diff --git a/fitz/res_path.c b/fitz/res_path.c index 9c2072c1..45ead677 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -316,7 +316,7 @@ fz_transform_path(fz_context *ctx, fz_path *path, fz_matrix ctm) } void -fz_print_path(fz_context *ctx, fz_path *path, int indent) +fz_print_path(fz_context *ctx, FILE *out, fz_path *path, int indent) { float x, y; int i = 0; @@ -324,32 +324,32 @@ fz_print_path(fz_context *ctx, fz_path *path, int indent) while (i < path->len) { for (n = 0; n < indent; n++) - putchar(' '); + fputc(' ', out); switch (path->items[i++].k) { case FZ_MOVETO: x = path->items[i++].v; y = path->items[i++].v; - printf("%g %g m\n", x, y); + fprintf(out, "%g %g m\n", x, y); break; case FZ_LINETO: x = path->items[i++].v; y = path->items[i++].v; - printf("%g %g l\n", x, y); + fprintf(out, "%g %g l\n", x, y); break; case FZ_CURVETO: x = path->items[i++].v; y = path->items[i++].v; - printf("%g %g ", x, y); + fprintf(out, "%g %g ", x, y); x = path->items[i++].v; y = path->items[i++].v; - printf("%g %g ", x, y); + fprintf(out, "%g %g ", x, y); x = path->items[i++].v; y = path->items[i++].v; - printf("%g %g c\n", x, y); + fprintf(out, "%g %g c\n", x, y); break; case FZ_CLOSE_PATH: - printf("h\n"); + fprintf(out, "h\n"); break; } } diff --git a/fitz/res_shade.c b/fitz/res_shade.c index 59e3887e..d2b2f44b 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -68,59 +68,59 @@ fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm) } void -fz_print_shade(fz_context *ctx, fz_shade *shade) +fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade) { int i, j, n; float *vertex; int triangle; - printf("shading {\n"); + fprintf(out, "shading {\n"); switch (shade->type) { - case FZ_LINEAR: printf("\ttype linear\n"); break; - case FZ_RADIAL: printf("\ttype radial\n"); break; - case FZ_MESH: printf("\ttype mesh\n"); break; + case FZ_LINEAR: fprintf(out, "\ttype linear\n"); break; + case FZ_RADIAL: fprintf(out, "\ttype radial\n"); break; + case FZ_MESH: fprintf(out, "\ttype mesh\n"); break; } - printf("\tbbox [%g %g %g %g]\n", + fprintf(out, "\tbbox [%g %g %g %g]\n", shade->bbox.x0, shade->bbox.y0, shade->bbox.x1, shade->bbox.y1); - printf("\tcolorspace %s\n", shade->colorspace->name); + fprintf(out, "\tcolorspace %s\n", shade->colorspace->name); - printf("\tmatrix [%g %g %g %g %g %g]\n", + fprintf(out, "\tmatrix [%g %g %g %g %g %g]\n", shade->matrix.a, shade->matrix.b, shade->matrix.c, shade->matrix.d, shade->matrix.e, shade->matrix.f); if (shade->use_background) { - printf("\tbackground ["); + fprintf(out, "\tbackground ["); for (i = 0; i < shade->colorspace->n; i++) - printf("%s%g", i == 0 ? "" : " ", shade->background[i]); - printf("]\n"); + fprintf(out, "%s%g", i == 0 ? "" : " ", shade->background[i]); + fprintf(out, "]\n"); } if (shade->use_function) { - printf("\tfunction\n"); + fprintf(out, "\tfunction\n"); n = 3; } else n = 2 + shade->colorspace->n; - printf("\tvertices: %d\n", shade->mesh_len); + fprintf(out, "\tvertices: %d\n", shade->mesh_len); vertex = shade->mesh; triangle = 0; i = 0; while (i < shade->mesh_len) { - printf("\t%d:(%g, %g): ", triangle, vertex[0], vertex[1]); + fprintf(out, "\t%d:(%g, %g): ", triangle, vertex[0], vertex[1]); for (j = 2; j < n; j++) - printf("%s%g", j == 2 ? "" : " ", vertex[j]); - printf("\n"); + fprintf(out, "%s%g", j == 2 ? "" : " ", vertex[j]); + fprintf(out, "\n"); vertex += n; i++; @@ -128,5 +128,5 @@ fz_print_shade(fz_context *ctx, fz_shade *shade) triangle++; } - printf("}\n"); + fprintf(out, "}\n"); } diff --git a/fitz/res_store.c b/fitz/res_store.c index 1de4f240..8e5375d6 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -453,12 +453,12 @@ fz_drop_store_context(fz_context *ctx) } void -fz_print_store(fz_context *ctx) +fz_print_store(fz_context *ctx, FILE *out) { fz_item *item, *next; fz_store *store = ctx->store; - printf("-- resource store contents --\n"); + fprintf(out, "-- resource store contents --\n"); fz_lock(ctx, FZ_LOCK_ALLOC); for (item = store->head; item; item = next) @@ -466,10 +466,10 @@ fz_print_store(fz_context *ctx) next = item->next; if (next) next->val->refs++; - printf("store[*][refs=%d][size=%d] ", item->val->refs, item->size); + fprintf(out, "store[*][refs=%d][size=%d] ", item->val->refs, item->size); fz_unlock(ctx, FZ_LOCK_ALLOC); item->type->debug(item->key); - printf(" = %p\n", item->val); + fprintf(out, " = %p\n", item->val); fz_lock(ctx, FZ_LOCK_ALLOC); if (next) next->val->refs--; @@ -521,7 +521,7 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) #ifdef DEBUG_SCAVENGING printf("Scavenging: store=%d size=%d phase=%d\n", store->size, size, *phase); - fz_print_store(ctx); + fz_print_store(ctx, stderr); Memento_stats(); #endif do @@ -549,7 +549,7 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) { #ifdef DEBUG_SCAVENGING printf("scavenged: store=%d\n", store->size); - fz_print_store(ctx); + fz_print_store(ctx, stderr); Memento_stats(); #endif return 1; @@ -559,7 +559,7 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) #ifdef DEBUG_SCAVENGING printf("scavenging failed\n"); - fz_print_store(ctx); + fz_print_store(ctx, stderr); Memento_listBlocks(); #endif return 0; diff --git a/fitz/res_text.c b/fitz/res_text.c index 43b4471a..643b4c9f 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -118,23 +118,30 @@ fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, float y) text->len++; } -static int isxmlmeta(int c) +static int +isxmlmeta(int c) { return c < 32 || c >= 128 || c == '&' || c == '<' || c == '>' || c == '\'' || c == '"'; } -void fz_print_text(fz_context *ctx, fz_text *text, int indent) +static void +do_print_text(FILE *out, fz_text *text, int indent) { int i, n; for (i = 0; i < text->len; i++) { for (n = 0; n < indent; n++) - putchar(' '); + fputc(' ', out); if (!isxmlmeta(text->items[i].ucs)) - printf("\n", + fprintf(out, "\n", text->items[i].ucs, text->items[i].gid, text->items[i].x, text->items[i].y); else - printf("\n", + fprintf(out, "\n", text->items[i].ucs, text->items[i].gid, text->items[i].x, text->items[i].y); } } + +void fz_print_text(fz_context *ctx, FILE *out, fz_text *text) +{ + do_print_text(out, text, 0); +} -- cgit v1.2.3